Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xbe8666fd6873b0e188898180f922a49c3dd14c20.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- BribeFactory
- Optimization enabled
- true
- Compiler version
- v0.8.13+commit.abaa5c0e
- Optimization runs
- 200
- Verified at
- 2023-08-25T19:26:29.411982Z
Contract source code
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; interface IBribeFactory { function createExternalBribe(address[] memory) external returns (address); } // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } } interface IBribe { function _deposit(uint amount, uint tokenId) external; function _withdraw(uint amount, uint tokenId) external; function getRewardForOwner(uint tokenId, address[] memory tokens) external; function notifyRewardAmount(address token, uint amount) external; function left(address token) external view returns (uint); } interface IERC20 { function totalSupply() external view returns (uint256); function transfer(address recipient, uint amount) external returns (bool); function decimals() external view returns (uint8); function symbol() external view returns (string memory); function balanceOf(address) external view returns (uint); function transferFrom(address sender, address recipient, uint amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); } interface IGauge { function notifyRewardAmount(address token, uint amount) external; function getReward(address account, address[] memory tokens) external; function left(address token) external view returns (uint); function stake() external view returns (address); } interface IVoter { function _ve() external view returns (address); function governor() external view returns (address); function emergencyCouncil() external view returns (address); function attachTokenToGauge(uint _tokenId, address account) external; function detachTokenFromGauge(uint _tokenId, address account) external; function emitDeposit(uint _tokenId, address account, uint amount) external; function emitWithdraw(uint _tokenId, address account, uint amount) external; function isWhitelisted(address token) external view returns (bool); function notifyRewardAmount(uint amount) external; function distribute(address _gauge) external; function gauges(address) external view returns (address); } interface IVotingEscrow { struct Point { int128 bias; int128 slope; // # -dweight / dt uint256 ts; uint256 blk; // block } function token() external view returns (address); function team() external returns (address); function epoch() external view returns (uint); function point_history(uint loc) external view returns (Point memory); function user_point_history(uint tokenId, uint loc) external view returns (Point memory); function user_point_epoch(uint tokenId) external view returns (uint); function ownerOf(uint) external view returns (address); function isApprovedOrOwner(address, uint) external view returns (bool); function transferFrom(address, address, uint) external; function voting(uint tokenId) external; function abstain(uint tokenId) external; function attach(uint tokenId) external; function detach(uint tokenId) external; function checkpoint() external; function deposit_for(uint tokenId, uint value) external; function create_lock_for(uint, uint, address) external returns (uint); function balanceOfNFT(uint) external view returns (uint); function totalSupply() external view returns (uint); } // 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; 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; address[] public rewards; mapping(address => bool) public isReward; /// @notice A checkpoint for marking balance struct Checkpoint { uint timestamp; uint balanceOf; } /// @notice A checkpoint for marking supply struct SupplyCheckpoint { uint timestamp; uint supply; } /// @notice A record of balance checkpoints for each account, by index mapping (uint => mapping (uint => Checkpoint)) public checkpoints; /// @notice The number of checkpoints for each account mapping (uint => uint) public numCheckpoints; /// @notice A record of balance checkpoints for each token, by index mapping (uint => 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); event HandleLeftOverRewards(address indexed reward, uint originalEpoch, uint updatedEpoch, uint amount); constructor(address _voter, address[] memory _allowedRewardTokens) { voter = _voter; _ve = IVoter(_voter)._ve(); for (uint i; i < _allowedRewardTokens.length; i++) { if (_allowedRewardTokens[i] != address(0)) { isReward[_allowedRewardTokens[i]] = true; rewards.push(_allowedRewardTokens[i]); } } } // simple re-entrancy check uint internal _unlocked = 1; modifier lock() { require(_unlocked == 1); _unlocked = 2; _; _unlocked = 1; } function _bribeStart(uint timestamp) internal pure returns (uint) { return timestamp - (timestamp % (7 days)); } function getEpochStart(uint timestamp) public pure returns (uint) { uint bribeStart = _bribeStart(timestamp); uint 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]; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (checkpoints[tokenId][nCheckpoints - 1].timestamp <= timestamp) { return (nCheckpoints - 1); } // Next check implicit zero balance if (checkpoints[tokenId][0].timestamp > timestamp) { return 0; } uint lower = 0; uint upper = nCheckpoints - 1; while (upper > lower) { uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[tokenId][center]; if (cp.timestamp == timestamp) { return center; } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } return lower; } function getPriorSupplyIndex(uint timestamp) public view returns (uint) { uint nCheckpoints = supplyNumCheckpoints; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (supplyCheckpoints[nCheckpoints - 1].timestamp <= timestamp) { return (nCheckpoints - 1); } // Next check implicit zero balance if (supplyCheckpoints[0].timestamp > timestamp) { return 0; } uint lower = 0; uint upper = nCheckpoints - 1; while (upper > lower) { uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow SupplyCheckpoint memory cp = supplyCheckpoints[center]; if (cp.timestamp == timestamp) { return center; } else if (cp.timestamp < timestamp) { lower = center; } else { upper = center - 1; } } 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) { checkpoints[tokenId][_nCheckPoints - 1].balanceOf = balance; } else { checkpoints[tokenId][_nCheckPoints] = Checkpoint(_timestamp, balance); numCheckpoints[tokenId] = _nCheckPoints + 1; } } function _writeSupplyCheckpoint() internal { uint _nCheckPoints = supplyNumCheckpoints; uint _timestamp = block.timestamp; if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) { supplyCheckpoints[_nCheckPoints - 1].supply = totalSupply; } else { supplyCheckpoints[_nCheckPoints] = SupplyCheckpoint(_timestamp, totalSupply); supplyNumCheckpoints = _nCheckPoints + 1; } } function rewardsListLength() external view returns (uint) { return rewards.length; } // returns the last time the reward was modified or periodFinish if the reward has ended function lastTimeRewardApplicable(address token) public view returns (uint) { return Math.min(block.timestamp, periodFinish[token]); } // allows a user to claim rewards for a given token function getReward(uint 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); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward); emit ClaimRewards(msg.sender, tokens[i], _reward); } } // used by Voter to allow batched reward claims function getRewardForOwner(uint 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); lastEarn[tokens[i]][tokenId] = block.timestamp; if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward); emit ClaimRewards(_owner, tokens[i], _reward); } } function earned(address token, uint tokenId) public view returns (uint) { if (numCheckpoints[tokenId] == 0) { return 0; } uint reward = 0; uint _bal = 0; uint _supply = 1; uint _index = 0; uint _currTs = _bribeStart(lastEarn[token][tokenId]); // take epoch last claimed in as starting point _index = getPriorBalanceIndex(tokenId, _currTs); // accounts for case where lastEarn is before first checkpoint _currTs = Math.max(_currTs, _bribeStart(checkpoints[tokenId][_index].timestamp)); // get epochs between current epoch and first checkpoint in same epoch as last claim uint numEpochs = (_bribeStart(block.timestamp) - _currTs) / DURATION; if (numEpochs > 0) { for (uint256 i = 0; i < numEpochs; i++) { // get index of last checkpoint in this epoch _index = getPriorBalanceIndex(tokenId, _currTs + DURATION); // get checkpoint in this epoch _bal = checkpoints[tokenId][_index].balanceOf; // get supply of last checkpoint in this epoch _supply = supplyCheckpoints[getPriorSupplyIndex(_currTs + DURATION)].supply; if (_supply != 0) { reward += _bal * tokenRewardsPerEpoch[token][_currTs] / _supply; } _currTs += DURATION; } } 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 { require(msg.sender == voter); totalSupply += amount; balanceOf[tokenId] += amount; _writeCheckpoint(tokenId, balanceOf[tokenId]); _writeSupplyCheckpoint(); emit Deposit(msg.sender, tokenId, amount); } function _withdraw(uint amount, uint tokenId) external { require(msg.sender == voter); totalSupply -= amount; balanceOf[tokenId] -= amount; _writeCheckpoint(tokenId, balanceOf[tokenId]); _writeSupplyCheckpoint(); emit Withdraw(msg.sender, tokenId, amount); } function left(address token) external view returns (uint) { uint adjustedTstamp = getEpochStart(block.timestamp); return tokenRewardsPerEpoch[token][adjustedTstamp]; } function notifyRewardAmount(address token, uint 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"); } // bribes kick in at the start of next bribe period uint adjustedTstamp = getEpochStart(block.timestamp); uint epochRewards = tokenRewardsPerEpoch[token][adjustedTstamp]; uint256 balanceBefore = IERC20(token).balanceOf(address(this)); _safeTransferFrom(token, msg.sender, address(this), amount); uint256 balanceAfter = IERC20(token).balanceOf(address(this)); amount = balanceAfter - balanceBefore; tokenRewardsPerEpoch[token][adjustedTstamp] = epochRewards + amount; periodFinish[token] = adjustedTstamp + DURATION; if (!isReward[token]) { isReward[token] = true; rewards.push(token); } emit NotifyReward(msg.sender, token, adjustedTstamp, amount); } // This is an external function that can only be called by teams to handle unclaimed rewards due to zero vote function handleLeftOverRewards(uint epochTimestamp, address[] memory tokens) external { require(msg.sender == IVotingEscrow(_ve).team(), "only team"); // require that supply of that epoch to be ZERO uint epochStart = getEpochStart(epochTimestamp); SupplyCheckpoint memory sp0 = supplyCheckpoints[getPriorSupplyIndex(epochStart + DURATION)]; if (epochStart + DURATION > _bribeStart(sp0.timestamp)) { require(sp0.supply == 0, "this epoch has votes"); } // do sth like notifyRewardAmount uint length = tokens.length; for (uint i = 0; i < length;) { // check bribe amount uint previousEpochRewards = tokenRewardsPerEpoch[tokens[i]][epochStart]; require(previousEpochRewards != 0, "no bribes for this epoch"); // get timestamp of current epoch uint adjustedTstamp = getEpochStart(block.timestamp); // get notified reward of current epoch uint currentEpochRewards = tokenRewardsPerEpoch[tokens[i]][adjustedTstamp]; // add previous unclaimed rewards to current epoch tokenRewardsPerEpoch[tokens[i]][adjustedTstamp] = currentEpochRewards + previousEpochRewards; // remove token rewards from previous epoch tokenRewardsPerEpoch[tokens[i]][epochStart] = 0; // amend period finish periodFinish[tokens[i]] = adjustedTstamp + DURATION; emit HandleLeftOverRewards(tokens[i], epochStart, adjustedTstamp, previousEpochRewards); unchecked { ++i; } } } function swapOutRewardToken(uint 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 { require(token.code.length > 0); (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 { require(token.code.length > 0); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool)))); } } contract BribeFactory is IBribeFactory { address public last_external_bribe; function createExternalBribe(address[] memory allowedRewards) external returns (address) { last_external_bribe = address(new ExternalBribe(msg.sender, allowedRewards)); return last_external_bribe; } }
Contract ABI
[{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"createExternalBribe","inputs":[{"type":"address[]","name":"allowedRewards","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"last_external_bribe","inputs":[]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50612559806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636485f0c41461003b578063b0ad856f1461006a575b600080fd5b61004e610049366004610119565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b6000338260405161008d906100da565b6100989291906101de565b604051809103906000f0801580156100b4573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6122e98061023b83390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b038116811461011457600080fd5b919050565b6000602080838503121561012c57600080fd5b823567ffffffffffffffff8082111561014457600080fd5b818501915085601f83011261015857600080fd5b81358181111561016a5761016a6100e7565b8060051b604051601f19603f8301168101818110858211171561018f5761018f6100e7565b6040529182528482019250838101850191888311156101ad57600080fd5b938501935b828510156101d2576101c3856100fd565b845293850193928501926101b2565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b8181101561022c57855185168352948301949183019160010161020e565b50909897505050505050505056fe60c06040526001600b553480156200001657600080fd5b50604051620022e9380380620022e98339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611f47620003a260003960008181610309015281816104e801528181610c010152818161103b015261169b01526000818161020a01528181610dcf01528181610ff80152818161123601526115ae0152611f476000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806399bcc052116100f9578063e688639611610097578063f301af4211610071578063f301af4214610444578063f320772314610457578063f5f8d3651461046a578063f7412baf1461047d57600080fd5b8063e688639614610408578063e8111a1214610410578063f25e55a51461041957600080fd5b8063a28d4c9c116100d3578063a28d4c9c146103af578063a7852afa146103c2578063b66503cf146103d5578063da09d19d146103e857600080fd5b806399bcc052146103695780639cc7f7081461037c5780639e2bf22c1461039c57600080fd5b80634d5ce0381161016657806376f4be361161014057806376f4be36146102f15780638dd598fb1461030457806392777b291461032b5780639418f9391461035657600080fd5b80634d5ce0381461028b57806350589793146102be578063638634ee146102de57600080fd5b80630175e23b146101ae57806312a24cbb146101d457806318160ddd146101e95780633e491d47146101f257806346c96aac1461020557806349dcc20414610244575b600080fd5b6101c16101bc366004611bd8565b6104a4565b6040519081526020015b60405180910390f35b6101e76101e2366004611c2f565b6104e6565b005b6101c160005481565b6101c1610200366004611d00565b610903565b61022c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101cb565b610276610252366004611d2c565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101cb565b6102ae610299366004611d4e565b60066020526000908152604090205460ff1681565b60405190151581526020016101cb565b6101c16102cc366004611bd8565b60086020526000908152604090205481565b6101c16102ec366004611d4e565b610aa7565b6101c16102ff366004611bd8565b610acb565b61022c7f000000000000000000000000000000000000000000000000000000000000000081565b6101c1610339366004611d00565b600260209081526000928352604080842090915290825290205481565b6101e7610364366004611d6b565b610bff565b6101c1610377366004611d4e565b610d8b565b6101c161038a366004611bd8565b60016020526000908152604090205481565b6101e76103aa366004611d2c565b610dc4565b6101c16103bd366004611d2c565b610e94565b6101e76103d0366004611c2f565b610fd9565b6101e76103e3366004611d00565b6111d9565b6101c16103f6366004611d4e565b60036020526000908152604090205481565b6005546101c1565b6101c1600a5481565b6101c1610427366004611d00565b600460209081526000928352604080842090915290825290205481565b61022c610452366004611bd8565b611579565b6101e7610465366004611d2c565b6115a3565b6101e7610478366004611c2f565b61166b565b61027661048b366004611bd8565b6009602052600090815260409020805460019091015482565b6000806104b08361183f565b905060006104c162093a8083611dc3565b90508084106104dc576104d78262093a80611dc3565b6104de565b815b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056a9190611ddb565b6001600160a01b0316336001600160a01b0316146105bb5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b60006105c6836104a4565b905060006009816105dd6102ff62093a8086611dc3565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050610619816000015161183f565b61062662093a8084611dc3565b1115610675576020810151156106755760405162461bcd60e51b8152602060048201526014602482015273746869732065706f63682068617320766f74657360601b60448201526064016105b2565b825160005b818110156108fb5760006002600087848151811061069a5761069a611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000868152602001908152602001600020549050806000036107265760405162461bcd60e51b815260206004820152601860248201527f6e6f2062726962657320666f7220746869732065706f6368000000000000000060448201526064016105b2565b6000610731426104a4565b905060006002600089868151811061074b5761074b611df8565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054905082816107939190611dc3565b600260008a87815181106107a9576107a9611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000848152602001908152602001600020819055506000600260008a87815181106107fe576107fe611df8565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208b825290925290205561083c62093a8083611dc3565b600360008a878151811061085257610852611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555087848151811061089057610890611df8565b60200260200101516001600160a01b03167f2f0115ef57ea10e148aca7cdcd12459faf11fec4747cc945b56ad984611d23988884866040516108e5939291909283526020830191909152604082015260600190565b60405180910390a283600101935050505061067a565b505050505050565b600081815260086020526040812054810361092057506000610aa1565b6001600160a01b03831660009081526004602090815260408083208584529091528120548190600190829081906109569061183f565b90506109628782610e94565b600088815260076020908152604080832084845290915290205490925061099390829061098e9061183f565b611858565b9050600062093a80826109a54261183f565b6109af9190611e0e565b6109b99190611e3b565b90508015610a985760005b81811015610a96576109dd896103bd62093a8086611dc3565b60008a81526007602090815260408083208484529091528120600101549750909450600990610a126102ff62093a8087611dc3565b815260200190815260200160002060010154945084600014610a75576001600160a01b038a1660009081526002602090815260408083208684529091529020548590610a5e9088611e4f565b610a689190611e3b565b610a729088611dc3565b96505b610a8262093a8084611dc3565b925080610a8e81611e6e565b9150506109c4565b505b50939450505050505b92915050565b6001600160a01b038116600090815260036020526040812054610aa190429061186e565b600a54600090808203610ae15750600092915050565b8260096000610af1600185611e0e565b81526020019081526020016000206000015411610b1a57610b13600182611e0e565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b54831015610b555750600092915050565b600080610b63600184611e0e565b90505b81811115610bf75760006002610b7c8484611e0e565b610b869190611e3b565b610b909083611e0e565b600081815260096020908152604091829020825180840190935280548084526001909101549183019190915291925090879003610bd1575095945050505050565b8051871115610be257819350610bf0565b610bed600183611e0e565b92505b5050610b66565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610c5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c839190611ddb565b6001600160a01b0316336001600160a01b031614610ccf5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064016105b2565b816001600160a01b031660058481548110610cec57610cec611df8565b6000918252602090912001546001600160a01b031614610d0b57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff1990811690915592841682529020805490911660011790556005805482919085908110610d5857610d58611df8565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610d97426104a4565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610df957600080fd5b81600080828254610e0a9190611e0e565b909155505060008181526001602052604081208054849290610e2d908490611e0e565b9091555050600081815260016020526040902054610e4c90829061187d565b610e54611956565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610eb4576000915050610aa1565b60008481526007602052604081208491610ecf600185611e0e565b81526020019081526020016000206000015411610ef957610ef1600182611e0e565b915050610aa1565b6000848152600760209081526040808320838052909152902054831015610f24576000915050610aa1565b600080610f32600184611e0e565b90505b81811115610fd05760006002610f4b8484611e0e565b610f559190611e3b565b610f5f9083611e0e565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610faa57509350610aa192505050565b8051871115610fbb57819350610fc9565b610fc6600183611e0e565b92505b5050610f35565b50949350505050565b600b54600114610fe857600080fd5b6002600b55336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461102257600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561108a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ae9190611ddb565b905060005b82518110156111ce5760006110e18483815181106110d3576110d3611df8565b602002602001015186610903565b905042600460008685815181106110fa576110fa611df8565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156111555761115584838151811061114657611146611df8565b602002602001015184836119f9565b83828151811061116757611167611df8565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516111b391815260200190565b60405180910390a350806111c681611e6e565b9150506110b3565b50506001600b555050565b600b546001146111e857600080fd5b6002600b55806111f757600080fd5b6001600160a01b03821660009081526006602052604090205460ff1661133f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa15801561127d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a19190611e87565b6112ed5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016105b2565b60055460101161133f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016105b2565b600061134a426104a4565b6001600160a01b03841660008181526002602090815260408083208584529091528082205490516370a0823160e01b8152306004820152939450929091906370a0823190602401602060405180830381865afa1580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d29190611ea9565b90506113e085333087611ae8565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015611427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144b9190611ea9565b90506114578282611e0e565b94506114638584611dc3565b6001600160a01b038716600090815260026020908152604080832088845290915290205561149462093a8085611dc3565b6001600160a01b03871660009081526003602090815260408083209390935560069052205460ff16611526576001600160a01b0386166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051858152602081018790526001600160a01b0388169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b5550505050565b6005818154811061158957600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146115d857600080fd5b816000808282546115e99190611dc3565b90915550506000818152600160205260408120805484929061160c908490611dc3565b909155505060008181526001602052604090205461162b90829061187d565b611633611956565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610e88565b600b5460011461167a57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156116ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170e9190611e87565b61171757600080fd5b60005b815181101561183557600061174883838151811061173a5761173a611df8565b602002602001015185610903565b9050426004600085858151811061176157611761611df8565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156117bc576117bc8383815181106117ad576117ad611df8565b602002602001015133836119f9565b8282815181106117ce576117ce611df8565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161181a91815260200190565b60405180910390a3508061182d81611e6e565b91505061171a565b50506001600b5550565b600061184e62093a8083611ec2565b610aa19083611e0e565b60008183116118675781610b13565b5090919050565b60008183106118675781610b13565b600082815260086020526040902054429080158015906118c75750600084815260076020526040812083916118b3600185611e0e565b815260200190815260200160002060000154145b1561190057600084815260076020526040812084916118e7600185611e0e565b8152602081019190915260400160002060010155611950565b6040805180820182528381526020808201868152600088815260078352848120868252909252929020905181559051600191820155611940908290611dc3565b6000858152600860205260409020555b50505050565b600a5442811580159061198857508060096000611974600186611e0e565b815260200190815260200160002060000154145b156119b957600054600960006001856119a19190611e0e565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556119f2908390611dc3565b600a555050565b6000836001600160a01b03163b11611a1057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611a6c9190611ed6565b6000604051808303816000865af19150503d8060008114611aa9576040519150601f19603f3d011682016040523d82523d6000602084013e611aae565b606091505b5091509150818015611ad8575080511580611ad8575080806020019051810190611ad89190611e87565b611ae157600080fd5b5050505050565b6000846001600160a01b03163b11611aff57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611b639190611ed6565b6000604051808303816000865af19150503d8060008114611ba0576040519150601f19603f3d011682016040523d82523d6000602084013e611ba5565b606091505b5091509150818015611bcf575080511580611bcf575080806020019051810190611bcf9190611e87565b6108fb57600080fd5b600060208284031215611bea57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611c1c57600080fd5b50565b8035611c2a81611c07565b919050565b60008060408385031215611c4257600080fd5b8235915060208084013567ffffffffffffffff80821115611c6257600080fd5b818601915086601f830112611c7657600080fd5b813581811115611c8857611c88611bf1565b8060051b604051601f19603f83011681018181108582111715611cad57611cad611bf1565b604052918252848201925083810185019189831115611ccb57600080fd5b938501935b82851015611cf057611ce185611c1f565b84529385019392850192611cd0565b8096505050505050509250929050565b60008060408385031215611d1357600080fd5b8235611d1e81611c07565b946020939093013593505050565b60008060408385031215611d3f57600080fd5b50508035926020909101359150565b600060208284031215611d6057600080fd5b8135610b1381611c07565b600080600060608486031215611d8057600080fd5b833592506020840135611d9281611c07565b91506040840135611da281611c07565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008219821115611dd657611dd6611dad565b500190565b600060208284031215611ded57600080fd5b8151610b1381611c07565b634e487b7160e01b600052603260045260246000fd5b600082821015611e2057611e20611dad565b500390565b634e487b7160e01b600052601260045260246000fd5b600082611e4a57611e4a611e25565b500490565b6000816000190483118215151615611e6957611e69611dad565b500290565b600060018201611e8057611e80611dad565b5060010190565b600060208284031215611e9957600080fd5b81518015158114610b1357600080fd5b600060208284031215611ebb57600080fd5b5051919050565b600082611ed157611ed1611e25565b500690565b6000825160005b81811015611ef75760208186018101518583015201611edd565b81811115611f06576000828501525b50919091019291505056fea26469706673582212204f7435a280bdffecbea0ee7ddb14df42181fe6e1a0d595cd66898d91f610d69c64736f6c634300080d0033a26469706673582212205fd11251b709b968b4cba7717a50ffe5b58492fca303e076bd8333e25a48216864736f6c634300080d0033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c80636485f0c41461003b578063b0ad856f1461006a575b600080fd5b61004e610049366004610119565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b60005461004e906001600160a01b031681565b6000338260405161008d906100da565b6100989291906101de565b604051809103906000f0801580156100b4573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216918217905592915050565b6122e98061023b83390190565b634e487b7160e01b600052604160045260246000fd5b80356001600160a01b038116811461011457600080fd5b919050565b6000602080838503121561012c57600080fd5b823567ffffffffffffffff8082111561014457600080fd5b818501915085601f83011261015857600080fd5b81358181111561016a5761016a6100e7565b8060051b604051601f19603f8301168101818110858211171561018f5761018f6100e7565b6040529182528482019250838101850191888311156101ad57600080fd5b938501935b828510156101d2576101c3856100fd565b845293850193928501926101b2565b98975050505050505050565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b8181101561022c57855185168352948301949183019160010161020e565b50909897505050505050505056fe60c06040526001600b553480156200001657600080fd5b50604051620022e9380380620022e98339810160408190526200003991620001f8565b6001600160a01b038216608081905260408051638dd598fb60e01b81529051638dd598fb916004808201926020929091908290030181865afa15801562000084573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000aa9190620002e1565b6001600160a01b031660a05260005b8151811015620001bc5760006001600160a01b0316828281518110620000e357620000e362000306565b60200260200101516001600160a01b031614620001a75760016006600084848151811062000115576200011562000306565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff02191690831515021790555060058282815181106200016b576200016b62000306565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790555b80620001b3816200031c565b915050620000b9565b50505062000344565b80516001600160a01b0381168114620001dd57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200020c57600080fd5b6200021783620001c5565b602084810151919350906001600160401b03808211156200023757600080fd5b818601915086601f8301126200024c57600080fd5b815181811115620002615762000261620001e2565b8060051b604051601f19603f83011681018181108582111715620002895762000289620001e2565b604052918252848201925083810185019189831115620002a857600080fd5b938501935b82851015620002d157620002c185620001c5565b84529385019392850192620002ad565b8096505050505050509250929050565b600060208284031215620002f457600080fd5b620002ff82620001c5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a051611f47620003a260003960008181610309015281816104e801528181610c010152818161103b015261169b01526000818161020a01528181610dcf01528181610ff80152818161123601526115ae0152611f476000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806399bcc052116100f9578063e688639611610097578063f301af4211610071578063f301af4214610444578063f320772314610457578063f5f8d3651461046a578063f7412baf1461047d57600080fd5b8063e688639614610408578063e8111a1214610410578063f25e55a51461041957600080fd5b8063a28d4c9c116100d3578063a28d4c9c146103af578063a7852afa146103c2578063b66503cf146103d5578063da09d19d146103e857600080fd5b806399bcc052146103695780639cc7f7081461037c5780639e2bf22c1461039c57600080fd5b80634d5ce0381161016657806376f4be361161014057806376f4be36146102f15780638dd598fb1461030457806392777b291461032b5780639418f9391461035657600080fd5b80634d5ce0381461028b57806350589793146102be578063638634ee146102de57600080fd5b80630175e23b146101ae57806312a24cbb146101d457806318160ddd146101e95780633e491d47146101f257806346c96aac1461020557806349dcc20414610244575b600080fd5b6101c16101bc366004611bd8565b6104a4565b6040519081526020015b60405180910390f35b6101e76101e2366004611c2f565b6104e6565b005b6101c160005481565b6101c1610200366004611d00565b610903565b61022c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101cb565b610276610252366004611d2c565b60076020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101cb565b6102ae610299366004611d4e565b60066020526000908152604090205460ff1681565b60405190151581526020016101cb565b6101c16102cc366004611bd8565b60086020526000908152604090205481565b6101c16102ec366004611d4e565b610aa7565b6101c16102ff366004611bd8565b610acb565b61022c7f000000000000000000000000000000000000000000000000000000000000000081565b6101c1610339366004611d00565b600260209081526000928352604080842090915290825290205481565b6101e7610364366004611d6b565b610bff565b6101c1610377366004611d4e565b610d8b565b6101c161038a366004611bd8565b60016020526000908152604090205481565b6101e76103aa366004611d2c565b610dc4565b6101c16103bd366004611d2c565b610e94565b6101e76103d0366004611c2f565b610fd9565b6101e76103e3366004611d00565b6111d9565b6101c16103f6366004611d4e565b60036020526000908152604090205481565b6005546101c1565b6101c1600a5481565b6101c1610427366004611d00565b600460209081526000928352604080842090915290825290205481565b61022c610452366004611bd8565b611579565b6101e7610465366004611d2c565b6115a3565b6101e7610478366004611c2f565b61166b565b61027661048b366004611bd8565b6009602052600090815260409020805460019091015482565b6000806104b08361183f565b905060006104c162093a8083611dc3565b90508084106104dc576104d78262093a80611dc3565b6104de565b815b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056a9190611ddb565b6001600160a01b0316336001600160a01b0316146105bb5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064015b60405180910390fd5b60006105c6836104a4565b905060006009816105dd6102ff62093a8086611dc3565b8152602001908152602001600020604051806040016040529081600082015481526020016001820154815250509050610619816000015161183f565b61062662093a8084611dc3565b1115610675576020810151156106755760405162461bcd60e51b8152602060048201526014602482015273746869732065706f63682068617320766f74657360601b60448201526064016105b2565b825160005b818110156108fb5760006002600087848151811061069a5761069a611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000868152602001908152602001600020549050806000036107265760405162461bcd60e51b815260206004820152601860248201527f6e6f2062726962657320666f7220746869732065706f6368000000000000000060448201526064016105b2565b6000610731426104a4565b905060006002600089868151811061074b5761074b611df8565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002054905082816107939190611dc3565b600260008a87815181106107a9576107a9611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000848152602001908152602001600020819055506000600260008a87815181106107fe576107fe611df8565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208b825290925290205561083c62093a8083611dc3565b600360008a878151811061085257610852611df8565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555087848151811061089057610890611df8565b60200260200101516001600160a01b03167f2f0115ef57ea10e148aca7cdcd12459faf11fec4747cc945b56ad984611d23988884866040516108e5939291909283526020830191909152604082015260600190565b60405180910390a283600101935050505061067a565b505050505050565b600081815260086020526040812054810361092057506000610aa1565b6001600160a01b03831660009081526004602090815260408083208584529091528120548190600190829081906109569061183f565b90506109628782610e94565b600088815260076020908152604080832084845290915290205490925061099390829061098e9061183f565b611858565b9050600062093a80826109a54261183f565b6109af9190611e0e565b6109b99190611e3b565b90508015610a985760005b81811015610a96576109dd896103bd62093a8086611dc3565b60008a81526007602090815260408083208484529091528120600101549750909450600990610a126102ff62093a8087611dc3565b815260200190815260200160002060010154945084600014610a75576001600160a01b038a1660009081526002602090815260408083208684529091529020548590610a5e9088611e4f565b610a689190611e3b565b610a729088611dc3565b96505b610a8262093a8084611dc3565b925080610a8e81611e6e565b9150506109c4565b505b50939450505050505b92915050565b6001600160a01b038116600090815260036020526040812054610aa190429061186e565b600a54600090808203610ae15750600092915050565b8260096000610af1600185611e0e565b81526020019081526020016000206000015411610b1a57610b13600182611e0e565b9392505050565b6000805260096020527fec8156718a8372b1db44bb411437d0870f3e3790d4a08526d024ce1b0b668f6b54831015610b555750600092915050565b600080610b63600184611e0e565b90505b81811115610bf75760006002610b7c8484611e0e565b610b869190611e3b565b610b909083611e0e565b600081815260096020908152604091829020825180840190935280548084526001909101549183019190915291925090879003610bd1575095945050505050565b8051871115610be257819350610bf0565b610bed600183611e0e565b92505b5050610b66565b509392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f2aef26040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610c5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c839190611ddb565b6001600160a01b0316336001600160a01b031614610ccf5760405162461bcd60e51b81526020600482015260096024820152686f6e6c79207465616d60b81b60448201526064016105b2565b816001600160a01b031660058481548110610cec57610cec611df8565b6000918252602090912001546001600160a01b031614610d0b57600080fd5b6001600160a01b03808316600090815260066020526040808220805460ff1990811690915592841682529020805490911660011790556005805482919085908110610d5857610d58611df8565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b600080610d97426104a4565b6001600160a01b039093166000908152600260209081526040808320958352949052929092205492915050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610df957600080fd5b81600080828254610e0a9190611e0e565b909155505060008181526001602052604081208054849290610e2d908490611e0e565b9091555050600081815260016020526040902054610e4c90829061187d565b610e54611956565b604080518281526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b56891015b60405180910390a25050565b600082815260086020526040812054808203610eb4576000915050610aa1565b60008481526007602052604081208491610ecf600185611e0e565b81526020019081526020016000206000015411610ef957610ef1600182611e0e565b915050610aa1565b6000848152600760209081526040808320838052909152902054831015610f24576000915050610aa1565b600080610f32600184611e0e565b90505b81811115610fd05760006002610f4b8484611e0e565b610f559190611e3b565b610f5f9083611e0e565b6000888152600760209081526040808320848452825291829020825180840190935280548084526001909101549183019190915291925090879003610faa57509350610aa192505050565b8051871115610fbb57819350610fc9565b610fc6600183611e0e565b92505b5050610f35565b50949350505050565b600b54600114610fe857600080fd5b6002600b55336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461102257600080fd5b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561108a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ae9190611ddb565b905060005b82518110156111ce5760006110e18483815181106110d3576110d3611df8565b602002602001015186610903565b905042600460008685815181106110fa576110fa611df8565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812089825290925290205580156111555761115584838151811061114657611146611df8565b602002602001015184836119f9565b83828151811061116757611167611df8565b60200260200101516001600160a01b0316836001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc9836040516111b391815260200190565b60405180910390a350806111c681611e6e565b9150506110b3565b50506001600b555050565b600b546001146111e857600080fd5b6002600b55806111f757600080fd5b6001600160a01b03821660009081526006602052604090205460ff1661133f57604051633af32abf60e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690633af32abf90602401602060405180830381865afa15801561127d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a19190611e87565b6112ed5760405162461bcd60e51b815260206004820181905260248201527f627269626520746f6b656e73206d7573742062652077686974656c697374656460448201526064016105b2565b60055460101161133f5760405162461bcd60e51b815260206004820152601760248201527f746f6f206d616e79207265776172647320746f6b656e7300000000000000000060448201526064016105b2565b600061134a426104a4565b6001600160a01b03841660008181526002602090815260408083208584529091528082205490516370a0823160e01b8152306004820152939450929091906370a0823190602401602060405180830381865afa1580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d29190611ea9565b90506113e085333087611ae8565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015611427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144b9190611ea9565b90506114578282611e0e565b94506114638584611dc3565b6001600160a01b038716600090815260026020908152604080832088845290915290205561149462093a8085611dc3565b6001600160a01b03871660009081526003602090815260408083209390935560069052205460ff16611526576001600160a01b0386166000818152600660205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b60408051858152602081018790526001600160a01b0388169133917f52977ea98a2220a03ee9ba5cb003ada08d394ea10155483c95dc2dc77a7eb24b910160405180910390a350506001600b5550505050565b6005818154811061158957600080fd5b6000918252602090912001546001600160a01b0316905081565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146115d857600080fd5b816000808282546115e99190611dc3565b90915550506000818152600160205260408120805484929061160c908490611dc3565b909155505060008181526001602052604090205461162b90829061187d565b611633611956565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a159101610e88565b600b5460011461167a57600080fd5b6002600b5560405163430c208160e01b8152336004820152602481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063430c208190604401602060405180830381865afa1580156116ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170e9190611e87565b61171757600080fd5b60005b815181101561183557600061174883838151811061173a5761173a611df8565b602002602001015185610903565b9050426004600085858151811061176157611761611df8565b6020908102919091018101516001600160a01b03168252818101929092526040908101600090812088825290925290205580156117bc576117bc8383815181106117ad576117ad611df8565b602002602001015133836119f9565b8282815181106117ce576117ce611df8565b60200260200101516001600160a01b0316336001600160a01b03167f9aa05b3d70a9e3e2f004f039648839560576334fb45c81f91b6db03ad9e2efc98360405161181a91815260200190565b60405180910390a3508061182d81611e6e565b91505061171a565b50506001600b5550565b600061184e62093a8083611ec2565b610aa19083611e0e565b60008183116118675781610b13565b5090919050565b60008183106118675781610b13565b600082815260086020526040902054429080158015906118c75750600084815260076020526040812083916118b3600185611e0e565b815260200190815260200160002060000154145b1561190057600084815260076020526040812084916118e7600185611e0e565b8152602081019190915260400160002060010155611950565b6040805180820182528381526020808201868152600088815260078352848120868252909252929020905181559051600191820155611940908290611dc3565b6000858152600860205260409020555b50505050565b600a5442811580159061198857508060096000611974600186611e0e565b815260200190815260200160002060000154145b156119b957600054600960006001856119a19190611e0e565b81526020810191909152604001600020600101555050565b604080518082018252828152600080546020808401918252868352600990529290209051815590516001918201556119f2908390611dc3565b600a555050565b6000836001600160a01b03163b11611a1057600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611a6c9190611ed6565b6000604051808303816000865af19150503d8060008114611aa9576040519150601f19603f3d011682016040523d82523d6000602084013e611aae565b606091505b5091509150818015611ad8575080511580611ad8575080806020019051810190611ad89190611e87565b611ae157600080fd5b5050505050565b6000846001600160a01b03163b11611aff57600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b1790529151600092839290881691611b639190611ed6565b6000604051808303816000865af19150503d8060008114611ba0576040519150601f19603f3d011682016040523d82523d6000602084013e611ba5565b606091505b5091509150818015611bcf575080511580611bcf575080806020019051810190611bcf9190611e87565b6108fb57600080fd5b600060208284031215611bea57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611c1c57600080fd5b50565b8035611c2a81611c07565b919050565b60008060408385031215611c4257600080fd5b8235915060208084013567ffffffffffffffff80821115611c6257600080fd5b818601915086601f830112611c7657600080fd5b813581811115611c8857611c88611bf1565b8060051b604051601f19603f83011681018181108582111715611cad57611cad611bf1565b604052918252848201925083810185019189831115611ccb57600080fd5b938501935b82851015611cf057611ce185611c1f565b84529385019392850192611cd0565b8096505050505050509250929050565b60008060408385031215611d1357600080fd5b8235611d1e81611c07565b946020939093013593505050565b60008060408385031215611d3f57600080fd5b50508035926020909101359150565b600060208284031215611d6057600080fd5b8135610b1381611c07565b600080600060608486031215611d8057600080fd5b833592506020840135611d9281611c07565b91506040840135611da281611c07565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008219821115611dd657611dd6611dad565b500190565b600060208284031215611ded57600080fd5b8151610b1381611c07565b634e487b7160e01b600052603260045260246000fd5b600082821015611e2057611e20611dad565b500390565b634e487b7160e01b600052601260045260246000fd5b600082611e4a57611e4a611e25565b500490565b6000816000190483118215151615611e6957611e69611dad565b500290565b600060018201611e8057611e80611dad565b5060010190565b600060208284031215611e9957600080fd5b81518015158114610b1357600080fd5b600060208284031215611ebb57600080fd5b5051919050565b600082611ed157611ed1611e25565b500690565b6000825160005b81811015611ef75760208186018101518583015201611edd565b81811115611f06576000828501525b50919091019291505056fea26469706673582212204f7435a280bdffecbea0ee7ddb14df42181fe6e1a0d595cd66898d91f610d69c64736f6c634300080d0033a26469706673582212205fd11251b709b968b4cba7717a50ffe5b58492fca303e076bd8333e25a48216864736f6c634300080d0033