diff --git a/.gitignore b/.gitignore index 323a3d12..09800555 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,9 @@ 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 + 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/contractNameAndAddress.ts b/contractNameAndAddress.ts new file mode 100644 index 00000000..2ad237cb --- /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: false + }) +} +export default func diff --git a/contracts/ExternalBribe.sol b/contracts/ExternalBribe.sol index e7bfe393..a7a60a2d 100644 --- a/contracts/ExternalBribe.sol +++ b/contracts/ExternalBribe.sol @@ -1,63 +1,73 @@ // 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 "openzeppelin-contracts/contracts/utils/math/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 +76,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 +84,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 +119,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 +135,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 +155,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 +171,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) { + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { return Math.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 +232,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 +247,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 +313,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 +325,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 +359,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/ExternalBribeV.sol b/contracts/ExternalBribeV.sol new file mode 100644 index 00000000..e69de29b diff --git a/contracts/Velo.sol b/contracts/Flow.sol similarity index 59% rename from contracts/Velo.sol rename to contracts/Flow.sol index 47cd3382..20d75888 100644 --- a/contracts/Velo.sol +++ b/contracts/Flow.sol @@ -1,25 +1,28 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT 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"; +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; @@ -42,23 +45,20 @@ contract Velo is IVelo { 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, 82 * 1e6 * 1e18); + _mint(_recipient, 400 * 1e6 * 1e18); //#settings } - 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 +67,11 @@ contract Velo is IVelo { 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 +80,29 @@ contract Velo is IVelo { 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/contracts/VeloGovernor.sol b/contracts/FlowGovernor.sol similarity index 96% rename from contracts/VeloGovernor.sol rename to contracts/FlowGovernor.sol index faa0804f..05d2bdaa 100644 --- a/contracts/VeloGovernor.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, @@ -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/Gauge.sol b/contracts/Gauge.sol index 611e35df..9ecbe763 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 "openzeppelin-contracts/contracts/utils/math/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,50 +292,80 @@ 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) { + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { return Math.min(block.timestamp, periodFinish[token]); } @@ -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) - + Math.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 = Math.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 = Math.max(timestamp1, startTimestamp); + return ( + (((Math.min(endTime, periodFinish[token]) - + Math.min( + Math.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 = Math.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), + Math.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 = Math.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) - + Math.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..977147ba 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 "openzeppelin-contracts/contracts/utils/math/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 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) { + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { return Math.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) - + Math.min(lastUpdateTime[token], periodFinish[token])) * + rewardRate[token] * + 10**IERC20(token).decimals()) / 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 = Math.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 = Math.max(timestamp1, startTimestamp); + return ( + (((Math.min(endTime, periodFinish[token]) - + Math.min( + Math.max(timestamp0, startTimestamp), + periodFinish[token] + )) * + rewardRate[token] * + 10**IERC20(token).decimals()) / 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 = Math.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), + Math.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 = Math.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)) / + 10**IERC20(token).decimals(); } } 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) - + Math.max( + _rewardPerTokenStored, + userRewardPerTokenStored[token][tokenId] + ))) / + 10**IERC20(token).decimals(); 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..36bde0de 100644 --- a/contracts/Minter.sol +++ b/contracts/Minter.sol @@ -1,35 +1,41 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import "contracts/libraries/Math.sol"; +import "openzeppelin-contracts/contracts/utils/math/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"; // 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; - IVelo public immutable _velo; + 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; + IFlow public immutable _flow; 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 FLOW (FLOW 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; // 5% max - 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 @@ -38,8 +44,8 @@ contract Minter is IMinter { ) { initializer = msg.sender; team = msg.sender; - teamRate = 30; // 30 bps = 0.03% - _velo = IVelo(IVotingEscrow(__ve).token()); + teamRate = 30; // 30 bps = 3% + _flow = IFlow(IVotingEscrow(__ve).token()); _voter = IVoter(__voter); _ve = IVotingEscrow(__ve); _rewards_distributor = IRewardsDistributor(__rewards_distributor); @@ -47,14 +53,14 @@ 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 + 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); - _velo.mint(address(this), max); - _velo.approve(address(_ve), type(uint).max); - for (uint i = 0; i < claimants.length; i++) { + _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]); } initializer = address(0); @@ -71,69 +77,75 @@ 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) { - return _velo.totalSupply() - _ve.totalSupply(); + function circulating_supply() public view returns (uint256) { + return _flow.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) { + function weekly_emission() public view returns (uint256) { return Math.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 _flowTotal = _flow.totalSupply(); return - (((((_minted * _veTotal) / _veloTotal) * _veTotal) / _veloTotal) * + (((((_minted * _veTotal) / _flowTotal) * _veTotal) / _flowTotal) * _veTotal) / - _veloTotal / + _flowTotal / 2; } // 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 = _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(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..5e2eab5b 100644 --- a/contracts/Pair.sol +++ b/contracts/Pair.sol @@ -1,16 +1,17 @@ // 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 "openzeppelin-contracts/contracts/utils/math/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/interfaces/IBribe.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,86 +19,136 @@ 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; address public immutable fees; address immutable factory; + address public externalBribe; + address public voter; + 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 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)); + // externalBribe = address(); this does not need to be set at the time of creation 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 +158,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 +166,60 @@ contract Pair is IPair { _unlocked = 1; } - function observationLength() external view returns (uint) { - return observations.length; + // 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 lastObservation() public view returns (Observation memory) { - return observations[observations.length-1]; + function getAndSetTank(address factory) external returns (address) { + address _tank = PairFactory(factory).tank(); + tank = _tank; + return _tank; } - 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); + 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; + } + + function lastObservation() public view returns (Observation memory) { + 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 +227,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]; @@ -148,45 +243,88 @@ contract Pair is IPair { } } + // dunks update0 + // Accrue fees on token0 - function _update0(uint 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; + // 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 { + 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(uint amount) internal { - _safeTransfer(token1, fees, amount); - uint256 _ratio = amount * 1e18 / totalSupply; - if (_ratio > 0) { - index1 += _ratio; + function _update1(uint256 amount) internal { + 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 // 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 +333,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 +364,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 +379,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 +490,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; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { - liquidity = Math.min(_amount0 * _totalSupply / _reserve0, _amount1 * _totalSupply / _reserve1); + liquidity = Math.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 +516,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 +542,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 +597,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 +662,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 +802,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 +816,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..4b9554d7 100644 --- a/contracts/RewardsDistributor.sol +++ b/contracts/RewardsDistributor.sol @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: MIT 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 "openzeppelin-contracts/contracts/utils/math/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 + Math.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] = Math.max( + uint256(int256(pt.bias - pt.slope * dt)), + 0 + ); } t += WEEK; } @@ -167,49 +206,70 @@ 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 = Math.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; } @@ -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 = Math.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..008181ed 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 "openzeppelin-contracts/contracts/utils/math/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,13 +151,21 @@ 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); @@ -119,15 +174,28 @@ contract Router is IRouter { (amountA, amountB) = (amountADesired, amountBDesired); liquidity = Math.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 = Math.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 = Math.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/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/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/Voter.sol b/contracts/Voter.sol index 9f086005..b6580806 100644 --- a/contracts/Voter.sol +++ b/contracts/Voter.sol @@ -1,31 +1,32 @@ // 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 "openzeppelin-contracts/contracts/utils/math/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/Pair.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 +34,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 +96,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 +104,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 +131,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 +152,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 +172,47 @@ contract Voter is IVoter { delete poolVote[_tokenId]; } - function poke(uint _tokenId) external { + // remove poke function + + function poke(uint256 _tokenId) external { + require( + IVotingEscrow(_ve).isApprovedOrOwner(msg.sender, _tokenId) || + msg.sender == governor + ); address[] memory _poolVote = poolVote[_tokenId]; - uint _poolCnt = _poolVote.length; + uint256 _poolCnt = _poolVote.length; uint256[] memory _weights = new uint256[](_poolCnt); - for (uint i = 0; i < _poolCnt; i ++) { + for (uint256 i = 0; i < _poolCnt; i++) { _weights[i] = votes[_tokenId][_poolVote[i]]; } _vote(_tokenId, _poolVote, _weights); } - function _vote(uint _tokenId, address[] memory _poolVote, uint256[] memory _weights) internal { + 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 +221,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 +239,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 +277,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-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"); + 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 +312,15 @@ contract Voter is IVoter { isAlive[_gauge] = true; _updateFor(_gauge); pools.push(_pool); - emit GaugeCreated(_gauge, msg.sender, _internal_bribe, _external_bribe, _pool); + Pair(_pool).setHasGauge(true); // may need to switch to IPair? + Pair(_pool).setExternalBribe(_external_bribe); + emit GaugeCreated( + _gauge, + msg.sender, + _internal_bribe, + _external_bribe, + _pool + ); return _gauge; } @@ -258,41 +339,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 +389,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 +412,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 +427,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 +468,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 +486,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/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/WrappedExternalBribe.sol b/contracts/WrappedExternalBribe.sol index 9017f9a3..0b5f8d16 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 "openzeppelin-contracts/contracts/utils/math/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) { + function lastTimeRewardApplicable(address token) + public + view + returns (uint256) + { return Math.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/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 fda59613..84758461 100644 --- a/contracts/factories/BribeFactory.sol +++ b/contracts/factories/BribeFactory.sol @@ -2,20 +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; } } diff --git a/contracts/factories/PairFactory.sol b/contracts/factories/PairFactory.sol index 752324e9..ecba628c 100644 --- a/contracts/factories/PairFactory.sol +++ b/contracts/factories/PairFactory.sol @@ -1,22 +1,27 @@ // 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; + address public voter; + address public team; + address public pendingTank; + address public tank; + address public deployer; + + 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 +29,64 @@ 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% + deployer = msg.sender; + } + + // 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; + } + + // 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; + } + + // function set tank on factory require team + + function setTank(address _tank) external { + require(msg.sender == deployer); // this should be updateable to team but adding deployer so that init script can run.. + 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 + + function getVoter() external view returns (address) { + return voter; } - function allPairsLength() external view returns (uint) { + function allPairsLength() external view returns (uint256) { return allPairs.length; } @@ -54,19 +106,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 +126,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 +134,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/contracts/interfaces/IVelo.sol b/contracts/interfaces/IFlow.sol similarity index 96% rename from contracts/interfaces/IVelo.sol rename to contracts/interfaces/IFlow.sol index 8c8d1e33..ac81b10b 100644 --- a/contracts/interfaces/IVelo.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/libraries/Math.sol b/contracts/libraries/Math.sol index bb315bee..ee09791d 100644 --- a/contracts/libraries/Math.sol +++ b/contracts/libraries/Math.sol @@ -1,16 +1,19 @@ pragma solidity 0.8.13; +// this causes issue with forge test as there is already a Math.sol in the forge repo library Math { - function max(uint a, uint b) internal pure returns (uint) { + 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/contracts/redeem/MerkleClaim.sol b/contracts/redeem/MerkleClaim.sol index 6883ce58..6904237e 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 {IFlow} 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 + IFlow public immutable FLOW; /// @notice ERC20-claimee inclusion root bytes32 public immutable merkleRoot; @@ -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) { - VELO = IVelo(_velo); + constructor(address _flow, bytes32 _merkleRoot) { + FLOW = IFlow(_flow); 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..2dc1c640 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; + IFlow public immutable FLOW; uint16 public immutable fantomChainId; // 12 for FTM, 10012 for FTM testnet address public immutable endpoint; @@ -22,19 +22,19 @@ 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, - address _velo, + address _flow, uint16 _fantomChainId, address _endpoint ) { require(_fantomChainId == 12 || _fantomChainId == 10012, "CHAIN_ID_NOT_FTM"); USDC = IERC20(_usdc); - VELO = IVelo(_velo); + FLOW = IFlow(_flow); 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/contracts/routerV.sol b/contracts/routerV.sol new file mode 100644 index 00000000..e69de29b diff --git a/deploy/00_velo.ts b/deploy/00_velo.ts new file mode 100644 index 00000000..6f0b067c --- /dev/null +++ b/deploy/00_velo.ts @@ -0,0 +1,21 @@ +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 + + const { deployer } = await getNamedAccounts() + + await deploy('Flow', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Flow'] +func.id = 'flow' diff --git a/deploy/01_gaugeFactory.ts b/deploy/01_gaugeFactory.ts new file mode 100644 index 00000000..9c2060c3 --- /dev/null +++ b/deploy/01_gaugeFactory.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() + + await deploy('GaugeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['GaugeFactory'] +func.id = 'gaugeFactory' diff --git a/deploy/02_bribeFactory.ts b/deploy/02_bribeFactory.ts new file mode 100644 index 00000000..48026f68 --- /dev/null +++ b/deploy/02_bribeFactory.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() + + await deploy('BribeFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['BribeFactory'] +func.id = 'bribeFactory' diff --git a/deploy/04_pairFactory.ts b/deploy/04_pairFactory.ts new file mode 100644 index 00000000..ea1e4040 --- /dev/null +++ b/deploy/04_pairFactory.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() + + await deploy('PairFactory', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['PairFactory'] +func.id = 'pairFactory' diff --git a/deploy/05_router.ts b/deploy/05_router.ts new file mode 100644 index 00000000..9cb552eb --- /dev/null +++ b/deploy/05_router.ts @@ -0,0 +1,24 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import arbConfig from '../tasks/deploy/constants/arbConfig' +const ARB_TEST_CONFIG = arbConfig + +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, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Router'] +func.id = 'router' diff --git a/deploy/06_library.ts b/deploy/06_library.ts new file mode 100644 index 00000000..ec1250ad --- /dev/null +++ b/deploy/06_library.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 router = await deployments.get('Router') + + await deploy('VelocimeterLibrary', { + from: deployer, + args: [router.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['VelocimeterLibrary'] +func.id = 'velocimeterLibrary' diff --git a/deploy/07_veArtProxy.ts b/deploy/07_veArtProxy.ts new file mode 100644 index 00000000..b1be7f86 --- /dev/null +++ b/deploy/07_veArtProxy.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() + + await deploy('VeArtProxy', { + from: deployer, + args: [], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['VeArtProxy'] +func.id = 'veArtProxy' diff --git a/deploy/08_votingEscrow.ts b/deploy/08_votingEscrow.ts new file mode 100644 index 00000000..96215eb3 --- /dev/null +++ b/deploy/08_votingEscrow.ts @@ -0,0 +1,22 @@ +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 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 + }) +} +export default func +func.tags = ['VotingEscrow'] +func.id = 'votingEscrow' diff --git a/deploy/09_rewardsDist.ts b/deploy/09_rewardsDist.ts new file mode 100644 index 00000000..5a6541af --- /dev/null +++ b/deploy/09_rewardsDist.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') + + await deploy('RewardsDistributor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['RewardsDistributor'] +func.id = 'rewardsDistributor' diff --git a/deploy/10_voter.ts b/deploy/10_voter.ts new file mode 100644 index 00000000..d0e74956 --- /dev/null +++ b/deploy/10_voter.ts @@ -0,0 +1,29 @@ +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, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Voter'] +func.id = 'voter' diff --git a/deploy/11_minter.ts b/deploy/11_minter.ts new file mode 100644 index 00000000..1c0a0ffd --- /dev/null +++ b/deploy/11_minter.ts @@ -0,0 +1,23 @@ +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, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['Minter'] +func.id = 'minter' diff --git a/deploy/15_init.ts b/deploy/15_init.ts new file mode 100644 index 00000000..ede2f01b --- /dev/null +++ b/deploy/15_init.ts @@ -0,0 +1,111 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import arbConfig from '../tasks/deploy/constants/arbConfig' + +const ARB_TEST_CONFIG = arbConfig + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployments, getNamedAccounts, ethers } = hre + + const { deployer } = await getNamedAccounts() + + 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('400m 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 on flow contract') + + await pairFactory.setPauser(ARB_TEST_CONFIG.teamMultisig) + console.log( + 'Pauser set on pair factory to multisig: ', + ARB_TEST_CONFIG.teamMultisig + ) + + // how to use msg.sender in hardhat scripts is the deployer address + + await escrow.setVoter(voter.address) + console.log( + 'idk how Voter set when it requires msg.sender to be the voter contract print msg.sender:', + deployer, + 'voter address: ', + voter.address, + 'escrow address: ', + escrow.address + ) + + await escrow.setTeam(ARB_TEST_CONFIG.teamMultisig) + console.log('Team multisig set for escrow', ARB_TEST_CONFIG.teamMultisig) + + await voter.setGovernor(ARB_TEST_CONFIG.teamMultisig) + console.log('Governor set on voter to: ', ARB_TEST_CONFIG.teamMultisig) + + await voter.setEmergencyCouncil(ARB_TEST_CONFIG.teamMultisig) + console.log( + 'Emergency Council set on voter to: ', + ARB_TEST_CONFIG.teamMultisig + ) + + await distributor.setDepositor(minter.address) + console.log('Depositor set to minter contract address') + + // 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 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 Pair factory to multisig: ', + ARB_TEST_CONFIG.teamMultisig + ) + + await pairFactory.setTank(ARB_TEST_CONFIG.teamMultisig) + console.log( + '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 Pair factory to to voter contract: ', voter.address) + + // 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 +} +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..8354d3f6 --- /dev/null +++ b/deploy/16_whitelist.ts @@ -0,0 +1,25 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import arbConfig from '../tasks/deploy/constants/arbConfig' + +const ARB_TEST_CONFIG = arbConfig + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + 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 +} +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..c96206d4 --- /dev/null +++ b/deploy/17_dist.ts @@ -0,0 +1,74 @@ +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 arbConfig from '../tasks/deploy/constants/arbConfig' + +const ARB_TEST_CONFIG = arbConfig + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + 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 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') + + 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') +} +export default func +func.tags = ['initial_dist'] +func.id = 'initial_dist' 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/.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/.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 new file mode 100644 index 00000000..c2c76ef9 --- /dev/null +++ b/deployments/arbitrumGoerli/BribeFactory.json @@ -0,0 +1,128 @@ +{ + "address": "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2", + "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": "0x76a367f2e00261a614c72434d880ef766013a1903b13708e8f4e128d02fe699c", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2", + "transactionIndex": 1, + "gasUsed": "4288879", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb7b011797f137749c567c8e5322baff5538d1f5ffc0756a97207d81517f636bc", + "transactionHash": "0x76a367f2e00261a614c72434d880ef766013a1903b13708e8f4e128d02fe699c", + "logs": [], + "blockNumber": 6188425, + "cumulativeGasUsed": "4288879", + "status": 1, + "byzantium": true + }, + "args": [], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21323, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_internal_bribe", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21325, + "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/Flow.json b/deployments/arbitrumGoerli/Flow.json new file mode 100644 index 00000000..edc5fc55 --- /dev/null +++ b/deployments/arbitrumGoerli/Flow.json @@ -0,0 +1,522 @@ +{ + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "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": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "transactionIndex": 1, + "gasUsed": "537302", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000080000000000000000000000400000000000000000000000000000000000000080000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000080000000000000000000000000000000000000000", + "blockHash": "0x78f094f17222191c24acaaf18d4c8bc0a3ffb69d577bcc665f27a2d805a3afb3", + "transactionHash": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 6188400, + "transactionHash": "0x8162d4143bba22a7aa330be80d18f4f89ae72a86d155b63a65f646aea577e48b", + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000053f3b51fd7f327e1ec4e6eaa3a049149cb2acad2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 0, + "blockHash": "0x78f094f17222191c24acaaf18d4c8bc0a3ffb69d577bcc665f27a2d805a3afb3" + } + ], + "blockNumber": 6188400, + "cumulativeGasUsed": "537302", + "status": 1, + "byzantium": true + }, + "args": [], + "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": {}, + "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/arbitrumGoerli/FlowGovernor.json b/deployments/arbitrumGoerli/FlowGovernor.json new file mode 100644 index 00000000..feb4820c --- /dev/null +++ b/deployments/arbitrumGoerli/FlowGovernor.json @@ -0,0 +1,1459 @@ +{ + "address": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", + "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": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", + "transactionIndex": 1, + "gasUsed": "2742890", + "logsBloom": "0x00000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000004000000000040000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa0007d324cd128170d9c0150a633357d987c4063f5166568e6ff1daf28aa8472", + "transactionHash": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 6188476, + "transactionHash": "0xcbe7f6b35db978e40a7e9a27c31152cc21533bd56987ef3cd6dece199dce59a0", + "address": "0x89b3ba263B34F95118cE4ed8Fb8A417Fc406ab61", + "topics": [ + "0x0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", + "logIndex": 0, + "blockHash": "0xa0007d324cd128170d9c0150a633357d987c4063f5166568e6ff1daf28aa8472" + } + ], + "blockNumber": 6188476, + "cumulativeGasUsed": "2742890", + "status": 1, + "byzantium": true + }, + "args": [ + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6" + ], + "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()": [ + { + "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": 21937, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_name", + "offset": 0, + "slot": "0", + "type": "t_string_storage" + }, + { + "astId": 21942, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_proposals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(ProposalCore)21935_storage)" + }, + { + "astId": 21945, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_governanceCall", + "offset": 0, + "slot": "2", + "type": "t_struct(Bytes32Deque)30250_storage" + }, + { + "astId": 23201, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_proposalVotes", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_struct(ProposalVote)23196_storage)" + }, + { + "astId": 23454, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_quorumNumerator", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 1705, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "team", + "offset": 0, + "slot": "6", + "type": "t_address" + }, + { + "astId": 1714, + "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)21935_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct L2Governor.ProposalCore)", + "numberOfBytes": "32", + "value": "t_struct(ProposalCore)21935_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)23196_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Bytes32Deque)30250_storage": { + "encoding": "inplace", + "label": "struct DoubleEndedQueue.Bytes32Deque", + "members": [ + { + "astId": 30243, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_begin", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30245, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_end", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 30249, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "_data", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_int128,t_bytes32)" + } + ], + "numberOfBytes": "64" + }, + "t_struct(ProposalCore)21935_storage": { + "encoding": "inplace", + "label": "struct L2Governor.ProposalCore", + "members": [ + { + "astId": 21927, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "voteStart", + "offset": 0, + "slot": "0", + "type": "t_struct(Timestamp)26451_storage" + }, + { + "astId": 21930, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "voteEnd", + "offset": 0, + "slot": "1", + "type": "t_struct(Timestamp)26451_storage" + }, + { + "astId": 21932, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "executed", + "offset": 0, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 21934, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "canceled", + "offset": 1, + "slot": "2", + "type": "t_bool" + } + ], + "numberOfBytes": "96" + }, + "t_struct(ProposalVote)23196_storage": { + "encoding": "inplace", + "label": "struct L2GovernorCountingSimple.ProposalVote", + "members": [ + { + "astId": 23187, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "againstVotes", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 23189, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "forVotes", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 23191, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "abstainVotes", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 23195, + "contract": "contracts/FlowGovernor.sol:FlowGovernor", + "label": "hasVoted", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "numberOfBytes": "128" + }, + "t_struct(Timestamp)26451_storage": { + "encoding": "inplace", + "label": "struct Timers.Timestamp", + "members": [ + { + "astId": 26450, + "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 new file mode 100644 index 00000000..65c59390 --- /dev/null +++ b/deployments/arbitrumGoerli/GaugeFactory.json @@ -0,0 +1,113 @@ +{ + "address": "0x3d396484a6a2759074dD879865c22Ac939C4a711", + "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": "0xdb808601bc16218167c22eacea3be6b21e783ebc02f7b51b39393e75c4366d68", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x3d396484a6a2759074dD879865c22Ac939C4a711", + "transactionIndex": 1, + "gasUsed": "3308285", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x469bf9741a6f689578b2873fa304effbd7c4dca71a3095e0a3cecfd409ee556a", + "transactionHash": "0xdb808601bc16218167c22eacea3be6b21e783ebc02f7b51b39393e75c4366d68", + "logs": [], + "blockNumber": 6188413, + "cumulativeGasUsed": "3308285", + "status": 1, + "byzantium": true + }, + "args": [], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21382, + "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..dcd9f004 --- /dev/null +++ b/deployments/arbitrumGoerli/MerkleClaim.json @@ -0,0 +1,220 @@ +{ + "address": "0x9c9dd01E65E0285dc9FDfb470347A39Be4a14399", + "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" + } + ], + "transactionHash": "0x80ebb09af24a530b8e63e87c518de1fa19da091dacaf99f09a47f021d87871d8", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x9c9dd01E65E0285dc9FDfb470347A39Be4a14399", + "transactionIndex": 1, + "gasUsed": "356966", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc8ad8914a7ac3b25b8aab87c1c4b5215c7f44d4eaac39ffaab0096072a43f405", + "transactionHash": "0x80ebb09af24a530b8e63e87c518de1fa19da091dacaf99f09a47f021d87871d8", + "logs": [], + "blockNumber": 6188491, + "cumulativeGasUsed": "356966", + "status": 1, + "byzantium": true + }, + "args": [ + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f" + ], + "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": { + "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 + }, + "storageLayout": { + "storage": [ + { + "astId": 24474, + "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..681590f8 --- /dev/null +++ b/deployments/arbitrumGoerli/Minter.json @@ -0,0 +1,427 @@ +{ + "address": "0xe66A8A93C38234782f84BF42ed855d857b372b3c", + "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" + } + ], + "transactionHash": "0x230d64da6bcdb9a53d75ebd2ce10a7ad8625e53acc702545a0805dc99172b40d", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xe66A8A93C38234782f84BF42ed855d857b372b3c", + "transactionIndex": 1, + "gasUsed": "1199219", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1cb2b4dc2ef616c62e6bc89e574b79e02c9bb63bc8ec88692524921dfe9952ee", + "transactionHash": "0x230d64da6bcdb9a53d75ebd2ce10a7ad8625e53acc702545a0805dc99172b40d", + "logs": [], + "blockNumber": 6188470, + "cumulativeGasUsed": "1199219", + "status": 1, + "byzantium": true + }, + "args": [ + "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3" + ], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6680, + "contract": "contracts/Minter.sol:Minter", + "label": "weekly", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6682, + "contract": "contracts/Minter.sol:Minter", + "label": "active_period", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6693, + "contract": "contracts/Minter.sol:Minter", + "label": "initializer", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 6695, + "contract": "contracts/Minter.sol:Minter", + "label": "team", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 6697, + "contract": "contracts/Minter.sol:Minter", + "label": "pendingTeam", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 6699, + "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..f1332cc7 --- /dev/null +++ b/deployments/arbitrumGoerli/PairFactory.json @@ -0,0 +1,577 @@ +{ + "address": "0x22E98754dBa170A64724558E668cb380516e0BE9", + "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": "0x994de9f23ee6a194c7496e974556026276c1477f1a1865afbd3295ba491531fe", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x22E98754dBa170A64724558E668cb380516e0BE9", + "transactionIndex": 1, + "gasUsed": "4628142", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3b7582ebabdf03f5525a18721c2d886a61bebe8bd486da60177cd408650dda52", + "transactionHash": "0x994de9f23ee6a194c7496e974556026276c1477f1a1865afbd3295ba491531fe", + "logs": [], + "blockNumber": 6188430, + "cumulativeGasUsed": "4628142", + "status": 1, + "byzantium": true + }, + "args": [], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21430, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPaused", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 21432, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pauser", + "offset": 1, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21434, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingPauser", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 21436, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "stableFee", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 21438, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "volatileFee", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 21443, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "feeManager", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 21445, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingFeeManager", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 21453, + "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": 21456, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "allPairs", + "offset": 0, + "slot": "7", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 21460, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPair", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 21462, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp0", + "offset": 0, + "slot": "9", + "type": "t_address" + }, + { + "astId": 21464, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp1", + "offset": 0, + "slot": "10", + "type": "t_address" + }, + { + "astId": 21466, + "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..4397a867 --- /dev/null +++ b/deployments/arbitrumGoerli/RedemptionReceiver.json @@ -0,0 +1,428 @@ +{ + "address": "0x11aa8e6D9e2802d3744F678dE55e22002241B474", + "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" + } + ], + "transactionHash": "0xd6fc16aa32f0149f52371821c9a733f078915a16ef7d70275c2e232257052409", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x11aa8e6D9e2802d3744F678dE55e22002241B474", + "transactionIndex": 1, + "gasUsed": "841985", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x034a599adf8724e3312da4117baf7827c0f57875195fbf9b19dd06ea9952939d", + "transactionHash": "0xd6fc16aa32f0149f52371821c9a733f078915a16ef7d70275c2e232257052409", + "logs": [], + "blockNumber": 6188482, + "cumulativeGasUsed": "841985", + "status": 1, + "byzantium": true + }, + "args": [ + "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + 10012, + "0x3c2269811836af69497E5F486A85D7316753cf62" + ], + "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": {}, + "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 + }, + "storageLayout": { + "storage": [ + { + "astId": 24586, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "team", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 24590, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "fantomSender", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 24597, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemedWEVE", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 24599, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableUSDC", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 24601, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "redeemableFLOW", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 24603, + "contract": "contracts/redeem/RedemptionReceiver.sol:RedemptionReceiver", + "label": "leftoverFLOW", + "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..acf4b7d9 --- /dev/null +++ b/deployments/arbitrumGoerli/RewardsDistributor.json @@ -0,0 +1,520 @@ +{ + "address": "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3", + "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": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xd1A4913ec6d68944C93056504655d1B3cbd4eBd3", + "transactionIndex": 1, + "gasUsed": "1623324", + "logsBloom": "0x00000000000000040000000000000000000000800000000000000000080000000000000000000000400000000000000000000000010000000000000080200000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000020000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe58bbbd28d39d27cbdc84c6daaa5d6274843927a7f3fdefcba783fe042c3e5fe", + "transactionHash": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 6188457, + "transactionHash": "0x19a62f40b488088580b9bd428cb0dce578126076213e61403a5aba853eeecc2a", + "address": "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000d1a4913ec6d68944c93056504655d1b3cbd4ebd3", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 0, + "blockHash": "0xe58bbbd28d39d27cbdc84c6daaa5d6274843927a7f3fdefcba783fe042c3e5fe" + } + ], + "blockNumber": 6188457, + "cumulativeGasUsed": "1623324", + "status": 1, + "byzantium": true + }, + "args": [ + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6" + ], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 9903, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "start_time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9905, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 9909, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor_of", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9913, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "user_epoch_of", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9915, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "last_token_time", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 9919, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "tokens_per_week", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9921, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "voting_escrow", + "offset": 0, + "slot": "1000000000000005", + "type": "t_address" + }, + { + "astId": 9923, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token", + "offset": 0, + "slot": "1000000000000006", + "type": "t_address" + }, + { + "astId": 9925, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token_last_balance", + "offset": 0, + "slot": "1000000000000007", + "type": "t_uint256" + }, + { + "astId": 9929, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "ve_supply", + "offset": 0, + "slot": "1000000000000008", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9931, + "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..9bc62d62 --- /dev/null +++ b/deployments/arbitrumGoerli/Router.json @@ -0,0 +1,1021 @@ +{ + "address": "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325", + "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": "0x9f716b1ac9238590393bf47d37f88307958c67e4898e85565179ab9065d93c65", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325", + "transactionIndex": 1, + "gasUsed": "3145971", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3bcfb08306f21919adec7e11f024590d9d1380d8dbd49d6f8367c04e09066b2e", + "transactionHash": "0x9f716b1ac9238590393bf47d37f88307958c67e4898e85565179ab9065d93c65", + "logs": [], + "blockNumber": 6188437, + "cumulativeGasUsed": "3145971", + "status": 1, + "byzantium": true + }, + "args": [ + "0x22E98754dBa170A64724558E668cb380516e0BE9", + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" + ], + "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": {}, + "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..5692bd08 --- /dev/null +++ b/deployments/arbitrumGoerli/VeArtProxy.json @@ -0,0 +1,75 @@ +{ + "address": "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0", + "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": "0xc72afd4e9fae71c82707ff37a5f382f266e90be6e8f1a7ab6f48a40584d7cb6c", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0", + "transactionIndex": 2, + "gasUsed": "615428", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x57978c2f0af190ea5c889143767e49c00bd8fab5642ca7691e649988bc642336", + "transactionHash": "0xc72afd4e9fae71c82707ff37a5f382f266e90be6e8f1a7ab6f48a40584d7cb6c", + "logs": [], + "blockNumber": 6188447, + "cumulativeGasUsed": "896801", + "status": 1, + "byzantium": true + }, + "args": [], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumGoerli/VelocimeterLibrary.json b/deployments/arbitrumGoerli/VelocimeterLibrary.json new file mode 100644 index 00000000..1dd16b71 --- /dev/null +++ b/deployments/arbitrumGoerli/VelocimeterLibrary.json @@ -0,0 +1,229 @@ +{ + "address": "0x162C6409a3086887411A965BE68878552F940143", + "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": "0x445278016ddb22a62ecad28a1289be911a5af65f5c634af02420955352083836", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x162C6409a3086887411A965BE68878552F940143", + "transactionIndex": 1, + "gasUsed": "904028", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5aa8ba07a9e00dc54aea96f3f6dfc416eaef85e40c2a781237fb0c0eb88ca31f", + "transactionHash": "0x445278016ddb22a62ecad28a1289be911a5af65f5c634af02420955352083836", + "logs": [], + "blockNumber": 6188439, + "cumulativeGasUsed": "904028", + "status": 1, + "byzantium": true + }, + "args": [ + "0x86Aa8EBc207134BC4965Cabc5f5C57559Fd5A325" + ], + "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": {}, + "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..26dc0ec7 --- /dev/null +++ b/deployments/arbitrumGoerli/Voter.json @@ -0,0 +1,1418 @@ +{ + "address": "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", + "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": "0xc7a89ae95f6266f5b11ace4896ee2f7f6ef2d2811ebfc58db2aa336f222cbcf3", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x809BCB4AC4c77F9F2B075ca9f29e160E8939D35f", + "transactionIndex": 1, + "gasUsed": "3013820", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xadbc9fa9ad293eda7ab9e75826675949e344db0e53f6d6b538ce9aed878db3c7", + "transactionHash": "0xc7a89ae95f6266f5b11ace4896ee2f7f6ef2d2811ebfc58db2aa336f222cbcf3", + "logs": [], + "blockNumber": 6188465, + "cumulativeGasUsed": "3013820", + "status": 1, + "byzantium": true + }, + "args": [ + "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "0x22E98754dBa170A64724558E668cb380516e0BE9", + "0x3d396484a6a2759074dD879865c22Ac939C4a711", + "0xb506F3C710Dbb31177A128d73bDA1D99b90512F2" + ], + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 14323, + "contract": "contracts/Voter.sol:Voter", + "label": "minter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 14325, + "contract": "contracts/Voter.sol:Voter", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14327, + "contract": "contracts/Voter.sol:Voter", + "label": "emergencyCouncil", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14329, + "contract": "contracts/Voter.sol:Voter", + "label": "totalWeight", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14332, + "contract": "contracts/Voter.sol:Voter", + "label": "pools", + "offset": 0, + "slot": "4", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 14336, + "contract": "contracts/Voter.sol:Voter", + "label": "gauges", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14340, + "contract": "contracts/Voter.sol:Voter", + "label": "poolForGauge", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14344, + "contract": "contracts/Voter.sol:Voter", + "label": "internal_bribes", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14348, + "contract": "contracts/Voter.sol:Voter", + "label": "external_bribes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14352, + "contract": "contracts/Voter.sol:Voter", + "label": "weights", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14358, + "contract": "contracts/Voter.sol:Voter", + "label": "votes", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14363, + "contract": "contracts/Voter.sol:Voter", + "label": "poolVote", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" + }, + { + "astId": 14367, + "contract": "contracts/Voter.sol:Voter", + "label": "usedWeights", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14371, + "contract": "contracts/Voter.sol:Voter", + "label": "lastVoted", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14375, + "contract": "contracts/Voter.sol:Voter", + "label": "isGauge", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14379, + "contract": "contracts/Voter.sol:Voter", + "label": "isWhitelisted", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14383, + "contract": "contracts/Voter.sol:Voter", + "label": "isAlive", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14529, + "contract": "contracts/Voter.sol:Voter", + "label": "_unlocked", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 15621, + "contract": "contracts/Voter.sol:Voter", + "label": "index", + "offset": 0, + "slot": "18", + "type": "t_uint256" + }, + { + "astId": 15625, + "contract": "contracts/Voter.sol:Voter", + "label": "supplyIndex", + "offset": 0, + "slot": "19", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15629, + "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..a2d236a7 --- /dev/null +++ b/deployments/arbitrumGoerli/VotingEscrow.json @@ -0,0 +1,2339 @@ +{ + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "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": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "transactionIndex": 1, + "gasUsed": "4240754", + "logsBloom": "0x00000000000000040000000000000000000000800000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072", + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 6188451, + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072" + }, + { + "transactionIndex": 1, + "blockNumber": 6188451, + "transactionHash": "0xcc3d7381e990dc406a7af4e2219465109ddea5f2000190e4feb327f0b7a0bb23", + "address": "0x38c8250FF6bD87812eDc5aAee577836c2B3c2aE6", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x00000000000000000000000038c8250ff6bd87812edc5aaee577836c2b3c2ae6", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x1ac11d1c1115d5c2473f5d63c4036e42e706c7001ce3730100036620cd607072" + } + ], + "blockNumber": 6188451, + "cumulativeGasUsed": "4240754", + "status": 1, + "byzantium": true + }, + "args": [ + "0x49E4eA802DdF4CAF7C699782a80DeefdC03Dcb4B", + "0x820D1Dc5A5B63490cBC521E18be5Aa948f49FDD0" + ], + "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).", + "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 + }, + "storageLayout": { + "storage": [ + { + "astId": 16269, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 16271, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "team", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 16273, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "artProxy", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16278, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "point_history", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_struct(Point)16228_storage)" + }, + { + "astId": 16283, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supportedInterfaces", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes4,t_bool)" + }, + { + "astId": 16298, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenId", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 16393, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_entered_state", + "offset": 0, + "slot": "6", + "type": "t_uint8" + }, + { + "astId": 16512, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToOwner", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16517, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenCount", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 16561, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToApprovals", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16568, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToOperators", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 16572, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownership_change", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17017, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenIdList", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 17022, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenToOwnerIndex", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17327, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_epoch", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "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)16228_storage)1000000000_storage)" + }, + { + "astId": 17339, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "locked", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16219_storage)" + }, + { + "astId": 17341, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "epoch", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 17345, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope_changes", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_uint256,t_int128)" + }, + { + "astId": 17347, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supply", + "offset": 0, + "slot": "19", + "type": "t_uint256" + }, + { + "astId": 19218, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "attachments", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 19222, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voted", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_uint256,t_bool)" + }, + { + "astId": 19453, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_delegates", + "offset": 0, + "slot": "22", + "type": "t_mapping(t_address,t_address)" + }, + { + "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)16234_storage))" + }, + { + "astId": 19469, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "numCheckpoints", + "offset": 0, + "slot": "24", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 19474, + "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)16228_storage)1000000000_storage": { + "base": "t_struct(Point)16228_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)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)16234_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)16228_storage)1000000000_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", + "numberOfBytes": "32", + "value": "t_array(t_struct(Point)16228_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)16219_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", + "numberOfBytes": "32", + "value": "t_struct(LockedBalance)16219_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)16228_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)16234_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)16234_storage" + }, + "t_struct(Checkpoint)16234_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Checkpoint", + "members": [ + { + "astId": 16230, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "timestamp", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 16233, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenIds", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)dyn_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(LockedBalance)16219_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.LockedBalance", + "members": [ + { + "astId": 16216, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16218, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "end", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Point)16228_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Point", + "members": [ + { + "astId": 16221, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "bias", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16223, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16225, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ts", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 16227, + "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/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/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.json b/deployments/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.json new file mode 100644 index 00000000..b1e2fb90 --- /dev/null +++ b/deployments/arbitrumGoerli/solcInputs/d2a2160297444b93438826228d1e185d.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__": "0x0000000000000031363734393838363334363530" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne.zip b/deployments/arbitrumOne.zip new file mode 100644 index 00000000..5edfa33c Binary files /dev/null and b/deployments/arbitrumOne.zip differ diff --git a/deployments/arbitrumOne/.chainId b/deployments/arbitrumOne/.chainId new file mode 100644 index 00000000..7df83ecb --- /dev/null +++ b/deployments/arbitrumOne/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/deployments/arbitrumOne/.migrations.json b/deployments/arbitrumOne/.migrations.json new file mode 100644 index 00000000..9b57fb51 --- /dev/null +++ b/deployments/arbitrumOne/.migrations.json @@ -0,0 +1,5 @@ +{ + "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 new file mode 100644 index 00000000..c3551454 --- /dev/null +++ b/deployments/arbitrumOne/BribeFactory.json @@ -0,0 +1,128 @@ +{ + "address": "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9", + "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": "0xbf242241c92ba4fe4c8c398fb59ba800f65487e29c50dddc5199b54763cffee9", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9", + "transactionIndex": 1, + "gasUsed": "26772550", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x6f3249adc0248d06500dda140b6f84fa675bf831f30e5a226917ffa5d23c4923", + "transactionHash": "0xbf242241c92ba4fe4c8c398fb59ba800f65487e29c50dddc5199b54763cffee9", + "logs": [], + "blockNumber": 58032009, + "cumulativeGasUsed": "26772550", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21361, + "contract": "contracts/factories/BribeFactory.sol:BribeFactory", + "label": "last_internal_bribe", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21363, + "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/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 new file mode 100644 index 00000000..d47bf99b --- /dev/null +++ b/deployments/arbitrumOne/GaugeFactory.json @@ -0,0 +1,113 @@ +{ + "address": "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", + "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": "0x09f6670bba024fa701ea9d9b3063e28841cf575d2835f1cf7b62e001ba978aef", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", + "transactionIndex": 1, + "gasUsed": "22312361", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9549973db6314c602849799444ad26a0d1adc452c46b8d6a18749a87566b018b", + "transactionHash": "0x09f6670bba024fa701ea9d9b3063e28841cf575d2835f1cf7b62e001ba978aef", + "logs": [], + "blockNumber": 58031998, + "cumulativeGasUsed": "22312361", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21420, + "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/Minter.json b/deployments/arbitrumOne/Minter.json new file mode 100644 index 00000000..ffa42aa3 --- /dev/null +++ b/deployments/arbitrumOne/Minter.json @@ -0,0 +1,427 @@ +{ + "address": "0xA9ee0C9f59Cf387859c8E9e3b333F9e8c2ea51F4", + "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" + } + ], + "transactionHash": "0x9f4423eed3e5dbb799714e6f2c6deefbf9229630f1a821c03649730155b199ed", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xA9ee0C9f59Cf387859c8E9e3b333F9e8c2ea51F4", + "transactionIndex": 1, + "gasUsed": "8439331", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x686c7d9ee125145ef07f8d91dbbf258c59b1ea893818bad00d5cfeb689dd1dbb", + "transactionHash": "0x9f4423eed3e5dbb799714e6f2c6deefbf9229630f1a821c03649730155b199ed", + "logs": [], + "blockNumber": 58032111, + "cumulativeGasUsed": "8439331", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "0xffCC209120a8fb388140689ea1235e4eD78620d5" + ], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6699, + "contract": "contracts/Minter.sol:Minter", + "label": "weekly", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 6701, + "contract": "contracts/Minter.sol:Minter", + "label": "active_period", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6712, + "contract": "contracts/Minter.sol:Minter", + "label": "initializer", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 6714, + "contract": "contracts/Minter.sol:Minter", + "label": "team", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 6716, + "contract": "contracts/Minter.sol:Minter", + "label": "pendingTeam", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 6718, + "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/arbitrumOne/PairFactory.json b/deployments/arbitrumOne/PairFactory.json new file mode 100644 index 00000000..83e26eff --- /dev/null +++ b/deployments/arbitrumOne/PairFactory.json @@ -0,0 +1,577 @@ +{ + "address": "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "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": "0x806f757dba4c1e4adee2d353b31c86b731de7f0f1928fa007e126b9f2c830303", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "transactionIndex": 1, + "gasUsed": "30447801", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xcd403376b36713664b24f1b8f61efb3b435076d8ab533c85ddefbe114c0a33d0", + "transactionHash": "0x806f757dba4c1e4adee2d353b31c86b731de7f0f1928fa007e126b9f2c830303", + "logs": [], + "blockNumber": 58032024, + "cumulativeGasUsed": "30447801", + "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\":\"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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21468, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPaused", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 21470, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pauser", + "offset": 1, + "slot": "0", + "type": "t_address" + }, + { + "astId": 21472, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingPauser", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 21474, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "stableFee", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 21476, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "volatileFee", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 21481, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "feeManager", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 21483, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "pendingFeeManager", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 21491, + "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": 21494, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "allPairs", + "offset": 0, + "slot": "7", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 21498, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "isPair", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 21500, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp0", + "offset": 0, + "slot": "9", + "type": "t_address" + }, + { + "astId": 21502, + "contract": "contracts/factories/PairFactory.sol:PairFactory", + "label": "_temp1", + "offset": 0, + "slot": "10", + "type": "t_address" + }, + { + "astId": 21504, + "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/RewardsDistributor.json b/deployments/arbitrumOne/RewardsDistributor.json new file mode 100644 index 00000000..deff378b --- /dev/null +++ b/deployments/arbitrumOne/RewardsDistributor.json @@ -0,0 +1,520 @@ +{ + "address": "0xffCC209120a8fb388140689ea1235e4eD78620d5", + "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": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xffCC209120a8fb388140689ea1235e4eD78620d5", + "transactionIndex": 1, + "gasUsed": "11095108", + "logsBloom": "0x00000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000200000001000000000000000000000000000000000000000000000000000004000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000080000000000000000000000010000000000000000008000000000000000000000000000000000000000000", + "blockHash": "0xf085e2ae966db473e170c44b22f33fa05b9bd636e4cdcdc9851084d9bffb44da", + "transactionHash": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 58032088, + "transactionHash": "0x85ea47b88d45de5a7f710b4cd864e46dea3cc99afefa103fa54aafee1b7d2a28", + "address": "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "topics": [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0x000000000000000000000000ffcc209120a8fb388140689ea1235e4ed78620d5", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787" + ], + "data": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "logIndex": 0, + "blockHash": "0xf085e2ae966db473e170c44b22f33fa05b9bd636e4cdcdc9851084d9bffb44da" + } + ], + "blockNumber": 58032088, + "cumulativeGasUsed": "11095108", + "status": 1, + "byzantium": true + }, + "args": [ + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787" + ], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 9922, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "start_time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9924, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 9928, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "time_cursor_of", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9932, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "user_epoch_of", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 9934, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "last_token_time", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 9938, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "tokens_per_week", + "offset": 0, + "slot": "5", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9940, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "voting_escrow", + "offset": 0, + "slot": "1000000000000005", + "type": "t_address" + }, + { + "astId": 9942, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token", + "offset": 0, + "slot": "1000000000000006", + "type": "t_address" + }, + { + "astId": 9944, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "token_last_balance", + "offset": 0, + "slot": "1000000000000007", + "type": "t_uint256" + }, + { + "astId": 9948, + "contract": "contracts/RewardsDistributor.sol:RewardsDistributor", + "label": "ve_supply", + "offset": 0, + "slot": "1000000000000008", + "type": "t_array(t_uint256)1000000000000000_storage" + }, + { + "astId": 9950, + "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/arbitrumOne/Router.json b/deployments/arbitrumOne/Router.json new file mode 100644 index 00000000..228cb071 --- /dev/null +++ b/deployments/arbitrumOne/Router.json @@ -0,0 +1,1021 @@ +{ + "address": "0x52A18b2386D6221Cf9DbcD4790456a23249e5279", + "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": "0x72fccd23138adb616617ec4533ef557da429f67f176c253b006ab42fbece6e31", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x52A18b2386D6221Cf9DbcD4790456a23249e5279", + "transactionIndex": 1, + "gasUsed": "21295455", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9da58c9904a2b1d24f1ad4708e16cc5162f74d5dd93eab180840de7505d469aa", + "transactionHash": "0x72fccd23138adb616617ec4533ef557da429f67f176c253b006ab42fbece6e31", + "logs": [], + "blockNumber": 58032037, + "cumulativeGasUsed": "21295455", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" + ], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrumOne/VeArtProxy.json b/deployments/arbitrumOne/VeArtProxy.json new file mode 100644 index 00000000..51e5cbe9 --- /dev/null +++ b/deployments/arbitrumOne/VeArtProxy.json @@ -0,0 +1,75 @@ +{ + "address": "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915", + "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": "0x05ebd073334884df4f081143a654a086464a4d49c43b0dad58fcb7700384d68a", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915", + "transactionIndex": 1, + "gasUsed": "5528609", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x94b1baa3d151e633a8a54630bf168cef2ccec575c61567ee62a6a36b1a8db72d", + "transactionHash": "0x05ebd073334884df4f081143a654a086464a4d49c43b0dad58fcb7700384d68a", + "logs": [], + "blockNumber": 58032060, + "cumulativeGasUsed": "5528609", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..717da6d6 --- /dev/null +++ b/deployments/arbitrumOne/Voter.json @@ -0,0 +1,1418 @@ +{ + "address": "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", + "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": "0x6ce83e7ad5d102309efb3a54d6b379a5bcce7218756a507aad0c0fe1228f6ac8", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5", + "transactionIndex": 1, + "gasUsed": "21090155", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9eef43e5bae2e6ddc3ce3985dac30acd1664cdbfa05d5325050adaf477343f4e", + "transactionHash": "0x6ce83e7ad5d102309efb3a54d6b379a5bcce7218756a507aad0c0fe1228f6ac8", + "logs": [], + "blockNumber": 58032097, + "cumulativeGasUsed": "21090155", + "status": 1, + "byzantium": true + }, + "args": [ + "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "0x9f7fdaB9317f1442808B90B819Ed0a4eF4f74994", + "0x2B0BB6962e89bD5FE9510Ff09Af8D709be21AAD7", + "0xf4F344Cfa1A82eDD37C96E879f01D9CA03f385b9" + ], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 14342, + "contract": "contracts/Voter.sol:Voter", + "label": "minter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 14344, + "contract": "contracts/Voter.sol:Voter", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 14346, + "contract": "contracts/Voter.sol:Voter", + "label": "emergencyCouncil", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 14348, + "contract": "contracts/Voter.sol:Voter", + "label": "totalWeight", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 14351, + "contract": "contracts/Voter.sol:Voter", + "label": "pools", + "offset": 0, + "slot": "4", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 14355, + "contract": "contracts/Voter.sol:Voter", + "label": "gauges", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14359, + "contract": "contracts/Voter.sol:Voter", + "label": "poolForGauge", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14363, + "contract": "contracts/Voter.sol:Voter", + "label": "internal_bribes", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14367, + "contract": "contracts/Voter.sol:Voter", + "label": "external_bribes", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 14371, + "contract": "contracts/Voter.sol:Voter", + "label": "weights", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 14377, + "contract": "contracts/Voter.sol:Voter", + "label": "votes", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 14382, + "contract": "contracts/Voter.sol:Voter", + "label": "poolVote", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)" + }, + { + "astId": 14386, + "contract": "contracts/Voter.sol:Voter", + "label": "usedWeights", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14390, + "contract": "contracts/Voter.sol:Voter", + "label": "lastVoted", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 14394, + "contract": "contracts/Voter.sol:Voter", + "label": "isGauge", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14398, + "contract": "contracts/Voter.sol:Voter", + "label": "isWhitelisted", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14402, + "contract": "contracts/Voter.sol:Voter", + "label": "isAlive", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 14548, + "contract": "contracts/Voter.sol:Voter", + "label": "_unlocked", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 15657, + "contract": "contracts/Voter.sol:Voter", + "label": "index", + "offset": 0, + "slot": "18", + "type": "t_uint256" + }, + { + "astId": 15661, + "contract": "contracts/Voter.sol:Voter", + "label": "supplyIndex", + "offset": 0, + "slot": "19", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 15665, + "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/arbitrumOne/VotingEscrow.json b/deployments/arbitrumOne/VotingEscrow.json new file mode 100644 index 00000000..4fbd69f7 --- /dev/null +++ b/deployments/arbitrumOne/VotingEscrow.json @@ -0,0 +1,2339 @@ +{ + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "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": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "transactionIndex": 1, + "gasUsed": "30470284", + "logsBloom": "0x00000000000000000000000000000000000000000000400000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000100000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000008000000000000000000000000000000002000000000", + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52", + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 58032078, + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52" + }, + { + "transactionIndex": 1, + "blockNumber": 58032078, + "transactionHash": "0xd3b7df5588e008b92a1b951bfba42d6598a0d14a3f6d66b17ce66ef8c9efa053", + "address": "0xfa01adbAA40f0EEeCEA76b7B18AC8bE064536787", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000fa01adbaa40f0eeecea76b7b18ac8be064536787", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xa8c0d8777601b5c5671d1684e9c34fe7272b0cd70b1058add4b25afc46969f52" + } + ], + "blockNumber": 58032078, + "cumulativeGasUsed": "30470284", + "status": 1, + "byzantium": true + }, + "args": [ + "0x944AF7785d57bcfC00e95388453B93DAD373216e", + "0x0bd9d21b40428a650DbFC0F7bd3F7B6FA321F915" + ], + "numDeployments": 1, + "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).", + "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 + }, + "storageLayout": { + "storage": [ + { + "astId": 16307, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voter", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 16309, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "team", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 16311, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "artProxy", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 16316, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "point_history", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_struct(Point)16266_storage)" + }, + { + "astId": 16321, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supportedInterfaces", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_bytes4,t_bool)" + }, + { + "astId": 16336, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenId", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 16431, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_entered_state", + "offset": 0, + "slot": "6", + "type": "t_uint8" + }, + { + "astId": 16550, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToOwner", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16555, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenCount", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 16599, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "idToApprovals", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 16606, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToOperators", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 16610, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownership_change", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17055, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ownerToNFTokenIdList", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 17060, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenToOwnerIndex", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 17365, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "user_point_epoch", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "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)16266_storage)1000000000_storage)" + }, + { + "astId": 17377, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "locked", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_uint256,t_struct(LockedBalance)16257_storage)" + }, + { + "astId": 17379, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "epoch", + "offset": 0, + "slot": "17", + "type": "t_uint256" + }, + { + "astId": 17383, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope_changes", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_uint256,t_int128)" + }, + { + "astId": 17385, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "supply", + "offset": 0, + "slot": "19", + "type": "t_uint256" + }, + { + "astId": 19256, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "attachments", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 19260, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "voted", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_uint256,t_bool)" + }, + { + "astId": 19491, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "_delegates", + "offset": 0, + "slot": "22", + "type": "t_mapping(t_address,t_address)" + }, + { + "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)16272_storage))" + }, + { + "astId": 19507, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "numCheckpoints", + "offset": 0, + "slot": "24", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 19512, + "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)16266_storage)1000000000_storage": { + "base": "t_struct(Point)16266_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)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)16272_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)16266_storage)1000000000_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.Point[1000000000])", + "numberOfBytes": "32", + "value": "t_array(t_struct(Point)16266_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)16257_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct VotingEscrow.LockedBalance)", + "numberOfBytes": "32", + "value": "t_struct(LockedBalance)16257_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)16266_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)16272_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct VotingEscrow.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)16272_storage" + }, + "t_struct(Checkpoint)16272_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Checkpoint", + "members": [ + { + "astId": 16268, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "timestamp", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 16271, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "tokenIds", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)dyn_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(LockedBalance)16257_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.LockedBalance", + "members": [ + { + "astId": 16254, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16256, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "end", + "offset": 0, + "slot": "1", + "type": "t_uint256" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Point)16266_storage": { + "encoding": "inplace", + "label": "struct VotingEscrow.Point", + "members": [ + { + "astId": 16259, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "bias", + "offset": 0, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16261, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "slope", + "offset": 16, + "slot": "0", + "type": "t_int128" + }, + { + "astId": 16263, + "contract": "contracts/VotingEscrow.sol:VotingEscrow", + "label": "ts", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 16265, + "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/arbitrumOne/WrappedExternalBribeFactory.json b/deployments/arbitrumOne/WrappedExternalBribeFactory.json new file mode 100644 index 00000000..3978894a --- /dev/null +++ b/deployments/arbitrumOne/WrappedExternalBribeFactory.json @@ -0,0 +1,148 @@ +{ + "address": "0x76C9347739842E72509106e6aef616552bD0C9a7", + "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": "0x1108f76fd230452fdc0732a9528c0f8257954178702f04a5dc763d34aee5cf16", + "receipt": { + "to": null, + "from": "0x53f3B51FD7F327E1Ec4E6eAa3A049149cB2acaD2", + "contractAddress": "0x76C9347739842E72509106e6aef616552bD0C9a7", + "transactionIndex": 3, + "gasUsed": "11333646", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1c406f984b385a93f37729f64bc8a2b4ae40913808c4cee065716f60de1acab1", + "transactionHash": "0x1108f76fd230452fdc0732a9528c0f8257954178702f04a5dc763d34aee5cf16", + "logs": [], + "blockNumber": 58032225, + "cumulativeGasUsed": "13108501", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2862Bf1ADC96d485B6E85C062b170903DE9A2Bd5" + ], + "numDeployments": 1, + "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": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 21862, + "contract": "contracts/factories/WrappedExternalBribeFactory.sol:WrappedExternalBribeFactory", + "label": "oldBribeToNew", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 21864, + "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/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/arbitrumOneOLD/MerkleClaim.json b/deployments/arbitrumOneOLD/MerkleClaim.json new file mode 100644 index 00000000..08d8fc91 --- /dev/null +++ b/deployments/arbitrumOneOLD/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/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/arbitrumOneOLD/RedemptionReceiver.json b/deployments/arbitrumOneOLD/RedemptionReceiver.json new file mode 100644 index 00000000..8bf7f47c --- /dev/null +++ b/deployments/arbitrumOneOLD/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/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/arbitrumOneOLD/Velo.json b/deployments/arbitrumOneOLD/Velo.json new file mode 100644 index 00000000..4ad69e78 --- /dev/null +++ b/deployments/arbitrumOneOLD/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/arbitrumOneOLD/VeloGovernor.json b/deployments/arbitrumOneOLD/VeloGovernor.json new file mode 100644 index 00000000..6a7f196a --- /dev/null +++ b/deployments/arbitrumOneOLD/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/arbitrumOneOLD/VelodromeLibrary.json b/deployments/arbitrumOneOLD/VelodromeLibrary.json new file mode 100644 index 00000000..960d9cfb --- /dev/null +++ b/deployments/arbitrumOneOLD/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/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/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json b/deployments/arbitrumOneOLD/solcInputs/4e21824d68c90a2d8601cfb8f8d80414.json new file mode 100644 index 00000000..58802f43 --- /dev/null +++ b/deployments/arbitrumOneOLD/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/deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json b/deployments/arbitrumOneOLD/solcInputs/f93feb6db909c3f14d7eec3a3196fbbd.json new file mode 100644 index 00000000..565546d0 --- /dev/null +++ b/deployments/arbitrumOneOLD/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/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..2255cecc --- /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..1e786acb --- /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('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 new file mode 100644 index 00000000..2255cecc --- /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..950278e1 --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..e551ecd2 --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..da9eea4a --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..ad7b5da0 --- /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 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'; diff --git a/dist/deploy/06_library.d.ts b/dist/deploy/06_library.d.ts new file mode 100644 index 00000000..2255cecc --- /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..040d5615 --- /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('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 new file mode 100644 index 00000000..2255cecc --- /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..bc6cfdef --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..17a5120d --- /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 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 new file mode 100644 index 00000000..2255cecc --- /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..9a3f90bb --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..b223fd45 --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..6fe5830e --- /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: 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 new file mode 100644 index 00000000..2255cecc --- /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..6eb7091b --- /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('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 new file mode 100644 index 00000000..2255cecc --- /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..8af8beaf --- /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 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'; diff --git a/dist/deploy/14_merkleClaim.d.ts b/dist/deploy/14_merkleClaim.d.ts new file mode 100644 index 00000000..2255cecc --- /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..392dbea4 --- /dev/null +++ b/dist/deploy/14_merkleClaim.js @@ -0,0 +1,23 @@ +"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'; diff --git a/dist/deploy/15_init.d.ts b/dist/deploy/15_init.d.ts new file mode 100644 index 00000000..2255cecc --- /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..07bf7f26 --- /dev/null +++ b/dist/deploy/15_init.js @@ -0,0 +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 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'); + 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 new file mode 100644 index 00000000..2255cecc --- /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..913fd425 --- /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 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'; diff --git a/dist/deploy/17_dist.d.ts b/dist/deploy/17_dist.d.ts new file mode 100644 index 00000000..2255cecc --- /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..15bc6799 --- /dev/null +++ b/dist/deploy/17_dist.js @@ -0,0 +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 +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') + + // 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/dist/hardhat.config.d.ts b/dist/hardhat.config.d.ts new file mode 100644 index 00000000..69885bae --- /dev/null +++ b/dist/hardhat.config.d.ts @@ -0,0 +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 './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 new file mode 100644 index 00000000..6711990e --- /dev/null +++ b/dist/hardhat.config.js @@ -0,0 +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 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('=')); +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] + }, + 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!] + // } + }, + 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!, + arbitrumOne: process.env.ARB_SCAN_API_KEY, + arbitrumGoerli: process.env.ARB_SCAN_API_KEY + } + } +}; +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.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..e9180518 --- /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 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, 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 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..5c7d171f --- /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 [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.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..ba696388 --- /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 [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 + // 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: flow.address, + // contract: 'contracts/Flow.sol:MyContract', //Filename.sol:ClassName + // constructorArguments: [arg1, arg2, arg3] + // }) + // WIP ^^ + 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); + const temp1 = { + [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); + } + }); + // 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('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.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'); + // Whitelist + 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'); +}); diff --git a/dist/tasks/deploy/constants/arbConfig.d.ts b/dist/tasks/deploy/constants/arbConfig.d.ts new file mode 100644 index 00000000..f9f4fb8b --- /dev/null +++ b/dist/tasks/deploy/constants/arbConfig.d.ts @@ -0,0 +1,26 @@ +import { ethers } from 'ethers'; +declare const arbConfig: { + lzChainId: number; + lzEndpoint: string; + WETH: string; + 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[]; + 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..d6cccb6e --- /dev/null +++ b/dist/tasks/deploy/constants/arbConfig.js @@ -0,0 +1,206 @@ +'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') +) +console.log(MILLION) +const HALF_MILLION = ethers_1.ethers.BigNumber.from('.5') + .mul(MILLION) + .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 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('90') // It will literally mint this many tokens so be careful with it.. + .mul(MILLION) + .mul(TOKEN_DECIMALS) +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 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, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + // Tokens + WETH: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + coolie: TEAM_EOA, + dunks: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + ceazor: '0x3c5Aac016EF2F178e8699D6208796A2D67557fe2', + faeflow: TEAM_EOA, + 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 + '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', + '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', + '0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F', + '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', + // '0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9', // sUSD not sure on this one + '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, + '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + coolie, + ceazor, + '0xf78da0B8Ae888C318e1A19415d593729A61Ac0c3', + '0x78e801136F77805239A7F533521A7a5570F572C8', + '0x0b776552c1Aef1Dc33005DD25AcDA22493b6615d' + ], + partnerAmts: [ + SIXTY_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..f5d5c409 --- /dev/null +++ b/dist/tasks/deploy/constants/arbHardhatConfig.js @@ -0,0 +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); +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: '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/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 new file mode 100644 index 00000000..f5d5c409 --- /dev/null +++ b/dist/tasks/deploy/constants/arbTestnetConfig.js @@ -0,0 +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); +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: '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/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..c23f753f --- /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_flow = +// 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_flow +// ); +// 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..1276b7ee --- /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 [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'); + // 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'); + // Whitelist + 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'); +}); diff --git a/exported.json b/exported.json new file mode 100644 index 00000000..9c1181d1 --- /dev/null +++ b/exported.json @@ -0,0 +1,7535 @@ +{ + "name": "arbitrumGoerli", + "chainId": "421613", + "contracts": { + "BribeFactory": { + "address": "0x5cD2336a80E72bf0480ae704df021e4531A09671", + "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" + } + ] + }, + "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": "0xA957E3958C7ed4590a28C5564438E89238b34EC1", + "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": "0x7F86f722a510CACb2cCD880a41dfE64773bfb371", + "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" + } + ] + }, + "Minter": { + "address": "0x388c6C5e6D27E3b6fa40eb98e0ef573D9E8e037E", + "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" + } + ] + }, + "PairFactory": { + "address": "0xddadFF10D1C9eb062180a870150D11673FFf7ad6", + "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": "0x552dD2458Ac8Fb7bC83a2BFF16e57e44Aa30cd4F", + "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" + } + ] + }, + "RewardsDistributor": { + "address": "0xEED0deFB831F96fC45B5e0ACb477F517F186496F", + "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": "0x49fb251F8Ff60bcd975D2018D0011D7a6065000B", + "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": "0xDe032908A79276B257d1ae80f0C0A2c070eDa1F4", + "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": "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" + } + ] + }, + "VeloGovernor": { + "address": "0xB843444d08bee4f79f571Bd34D13Ec71D4194b40", + "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" + } + ] + }, + "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": [ + { + "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": "0x362502b7139761937067cf81a73Dc18D315f10A0", + "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": "0xC43f6EbF97f9D99FF8a3aFe1413599e8DEc2aDB3", + "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/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..54259b81 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,88 +1,117 @@ -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 'hardhat-deploy' +import { config as dotenvConfig } from 'dotenv' +import { HardhatUserConfig, task } from 'hardhat/config' -import "./tasks/accounts"; -import "./tasks/deploy"; +import fs from 'fs' +import { resolve } from 'path' -import fs from "fs"; -import { resolve } from "path"; +import './tasks/accounts' +import './tasks/deploy' +import './tasks/batchCreateLockFor' +import './tasks/createLockFor' -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: { 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", - accounts: [process.env.PRIVATE_KEY!], - }, - ftmTestnet: { - url: "https://rpc.testnet.fantom.network", - accounts: [process.env.PRIVATE_KEY!], + url: 'https://rpc.fantom.network', + accounts: [process.env.PRIVATE_KEY!] }, - optimisticEthereum: { - url: "https://mainnet.optimism.io", + 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! + } + } }, - optimisticKovan: { - url: "https://kovan.optimism.io", + 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!] + // } }, 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: { - 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!, + // 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! } } -}; +} -export default config; +export default config 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/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/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 dd8e722d..1eaa7a6c 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,24 @@ { - "name": "velodrome", + "name": "velocimeter", "version": "1.0.0", - "description": "Base layer AMM on Optimism", + "description": "Base layer AMM on Arbitrum", "directories": { "lib": "lib" }, + "scripts": { + "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 deploy --network arbitrumGoerli", + "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", + "batchMint": "npx hardhat batch-create-lock-for --network arbitrumOne --token 0xC33f7f83CbB021846Cb9c58f2d8E3df428dbC8C1 --contract 0x10Df81252069C1095F541FAca61646cb9Ae76703" + }, "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.6", - "@nomiclabs/hardhat-etherscan": "^3.0.4", + "@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", "@typechain/hardhat": "^6.0.0", @@ -15,16 +26,25 @@ "@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", "typechain": "^8.0.0", "typescript": "^4.6.4" - } -} + }, + "dependencies": { + "zod": "^3.20.2" + }, + "packageManager": "yarn@3.3.1" +} \ No newline at end of file diff --git a/readme.md b/readme.md index 402b037e..1b1eb366 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,35 @@ -# Velodrome - -This repo contains the contracts for Velodrome Finance, an AMM on Optimism inspired by Solidly. - +# 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 + +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: '0x560b401d9F28F80980451d8582DEe903dD5295c3', + GaugeFactory: '0xeAA8Ebb77A7e3b7AE2d8090E7A1c2F9B605dc919', + MerkleClaim: '0x92eB499DBC33446Ace4f84Fba84E3A230370858D', + Minter: '0x402f3c314149F252144EE4Ca8646b4a215ACD6aC', + PairFactory: '0x6389e934d35fC9e066FAb549C8DBc9FddaC10e0D', + RedemptionReceiver: '0x52018E83E84ebe30ac6923F3747c7aE503923aaB', + RewardsDistributor: '0xc4b9295487B4C43C1929299076820D8f55BBf957', + Router: '0x1B0aC6bf6f35E638f6cce8D69C6074561273dc52', + VeArtProxy: '0x821B98D42D3AB509AF4F54205f0c52B019b9E2D5', + Flow: '0x84Ca387E7ede764A3284c67Ff8c68a305a9030a0', + FlowGovernor: '0x1a79b9daa3E741774bf67732F8a8B5820De8A53a', + VelocimeterLibrary: '0xcbE4714A95f866EB9C2eB50856F431f9E7353Ab6', + Voter: '0x854086d39955d28317aE3856399312b8Edb1B473', + VotingEscrow: '0xBf05364D6cf1586852c18c6b1CbEe218E3e09885' +} +// asdfa;kjsdhf ## Testing This repo uses both Foundry (for Solidity testing) and Hardhat (for deployment). @@ -33,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) | @@ -48,7 +76,7 @@ The Velodrome team engaged with Code 4rena for a security review. The results of | 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/removed/_____13_redemptionReceiver.ts b/removed/_____13_redemptionReceiver.ts new file mode 100644 index 00000000..e54f10e9 --- /dev/null +++ b/removed/_____13_redemptionReceiver.ts @@ -0,0 +1,32 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import arbConfig from '../tasks/deploy/constants/arbConfig' +import testFantomConfig from '../tasks/deploy/constants/testFantomConfig' + +const ARB_TEST_CONFIG = arbConfig +const FTM_CONFIG = testFantomConfig + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + 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 + }) +} +export default func +func.tags = ['RedemptionReceiver'] +func.id = 'redemptionReceiver' diff --git a/removed/_____14_merkleClaim.ts b/removed/_____14_merkleClaim.ts new file mode 100644 index 00000000..eb7ace46 --- /dev/null +++ b/removed/_____14_merkleClaim.ts @@ -0,0 +1,26 @@ +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 = arbConfig + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + 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 + }) +} +export default func +func.tags = ['MerkleClaim'] +func.id = 'merkleClaim' diff --git a/removed/_______12_veloGovernor.ts b/removed/_______12_veloGovernor.ts new file mode 100644 index 00000000..55ef6d0a --- /dev/null +++ b/removed/_______12_veloGovernor.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') + + await deploy('FlowGovernor', { + from: deployer, + args: [escrow.address], + log: true, + skipIfAlreadyDeployed: false + }) +} +export default func +func.tags = ['FlowGovernor'] +func.id = 'FlowGovernor' diff --git a/scripts/k.js b/scripts/k.js index 9ab02728..8a3b8841 100644 --- a/scripts/k.js +++ b/scripts/k.js @@ -1,35 +1,35 @@ -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 = Math.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) + 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) } /*function get_y(xIn, a, b) { @@ -43,36 +43,36 @@ 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 = 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 = 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 - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutAbove))) * 2; + _kA2 = Math.sqrt(Math.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 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOutAbove))) * 2 } - yOutBelow = yOutAbove; - _kA2 = Math.sqrt(Math.sqrt(_k(x+xIn, y-yOutAbove))) * 2; + yOutBelow = yOutAbove + _kA2 = Math.sqrt(Math.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 = Math.sqrt(Math.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 = Math.sqrt(Math.sqrt(_k(x + xIn, y - yOut))) * 2 /*while (_kA2 != _kB) { diff = _kA2 - _kB; yOut = (yOutBelow+yOutAbove)/2; @@ -81,22 +81,22 @@ function getAmountOut(xIn, x, y) { }*/ for (i = 0; i < 255; i++) { - _kA2 = Math.sqrt(Math.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 + 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..4472836f 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 Math.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..aa2a5f1b 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 Math.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/accounts.ts b/tasks/accounts.ts index 86e29167..008af1d9 100644 --- a/tasks/accounts.ts +++ b/tasks/accounts.ts @@ -1,10 +1,10 @@ -import { Signer } from "@ethersproject/abstract-signer"; -import { task } from "hardhat/config"; +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(); +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()); + console.log(await account.getAddress()) } -}); \ No newline at end of file +}) diff --git a/tasks/batchCreateLockFor.ts b/tasks/batchCreateLockFor.ts new file mode 100644 index 00000000..fec8d75b --- /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 +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/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 diff --git a/tasks/deploy/arb.ts b/tasks/deploy/arb.ts new file mode 100644 index 00000000..6a28d550 --- /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/arbConfig' +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 [ + 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 contracts deployed') +}) diff --git a/tasks/deploy/arbHardhat.ts b/tasks/deploy/arbHardhat.ts new file mode 100644 index 00000000..1ef3e463 --- /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 [ + 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/tasks/deploy/arbTest.ts b/tasks/deploy/arbTest.ts new file mode 100644 index 00000000..b77fdaf0 --- /dev/null +++ b/tasks/deploy/arbTest.ts @@ -0,0 +1,279 @@ +import { task } from 'hardhat/config' +var fs = require('fs') + +import optimismConfig from './constants/optimismConfig' +import testOptimismConfig from './constants/testOptimismConfig' +import arbTestnetConfig from './constants/arbConfig' + +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 [ + 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 + // 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: flow.address, + // contract: 'contracts/Flow.sol:MyContract', //Filename.sol:ClassName + // constructorArguments: [arg1, arg2, arg3] + // }) + + // WIP ^^ + + 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', //Filename.sol:ClassName + 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) + 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('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.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') + + // Whitelist + 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') +}) diff --git a/tasks/deploy/constants/arbConfig.ts b/tasks/deploy/constants/arbConfig.ts new file mode 100644 index 00000000..b2e48cf2 --- /dev/null +++ b/tasks/deploy/constants/arbConfig.ts @@ -0,0 +1,213 @@ +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') +) + +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) +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('600') // It will literally mint this many tokens so be careful with it.. + .mul(MILLION) + .mul(TOKEN_DECIMALS) + +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 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 + lzChainId: 110, + lzEndpoint: '0x3c2269811836af69497E5F486A85D7316753cf62', + + // Tokens + 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: [dunks], + partnerAmts: [ONE_MILLION], // MILLION Mint 0.001 WTF pls halp + partnerMax: PARTNER_MAX, + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: TEAM_MULTISIG, + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + // '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 + // '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 + // ], +} + +export default arbConfig diff --git a/tasks/deploy/constants/arbHardhatConfig.ts b/tasks/deploy/constants/arbHardhatConfig.ts new file mode 100644 index 00000000..7a90f335 --- /dev/null +++ b/tasks/deploy/constants/arbHardhatConfig.ts @@ -0,0 +1,92 @@ +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: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', // updated by dunks w/ arb agor WETH + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', //TODO + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + // todo update whitelist with actual goerli tokens + '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..7a90f335 --- /dev/null +++ b/tasks/deploy/constants/arbTestnetConfig.ts @@ -0,0 +1,92 @@ +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: '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', // updated by dunks w/ arb agor WETH + USDC: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', //TODO + + // Addresses + teamEOA: TEAM_EOA, + teamMultisig: TEAM_MULTISIG, + emergencyCouncil: '0x069e85D4F1010DD961897dC8C095FBB5FF297434', + + merkleRoot: + '0xbb99a09fb3b8499385659e82a8da93596dd07082fe86981ec06c83181dee489f', + tokenWhitelist: [ + // todo update whitelist with actual goerli tokens + '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/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/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 e6fecd13..cd0c5f77 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, @@ -28,176 +28,179 @@ task("deploy:op", "Deploys Optimism contracts").setAction(async function ( RewardsDistributor, Voter, Minter, - VeloGovernor, + FlowGovernor, 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('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: ", + ) + 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 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(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/tasks/log/failed.csv b/tasks/log/failed.csv new file mode 100644 index 00000000..9cbe67c1 --- /dev/null +++ b/tasks/log/failed.csv @@ -0,0 +1,2 @@ +recipient,amountInMillion,durationInYear + diff --git a/tasks/log/successful.csv b/tasks/log/successful.csv new file mode 100644 index 00000000..f42f8982 --- /dev/null +++ b/tasks/log/successful.csv @@ -0,0 +1,3 @@ +recipient,txHash +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,0x387991237fabb35fce02398147114e29115b7ee4235feb3f99274b50deab382c +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,0x3b6ff023cf2fb6e11baac5333f385bf681b825ebc842aa3fdc015d061bb55ea6 diff --git a/tasks/sample_partners.csv b/tasks/sample_partners.csv new file mode 100644 index 00000000..8c4e7ba4 --- /dev/null +++ b/tasks/sample_partners.csv @@ -0,0 +1,4 @@ +recipient,amountInMillion,durationInYear +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,1,4 +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,2,2 +0x16ec7CD5E35682B751d0c77c41A4e6a1A3E2DE01,4,4 \ No newline at end of file diff --git a/test/BaseTest.sol b/test/BaseTest.sol index a5629e70..cd9bd973 100644 --- a/test/BaseTest.sol +++ b/test/BaseTest.sol @@ -17,8 +17,8 @@ import "contracts/Pair.sol"; import "contracts/PairFees.sol"; import "contracts/RewardsDistributor.sol"; import "contracts/Router.sol"; -import "contracts/Velo.sol"; -import "contracts/VelodromeLibrary.sol"; +import "contracts/Flow.sol"; +import "contracts/VelocimeterLibrary.sol"; import "contracts/Voter.sol"; import "contracts/VeArtProxy.sol"; import "contracts/VotingEscrow.sol"; @@ -47,13 +47,13 @@ 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) PairFactory factory; Router router; - VelodromeLibrary lib; + VelocimeterLibrary lib; Pair pair; Pair pair2; Pair pair3; @@ -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(); @@ -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 { 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 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/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 { 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)); } 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"; 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 { 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/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==