More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,485 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim All | 17021796 | 663 days ago | IN | 0 ETH | 0.00302427 | ||||
Claim All | 17016594 | 663 days ago | IN | 0 ETH | 0.00218697 | ||||
Claim All | 17013111 | 664 days ago | IN | 0 ETH | 0.00464598 | ||||
Claim All | 17009797 | 664 days ago | IN | 0 ETH | 0.00255814 | ||||
Claim All | 17003386 | 665 days ago | IN | 0 ETH | 0.00120523 | ||||
Claim All | 17002512 | 665 days ago | IN | 0 ETH | 0.00244083 | ||||
Claim All | 17000674 | 666 days ago | IN | 0 ETH | 0.00305821 | ||||
Claim | 16999361 | 666 days ago | IN | 0 ETH | 0.00207388 | ||||
Claim | 16997155 | 666 days ago | IN | 0 ETH | 0.00252308 | ||||
Claim | 16997147 | 666 days ago | IN | 0 ETH | 0.00260656 | ||||
Claim | 16996958 | 666 days ago | IN | 0 ETH | 0.00332675 | ||||
Claim All | 16995944 | 666 days ago | IN | 0 ETH | 0.00223736 | ||||
Claim All | 16995937 | 666 days ago | IN | 0 ETH | 0.00224209 | ||||
Claim All | 16995545 | 666 days ago | IN | 0 ETH | 0.00231758 | ||||
Claim All | 16993418 | 667 days ago | IN | 0 ETH | 0.00235883 | ||||
Claim All | 16993119 | 667 days ago | IN | 0 ETH | 0.0022017 | ||||
Claim All | 16993119 | 667 days ago | IN | 0 ETH | 0.0022017 | ||||
Claim All | 16993057 | 667 days ago | IN | 0 ETH | 0.00231758 | ||||
Claim All | 16992574 | 667 days ago | IN | 0 ETH | 0.00258549 | ||||
Claim All | 16992571 | 667 days ago | IN | 0 ETH | 0.00262182 | ||||
Claim All | 16990430 | 667 days ago | IN | 0 ETH | 0.00366264 | ||||
Claim All | 16990192 | 667 days ago | IN | 0 ETH | 0.00312873 | ||||
Claim | 16989696 | 667 days ago | IN | 0 ETH | 0.00325745 | ||||
Claim All | 16988889 | 667 days ago | IN | 0 ETH | 0.00324461 | ||||
Claim All | 16988351 | 667 days ago | IN | 0 ETH | 0.00327462 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
16376672 | 753 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Platform
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-01-10 */ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.17; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } } /* ▄▄▄█████▓ ██░ ██ ▓█████ ██░ ██ ▓█████ ██▀███ ▓█████▄ ▓ ██▒ ▓▒▓██░ ██▒▓█ ▀ ▓██░ ██▒▓█ ▀ ▓██ ▒ ██▒▒██▀ ██▌ ▒ ▓██░ ▒░▒██▀▀██░▒███ ▒██▀▀██░▒███ ▓██ ░▄█ ▒░██ █▌ ░ ▓██▓ ░ ░▓█ ░██ ▒▓█ ▄ ░▓█ ░██ ▒▓█ ▄ ▒██▀▀█▄ ░▓█▄ ▌ ▒██▒ ░ ░▓█▒░██▓░▒████▒ ░▓█▒░██▓░▒████▒░██▓ ▒██▒░▒████▓ ▒ ░░ ▒ ░░▒░▒░░ ▒░ ░ ▒ ░░▒░▒░░ ▒░ ░░ ▒▓ ░▒▓░ ▒▒▓ ▒ ░ ▒ ░▒░ ░ ░ ░ ░ ▒ ░▒░ ░ ░ ░ ░ ░▒ ░ ▒░ ░ ▒ ▒ ░ ░ ░░ ░ ░ ░ ░░ ░ ░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ .,;>>%%%%%>>;,. .>%%%%%%%%%%%%%%%%%%%%>,. .>%%%%%%%%%%%%%%%%%%>>,%%%%%%;,. .>>>>%%%%%%%%%%%%%>>,%%%%%%%%%%%%,>>%%,. .>>%>>>>%%%%%%%%%>>,%%%%%%%%%%%%%%%%%,>>%%%%%,. .>>%%%%%>>%%%%>>,%%>>%%%%%%%%%%%%%%%%%%%%,>>%%%%%%%, .>>%%%%%%%%%%>>,%%%%%%>>%%%%%%%%%%%%%%%%%%,>>%%%%%%%%%%. .>>%%%%%%%%%%>>,>>>>%%%%%%%%%%'..`%%%%%%%%,;>>%%%%%%%%%>%%. .>>%%%>>>%%%%%>,%%%%%%%%%%%%%%.%%%,`%%%%%%,;>>%%%%%%%%>>>%%%%. >>%%>%>>>%>%%%>,%%%%%>>%%%%%%%%%%%%%`%%%%%%,>%%%%%%%>>>>%%%%%%%. >>%>>>%%>>>%%%%>,%>>>%%%%%%%%%%%%%%%%`%%%%%%%%%%%%%%%%%%%%%%%%%%. >>%%%%%%%%%%%%%%,>%%%%%%%%%%%%%%%%%%%'%%%,>>%%%%%%%%%%%%%%%%%%%%%. >>%%%%%%%%%%%%%%%,>%%%>>>%%%%%%%%%%%%%%%,>>%%%%%%%%>>>>%%%%%%%%%%%. >>%%%%%%%%;%;%;%%;,%>>>>%%%%%%%%%%%%%%%,>>>%%%%%%>>;";>>%%%%%%%%%%%%. `>%%%%%%%%%;%;;;%;%,>%%%%%%%%%>>%%%%%%%%,>>>%%%%%%%%%%%%%%%%%%%%%%%%%%. >>%%%%%%%%%,;;;;;%%>,%%%%%%%%>>>>%%%%%%%%,>>%%%%%%%%%%%%%%%%%%%%%%%%%%%. `>>%%%%%%%%%,%;;;;%%%>,%%%%%%%%>>>>%%%%%%%%,>%%%%%%'%%%%%%%%%%%%%%%%%%%>>. `>>%%%%%%%%%%>,;;%%%%%>>,%%%%%%%%>>%%%%%%';;;>%%%%%,`%%%%%%%%%%%%%%%>>%%>. >>>%%%%%%%%%%>> %%%%%%%%>>,%%%%>>>%%%%%';;;;;;>>,%%%,`% `;>%%%%%%>>%% `>>%%%%%%%%%%>> %%%%%%%%%>>>>>>>>;;;;'.;;;;;>>%%' `%%' ;>%%%%%> >>%%%%%%%%%>>; %%%%%%%%>>;;;;;;'' ;;;;;>>%%% ;>%%%% `>>%%%%%%%>>>, %%%%%%%%%>>;;' ;;;;>>%%%' ;>%%% >>%%%%%%>>>':.%%%%%%%%%%>>; .;;;>>%%%% ;>%%%' `>>%%%%%>>> ::`%%%%%%%%%%>>;. ;;;>>%%%%' ;>%%%' `>>%%%%>>> `:::`%%%%%%%%%%>;. ;;>>%%%%% ;>%%' `>>%%%%>>, `::::`%%%%%%%%%%>, .;>>%%%%%' ;>%' `>>%%%%>>, `:::::`%%%%%%%%%>>. ;;>%%%%%% ;>%, `>>%%%%>>, :::::::`>>>%%%%>>> ;;>%%%%%' ;>%, `>>%%%%>>,::::::,>>>>>>>>>>' ;;>%%%%% ;%%, >>%%%%>>,:::,%%>>>>>>>>' ;>%%%%%. ;%% >>%%%%>>``%%%%%>>>>>' `>%%%%%%. >>%%%%>> `@@a%%%%%%' .%%%%%%%%%. `a@@a%@' `%a@@' `a@@a%a@@a */ interface Factory { function feeCollector() external view returns (address); function platformFeeManager(address) external view returns (address); function recipient(address, address) external view returns (address); } interface GaugeController { struct VotedSlope { uint256 slope; uint256 power; uint256 end; } struct Point { uint256 bias; uint256 slope; } function vote_user_slopes(address, address) external view returns (VotedSlope memory); function add_gauge(address, int128) external; function WEIGHT_VOTE_DELAY() external view returns (uint256); function last_user_vote(address, address) external view returns (uint256); function points_weight(address, uint256) external view returns (Point memory); function checkpoint_gauge(address) external; //solhint-disable-next-line function gauge_types(address addr) external view returns (int128); //solhint-disable-next-line function gauge_relative_weight_write(address addr, uint256 timestamp) external returns (uint256); //solhint-disable-next-line function gauge_relative_weight(address addr) external view returns (uint256); //solhint-disable-next-line function gauge_relative_weight(address addr, uint256 timestamp) external view returns (uint256); //solhint-disable-next-line function get_total_weight() external view returns (uint256); //solhint-disable-next-line function get_gauge_weight(address addr) external view returns (uint256); function vote_for_gauge_weights(address, uint256) external; function add_type(string memory, uint256) external; function admin() external view returns (address); } /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() virtual { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } } /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } } /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } } /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } } contract FeeManager is Owned { using SafeTransferLib for ERC20; uint256 public totalFee; uint256 internal constant _DEFAULT_FEE = 2e16; // 2% struct FeeRecipient { address recipient; uint256 fee; } FeeRecipient[] public recipients; /// @notice Thrown if the fee percentage is invalid. error INCORRECT_FEE(); constructor(address _feeRecipient) Owned(_feeRecipient) { totalFee = _DEFAULT_FEE; recipients.push(FeeRecipient(_feeRecipient, _DEFAULT_FEE)); } function disperseFees(address _token) external { uint256 length = recipients.length; uint256 totalBal = ERC20(_token).balanceOf(address(this)); uint256 amount; for (uint256 i; i < length; ) { FeeRecipient memory recipient = recipients[i]; amount = (totalBal * recipient.fee) / totalFee; ERC20(_token).safeTransfer(recipient.recipient, amount); unchecked { i++; } } } function addRecipient(address _recipient, uint256 _fee) external onlyOwner { if (_fee > 1e18) revert INCORRECT_FEE(); recipients.push(FeeRecipient(_recipient, _fee)); totalFee += _fee; } function removeRecipient(uint256 _index) external onlyOwner { totalFee -= recipients[_index].fee; recipients[_index] = recipients[recipients.length - 1]; recipients.pop(); } function updateRecipient( uint256 _index, address _recipient, uint256 _fee ) external onlyOwner { if (_fee > 1e18) revert INCORRECT_FEE(); totalFee -= recipients[_index].fee; recipients[_index].recipient = _recipient; recipients[_index].fee = _fee; totalFee += _fee; } function totalFeeRecipients() external view returns (uint256) { return recipients.length; } } /// version 1.5.0 /// @title Platform /// @author Stake DAO contract Platform is ReentrancyGuard { using SafeTransferLib for ERC20; using FixedPointMathLib for uint256; //////////////////////////////////////////////////////////////// /// --- EMERGENCY SHUTDOWN /////////////////////////////////////////////////////////////// /// @notice Emergency shutdown flag bool public isKilled; //////////////////////////////////////////////////////////////// /// --- STRUCTS /////////////////////////////////////////////////////////////// /// @notice Bribe struct requirements. struct Bribe { // Address of the target gauge. address gauge; // Manager. address manager; // Address of the ERC20 used for rewards. address rewardToken; // Number of periods. uint8 numberOfPeriods; // Timestamp where the bribe become unclaimable. uint256 endTimestamp; // Max Price per vote. uint256 maxRewardPerVote; // Total Reward Added. uint256 totalRewardAmount; // Blacklisted addresses. address[] blacklist; } /// @notice Period struct. struct Period { // Period id. // Eg: 0 is the first period, 1 is the second period, etc. uint8 id; // Timestamp of the period start. uint256 timestamp; // Reward amount distributed during the period. uint256 rewardPerPeriod; } struct Upgrade { // Number of periods after increase. uint8 numberOfPeriods; // Total reward amount after increase. uint256 totalRewardAmount; // New max reward per vote after increase. uint256 maxRewardPerVote; // New end timestamp after increase. uint256 endTimestamp; // Blacklisted addresses. address[] blacklist; } //////////////////////////////////////////////////////////////// /// --- CONSTANTS & IMMUTABLES /////////////////////////////////////////////////////////////// /// @notice Week in seconds. uint256 private constant _WEEK = 1 weeks; /// @notice Base unit for fixed point compute. uint256 private constant _BASE_UNIT = 1e18; /// @notice Minimum duration a Bribe. uint8 public constant MINIMUM_PERIOD = 2; /// @notice Factory contract. Factory public immutable factory; /// @notice Gauge Controller. GaugeController public immutable gaugeController; //////////////////////////////////////////////////////////////// /// --- STORAGE VARS /////////////////////////////////////////////////////////////// /// @notice Bribe ID Counter. uint256 public nextID; /// @notice ID => Bribe. mapping(uint256 => Bribe) public bribes; /// @notice ID => Bribe In Queue to be upgraded. mapping(uint256 => Upgrade) public upgradeBribeQueue; /// @notice ID => Period running. mapping(uint256 => Period) public activePeriod; /// @notice BribeId => isUpgradeable. If true, the bribe can be upgraded. mapping(uint256 => bool) public isUpgradeable; /// @notice ID => Amount Claimed per Bribe. mapping(uint256 => uint256) public amountClaimed; /// @notice ID => Amount of reward per vote distributed. mapping(uint256 => uint256) public rewardPerVote; /// @notice Blacklisted addresses per bribe that aren't counted for rewards arithmetics. mapping(uint256 => mapping(address => bool)) public isBlacklisted; /// @notice Last time a user claimed mapping(address => mapping(uint256 => uint256)) public lastUserClaim; //////////////////////////////////////////////////////////////// /// --- MODIFIERS /////////////////////////////////////////////////////////////// modifier onlyManager(uint256 _id) { if (msg.sender != bribes[_id].manager) revert AUTH_MANAGER_ONLY(); _; } modifier notKilled() { if (isKilled) revert KILLED(); _; } //////////////////////////////////////////////////////////////// /// --- EVENTS /////////////////////////////////////////////////////////////// /// @notice Emitted when a new bribe is created. event BribeCreated( uint256 indexed id, address indexed gauge, address manager, address indexed rewardToken, uint8 numberOfPeriods, uint256 maxRewardPerVote, uint256 rewardPerPeriod, uint256 totalRewardAmount, bool isUpgradeable ); /// @notice Emitted when a bribe is closed. event BribeClosed(uint256 id, uint256 remainingReward); /// @notice Emitted when a bribe period is rolled over. event PeriodRolledOver( uint256 id, uint256 periodId, uint256 timestamp, uint256 rewardPerPeriod ); /// @notice Emitted on claim. event Claimed( address indexed user, address indexed rewardToken, uint256 indexed bribeId, uint256 amount, uint256 protocolFees, uint256 period ); /// @notice Emitted when a bribe is queued to upgrade. event BribeDurationIncreaseQueued( uint256 id, uint8 numberOfPeriods, uint256 totalRewardAmount, uint256 maxRewardPerVote ); /// @notice Emitted when a bribe is upgraded. event BribeDurationIncreased( uint256 id, uint8 numberOfPeriods, uint256 totalRewardAmount, uint256 maxRewardPerVote ); /// @notice Emitted when a bribe manager is updated. event ManagerUpdated(uint256 id, address indexed manager); //////////////////////////////////////////////////////////////// /// --- ERRORS /////////////////////////////////////////////////////////////// error KILLED(); error WRONG_INPUT(); error ZERO_ADDRESS(); error NO_PERIODS_LEFT(); error NOT_UPGRADEABLE(); error AUTH_MANAGER_ONLY(); error ALREADY_INCREASED(); error NOT_ALLOWED_OPERATION(); error INVALID_NUMBER_OF_PERIODS(); //////////////////////////////////////////////////////////////// /// --- CONSTRUCTOR /////////////////////////////////////////////////////////////// /// @notice Create Bribe platform. /// @param _gaugeController Address of the gauge controller. constructor(address _gaugeController, address _factory) { factory = Factory(_factory); gaugeController = GaugeController(_gaugeController); } //////////////////////////////////////////////////////////////// /// --- BRIBE CREATION LOGIC /////////////////////////////////////////////////////////////// /// @notice Create a new bribe. /// @param gauge Address of the target gauge. /// @param rewardToken Address of the ERC20 used or rewards. /// @param numberOfPeriods Number of periods. /// @param maxRewardPerVote Target Bias for the Gauge. /// @param totalRewardAmount Total Reward Added. /// @param blacklist Array of addresses to blacklist. /// @return newBribeID of the bribe created. function createBribe( address gauge, address manager, address rewardToken, uint8 numberOfPeriods, uint256 maxRewardPerVote, uint256 totalRewardAmount, address[] calldata blacklist, bool upgradeable ) external nonReentrant notKilled returns (uint256 newBribeID) { if (rewardToken == address(0)) revert ZERO_ADDRESS(); if (gaugeController.gauge_types(gauge) < 0) return newBribeID; if (numberOfPeriods < MINIMUM_PERIOD) revert INVALID_NUMBER_OF_PERIODS(); if (totalRewardAmount == 0 || maxRewardPerVote == 0) revert WRONG_INPUT(); // Transfer the rewards to the contracts. ERC20(rewardToken).safeTransferFrom( msg.sender, address(this), totalRewardAmount ); unchecked { // Get the ID for that new Bribe and increment the nextID counter. newBribeID = nextID; ++nextID; } uint256 rewardPerPeriod = totalRewardAmount.mulDivDown( 1, numberOfPeriods ); uint256 currentPeriod = getCurrentPeriod(); bribes[newBribeID] = Bribe({ gauge: gauge, manager: manager, rewardToken: rewardToken, numberOfPeriods: numberOfPeriods, endTimestamp: currentPeriod + ((numberOfPeriods + 1) * _WEEK), maxRewardPerVote: maxRewardPerVote, totalRewardAmount: totalRewardAmount, blacklist: blacklist }); emit BribeCreated( newBribeID, gauge, manager, rewardToken, numberOfPeriods, maxRewardPerVote, rewardPerPeriod, totalRewardAmount, upgradeable ); // Set Upgradeable status. isUpgradeable[newBribeID] = upgradeable; // Starting from next period. activePeriod[newBribeID] = Period( 0, currentPeriod + _WEEK, rewardPerPeriod ); // Add the addresses to the blacklist. uint256 length = blacklist.length; for (uint256 i = 0; i < length; ) { isBlacklisted[newBribeID][blacklist[i]] = true; unchecked { ++i; } } } /// @notice Claim rewards for a given bribe. /// @param bribeId ID of the bribe. /// @return Amount of rewards claimed. function claimFor(address user, uint256 bribeId) external returns (uint256) { address recipient = factory.recipient(user, address(gaugeController)); return _claim(user, recipient != address(0) ? recipient : user, bribeId); } function claimAllFor(address user, uint256[] calldata ids) external { address recipient = factory.recipient(user, address(gaugeController)); uint256 length = ids.length; for (uint256 i = 0; i < length; ) { uint256 id = ids[i]; _claim(user, recipient != address(0) ? recipient : user, id); unchecked { ++i; } } } /// @notice Claim rewards for a given bribe. /// @param bribeId ID of the bribe. /// @return Amount of rewards claimed. function claim(uint256 bribeId) external returns (uint256) { address recipient = factory.recipient( msg.sender, address(gaugeController) ); return _claim( msg.sender, recipient != address(0) ? recipient : msg.sender, bribeId ); } /// @notice Update Bribe for a given id. /// @param bribeId ID of the bribe. function updateBribePeriod(uint256 bribeId) external nonReentrant { _updateBribePeriod(bribeId); } /// @notice Update multiple bribes for given ids. /// @param ids Array of Bribe IDs. function updateBribePeriods(uint256[] calldata ids) external nonReentrant { uint256 length = ids.length; for (uint256 i = 0; i < length; ) { _updateBribePeriod(ids[i]); unchecked { ++i; } } } /// @notice Claim all rewards for multiple bribes. /// @param ids Array of bribe IDs to claim. function claimAll(uint256[] calldata ids) external { address recipient = factory.recipient( msg.sender, address(gaugeController) ); recipient = recipient != address(0) ? recipient : msg.sender; uint256 length = ids.length; for (uint256 i = 0; i < length; ) { uint256 id = ids[i]; _claim(msg.sender, recipient, id); unchecked { ++i; } } } //////////////////////////////////////////////////////////////// /// --- INTERNAL LOGIC /////////////////////////////////////////////////////////////// /// @notice Claim rewards for a given bribe. /// @param user Address of the user. /// @param bribeId ID of the bribe. /// @return amount of rewards claimed. function _claim( address user, address recipient, uint256 bribeId ) internal nonReentrant notKilled returns (uint256 amount) { if (isBlacklisted[bribeId][user]) return 0; // Update if needed the current period. uint256 currentPeriod = _updateBribePeriod(bribeId); Bribe storage bribe = bribes[bribeId]; // Get the last_vote timestamp. uint256 lastVote = gaugeController.last_user_vote(user, bribe.gauge); GaugeController.VotedSlope memory userSlope = gaugeController .vote_user_slopes(user, bribe.gauge); if ( userSlope.slope == 0 || lastUserClaim[user][bribeId] >= currentPeriod || currentPeriod >= userSlope.end || currentPeriod <= lastVote || currentPeriod >= bribe.endTimestamp || currentPeriod != getCurrentPeriod() || amountClaimed[bribeId] == bribe.totalRewardAmount ) return 0; // Update User last claim period. lastUserClaim[user][bribeId] = currentPeriod; // Voting Power = userSlope * dt // with dt = lock_end - period. uint256 _bias = _getAddrBias( userSlope.slope, userSlope.end, currentPeriod ); // Compute the reward amount based on // Reward / Total Votes. amount = _bias.mulWadDown(rewardPerVote[bribeId]); // Compute the reward amount based on // the max price to pay. uint256 _amountWithMaxPrice = _bias.mulWadDown(bribe.maxRewardPerVote); // Distribute the _min between the amount based on votes, and price. amount = _min(amount, _amountWithMaxPrice); // Update the amount claimed. uint256 _amountClaimed = amountClaimed[bribeId]; if (amount + _amountClaimed > bribe.totalRewardAmount) { amount = bribe.totalRewardAmount - _amountClaimed; } amountClaimed[bribeId] += amount; uint256 feeAmount; address feeManager = factory.platformFeeManager( address(gaugeController) ); uint256 platformFee = FeeManager(feeManager).totalFee(); if (platformFee != 0) { feeAmount = amount.mulWadDown(platformFee); amount -= feeAmount; // Transfer fees. ERC20(bribe.rewardToken).safeTransfer(feeManager, feeAmount); } // Transfer to user. ERC20(bribe.rewardToken).safeTransfer(recipient, amount); emit Claimed( user, bribe.rewardToken, bribeId, amount, feeAmount, currentPeriod ); } /// @notice Update the current period for a given bribe. /// @param bribeId Bribe ID. /// @return current/updated period. function _updateBribePeriod(uint256 bribeId) internal returns (uint256) { Period storage _activePeriod = activePeriod[bribeId]; uint256 currentPeriod = getCurrentPeriod(); if (_activePeriod.id == 0 && currentPeriod == _activePeriod.timestamp) { // Checkpoint gauge to have up to date gauge weight. gaugeController.checkpoint_gauge(bribes[bribeId].gauge); // Initialize reward per token. // Only for the first period, and if not already initialized. _updateRewardPerToken(bribeId, currentPeriod); } // Increase Period if (block.timestamp >= _activePeriod.timestamp + _WEEK) { // Checkpoint gauge to have up to date gauge weight. gaugeController.checkpoint_gauge(bribes[bribeId].gauge); // Roll to next period. _rollOverToNextPeriod(bribeId, currentPeriod); return currentPeriod; } return _activePeriod.timestamp; } /// @notice Roll over to next period. /// @param bribeId Bribe ID. /// @param currentPeriod Next period timestamp. function _rollOverToNextPeriod(uint256 bribeId, uint256 currentPeriod) internal { uint8 index = getActivePeriodPerBribe(bribeId); Upgrade storage upgradedBribe = upgradeBribeQueue[bribeId]; // Check if there is an upgrade in queue. if (upgradedBribe.totalRewardAmount != 0) { // Save new values. bribes[bribeId].numberOfPeriods = upgradedBribe.numberOfPeriods; bribes[bribeId].totalRewardAmount = upgradedBribe.totalRewardAmount; bribes[bribeId].maxRewardPerVote = upgradedBribe.maxRewardPerVote; bribes[bribeId].endTimestamp = upgradedBribe.endTimestamp; if (upgradedBribe.blacklist.length > 0) { bribes[bribeId].blacklist = upgradedBribe.blacklist; } emit BribeDurationIncreased( bribeId, upgradedBribe.numberOfPeriods, upgradedBribe.totalRewardAmount, upgradedBribe.maxRewardPerVote ); // Reset the next values. delete upgradeBribeQueue[bribeId]; } Bribe storage bribe = bribes[bribeId]; uint256 periodsLeft = getPeriodsLeft(bribeId); uint256 rewardPerPeriod; rewardPerPeriod = bribe.totalRewardAmount - amountClaimed[bribeId]; if (bribe.endTimestamp > currentPeriod + _WEEK && periodsLeft > 1) { rewardPerPeriod = rewardPerPeriod.mulDivDown(1, periodsLeft); } // Get adjusted slope without blacklisted addresses. uint256 gaugeBias = _getAdjustedBias( bribe.gauge, bribe.blacklist, currentPeriod ); rewardPerVote[bribeId] = rewardPerPeriod.mulDivDown( _BASE_UNIT, gaugeBias ); activePeriod[bribeId] = Period(index, currentPeriod, rewardPerPeriod); emit PeriodRolledOver(bribeId, index, currentPeriod, rewardPerPeriod); } /// @notice Update the amount of reward per token for a given bribe. /// @dev This function is only called once per Bribe. function _updateRewardPerToken(uint256 bribeId, uint256 currentPeriod) internal { if (rewardPerVote[bribeId] == 0) { uint256 gaugeBias = _getAdjustedBias( bribes[bribeId].gauge, bribes[bribeId].blacklist, currentPeriod ); if (gaugeBias != 0) { rewardPerVote[bribeId] = activePeriod[bribeId] .rewardPerPeriod .mulDivDown(_BASE_UNIT, gaugeBias); } } } //////////////////////////////////////////////////////////////// /// --- VIEWS /////////////////////////////////////////////////////////////// /// @notice Get an estimate of the reward amount for a given user. /// @param user Address of the user. /// @param bribeId ID of the bribe. /// @return amount of rewards. /// Mainly used for UI. function claimable(address user, uint256 bribeId) external view returns (uint256 amount) { if (isBlacklisted[bribeId][user]) return 0; Bribe memory bribe = bribes[bribeId]; // If there is an upgrade in progress but period hasn't been rolled over yet. Upgrade storage upgradedBribe = upgradeBribeQueue[bribeId]; // Update if needed the current period. uint256 currentPeriod = getCurrentPeriod(); // End timestamp of the bribe. uint256 endTimestamp = _max( bribe.endTimestamp, upgradedBribe.endTimestamp ); // Get the last_vote timestamp. uint256 lastVote = gaugeController.last_user_vote(user, bribe.gauge); GaugeController.VotedSlope memory userSlope = gaugeController .vote_user_slopes(user, bribe.gauge); if ( userSlope.slope == 0 || lastUserClaim[user][bribeId] >= currentPeriod || currentPeriod >= userSlope.end || currentPeriod <= lastVote || currentPeriod >= endTimestamp || currentPeriod < getActivePeriod(bribeId).timestamp || amountClaimed[bribeId] >= bribe.totalRewardAmount ) return 0; uint256 _rewardPerVote = rewardPerVote[bribeId]; // If period updated. if ( _rewardPerVote == 0 || (_rewardPerVote > 0 && getActivePeriod(bribeId).timestamp != currentPeriod) ) { uint256 _rewardPerPeriod; if (upgradedBribe.numberOfPeriods != 0) { // Update max reward per vote. bribe.maxRewardPerVote = upgradedBribe.maxRewardPerVote; bribe.totalRewardAmount = upgradedBribe.totalRewardAmount; } uint256 periodsLeft = endTimestamp > currentPeriod ? (endTimestamp - currentPeriod) / _WEEK : 0; _rewardPerPeriod = bribe.totalRewardAmount - amountClaimed[bribeId]; if (endTimestamp > currentPeriod + _WEEK && periodsLeft > 1) { _rewardPerPeriod = _rewardPerPeriod.mulDivDown(1, periodsLeft); } // Get Adjusted Slope without blacklisted addresses weight. uint256 gaugeBias = _getAdjustedBias( bribe.gauge, bribe.blacklist, currentPeriod ); _rewardPerVote = _rewardPerPeriod.mulDivDown(_BASE_UNIT, gaugeBias); } // Get user voting power. uint256 _bias = _getAddrBias( userSlope.slope, userSlope.end, currentPeriod ); // Estimation of the amount of rewards. amount = _bias.mulWadDown(_rewardPerVote); // Compute the reward amount based on // the max price to pay. uint256 _amountWithMaxPrice = _bias.mulWadDown(bribe.maxRewardPerVote); // Distribute the _min between the amount based on votes, and price. amount = _min(amount, _amountWithMaxPrice); uint256 _amountClaimed = amountClaimed[bribeId]; // Update the amount claimed. if (amount + _amountClaimed > bribe.totalRewardAmount) { amount = bribe.totalRewardAmount - _amountClaimed; } // Substract fees. uint256 platformFee = FeeManager( factory.platformFeeManager(address(gaugeController)) ).totalFee(); if (platformFee != 0) { amount = amount.mulWadDown(_BASE_UNIT - platformFee); } } //////////////////////////////////////////////////////////////// /// --- INTERNAL VIEWS /////////////////////////////////////////////////////////////// /// @notice Get adjusted slope from Gauge Controller for a given gauge address. /// Remove the weight of blacklisted addresses. /// @param gauge Address of the gauge. /// @param _addressesBlacklisted Array of blacklisted addresses. /// @param period Timestamp to check vote weight. function _getAdjustedBias( address gauge, address[] memory _addressesBlacklisted, uint256 period ) internal view returns (uint256 gaugeBias) { // Cache the user slope. GaugeController.VotedSlope memory userSlope; // Bias uint256 _bias; // Last Vote uint256 _lastVote; // Cache the length of the array. uint256 length = _addressesBlacklisted.length; // Cache blacklist. // Get the gauge slope. gaugeBias = gaugeController.points_weight(gauge, period).bias; for (uint256 i = 0; i < length; ) { // Get the user slope. userSlope = gaugeController.vote_user_slopes( _addressesBlacklisted[i], gauge ); _lastVote = gaugeController.last_user_vote( _addressesBlacklisted[i], gauge ); if (period > _lastVote) { _bias = _getAddrBias(userSlope.slope, userSlope.end, period); gaugeBias -= _bias; } // Increment i. unchecked { ++i; } } } //////////////////////////////////////////////////////////////// /// --- MANAGEMENT LOGIC /////////////////////////////////////////////////////////////// /// @notice Increase Bribe duration. /// @param _bribeId ID of the bribe. /// @param _additionnalPeriods Number of periods to add. /// @param _increasedAmount Total reward amount to add. /// @param _newMaxPricePerVote Total reward amount to add. function increaseBribeDuration( uint256 _bribeId, uint8 _additionnalPeriods, uint256 _increasedAmount, uint256 _newMaxPricePerVote, address[] calldata _addressesBlacklisted ) external nonReentrant notKilled onlyManager(_bribeId) { if (!isUpgradeable[_bribeId]) revert NOT_UPGRADEABLE(); if (getPeriodsLeft(_bribeId) < 1) revert NO_PERIODS_LEFT(); if (_increasedAmount == 0 || _newMaxPricePerVote == 0) revert WRONG_INPUT(); Bribe storage bribe = bribes[_bribeId]; Upgrade memory upgradedBribe = upgradeBribeQueue[_bribeId]; ERC20(bribe.rewardToken).safeTransferFrom( msg.sender, address(this), _increasedAmount ); if (upgradedBribe.totalRewardAmount != 0) { upgradedBribe = Upgrade({ numberOfPeriods: upgradedBribe.numberOfPeriods + _additionnalPeriods, totalRewardAmount: upgradedBribe.totalRewardAmount + _increasedAmount, maxRewardPerVote: _newMaxPricePerVote, endTimestamp: upgradedBribe.endTimestamp + (_additionnalPeriods * _WEEK), blacklist: _addressesBlacklisted }); } else { upgradedBribe = Upgrade({ numberOfPeriods: bribe.numberOfPeriods + _additionnalPeriods, totalRewardAmount: bribe.totalRewardAmount + _increasedAmount, maxRewardPerVote: _newMaxPricePerVote, endTimestamp: bribe.endTimestamp + (_additionnalPeriods * _WEEK), blacklist: _addressesBlacklisted }); } upgradeBribeQueue[_bribeId] = upgradedBribe; emit BribeDurationIncreaseQueued( _bribeId, upgradedBribe.numberOfPeriods, upgradedBribe.totalRewardAmount, _newMaxPricePerVote ); } /// @notice Close Bribe if there is remaining. /// @param bribeId ID of the bribe to close. function closeBribe(uint256 bribeId) external nonReentrant onlyManager(bribeId) { // Check if the currentPeriod is the last one. // If not, we can increase the duration. Bribe storage bribe = bribes[bribeId]; if (getCurrentPeriod() >= bribe.endTimestamp || isKilled) { uint256 leftOver; Upgrade memory upgradedBribe = upgradeBribeQueue[bribeId]; if (upgradedBribe.totalRewardAmount != 0) { leftOver = upgradedBribe.totalRewardAmount - amountClaimed[bribeId]; delete upgradeBribeQueue[bribeId]; } else { leftOver = bribes[bribeId].totalRewardAmount - amountClaimed[bribeId]; } // Transfer the left over to the owner. ERC20(bribe.rewardToken).safeTransfer(bribe.manager, leftOver); delete bribes[bribeId].manager; emit BribeClosed(bribeId, leftOver); } } /// @notice Update Bribe Manager. /// @param bribeId ID of the bribe. /// @param newManager Address of the new manager. function updateManager(uint256 bribeId, address newManager) external nonReentrant onlyManager(bribeId) { emit ManagerUpdated(bribeId, bribes[bribeId].manager = newManager); } function kill() external { if (msg.sender != address(factory)) revert NOT_ALLOWED_OPERATION(); isKilled = true; } //////////////////////////////////////////////////////////////// /// --- UTILS FUNCTIONS /////////////////////////////////////////////////////////////// /// @notice Returns the number of periods left for a given bribe. /// @param bribeId ID of the bribe. function getPeriodsLeft(uint256 bribeId) public view returns (uint256 periodsLeft) { Bribe storage bribe = bribes[bribeId]; uint256 currentPeriod = getCurrentPeriod(); periodsLeft = bribe.endTimestamp > currentPeriod ? (bribe.endTimestamp - currentPeriod) / _WEEK : 0; } /// @notice Return the bribe object for a given ID. /// @param bribeId ID of the bribe. function getBribe(uint256 bribeId) external view returns (Bribe memory) { return bribes[bribeId]; } /// @notice Return the bribe in queue for a given ID. /// @dev Can return an empty bribe if there is no upgrade. /// @param bribeId ID of the bribe. function getUpgradedBribeQueued(uint256 bribeId) external view returns (Upgrade memory) { return upgradeBribeQueue[bribeId]; } /// @notice Return the blacklisted addresses of a bribe for a given ID. /// @param bribeId ID of the bribe. function getBlacklistedAddressesForBribe(uint256 bribeId) external view returns (address[] memory) { return bribes[bribeId].blacklist; } /// @notice Return the active period running of bribe given an ID. /// @param bribeId ID of the bribe. function getActivePeriod(uint256 bribeId) public view returns (Period memory) { return activePeriod[bribeId]; } /// @notice Return the expected current period id. /// @param bribeId ID of the bribe. function getActivePeriodPerBribe(uint256 bribeId) public view returns (uint8) { Bribe storage bribe = bribes[bribeId]; uint256 currentPeriod = getCurrentPeriod(); uint256 periodsLeft = bribe.endTimestamp > currentPeriod ? (bribe.endTimestamp - currentPeriod) / _WEEK : 0; // If periodsLeft is superior, then the bribe didn't start yet. return uint8( periodsLeft > bribe.numberOfPeriods ? 0 : bribe.numberOfPeriods - periodsLeft ); } /// @notice Return the current period based on Gauge Controller rounding. function getCurrentPeriod() public view returns (uint256) { return (block.timestamp / _WEEK) * _WEEK; } /// @notice Return the minimum between two numbers. /// @param a First number. /// @param b Second number. function _min(uint256 a, uint256 b) private pure returns (uint256 min) { min = a < b ? a : b; } /// @notice Return the maximum between two numbers. /// @param a First number. /// @param b Second number. function _max(uint256 a, uint256 b) private pure returns (uint256 max) { max = a < b ? b : a; } /// @notice Return the bias of a given address based on its lock end date and the current period. /// @param userSlope User slope. /// @param endLockTime Lock end date of the address. /// @param currentPeriod Current period. function _getAddrBias( uint256 userSlope, uint256 endLockTime, uint256 currentPeriod ) internal pure returns (uint256) { if (currentPeriod + _WEEK >= endLockTime) return 0; return userSlope * (endLockTime - currentPeriod); } } /// @notice Library for converting between addresses and bytes32 values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol) library Bytes32AddressLib { function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { return address(uint160(uint256(bytesValue))); } function fillLast12Bytes(address addressValue) internal pure returns (bytes32) { return bytes32(bytes20(addressValue)); } } contract PlatformFactory is Owned, Factory { using Bytes32AddressLib for address; using Bytes32AddressLib for bytes32; /// @notice Fee recipient. address public feeCollector; /// @notice Fee Manager per gaugeController. mapping(address => address) public feeManagerPerGaugeController; /// @notice Recipient per address per gaugeController. mapping(address => mapping(address => address)) public recipient; /// @notice Emitted when a new platform is deployed. event PlatformDeployed( Platform indexed platform, address indexed gaugeController, FeeManager indexed feeManager ); /// @notice Emitted when a platform is killed. event PlatformKilled( Platform indexed platform, address indexed gaugeController ); /// @notice Emitted when a recipient is set for an address. event RecipientSet(address indexed sender, address indexed recipient); //////////////////////////////////////////////////////////////// /// --- CONSTRUCTOR /////////////////////////////////////////////////////////////// /// @notice Creates a Platform factory. /// @param _owner The owner of the factory. constructor(address _owner, address _feeCollector) Owned(_owner) { feeCollector = _feeCollector; } function deploy(address _gaugeController) external returns (Platform platform) { // Deploy the platform. platform = new Platform{ salt: address(_gaugeController).fillLast12Bytes() }(_gaugeController, address(this)); FeeManager feeManager = new FeeManager{ salt: address(_gaugeController).fillLast12Bytes() }(feeCollector); feeManagerPerGaugeController[_gaugeController] = address(feeManager); emit PlatformDeployed(platform, _gaugeController, feeManager); } /// @notice Computes a Platform address from its gauge controller. function getPlatformFromGaugeController(address gaugeController) external view returns (Platform) { return Platform( payable( keccak256( abi.encodePacked( bytes1(0xFF), address(this), address(gaugeController).fillLast12Bytes(), keccak256( abi.encodePacked( type(Platform).creationCode, abi.encode(gaugeController, address(this)) ) ) ) ).fromLast20Bytes() // Convert the CREATE2 hash into an address. ) ); } function setRecipient(address _recipient, address _gaugeController) external { recipient[msg.sender][_gaugeController] = _recipient; emit RecipientSet(msg.sender, _recipient); } function setRecipientFor( address _recipient, address _gaugeController, address _for ) external onlyOwner { recipient[_for][_gaugeController] = _recipient; emit RecipientSet(_for, _recipient); } function setFeeManager(address _gaugeController, address _feeManager) external onlyOwner { feeManagerPerGaugeController[_gaugeController] = _feeManager; } function platformFeeManager(address _gaugeController) external view returns (address) { return feeManagerPerGaugeController[_gaugeController]; } function setFeeCollector(address _feeCollector) external onlyOwner { feeCollector = _feeCollector; } function kill(address platform) external onlyOwner { Platform(platform).kill(); emit PlatformKilled( Platform(platform), address(Platform(platform).gaugeController()) ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_gaugeController","type":"address"},{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ALREADY_INCREASED","type":"error"},{"inputs":[],"name":"AUTH_MANAGER_ONLY","type":"error"},{"inputs":[],"name":"INVALID_NUMBER_OF_PERIODS","type":"error"},{"inputs":[],"name":"KILLED","type":"error"},{"inputs":[],"name":"NOT_ALLOWED_OPERATION","type":"error"},{"inputs":[],"name":"NOT_UPGRADEABLE","type":"error"},{"inputs":[],"name":"NO_PERIODS_LEFT","type":"error"},{"inputs":[],"name":"WRONG_INPUT","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingReward","type":"uint256"}],"name":"BribeClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"manager","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isUpgradeable","type":"bool"}],"name":"BribeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"}],"name":"BribeDurationIncreaseQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"}],"name":"BribeDurationIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"bribeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFees","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"ManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periodId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardPerPeriod","type":"uint256"}],"name":"PeriodRolledOver","type":"event"},{"inputs":[],"name":"MINIMUM_PERIOD","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"activePeriod","outputs":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"rewardPerPeriod","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"amountClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bribes","outputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"totalRewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"claimAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"claimAllFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"claimFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"closeBribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"internalType":"address[]","name":"blacklist","type":"address[]"},{"internalType":"bool","name":"upgradeable","type":"bool"}],"name":"createBribe","outputs":[{"internalType":"uint256","name":"newBribeID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gaugeController","outputs":[{"internalType":"contract GaugeController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getActivePeriod","outputs":[{"components":[{"internalType":"uint8","name":"id","type":"uint8"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"rewardPerPeriod","type":"uint256"}],"internalType":"struct Platform.Period","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getActivePeriodPerBribe","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getBlacklistedAddressesForBribe","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getBribe","outputs":[{"components":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"internalType":"address[]","name":"blacklist","type":"address[]"}],"internalType":"struct Platform.Bribe","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getPeriodsLeft","outputs":[{"internalType":"uint256","name":"periodsLeft","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"getUpgradedBribeQueued","outputs":[{"components":[{"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"address[]","name":"blacklist","type":"address[]"}],"internalType":"struct Platform.Upgrade","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bribeId","type":"uint256"},{"internalType":"uint8","name":"_additionnalPeriods","type":"uint8"},{"internalType":"uint256","name":"_increasedAmount","type":"uint256"},{"internalType":"uint256","name":"_newMaxPricePerVote","type":"uint256"},{"internalType":"address[]","name":"_addressesBlacklisted","type":"address[]"}],"name":"increaseBribeDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isKilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isUpgradeable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastUserClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardPerVote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"}],"name":"updateBribePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"updateBribePeriods","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bribeId","type":"uint256"},{"internalType":"address","name":"newManager","type":"address"}],"name":"updateManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"upgradeBribeQueue","outputs":[{"internalType":"uint8","name":"numberOfPeriods","type":"uint8"},{"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"internalType":"uint256","name":"maxRewardPerVote","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405260016000553480156200001657600080fd5b50604051620037633803806200376383398101604081905262000039916200006e565b6001600160a01b039081166080521660a052620000a6565b80516001600160a01b03811681146200006957600080fd5b919050565b600080604083850312156200008257600080fd5b6200008d8362000051565b91506200009d6020840162000051565b90509250929050565b60805160a0516135f66200016d6000396000818161049b015281816107f301528181610ba801528181610ca501528181610e9e015281816113c2015281816114570152818161170a01528181611a39015281816121020152818161219a015281816123a10152818161270a015281816127840152818161282e015281816129d30152612a830152600081816105c4015281816107c301528181610b7901528181610c7501528181610d4e0152818161173501528181611a0a01526123ce01526135f66000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806360efe3341161010f578063c29b6677116100a2578063ef2c408211610071578063ef2c408214610619578063f578c45b1461062c578063f8c07f2f1461063f578063f99673821461065257600080fd5b8063c29b66771461059f578063c45a0155146105bf578063d1d1bb4f146105e6578063de4aaaf41461060657600080fd5b80638fe8a101116100de5780638fe8a1011461048957806399eecb3b14610496578063a9d46e5b146104d5578063aca47b7d1461057c57600080fd5b806360efe334146103f35780636b5646aa146104065780637d8e376914610419578063832872731461042c57600080fd5b8063379607f5116101875780634fcf04f9116101565780634fcf04f91461037b57806351cd41e8146103a657806354d97ed5146103c057806360debfd3146103e057600080fd5b8063379607f5146103025780633ad86d721461031557806341c0e1b5146103355780634ae001d81461033d57600080fd5b806321bf936a116101c357806321bf936a14610250578063228c076c146102a257806328718374146102da57806328c77820146102ef57600080fd5b806306b6165f146101f5578063086146d21461021e5780630de05659146102345780631e96917d14610247575b600080fd5b610208610203366004612f97565b610665565b6040516102159190612ff4565b60405180910390f35b61022661079f565b604051908152602001610215565b610226610242366004613090565b6107be565b61022660025481565b61028361025e366004612f97565b60056020526000908152604090208054600182015460029092015460ff909116919083565b6040805160ff9094168452602084019290925290820152606001610215565b6102b56102b0366004612f97565b61089c565b60408051825160ff168152602080840151908201529181015190820152606001610215565b6102ed6102e8366004612f97565b6108ff565b005b6102ed6102fd366004613108565b610b5f565b610226610310366004612f97565b610c70565b610226610323366004612f97565b60086020526000908152604090205481565b6102ed610d43565b61036b61034b36600461314a565b600960209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610215565b610226610389366004613090565b600a60209081526000928352604080842090915290825290205481565b6103ae600281565b60405160ff9091168152602001610215565b6103d36103ce366004612f97565b610d9a565b604051610215919061317a565b6102266103ee3660046131dd565b610e09565b610226610401366004613090565b611274565b610226610414366004612f97565b61183b565b6103ae610427366004612f97565b61188c565b61046561043a366004612f97565b600460205260009081526040902080546001820154600283015460039093015460ff90921692909184565b6040805160ff90951685526020850193909352918301526060820152608001610215565b60015461036b9060ff1681565b6104bd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610215565b6105336104e3366004612f97565b60036020819052600091825260409091208054600182015460028301549383015460048401546005909401546001600160a01b03938416959284169493831693600160a01b90930460ff16929087565b604080516001600160a01b0398891681529688166020880152949096169385019390935260ff919091166060840152608083015260a082015260c081019190915260e001610215565b61036b61058a366004612f97565b60066020526000908152604090205460ff1681565b6105b26105ad366004612f97565b61191a565b6040516102159190613295565b6104bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102266105f4366004612f97565b60076020526000908152604090205481565b6102ed6106143660046132db565b6119f0565b6102ed61062736600461314a565b611b02565b6102ed61063a366004613330565b611bd0565b6102ed61064d366004613108565b611fab565b6102ed610660366004612f97565b612014565b6106cb60405180610100016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600060ff168152602001600081526020016000815260200160008152602001606081525090565b60008281526003602081815260409283902083516101008101855281546001600160a01b0390811682526001830154811682850152600283015490811682870152600160a01b900460ff166060820152928101546080840152600481015460a0840152600581015460c08401526006810180548551818502810185019096528086529394919360e086019383018282801561078f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610771575b5050505050815250509050919050565b600062093a806107af81426133b7565b6107b991906133d9565b905090565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2c616cb857f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b815260040161082f9291906133f0565b602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610870919061340a565b9050610892846001600160a01b03831661088a578561088c565b825b8561204d565b9150505b92915050565b6108c36040518060600160405280600060ff16815260200160008152602001600081525090565b506000908152600560209081526040918290208251606081018452815460ff168152600182015492810192909252600201549181019190915290565b60005460011461092a5760405162461bcd60e51b815260040161092190613427565b60405180910390fd5b600260009081558181526003602052604090206001015481906001600160a01b0316331461096b5760405163fabbbc6760e01b815260040160405180910390fd5b60008281526003602081905260409091209081015461098861079f565b101580610997575060015460ff165b15610b55576000838152600460208181526040808420815160a081018352815460ff1681526001820154818501526002820154818401526003820154606082015293810180548351818602810186019094528084528695949293608086019390929190830182828015610a3357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a15575b50505050508152505090508060200151600014610aad5760008581526007602090815260409091205490820151610a6a919061344b565b60008681526004602081905260408220805460ff19168155600181018390556002810183905560038101839055929450610aa690830182612ebc565b5050610ad8565b600085815260076020908152604080832054600390925290912060050154610ad5919061344b565b91505b60018301546002840154610af9916001600160a01b03918216911684612581565b60008581526003602090815260409182902060010180546001600160a01b031916905581518781529081018490527f046a3d8b38f161b27b53792783d95179ee019fafaf2aedf362807cb52fc2ab46910160405180910390a150505b5050600160005550565b60405163f2c616cb60e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2c616cb90610bd09033907f0000000000000000000000000000000000000000000000000000000000000000906004016133f0565b602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c11919061340a565b90506001600160a01b038116610c275733610c29565b805b90508160005b81811015610c69576000858583818110610c4b57610c4b61345e565b905060200201359050610c5f33858361204d565b5050600101610c2f565b5050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2c616cb337f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401610ce19291906133f0565b602060405180830381865afa158015610cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d22919061340a565b9050610d3c336001600160a01b03831661088a573361088c565b9392505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d8c5760405163f51fb3c360e01b815260040160405180910390fd5b6001805460ff191681179055565b600081815260036020908152604091829020600601805483518184028101840190945280845260609392830182828015610dfd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ddf575b50505050509050919050565b60008054600114610e2c5760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615610e55576040516363d8143160e01b815260040160405180910390fd5b6001600160a01b038816610e7c5760405163538ba4f960e01b815260040160405180910390fd5b604051633f9095b760e01b81526001600160a01b038b811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690633f9095b790602401602060405180830381865afa158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0b9190613474565b600f0b1261126257600260ff88161015610f3857604051634f9a14b160e11b815260040160405180910390fd5b841580610f43575085155b15610f61576040516356e43e7f60e01b815260040160405180910390fd5b610f766001600160a01b0389163330886125ff565b5060028054600180820190925590600090610f9690879060ff8b16612682565b90506000610fa261079f565b90506040518061010001604052808d6001600160a01b031681526020018c6001600160a01b031681526020018b6001600160a01b031681526020018a60ff16815260200162093a808b6001610ff79190613497565b60ff1661100491906133d9565b61100e90846134b0565b8152602001898152602001888152602001878780806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093909452505085815260036020818152604092839020855181546001600160a01b039182166001600160a01b0319918216178355878401516001840180549184169190921617905593860151600282018054606089015160ff16600160a01b026001600160a81b031990911692909616919091179490941790935560808501519183019190915560a0840151600483015560c0840151600583015560e084015180519293506111069260068501929190910190612edd565b5050604080516001600160a01b038e8116825260ff8d1660208301529181018b905260608101859052608081018a905286151560a0820152818d169250908e169085907f4ed4160f5ef12a0abd9d6134687dd7da5b8274bf240f997a1f377a76c52ccaf59060c00160405180910390a46000838152600660209081526040808320805460ff191688151517905580516060810190915291825281016111ae62093a80846134b0565b8152602090810184905260008581526005825260408082208451815460ff191660ff909116178155928401516001840155929092015160029091015585905b8181101561125d5760008581526009602052604081206001918a8a858181106112185761121861345e565b905060200201602081019061122d91906134c3565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016111ed565b505050505b60016000559998505050505050505050565b60008181526009602090815260408083206001600160a01b038616845290915281205460ff16156112a757506000610896565b600082815260036020818152604080842081516101008101835281546001600160a01b0390811682526001830154811682860152600283015490811682850152600160a01b900460ff166060820152938101546080850152600481015460a0850152600581015460c0850152600681018054835181860281018601909452808452919360e0860193929083018282801561136a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161134c575b50505091909252505050600084815260046020526040812091925061138d61079f565b905060006113a3846080015184600301546126a0565b84516040516303f20c7d60e51b81529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691637e418fa0916113f7918c916004016133f0565b602060405180830381865afa158015611414573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143891906134e0565b85516040516301e8cff360e31b81529192506000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691630f467f989161148c918d916004016133f0565b606060405180830381865afa1580156114a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cd91906134f9565b8051909150158061150157506001600160a01b0389166000908152600a602090815260408083208b84529091529020548411155b80611510575080604001518410155b8061151b5750818411155b806115265750828410155b8061153c57506115358861089c565b6020015184105b80611559575060c086015160008981526007602052604090205410155b1561156d5760009650505050505050610896565b6000888152600860205260409020548015806115a057506000811180156115a05750846115998a61089c565b6020015114155b1561167057855460009060ff16156115c757600287015460a0890152600187015460c08901525b60008686116115d75760006115ef565b62093a806115e5888861344b565b6115ef91906133b7565b60008c81526007602052604090205460c08b015191925061160f9161344b565b915061161e62093a80886134b0565b8611801561162c5750600181115b156116405761163d82600183612682565b91505b60006116558a600001518b60e001518a6126b5565b905061166a83670de0b6b3a764000083612682565b93505050505b60006116858360000151846040015188612914565b90506116918183612945565b985060006116ac8960a001518361294590919063ffffffff16565b90506116b88a8261295a565b60008c81526007602052604090205460c08b0151919b50906116da828d6134b0565b11156116f357808a60c001516116f0919061344b565b9a505b60405163200b788360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063200b788390602401602060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a2919061340a565b6001600160a01b0316631df4ccfc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180391906134e0565b9050801561182a5761182761182082670de0b6b3a764000061344b565b8d90612945565b9b505b505050505050505050505092915050565b60008181526003602052604081208161185261079f565b905080826003015411611866576000611884565b62093a8081836003015461187a919061344b565b61188491906133b7565b949350505050565b6000818152600360205260408120816118a361079f565b90506000818360030154116118b95760006118d7565b62093a808284600301546118cd919061344b565b6118d791906133b7565b6002840154909150600160a01b900460ff16811161190e576002830154611909908290600160a01b900460ff1661344b565b611911565b60005b95945050505050565b61194f6040518060a00160405280600060ff168152602001600081526020016000815260200160008152602001606081525090565b600082815260046020818152604092839020835160a081018552815460ff16815260018201548184015260028201548186015260038201546060820152928101805485518185028101850190965280865293949193608086019383018282801561078f576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610771575050505050815250509050919050565b60405163f2c616cb60e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2c616cb90611a619087907f0000000000000000000000000000000000000000000000000000000000000000906004016133f0565b602060405180830381865afa158015611a7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa2919061340a565b90508160005b81811015611afa576000858583818110611ac457611ac461345e565b60200291909101359150611af09050876001600160a01b038616611ae85788611aea565b855b8361204d565b5050600101611aa8565b505050505050565b600054600114611b245760405162461bcd60e51b815260040161092190613427565b600260009081558281526003602052604090206001015482906001600160a01b03163314611b655760405163fabbbc6760e01b815260040160405180910390fd5b60008381526003602090815260409182902060010180546001600160a01b0319166001600160a01b03861690811790915591518581527f5baaf19ee8739d1720c1401554ff4abe5682505ec43d3f2eb61b9dfc0abd9745910160405180910390a25050600160005550565b600054600114611bf25760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615611c1b576040516363d8143160e01b815260040160405180910390fd5b60008681526003602052604090206001015486906001600160a01b03163314611c575760405163fabbbc6760e01b815260040160405180910390fd5b60008781526006602052604090205460ff16611c865760405163dc370e0160e01b815260040160405180910390fd5b6001611c918861183b565b1015611cb057604051633bad1a5760e01b815260040160405180910390fd5b841580611cbb575083155b15611cd9576040516356e43e7f60e01b815260040160405180910390fd5b60008781526003602081815260408084206004808452828620835160a081018552815460ff168152600182015481870152600282015481860152958101546060870152908101805484518187028101870190955280855292969594919360808601939092830182828015611d7657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d58575b505050919092525050506002830154909150611d9d906001600160a01b031633308a6125ff565b602081015115611e46576040518060a00160405280898360000151611dc29190613497565b60ff168152602001888360200151611dda91906134b0565b815260208101889052604001611df662093a8060ff8c166133d9565b8360600151611e0591906134b0565b815260200186868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509152509050611eee565b6040518060a00160405280898460020160149054906101000a900460ff16611e6e9190613497565b60ff168152602001888460050154611e8691906134b0565b815260208101889052604001611ea262093a8060ff8c166133d9565b8460030154611eb191906134b0565b8152602001868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505091525090505b6000898152600460208181526040928390208451815460ff191660ff9091161781558482015160018201559284015160028401556060840151600384015560808401518051859493611f4593908501920190612edd565b50508151602080840151604080518e815260ff9094169284019290925290820152606081018890527f0c841045cbcf87e9cc7521ce9e85cf523d731f87fd5b45feea376cff34067263915060800160405180910390a15050600160005550505050505050565b600054600114611fcd5760405162461bcd60e51b815260040161092190613427565b6002600090815581905b8181101561200957612000848483818110611ff457611ff461345e565b90506020020135612970565b50600101611fd7565b505060016000555050565b6000546001146120365760405162461bcd60e51b815260040161092190613427565b600260005561204481612970565b50506001600055565b600080546001146120705760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615612099576040516363d8143160e01b815260040160405180910390fd5b60008281526009602090815260408083206001600160a01b038816845290915290205460ff16156120cc57506000612575565b60006120d783612970565b600084815260036020526040808220805491516303f20c7d60e51b8152939450926001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811692637e418fa09261213a928c9216906004016133f0565b602060405180830381865afa158015612157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217b91906134e0565b82546040516301e8cff360e31b81529192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811692630f467f98926121d2928d9216906004016133f0565b606060405180830381865afa1580156121ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221391906134f9565b8051909150158061224757506001600160a01b0388166000908152600a602090815260408083208984529091529020548411155b80612256575080604001518410155b806122615750818411155b80612270575082600301548410155b80612282575061227e61079f565b8414155b8061229e57506005830154600087815260076020526040902054145b156122b0576000945050505050612575565b6001600160a01b0388166000908152600a602090815260408083208984529091528082208690558251908301516122e8919087612914565b600088815260086020526040902054909150612305908290612945565b9550600061232085600401548361294590919063ffffffff16565b905061232c878261295a565b60008981526007602052604090205460058701549198509061234e828a6134b0565b111561236757808660050154612364919061344b565b97505b600089815260076020526040812080548a92906123859084906134b0565b909155505060405163200b788360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063200b788390602401602060405180830381865afa158015612415573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612439919061340a565b90506000816001600160a01b0316631df4ccfc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561247b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249f91906134e0565b905080156124d9576124b18b82612945565b92506124bd838c61344b565b60028a0154909b506124d9906001600160a01b03168385612581565b60028901546124f2906001600160a01b03168e8d612581565b8b8960020160009054906101000a90046001600160a01b03166001600160a01b03168f6001600160a01b03167f6f9c9826be5976f3f82a3490c52a83328ce2ec7be9e62dcb39c26da5148d7c768e878f604051612562939291909283526020830191909152604082015260600190565b60405180910390a4505050505050505050505b60016000559392505050565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806125f95760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610921565b50505050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610c695760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610921565b600082600019048411830215820261269957600080fd5b5091020490565b60008183106126af5782610d3c565b50919050565b60006126db60405180606001604052806000815260200160008152602001600081525090565b835160405163edba527360e01b81526001600160a01b03878116600483015260248201869052600092839290917f0000000000000000000000000000000000000000000000000000000000000000169063edba5273906044016040805180830381865afa158015612750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127749190613563565b51945060005b81811015612908577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630f467f988983815181106127c3576127c361345e565b60200260200101518b6040518363ffffffff1660e01b81526004016127e99291906133f0565b606060405180830381865afa158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a91906134f9565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637e418fa089838151811061286d5761286d61345e565b60200260200101518b6040518363ffffffff1660e01b81526004016128939291906133f0565b602060405180830381865afa1580156128b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d491906134e0565b925082871115612900576128f18560000151866040015189612914565b93506128fd848761344b565b95505b60010161277a565b50505050509392505050565b60008261292462093a80846134b0565b1061293157506000610d3c565b61293b828461344b565b61188490856133d9565b6000610d3c8383670de0b6b3a7640000612682565b60008183106129695781610d3c565b5090919050565b60008181526005602052604081208161298761079f565b825490915060ff1615801561299f5750816001015481145b15612a3b576000848152600360205260409081902054905163615e523760e01b81526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063615e523790602401600060405180830381600087803b158015612a1957600080fd5b505af1158015612a2d573d6000803e3d6000fd5b50505050612a3b8482612af6565b62093a808260010154612a4e91906134b0565b4210612aeb576000848152600360205260409081902054905163615e523760e01b81526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063615e523790602401600060405180830381600087803b158015612ac957600080fd5b505af1158015612add573d6000803e3d6000fd5b50505050610d3c8482612bcc565b506001015492915050565b6000828152600860205260408120549003612bc8576000828152600360209081526040808320805460069091018054835181860281018601909452808452612b89946001600160a01b039093169392830182828015612b7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612b60575b5050505050846126b5565b90508015612bc657600083815260056020526040902060020154612bb690670de0b6b3a764000083612682565b6000848152600860205260409020555b505b5050565b6000612bd78361188c565b600084815260046020526040902060018101549192509015612d0857805460008581526003602081905260409091206002808201805460ff60a01b191660ff909516600160a01b0294909417909355600184015460058201559183015460048084019190915581840154929091019190915581015415612c75576000848152600360205260409020600482018054612c73926006019190612f42565b505b8054600182015460028301546040805188815260ff909416602085015283019190915260608201527fe90b0f7fffa9942eb28c4453083b14e929e4f6d39de19dd5f8cef36148b9c63a9060800160405180910390a160008481526004602081905260408220805460ff191681556001810183905560028101839055600381018390559190612d0590830182612ebc565b50505b600084815260036020526040812090612d208661183b565b60008781526007602052604081205460058501549293509091612d43919061344b565b9050612d5262093a80876134b0565b8360030154118015612d645750600182115b15612d7857612d7581600184612682565b90505b825460068401805460408051602080840282018101909252828152600094612def946001600160a01b03909116939192909190830182828015612de457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612dc6575b5050505050896126b5565b9050612e0482670de0b6b3a764000083612682565b600089815260086020908152604080832093909355825160608101845260ff808b1682528183018c81528286018881528e865260059094529385902091518254911660ff199091161781559151600183015551600290910155517fb77c22cd311809931524bcc8d4a33a61a392e2304c8a7d476b64018e11ed6cb190612eaa908a9089908b90879093845260ff9290921660208401526040830152606082015260800190565b60405180910390a15050505050505050565b5080546000825590600052602060002090810190612eda9190612f82565b50565b828054828255906000526020600020908101928215612f32579160200282015b82811115612f3257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612efd565b50612f3e929150612f82565b5090565b828054828255906000526020600020908101928215612f325760005260206000209182015b82811115612f32578254825591600101919060010190612f67565b5b80821115612f3e5760008155600101612f83565b600060208284031215612fa957600080fd5b5035919050565b600081518084526020808501945080840160005b83811015612fe95781516001600160a01b031687529582019590820190600101612fc4565b509495945050505050565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015161303160608401826001600160a01b03169052565b50606083015160ff8116608084015250608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100808185015250610892610120840182612fb0565b6001600160a01b0381168114612eda57600080fd5b600080604083850312156130a357600080fd5b82356130ae8161307b565b946020939093013593505050565b60008083601f8401126130ce57600080fd5b50813567ffffffffffffffff8111156130e657600080fd5b6020830191508360208260051b850101111561310157600080fd5b9250929050565b6000806020838503121561311b57600080fd5b823567ffffffffffffffff81111561313257600080fd5b61313e858286016130bc565b90969095509350505050565b6000806040838503121561315d57600080fd5b82359150602083013561316f8161307b565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156131bb5783516001600160a01b031683529284019291840191600101613196565b50909695505050505050565b803560ff811681146131d857600080fd5b919050565b60008060008060008060008060006101008a8c0312156131fc57600080fd5b89356132078161307b565b985060208a01356132178161307b565b975060408a01356132278161307b565b965061323560608b016131c7565b955060808a0135945060a08a0135935060c08a013567ffffffffffffffff81111561325f57600080fd5b61326b8c828d016130bc565b90945092505060e08a0135801515811461328457600080fd5b809150509295985092959850929598565b6020815260ff82511660208201526020820151604082015260408201516060820152606082015160808201526000608083015160a08084015261089260c0840182612fb0565b6000806000604084860312156132f057600080fd5b83356132fb8161307b565b9250602084013567ffffffffffffffff81111561331757600080fd5b613323868287016130bc565b9497909650939450505050565b60008060008060008060a0878903121561334957600080fd5b86359550613359602088016131c7565b94506040870135935060608701359250608087013567ffffffffffffffff81111561338357600080fd5b61338f89828a016130bc565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b6000826133d457634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610896576108966133a1565b6001600160a01b0392831681529116602082015260400190565b60006020828403121561341c57600080fd5b8151610d3c8161307b565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b81810381811115610896576108966133a1565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561348657600080fd5b815180600f0b8114610d3c57600080fd5b60ff8181168382160190811115610896576108966133a1565b80820180821115610896576108966133a1565b6000602082840312156134d557600080fd5b8135610d3c8161307b565b6000602082840312156134f257600080fd5b5051919050565b60006060828403121561350b57600080fd5b6040516060810181811067ffffffffffffffff8211171561353c57634e487b7160e01b600052604160045260246000fd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b60006040828403121561357557600080fd5b6040516040810181811067ffffffffffffffff821117156135a657634e487b7160e01b600052604160045260246000fd5b60405282518152602092830151928101929092525091905056fea2646970667358221220acea1855ea1c703fe155e66a44918f85873963e86ab70c26b0d7928f4c009d4664736f6c634300081100330000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806360efe3341161010f578063c29b6677116100a2578063ef2c408211610071578063ef2c408214610619578063f578c45b1461062c578063f8c07f2f1461063f578063f99673821461065257600080fd5b8063c29b66771461059f578063c45a0155146105bf578063d1d1bb4f146105e6578063de4aaaf41461060657600080fd5b80638fe8a101116100de5780638fe8a1011461048957806399eecb3b14610496578063a9d46e5b146104d5578063aca47b7d1461057c57600080fd5b806360efe334146103f35780636b5646aa146104065780637d8e376914610419578063832872731461042c57600080fd5b8063379607f5116101875780634fcf04f9116101565780634fcf04f91461037b57806351cd41e8146103a657806354d97ed5146103c057806360debfd3146103e057600080fd5b8063379607f5146103025780633ad86d721461031557806341c0e1b5146103355780634ae001d81461033d57600080fd5b806321bf936a116101c357806321bf936a14610250578063228c076c146102a257806328718374146102da57806328c77820146102ef57600080fd5b806306b6165f146101f5578063086146d21461021e5780630de05659146102345780631e96917d14610247575b600080fd5b610208610203366004612f97565b610665565b6040516102159190612ff4565b60405180910390f35b61022661079f565b604051908152602001610215565b610226610242366004613090565b6107be565b61022660025481565b61028361025e366004612f97565b60056020526000908152604090208054600182015460029092015460ff909116919083565b6040805160ff9094168452602084019290925290820152606001610215565b6102b56102b0366004612f97565b61089c565b60408051825160ff168152602080840151908201529181015190820152606001610215565b6102ed6102e8366004612f97565b6108ff565b005b6102ed6102fd366004613108565b610b5f565b610226610310366004612f97565b610c70565b610226610323366004612f97565b60086020526000908152604090205481565b6102ed610d43565b61036b61034b36600461314a565b600960209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610215565b610226610389366004613090565b600a60209081526000928352604080842090915290825290205481565b6103ae600281565b60405160ff9091168152602001610215565b6103d36103ce366004612f97565b610d9a565b604051610215919061317a565b6102266103ee3660046131dd565b610e09565b610226610401366004613090565b611274565b610226610414366004612f97565b61183b565b6103ae610427366004612f97565b61188c565b61046561043a366004612f97565b600460205260009081526040902080546001820154600283015460039093015460ff90921692909184565b6040805160ff90951685526020850193909352918301526060820152608001610215565b60015461036b9060ff1681565b6104bd7f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb81565b6040516001600160a01b039091168152602001610215565b6105336104e3366004612f97565b60036020819052600091825260409091208054600182015460028301549383015460048401546005909401546001600160a01b03938416959284169493831693600160a01b90930460ff16929087565b604080516001600160a01b0398891681529688166020880152949096169385019390935260ff919091166060840152608083015260a082015260c081019190915260e001610215565b61036b61058a366004612f97565b60066020526000908152604090205460ff1681565b6105b26105ad366004612f97565b61191a565b6040516102159190613295565b6104bd7f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad588081565b6102266105f4366004612f97565b60076020526000908152604090205481565b6102ed6106143660046132db565b6119f0565b6102ed61062736600461314a565b611b02565b6102ed61063a366004613330565b611bd0565b6102ed61064d366004613108565b611fab565b6102ed610660366004612f97565b612014565b6106cb60405180610100016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600060ff168152602001600081526020016000815260200160008152602001606081525090565b60008281526003602081815260409283902083516101008101855281546001600160a01b0390811682526001830154811682850152600283015490811682870152600160a01b900460ff166060820152928101546080840152600481015460a0840152600581015460c08401526006810180548551818502810185019096528086529394919360e086019383018282801561078f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610771575b5050505050815250509050919050565b600062093a806107af81426133b7565b6107b991906133d9565b905090565b6000807f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad58806001600160a01b031663f2c616cb857f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb6040518363ffffffff1660e01b815260040161082f9291906133f0565b602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610870919061340a565b9050610892846001600160a01b03831661088a578561088c565b825b8561204d565b9150505b92915050565b6108c36040518060600160405280600060ff16815260200160008152602001600081525090565b506000908152600560209081526040918290208251606081018452815460ff168152600182015492810192909252600201549181019190915290565b60005460011461092a5760405162461bcd60e51b815260040161092190613427565b60405180910390fd5b600260009081558181526003602052604090206001015481906001600160a01b0316331461096b5760405163fabbbc6760e01b815260040160405180910390fd5b60008281526003602081905260409091209081015461098861079f565b101580610997575060015460ff165b15610b55576000838152600460208181526040808420815160a081018352815460ff1681526001820154818501526002820154818401526003820154606082015293810180548351818602810186019094528084528695949293608086019390929190830182828015610a3357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a15575b50505050508152505090508060200151600014610aad5760008581526007602090815260409091205490820151610a6a919061344b565b60008681526004602081905260408220805460ff19168155600181018390556002810183905560038101839055929450610aa690830182612ebc565b5050610ad8565b600085815260076020908152604080832054600390925290912060050154610ad5919061344b565b91505b60018301546002840154610af9916001600160a01b03918216911684612581565b60008581526003602090815260409182902060010180546001600160a01b031916905581518781529081018490527f046a3d8b38f161b27b53792783d95179ee019fafaf2aedf362807cb52fc2ab46910160405180910390a150505b5050600160005550565b60405163f2c616cb60e01b81526000906001600160a01b037f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880169063f2c616cb90610bd09033907f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb906004016133f0565b602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c11919061340a565b90506001600160a01b038116610c275733610c29565b805b90508160005b81811015610c69576000858583818110610c4b57610c4b61345e565b905060200201359050610c5f33858361204d565b5050600101610c2f565b5050505050565b6000807f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad58806001600160a01b031663f2c616cb337f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb6040518363ffffffff1660e01b8152600401610ce19291906133f0565b602060405180830381865afa158015610cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d22919061340a565b9050610d3c336001600160a01b03831661088a573361088c565b9392505050565b336001600160a01b037f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad58801614610d8c5760405163f51fb3c360e01b815260040160405180910390fd5b6001805460ff191681179055565b600081815260036020908152604091829020600601805483518184028101840190945280845260609392830182828015610dfd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ddf575b50505050509050919050565b60008054600114610e2c5760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615610e55576040516363d8143160e01b815260040160405180910390fd5b6001600160a01b038816610e7c5760405163538ba4f960e01b815260040160405180910390fd5b604051633f9095b760e01b81526001600160a01b038b811660048301526000917f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb90911690633f9095b790602401602060405180830381865afa158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0b9190613474565b600f0b1261126257600260ff88161015610f3857604051634f9a14b160e11b815260040160405180910390fd5b841580610f43575085155b15610f61576040516356e43e7f60e01b815260040160405180910390fd5b610f766001600160a01b0389163330886125ff565b5060028054600180820190925590600090610f9690879060ff8b16612682565b90506000610fa261079f565b90506040518061010001604052808d6001600160a01b031681526020018c6001600160a01b031681526020018b6001600160a01b031681526020018a60ff16815260200162093a808b6001610ff79190613497565b60ff1661100491906133d9565b61100e90846134b0565b8152602001898152602001888152602001878780806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093909452505085815260036020818152604092839020855181546001600160a01b039182166001600160a01b0319918216178355878401516001840180549184169190921617905593860151600282018054606089015160ff16600160a01b026001600160a81b031990911692909616919091179490941790935560808501519183019190915560a0840151600483015560c0840151600583015560e084015180519293506111069260068501929190910190612edd565b5050604080516001600160a01b038e8116825260ff8d1660208301529181018b905260608101859052608081018a905286151560a0820152818d169250908e169085907f4ed4160f5ef12a0abd9d6134687dd7da5b8274bf240f997a1f377a76c52ccaf59060c00160405180910390a46000838152600660209081526040808320805460ff191688151517905580516060810190915291825281016111ae62093a80846134b0565b8152602090810184905260008581526005825260408082208451815460ff191660ff909116178155928401516001840155929092015160029091015585905b8181101561125d5760008581526009602052604081206001918a8a858181106112185761121861345e565b905060200201602081019061122d91906134c3565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016111ed565b505050505b60016000559998505050505050505050565b60008181526009602090815260408083206001600160a01b038616845290915281205460ff16156112a757506000610896565b600082815260036020818152604080842081516101008101835281546001600160a01b0390811682526001830154811682860152600283015490811682850152600160a01b900460ff166060820152938101546080850152600481015460a0850152600581015460c0850152600681018054835181860281018601909452808452919360e0860193929083018282801561136a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161134c575b50505091909252505050600084815260046020526040812091925061138d61079f565b905060006113a3846080015184600301546126a0565b84516040516303f20c7d60e51b81529192506000916001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb1691637e418fa0916113f7918c916004016133f0565b602060405180830381865afa158015611414573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143891906134e0565b85516040516301e8cff360e31b81529192506000916001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb1691630f467f989161148c918d916004016133f0565b606060405180830381865afa1580156114a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114cd91906134f9565b8051909150158061150157506001600160a01b0389166000908152600a602090815260408083208b84529091529020548411155b80611510575080604001518410155b8061151b5750818411155b806115265750828410155b8061153c57506115358861089c565b6020015184105b80611559575060c086015160008981526007602052604090205410155b1561156d5760009650505050505050610896565b6000888152600860205260409020548015806115a057506000811180156115a05750846115998a61089c565b6020015114155b1561167057855460009060ff16156115c757600287015460a0890152600187015460c08901525b60008686116115d75760006115ef565b62093a806115e5888861344b565b6115ef91906133b7565b60008c81526007602052604090205460c08b015191925061160f9161344b565b915061161e62093a80886134b0565b8611801561162c5750600181115b156116405761163d82600183612682565b91505b60006116558a600001518b60e001518a6126b5565b905061166a83670de0b6b3a764000083612682565b93505050505b60006116858360000151846040015188612914565b90506116918183612945565b985060006116ac8960a001518361294590919063ffffffff16565b90506116b88a8261295a565b60008c81526007602052604090205460c08b0151919b50906116da828d6134b0565b11156116f357808a60c001516116f0919061344b565b9a505b60405163200b788360e01b81526001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb811660048301526000917f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad58809091169063200b788390602401602060405180830381865afa15801561177e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a2919061340a565b6001600160a01b0316631df4ccfc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180391906134e0565b9050801561182a5761182761182082670de0b6b3a764000061344b565b8d90612945565b9b505b505050505050505050505092915050565b60008181526003602052604081208161185261079f565b905080826003015411611866576000611884565b62093a8081836003015461187a919061344b565b61188491906133b7565b949350505050565b6000818152600360205260408120816118a361079f565b90506000818360030154116118b95760006118d7565b62093a808284600301546118cd919061344b565b6118d791906133b7565b6002840154909150600160a01b900460ff16811161190e576002830154611909908290600160a01b900460ff1661344b565b611911565b60005b95945050505050565b61194f6040518060a00160405280600060ff168152602001600081526020016000815260200160008152602001606081525090565b600082815260046020818152604092839020835160a081018552815460ff16815260018201548184015260028201548186015260038201546060820152928101805485518185028101850190965280865293949193608086019383018282801561078f576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610771575050505050815250509050919050565b60405163f2c616cb60e01b81526000906001600160a01b037f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880169063f2c616cb90611a619087907f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb906004016133f0565b602060405180830381865afa158015611a7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa2919061340a565b90508160005b81811015611afa576000858583818110611ac457611ac461345e565b60200291909101359150611af09050876001600160a01b038616611ae85788611aea565b855b8361204d565b5050600101611aa8565b505050505050565b600054600114611b245760405162461bcd60e51b815260040161092190613427565b600260009081558281526003602052604090206001015482906001600160a01b03163314611b655760405163fabbbc6760e01b815260040160405180910390fd5b60008381526003602090815260409182902060010180546001600160a01b0319166001600160a01b03861690811790915591518581527f5baaf19ee8739d1720c1401554ff4abe5682505ec43d3f2eb61b9dfc0abd9745910160405180910390a25050600160005550565b600054600114611bf25760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615611c1b576040516363d8143160e01b815260040160405180910390fd5b60008681526003602052604090206001015486906001600160a01b03163314611c575760405163fabbbc6760e01b815260040160405180910390fd5b60008781526006602052604090205460ff16611c865760405163dc370e0160e01b815260040160405180910390fd5b6001611c918861183b565b1015611cb057604051633bad1a5760e01b815260040160405180910390fd5b841580611cbb575083155b15611cd9576040516356e43e7f60e01b815260040160405180910390fd5b60008781526003602081815260408084206004808452828620835160a081018552815460ff168152600182015481870152600282015481860152958101546060870152908101805484518187028101870190955280855292969594919360808601939092830182828015611d7657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611d58575b505050919092525050506002830154909150611d9d906001600160a01b031633308a6125ff565b602081015115611e46576040518060a00160405280898360000151611dc29190613497565b60ff168152602001888360200151611dda91906134b0565b815260208101889052604001611df662093a8060ff8c166133d9565b8360600151611e0591906134b0565b815260200186868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509152509050611eee565b6040518060a00160405280898460020160149054906101000a900460ff16611e6e9190613497565b60ff168152602001888460050154611e8691906134b0565b815260208101889052604001611ea262093a8060ff8c166133d9565b8460030154611eb191906134b0565b8152602001868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250505091525090505b6000898152600460208181526040928390208451815460ff191660ff9091161781558482015160018201559284015160028401556060840151600384015560808401518051859493611f4593908501920190612edd565b50508151602080840151604080518e815260ff9094169284019290925290820152606081018890527f0c841045cbcf87e9cc7521ce9e85cf523d731f87fd5b45feea376cff34067263915060800160405180910390a15050600160005550505050505050565b600054600114611fcd5760405162461bcd60e51b815260040161092190613427565b6002600090815581905b8181101561200957612000848483818110611ff457611ff461345e565b90506020020135612970565b50600101611fd7565b505060016000555050565b6000546001146120365760405162461bcd60e51b815260040161092190613427565b600260005561204481612970565b50506001600055565b600080546001146120705760405162461bcd60e51b815260040161092190613427565b600260005560015460ff1615612099576040516363d8143160e01b815260040160405180910390fd5b60008281526009602090815260408083206001600160a01b038816845290915290205460ff16156120cc57506000612575565b60006120d783612970565b600084815260036020526040808220805491516303f20c7d60e51b8152939450926001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb811692637e418fa09261213a928c9216906004016133f0565b602060405180830381865afa158015612157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217b91906134e0565b82546040516301e8cff360e31b81529192506000916001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb811692630f467f98926121d2928d9216906004016133f0565b606060405180830381865afa1580156121ef573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221391906134f9565b8051909150158061224757506001600160a01b0388166000908152600a602090815260408083208984529091529020548411155b80612256575080604001518410155b806122615750818411155b80612270575082600301548410155b80612282575061227e61079f565b8414155b8061229e57506005830154600087815260076020526040902054145b156122b0576000945050505050612575565b6001600160a01b0388166000908152600a602090815260408083208984529091528082208690558251908301516122e8919087612914565b600088815260086020526040902054909150612305908290612945565b9550600061232085600401548361294590919063ffffffff16565b905061232c878261295a565b60008981526007602052604090205460058701549198509061234e828a6134b0565b111561236757808660050154612364919061344b565b97505b600089815260076020526040812080548a92906123859084906134b0565b909155505060405163200b788360e01b81526001600160a01b037f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb8116600483015260009182917f00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880169063200b788390602401602060405180830381865afa158015612415573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612439919061340a565b90506000816001600160a01b0316631df4ccfc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561247b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249f91906134e0565b905080156124d9576124b18b82612945565b92506124bd838c61344b565b60028a0154909b506124d9906001600160a01b03168385612581565b60028901546124f2906001600160a01b03168e8d612581565b8b8960020160009054906101000a90046001600160a01b03166001600160a01b03168f6001600160a01b03167f6f9c9826be5976f3f82a3490c52a83328ce2ec7be9e62dcb39c26da5148d7c768e878f604051612562939291909283526020830191909152604082015260600190565b60405180910390a4505050505050505050505b60016000559392505050565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806125f95760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610921565b50505050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610c695760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610921565b600082600019048411830215820261269957600080fd5b5091020490565b60008183106126af5782610d3c565b50919050565b60006126db60405180606001604052806000815260200160008152602001600081525090565b835160405163edba527360e01b81526001600160a01b03878116600483015260248201869052600092839290917f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb169063edba5273906044016040805180830381865afa158015612750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127749190613563565b51945060005b81811015612908577f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb6001600160a01b0316630f467f988983815181106127c3576127c361345e565b60200260200101518b6040518363ffffffff1660e01b81526004016127e99291906133f0565b606060405180830381865afa158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a91906134f9565b94507f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb6001600160a01b0316637e418fa089838151811061286d5761286d61345e565b60200260200101518b6040518363ffffffff1660e01b81526004016128939291906133f0565b602060405180830381865afa1580156128b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128d491906134e0565b925082871115612900576128f18560000151866040015189612914565b93506128fd848761344b565b95505b60010161277a565b50505050509392505050565b60008261292462093a80846134b0565b1061293157506000610d3c565b61293b828461344b565b61188490856133d9565b6000610d3c8383670de0b6b3a7640000612682565b60008183106129695781610d3c565b5090919050565b60008181526005602052604081208161298761079f565b825490915060ff1615801561299f5750816001015481145b15612a3b576000848152600360205260409081902054905163615e523760e01b81526001600160a01b0391821660048201527f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb9091169063615e523790602401600060405180830381600087803b158015612a1957600080fd5b505af1158015612a2d573d6000803e3d6000fd5b50505050612a3b8482612af6565b62093a808260010154612a4e91906134b0565b4210612aeb576000848152600360205260409081902054905163615e523760e01b81526001600160a01b0391821660048201527f0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb9091169063615e523790602401600060405180830381600087803b158015612ac957600080fd5b505af1158015612add573d6000803e3d6000fd5b50505050610d3c8482612bcc565b506001015492915050565b6000828152600860205260408120549003612bc8576000828152600360209081526040808320805460069091018054835181860281018601909452808452612b89946001600160a01b039093169392830182828015612b7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612b60575b5050505050846126b5565b90508015612bc657600083815260056020526040902060020154612bb690670de0b6b3a764000083612682565b6000848152600860205260409020555b505b5050565b6000612bd78361188c565b600084815260046020526040902060018101549192509015612d0857805460008581526003602081905260409091206002808201805460ff60a01b191660ff909516600160a01b0294909417909355600184015460058201559183015460048084019190915581840154929091019190915581015415612c75576000848152600360205260409020600482018054612c73926006019190612f42565b505b8054600182015460028301546040805188815260ff909416602085015283019190915260608201527fe90b0f7fffa9942eb28c4453083b14e929e4f6d39de19dd5f8cef36148b9c63a9060800160405180910390a160008481526004602081905260408220805460ff191681556001810183905560028101839055600381018390559190612d0590830182612ebc565b50505b600084815260036020526040812090612d208661183b565b60008781526007602052604081205460058501549293509091612d43919061344b565b9050612d5262093a80876134b0565b8360030154118015612d645750600182115b15612d7857612d7581600184612682565b90505b825460068401805460408051602080840282018101909252828152600094612def946001600160a01b03909116939192909190830182828015612de457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612dc6575b5050505050896126b5565b9050612e0482670de0b6b3a764000083612682565b600089815260086020908152604080832093909355825160608101845260ff808b1682528183018c81528286018881528e865260059094529385902091518254911660ff199091161781559151600183015551600290910155517fb77c22cd311809931524bcc8d4a33a61a392e2304c8a7d476b64018e11ed6cb190612eaa908a9089908b90879093845260ff9290921660208401526040830152606082015260800190565b60405180910390a15050505050505050565b5080546000825590600052602060002090810190612eda9190612f82565b50565b828054828255906000526020600020908101928215612f32579160200282015b82811115612f3257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612efd565b50612f3e929150612f82565b5090565b828054828255906000526020600020908101928215612f325760005260206000209182015b82811115612f32578254825591600101919060010190612f67565b5b80821115612f3e5760008155600101612f83565b600060208284031215612fa957600080fd5b5035919050565b600081518084526020808501945080840160005b83811015612fe95781516001600160a01b031687529582019590820190600101612fc4565b509495945050505050565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015161303160608401826001600160a01b03169052565b50606083015160ff8116608084015250608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100808185015250610892610120840182612fb0565b6001600160a01b0381168114612eda57600080fd5b600080604083850312156130a357600080fd5b82356130ae8161307b565b946020939093013593505050565b60008083601f8401126130ce57600080fd5b50813567ffffffffffffffff8111156130e657600080fd5b6020830191508360208260051b850101111561310157600080fd5b9250929050565b6000806020838503121561311b57600080fd5b823567ffffffffffffffff81111561313257600080fd5b61313e858286016130bc565b90969095509350505050565b6000806040838503121561315d57600080fd5b82359150602083013561316f8161307b565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156131bb5783516001600160a01b031683529284019291840191600101613196565b50909695505050505050565b803560ff811681146131d857600080fd5b919050565b60008060008060008060008060006101008a8c0312156131fc57600080fd5b89356132078161307b565b985060208a01356132178161307b565b975060408a01356132278161307b565b965061323560608b016131c7565b955060808a0135945060a08a0135935060c08a013567ffffffffffffffff81111561325f57600080fd5b61326b8c828d016130bc565b90945092505060e08a0135801515811461328457600080fd5b809150509295985092959850929598565b6020815260ff82511660208201526020820151604082015260408201516060820152606082015160808201526000608083015160a08084015261089260c0840182612fb0565b6000806000604084860312156132f057600080fd5b83356132fb8161307b565b9250602084013567ffffffffffffffff81111561331757600080fd5b613323868287016130bc565b9497909650939450505050565b60008060008060008060a0878903121561334957600080fd5b86359550613359602088016131c7565b94506040870135935060608701359250608087013567ffffffffffffffff81111561338357600080fd5b61338f89828a016130bc565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b6000826133d457634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610896576108966133a1565b6001600160a01b0392831681529116602082015260400190565b60006020828403121561341c57600080fd5b8151610d3c8161307b565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b81810381811115610896576108966133a1565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561348657600080fd5b815180600f0b8114610d3c57600080fd5b60ff8181168382160190811115610896576108966133a1565b80820180821115610896576108966133a1565b6000602082840312156134d557600080fd5b8135610d3c8161307b565b6000602082840312156134f257600080fd5b5051919050565b60006060828403121561350b57600080fd5b6040516060810181811067ffffffffffffffff8211171561353c57634e487b7160e01b600052604160045260246000fd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b60006040828403121561357557600080fd5b6040516040810181811067ffffffffffffffff821117156135a657634e487b7160e01b600052604160045260246000fd5b60405282518152602092830151928101929092525091905056fea2646970667358221220acea1855ea1c703fe155e66a44918f85873963e86ab70c26b0d7928f4c009d4664736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880
-----Decoded View---------------
Arg [0] : _gaugeController (address): 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB
Arg [1] : _factory (address): 0x90068d8c21Cb632CC14cf1dDC8427C1A71AD5880
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002f50d538606fa9edd2b11e2446beb18c9d5846bb
Arg [1] : 00000000000000000000000090068d8c21cb632cc14cf1ddc8427c1a71ad5880
Deployed Bytecode Sourcemap
32450:33172:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62630:113;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;64492:117;;;:::i;:::-;;;1964:25:1;;;1952:2;1937:18;64492:117:0;1818:177:1;42291:283:0;;;;;;:::i;:::-;;:::i;35180:21::-;;;;;;35442:46;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2684:4:1;2672:17;;;2654:36;;2721:2;2706:18;;2699:34;;;;2749:18;;;2742:34;2642:2;2627:18;35442:46:0;2456:326:1;63516:157:0;;;;;;:::i;:::-;;:::i;:::-;;;;3003:13:1;;3018:4;2999:24;2981:43;;3080:4;3068:17;;;3062:24;3040:20;;;3033:54;3131:17;;;3125:24;3103:20;;;3096:54;2969:2;2954:18;63516:157:0;2787:369:1;60275:1090:0;;;;;;:::i;:::-;;:::i;:::-;;44214:497;;;;;;:::i;:::-;;:::i;43148:364::-;;;;;;:::i;:::-;;:::i;35798:48::-;;;;;;:::i;:::-;;;;;;;;;;;;;;61736:136;;;:::i;35949:65::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4460:14:1;;4453:22;4435:41;;4423:2;4408:18;35949:65:0;4295:187:1;36065:68:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;34761:40;;34800:1;34761:40;;;;;4659:4:1;4647:17;;;4629:36;;4617:2;4602:18;34761:40:0;4487:184:1;63213:182:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39702:2446::-;;;;;;:::i;:::-;;:::i;52277:3676::-;;;;;;:::i;:::-;;:::i;62162:362::-;;;;;;:::i;:::-;;:::i;63778:627::-;;;;;;:::i;:::-;;:::i;35342:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6996:4:1;6984:17;;;6966:36;;7033:2;7018:18;;7011:34;;;;7061:18;;;7054:34;7119:2;7104:18;;7097:34;6953:3;6938:19;35342:52:0;6739:398:1;32790:20:0;;;;;;;;;34921:48;;;;;;;;-1:-1:-1;;;;;7329:32:1;;;7311:51;;7299:2;7284:18;34921:48:0;7142:226:1;35240:39:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;35240:39:0;;;;;;;;;;;;-1:-1:-1;;;35240:39:0;;;;;;;;;;;;;-1:-1:-1;;;;;7740:15:1;;;7722:34;;7792:15;;;7787:2;7772:18;;7765:43;7844:15;;;;7824:18;;;7817:43;;;;7908:4;7896:17;;;;7891:2;7876:18;;7869:45;7945:3;7930:19;;7923:35;7702:3;7974:19;;7967:35;8033:3;8018:19;;8011:35;;;;7671:3;7656:19;35240:39:0;7373:679:1;35576:45:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;62915:172;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;34845:32::-;;;;;35679:48;;;;;;:::i;:::-;;;;;;;;;;;;;;42582:423;;;;;;:::i;:::-;;:::i;61508:220::-;;;;;;:::i;:::-;;:::i;58117:2048::-;;;;;;:::i;:::-;;:::i;43822:279::-;;;;;;:::i;:::-;;:::i;43607:112::-;;;;;;:::i;:::-;;:::i;62630:113::-;62688:12;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62688:12:0;62720:15;;;;:6;:15;;;;;;;;;62713:22;;;;;;;;;-1:-1:-1;;;;;62713:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;62713:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62720:15;;62713:22;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;62713:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;62630:113;;;:::o;64492:117::-;64541:7;34599;64569:23;34599:7;64569:15;:23;:::i;:::-;64568:33;;;;:::i;:::-;64561:40;;64492:117;:::o;42291:283::-;42376:7;42401:17;42421:7;-1:-1:-1;;;;;42421:17:0;;42439:4;42453:15;42421:49;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42401:69;-1:-1:-1;42501:65:0;42508:4;-1:-1:-1;;;;;42514:23:0;;:42;;42552:4;42514:42;;;42540:9;42514:42;42558:7;42501:6;:65::i;:::-;42481:85;;;42291:283;;;;;:::o;63516:157::-;63606:13;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;63606:13:0;-1:-1:-1;63644:21:0;;;;:12;:21;;;;;;;;;63637:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63516:157::o;60275:1090::-;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;;;;;;;;;7211:1;7202:6;:10;;;36369:11;;;:6:::1;:11;::::0;;;;:19:::1;;::::0;:11;;-1:-1:-1;;;;;36369:19:0::1;36355:10;:33;36351:65;;36397:19;;-1:-1:-1::0;;;36397:19:0::1;;;;;;;;;;;36351:65;60504:19:::2;60526:15:::0;;;:6:::2;:15;::::0;;;;;;;60580:18;;::::2;::::0;60558::::2;:16;:18::i;:::-;:40;;:52;;;-1:-1:-1::0;60602:8:0::2;::::0;::::2;;60558:52;60554:804;;;60627:16;60689:26:::0;;;:17:::2;:26;::::0;;;;;;;60658:57;;::::2;::::0;::::2;::::0;;;;::::2;;::::0;;;;::::2;::::0;;;::::2;::::0;::::2;::::0;::::2;::::0;;;;;::::2;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;::::2;::::0;;;;;;;;;;60627:16;;60658:57;60689:26;;60658:57;;;;;;;;;::::2;::::0;;;::::2;;;;;;;;;;;;;;;;::::0;;-1:-1:-1;;;;;60658:57:0::2;::::0;;;;;::::2;::::0;::::2;;::::0;;::::2;;;;;;;;;;;::::0;::::2;;;60734:13;:31;;;60769:1;60734:36;60730:390;;60878:22;::::0;;;:13:::2;:22;::::0;;;;;;;;60823:31;;::::2;::::0;:77:::2;::::0;60878:22;60823:77:::2;:::i;:::-;60926:26;::::0;;;:17:::2;:26;::::0;;;;;;60919:33;;-1:-1:-1;;60919:33:0::2;::::0;;;;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;::::2;::::0;;;60791:109;;-1:-1:-1;60919:33:0::2;::::0;;::::2;60926:26:::0;60919:33:::2;:::i;:::-;;;60730:390;;;61082:22;::::0;;;:13:::2;:22;::::0;;;;;;;;61025:6:::2;:15:::0;;;;;;:33:::2;;::::0;:79:::2;::::0;61082:22;61025:79:::2;:::i;:::-;60993:111;;60730:390;61225:13;::::0;::::2;::::0;61193:17:::2;::::0;::::2;::::0;61187:62:::2;::::0;-1:-1:-1;;;;;61193:17:0;;::::2;::::0;61225:13:::2;61240:8:::0;61187:37:::2;:62::i;:::-;61271:15;::::0;;;:6:::2;:15;::::0;;;;;;;;:23:::2;;61264:30:::0;;-1:-1:-1;;;;;;61264:30:0::2;::::0;;61316;;11919:25:1;;;11960:18;;;11953:34;;;61316:30:0::2;::::0;11892:18:1;61316:30:0::2;;;;;;;60612:746;;60554:804;-1:-1:-1::0;;7248:1:0;7239:6;:10;-1:-1:-1;60275:1090:0:o;44214:497::-;44296:92;;-1:-1:-1;;;44296:92:0;;44276:17;;-1:-1:-1;;;;;44296:7:0;:17;;;;:92;;44328:10;;44361:15;;44296:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44276:112;-1:-1:-1;;;;;;44411:23:0;;:48;;44449:10;44411:48;;;44437:9;44411:48;44399:60;-1:-1:-1;44489:3:0;44472:14;44512:192;44536:6;44532:1;:10;44512:192;;;44561:10;44574:3;;44578:1;44574:6;;;;;;;:::i;:::-;;;;;;;44561:19;;44595:33;44602:10;44614:9;44625:2;44595:6;:33::i;:::-;-1:-1:-1;;44674:3:0;;44512:192;;;;44265:446;;44214:497;;:::o;43148:364::-;43198:7;43218:17;43238:7;-1:-1:-1;;;;;43238:17:0;;43270:10;43303:15;43238:92;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43218:112;-1:-1:-1;43361:143:0;43386:10;-1:-1:-1;;;;;43415:23:0;;:48;;43453:10;43415:48;;43361:143;43341:163;43148:364;-1:-1:-1;;;43148:364:0:o;61736:136::-;61776:10;-1:-1:-1;;;;;61798:7:0;61776:30;;61772:66;;61815:23;;-1:-1:-1;;;61815:23:0;;;;;;;;;;;61772:66;61860:4;61849:15;;-1:-1:-1;;61849:15:0;;;;;61736:136::o;63213:182::-;63362:15;;;;:6;:15;;;;;;;;;:25;;63355:32;;;;;;;;;;;;;;;;;63321:16;;63355:32;;;63362:25;63355:32;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63355:32:0;;;;;;;;;;;;;;;;;;;;;;;63213:182;;;:::o;39702:2446::-;40020:18;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;36480:8:::1;::::0;::::1;;36476:29;;;36497:8;;-1:-1:-1::0;;;36497:8:0::1;;;;;;;;;;;36476:29;-1:-1:-1::0;;;;;40055:25:0;::::2;40051:52;;40089:14;;-1:-1:-1::0;;;40089:14:0::2;;;;;;;;;;;40051:52;40118:34;::::0;-1:-1:-1;;;40118:34:0;;-1:-1:-1;;;;;7329:32:1;;;40118:34:0::2;::::0;::::2;7311:51:1::0;40155:1:0::2;::::0;40118:15:::2;:27:::0;;::::2;::::0;::::2;::::0;7284:18:1;;40118:34:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:38;;;40158:17;40114:61;34800:1;40190:32;::::0;::::2;;40186:85;;;40244:27;;-1:-1:-1::0;;;40244:27:0::2;;;;;;;;;;;40186:85;40286:22:::0;;;:47:::2;;-1:-1:-1::0;40312:21:0;;40286:47:::2;40282:86;;;40355:13;;-1:-1:-1::0;;;40355:13:0::2;;;;;;;;;;;40282:86;40432:131;-1:-1:-1::0;;;;;40432:35:0;::::2;40482:10;40515:4;40535:17:::0;40432:35:::2;:131::i;:::-;-1:-1:-1::0;40694:6:0::2;::::0;;40717:8:::2;::::0;;::::2;::::0;;;40694:6;40719::::2;::::0;40775:85:::2;::::0;:17;;:85:::2;::::0;::::2;:28;:85::i;:::-;40749:111;;40871:21;40895:18;:16;:18::i;:::-;40871:42;;40947:373;;;;;;;;40975:5;-1:-1:-1::0;;;;;40947:373:0::2;;;;;41004:7;-1:-1:-1::0;;;;;40947:373:0::2;;;;;41039:11;-1:-1:-1::0;;;;;40947:373:0::2;;;;;41082:15;40947:373;;;;;;34599:7;41144:15;41162:1;41144:19;;;;:::i;:::-;41143:29;;;;;;:::i;:::-;41126:47;::::0;:13;:47:::2;:::i;:::-;40947:373;;;;41206:16;40947:373;;;;41256:17;40947:373;;;;41299:9;;40947:373;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;-1:-1:-1;40947:373:0;;;;-1:-1:-1;;40926:18:0;;;:6:::2;:18;::::0;;;;;;;;:394;;;;-1:-1:-1;;;;;40926:394:0;;::::2;-1:-1:-1::0;;;;;;40926:394:0;;::::2;;::::0;;;;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;;;::::2;;::::0;;;;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;;-1:-1:-1::0;;;40926:394:0::2;-1:-1:-1::0;;;;;;40926:394:0;;;;;;::::2;::::0;;;;;;;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;::::2;::::0;;;:18;;-1:-1:-1;40926:394:0::2;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;;41338:265:0::2;::::0;;-1:-1:-1;;;;;13200:32:1;;;13182:51;;13281:4;13269:17;;13264:2;13249:18;;13242:45;13303:18;;;13296:34;;;13361:2;13346:18;;13339:34;;;13404:3;13389:19;;13382:35;;;13461:14;;13454:22;13220:3;13433:19;;13426:51;41338:265:0;;::::2;::::0;-1:-1:-1;41338:265:0;;::::2;::::0;41365:10;;41338:265:::2;::::0;13169:3:1;13154:19;41338:265:0::2;;;;;;;41652:25;::::0;;;:13:::2;:25;::::0;;;;;;;:39;;-1:-1:-1;;41652:39:0::2;::::0;::::2;;;::::0;;41768:99;;::::2;::::0;::::2;::::0;;;;;;;::::2;41805:21;34599:7;41805:13:::0;:21:::2;:::i;:::-;41768:99:::0;;::::2;::::0;;::::2;::::0;;;-1:-1:-1;41741:24:0;;;:12:::2;:24:::0;;;;;;:126;;;;-1:-1:-1;;41741:126:0::2;;::::0;;::::2;;::::0;;;;::::2;::::0;-1:-1:-1;41741:126:0;::::2;::::0;;;;::::2;::::0;::::2;::::0;;::::2;::::0;41945:9;;41972:169:::2;41996:6;41992:1;:10;41972:169;;;42021:25;::::0;;;:13:::2;:25;::::0;;;;42063:4:::2;::::0;42047:9;;42057:1;42047:12;;::::2;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;42021:39:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;42021:39:0;:46;;-1:-1:-1;;42021:46:0::2;::::0;::::2;;::::0;;;::::2;::::0;;-1:-1:-1;42111:3:0::2;41972:169;;;;40040:2108;;;36516:1;7248::::0;7239:6;:10;39702:2446;;-1:-1:-1;;;;;;;;;39702:2446:0:o;52277:3676::-;52377:14;52413:22;;;:13;:22;;;;;;;;-1:-1:-1;;;;;52413:28:0;;;;;;;;;;;;52409:42;;;-1:-1:-1;52450:1:0;52443:8;;52409:42;52464:18;52485:15;;;:6;:15;;;;;;;;52464:36;;;;;;;;;-1:-1:-1;;;;;52464:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52464:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52485:15;;52464:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52464:36:0;;;;;;;;;;;;;;;;-1:-1:-1;;;52464:36:0;;;;-1:-1:-1;;;52598:29:0;52630:26;;;:17;:26;;;;;52464:36;;-1:-1:-1;52742:18:0;:16;:18::i;:::-;52718:42;;52811:20;52834:89;52853:5;:18;;;52886:13;:26;;;52834:4;:89::i;:::-;53031:11;;52994:49;;-1:-1:-1;;;52994:49:0;;52811:112;;-1:-1:-1;52975:16:0;;-1:-1:-1;;;;;52994:15:0;:30;;;;:49;;53025:4;;52994:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53155:11;;53102:65;;-1:-1:-1;;;53102:65:0;;52975:68;;-1:-1:-1;53056:43:0;;-1:-1:-1;;;;;53102:15:0;:46;;;;:65;;53149:4;;53102:65;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53198:15;;53056:111;;-1:-1:-1;53198:20:0;;:82;;-1:-1:-1;;;;;;53235:19:0;;;;;;:13;:19;;;;;;;;:28;;;;;;;;;:45;-1:-1:-1;53235:45:0;53198:82;:129;;;;53314:9;:13;;;53297;:30;;53198:129;:171;;;;53361:8;53344:13;:25;;53198:171;:217;;;;53403:12;53386:13;:29;;53198:217;:284;;;;53448:24;53464:7;53448:15;:24::i;:::-;:34;;;53432:13;:50;53198:284;:350;;;-1:-1:-1;53525:23:0;;;;53499:22;;;;:13;:22;;;;;;:49;;53198:350;53180:388;;;53567:1;53560:8;;;;;;;;;;53180:388;53581:22;53606;;;:13;:22;;;;;;53688:19;;;:128;;;53742:1;53725:14;:18;:90;;;;;53802:13;53764:24;53780:7;53764:15;:24::i;:::-;:34;;;:51;;53725:90;53670:1200;;;53888:29;;53843:24;;53888:29;;:34;53884:254;;54016:30;;;;53991:22;;;:55;54091:31;;;;54065:23;;;:57;53884:254;54154:19;54191:13;54176:12;:28;:107;;54282:1;54176:107;;;34599:7;54225:28;54240:13;54225:12;:28;:::i;:::-;54224:38;;;;:::i;:::-;54343:22;;;;:13;:22;;;;;;54317:23;;;;54154:129;;-1:-1:-1;54317:48:0;;;:::i;:::-;54298:67;-1:-1:-1;54401:21:0;34599:7;54401:13;:21;:::i;:::-;54386:12;:36;:55;;;;;54440:1;54426:11;:15;54386:55;54382:158;;;54481:43;:16;54509:1;54512:11;54481:27;:43::i;:::-;54462:62;;54382:158;54629:17;54649:127;54684:5;:11;;;54714:5;:15;;;54748:13;54649:16;:127::i;:::-;54629:147;-1:-1:-1;54808:50:0;:16;34705:4;54629:147;54808:27;:50::i;:::-;54791:67;;53828:1042;;;53670:1200;54915:13;54931:109;54958:9;:15;;;54988:9;:13;;;55016;54931:12;:109::i;:::-;54915:125;-1:-1:-1;55109:32:0;54915:125;55126:14;55109:16;:32::i;:::-;55100:41;;55233:27;55263:40;55280:5;:22;;;55263:5;:16;;:40;;;;:::i;:::-;55233:70;;55401:33;55406:6;55414:19;55401:4;:33::i;:::-;55447:22;55472;;;:13;:22;;;;;;55574:23;;;;55392:42;;-1:-1:-1;55472:22:0;55548:23;55472:22;55392:42;55548:23;:::i;:::-;:49;55544:131;;;55649:14;55623:5;:23;;;:40;;;;:::i;:::-;55614:49;;55544:131;55760:52;;-1:-1:-1;;;55760:52:0;;-1:-1:-1;;;;;55795:15:0;7329:32:1;;55760:52:0;;;7311:51:1;-1:-1:-1;;55760:7:0;:26;;;;;;7284:18:1;;55760:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;55735:97:0;;:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;55713:121;-1:-1:-1;55849:16:0;;55845:101;;55891:43;55909:24;55922:11;34705:4;55909:24;:::i;:::-;55891:6;;:17;:43::i;:::-;55882:52;;55845:101;52398:3555;;;;;;;;;;;52277:3676;;;;:::o;62162:362::-;62251:19;62310:15;;;:6;:15;;;;;62251:19;62362:18;:16;:18::i;:::-;62338:42;;62426:13;62405:5;:18;;;:34;:111;;62515:1;62405:111;;;34599:7;62477:13;62456:5;:18;;;:34;;;;:::i;:::-;62455:44;;;;:::i;:::-;62391:125;62162:362;-1:-1:-1;;;;62162:362:0:o;63778:627::-;63876:5;63921:15;;;:6;:15;;;;;63876:5;63973:18;:16;:18::i;:::-;63949:42;;64002:19;64045:13;64024:5;:18;;;:34;:111;;64134:1;64024:111;;;34599:7;64096:13;64075:5;:18;;;:34;;;;:::i;:::-;64074:44;;;;:::i;:::-;64277:21;;;;64002:133;;-1:-1:-1;;;;64277:21:0;;;;64263:35;;:119;;64347:21;;;;:35;;64371:11;;-1:-1:-1;;;64347:21:0;;;;:35;:::i;:::-;64263:119;;;64322:1;64263:119;64219:178;63778:627;-1:-1:-1;;;;;63778:627:0:o;62915:172::-;63014:14;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63014:14:0;63053:26;;;;:17;:26;;;;;;;;;63046:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63053:26;;63046:33;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63046:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;62915:172;;;:::o;42582:423::-;42681:49;;-1:-1:-1;;;42681:49:0;;42661:17;;-1:-1:-1;;;;;42681:7:0;:17;;;;:49;;42699:4;;42713:15;;42681:49;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42661:69;-1:-1:-1;42758:3:0;42741:14;42781:217;42805:6;42801:1;:10;42781:217;;;42830:10;42843:3;;42847:1;42843:6;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;42864:60:0;;-1:-1:-1;42871:4:0;-1:-1:-1;;;;;42877:23:0;;:42;;42915:4;42877:42;;;42903:9;42877:42;42921:2;42864:6;:60::i;:::-;-1:-1:-1;;42968:3:0;;42781:217;;;;42650:355;;42582:423;;;:::o;61508:220::-;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;;;36369:11;;;:6:::1;:11;::::0;;;;:19:::1;;::::0;:11;;-1:-1:-1;;;;;36369:19:0::1;36355:10;:33;36351:65;;36397:19;;-1:-1:-1::0;;;36397:19:0::1;;;;;;;;;;;36351:65;61683:15:::2;::::0;;;:6:::2;:15;::::0;;;;;;;;:23:::2;;:36:::0;;-1:-1:-1;;;;;;61683:36:0::2;-1:-1:-1::0;;;;;61683:36:0;::::2;::::0;;::::2;::::0;;;61659:61;;1964:25:1;;;61659:61:0::2;::::0;1937:18:1;61659:61:0::2;;;;;;;-1:-1:-1::0;;7248:1:0;7239:6;:10;-1:-1:-1;61508:220:0:o;58117:2048::-;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;36480:8:::1;::::0;::::1;;36476:29;;;36497:8;;-1:-1:-1::0;;;36497:8:0::1;;;;;;;;;;;36476:29;36369:11:::2;::::0;;;:6:::2;:11;::::0;;;;:19:::2;;::::0;:11;;-1:-1:-1;;;;;36369:19:0::2;36355:10;:33;36351:65;;36397:19;;-1:-1:-1::0;;;36397:19:0::2;;;;;;;;;;;36351:65;58412:23:::3;::::0;;;:13:::3;:23;::::0;;;;;::::3;;58407:54;;58444:17;;-1:-1:-1::0;;;58444:17:0::3;;;;;;;;;;;58407:54;58503:1;58476:24;58491:8;58476:14;:24::i;:::-;:28;58472:58;;;58513:17;;-1:-1:-1::0;;;58513:17:0::3;;;;;;;;;;;58472:58;58545:21:::0;;;:49:::3;;-1:-1:-1::0;58570:24:0;;58545:49:::3;58541:88;;;58616:13;;-1:-1:-1::0;;;58616:13:0::3;;;;;;;;;;;58541:88;58642:19;58664:16:::0;;;:6:::3;:16;::::0;;;;;;;58722:17:::3;:27:::0;;;;;;58691:58;;::::3;::::0;::::3;::::0;;;;::::3;;::::0;;;;::::3;::::0;;;::::3;::::0;::::3;::::0;::::3;::::0;;;;;;;::::3;::::0;;;;;;;::::3;::::0;;;;;;::::3;::::0;;;;;;;;;;58664:16;;58642:19;58691:58;58722:27;;58691:58;;;;;;;::::3;::::0;;;::::3;;;;;;;;;;;;;;;;::::0;;-1:-1:-1;;;;;58691:58:0::3;::::0;;;;;::::3;::::0;::::3;;::::0;;::::3;;;;-1:-1:-1::0;;;58691:58:0;;;;-1:-1:-1;;;58768:17:0::3;::::0;::::3;::::0;58691:58;;-1:-1:-1;58762:136:0::3;::::0;-1:-1:-1;;;;;58768:17:0::3;58818:10;58851:4;58871:16:::0;58762:41:::3;:136::i;:::-;58915:31;::::0;::::3;::::0;:36;58911:988:::3;;58984:460;;;;;;;;59081:19;59028:13;:29;;;:72;;;;:::i;:::-;58984:460;;;;;;59193:16;59138:13;:31;;;:71;;;;:::i;:::-;58984:460:::0;;::::3;::::0;::::3;::::0;;;;;59349:27:::3;34599:7;59349:27;::::0;::::3;;:::i;:::-;59298:13;:26;;;:79;;;;:::i;:::-;58984:460;;;;59407:21;;58984:460;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;::::0;;;;-1:-1:-1;;;58984:460:0;;-1:-1:-1;58968:476:0;-1:-1:-1;58911:988:0::3;;;59493:394;;;;;;;;59561:19;59537:5;:21;;;;;;;;;;;;:43;;;;:::i;:::-;59493:394;;;;;;59644:16;59618:5;:23;;;:42;;;;:::i;:::-;59493:394:::0;;::::3;::::0;::::3;::::0;;;;;59792:27:::3;34599:7;59792:27;::::0;::::3;;:::i;:::-;59749:5;:18;;;:71;;;;:::i;:::-;59493:394;;;;59850:21;;59493:394;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;::::0;;;;-1:-1:-1;;;59493:394:0;;-1:-1:-1;59477:410:0;-1:-1:-1;58911:988:0::3;59911:27;::::0;;;:17:::3;:27;::::0;;;;;;;;:43;;;;-1:-1:-1;;59911:43:0::3;;::::0;;::::3;;::::0;;;;::::3;::::0;-1:-1:-1;59911:43:0;::::3;::::0;;;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;::::3;::::0;;;;;:27;:43:::3;::::0;;;::::3;::::0;::::3;::::0;::::3;:::i;:::-;-1:-1:-1::0;;60037:29:0;;60081:31:::3;::::0;;::::3;::::0;59972:185:::3;::::0;;14819:25:1;;;14892:4;14880:17;;;14860:18;;;14853:45;;;;14914:18;;;14907:34;14972:2;14957:18;;14950:34;;;59972:185:0::3;::::0;-1:-1:-1;14806:3:1;14791:19;59972:185:0::3;;;;;;;-1:-1:-1::0;;7248:1:0;7239:6;:10;-1:-1:-1;;;;;;;58117:2048:0:o;43822:279::-;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;;;43924:3;;43945:149:::1;43969:6;43965:1;:10;43945:149;;;43994:26;44013:3;;44017:1;44013:6;;;;;;;:::i;:::-;;;;;;;43994:18;:26::i;:::-;-1:-1:-1::0;44064:3:0::1;;43945:149;;;-1:-1:-1::0;;7248:1:0;7239:6;:10;-1:-1:-1;;43822:279:0:o;43607:112::-;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;43684:27:::1;43703:7:::0;43684:18:::1;:27::i;:::-;-1:-1:-1::0;;7248:1:0;7239:6;:10;43607:112::o;45065:2789::-;45206:14;7163:6;;7173:1;7163:11;7155:34;;;;-1:-1:-1;;;7155:34:0;;;;;;;:::i;:::-;7211:1;7202:6;:10;36480:8:::1;::::0;::::1;;36476:29;;;36497:8;;-1:-1:-1::0;;;36497:8:0::1;;;;;;;;;;;36476:29;45237:22:::2;::::0;;;:13:::2;:22;::::0;;;;;;;-1:-1:-1;;;;;45237:28:0;::::2;::::0;;;;;;;;::::2;;45233:42;;;-1:-1:-1::0;45274:1:0::2;45267:8;;45233:42;45335:21;45359:27;45378:7;45359:18;:27::i;:::-;45399:19;45421:15:::0;;;:6:::2;:15;::::0;;;;;45546:11;;45509:49;;-1:-1:-1;;;45509:49:0;;45335:51;;-1:-1:-1;45421:15:0;-1:-1:-1;;;;;45509:15:0::2;:30:::0;::::2;::::0;::::2;::::0;:49:::2;::::0;45540:4;;45546:11:::2;::::0;45509:49:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45670:11:::0;;45617:65:::2;::::0;-1:-1:-1;;;45617:65:0;;45490:68;;-1:-1:-1;45571:43:0::2;::::0;-1:-1:-1;;;;;45617:15:0::2;:46:::0;::::2;::::0;::::2;::::0;:65:::2;::::0;45664:4;;45670:11:::2;::::0;45617:65:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;45713:15:::0;;45571:111;;-1:-1:-1;45713:20:0;;:82:::2;;-1:-1:-1::0;;;;;;45750:19:0;::::2;;::::0;;;:13:::2;:19;::::0;;;;;;;:28;;;;;;;;;:45;-1:-1:-1;45750:45:0::2;45713:82;:129;;;;45829:9;:13;;;45812;:30;;45713:129;:171;;;;45876:8;45859:13;:25;;45713:171;:223;;;;45918:5;:18;;;45901:13;:35;;45713:223;:275;;;;45970:18;:16;:18::i;:::-;45953:13;:35;;45713:275;:341;;;-1:-1:-1::0;46031:23:0::2;::::0;::::2;::::0;46005:22:::2;::::0;;;:13:::2;:22;::::0;;;;;:49:::2;45713:341;45695:379;;;46073:1;46066:8;;;;;;;;45695:379;-1:-1:-1::0;;;;;46130:19:0;::::2;;::::0;;;:13:::2;:19;::::0;;;;;;;:28;;;;;;;;;:44;;;46313:15;;46343:13;;::::2;::::0;46286:109:::2;::::0;46313:15;46161:13;46286:12:::2;:109::i;:::-;46513:22;::::0;;;:13:::2;:22;::::0;;;;;46270:125;;-1:-1:-1;46496:40:0::2;::::0;46270:125;;46496:16:::2;:40::i;:::-;46487:49;;46628:27;46658:40;46675:5;:22;;;46658:5;:16;;:40;;;;:::i;:::-;46628:70;;46796:33;46801:6;46809:19;46796:4;:33::i;:::-;46881:22;46906::::0;;;:13:::2;:22;::::0;;;;;46971:23:::2;::::0;::::2;::::0;46787:42;;-1:-1:-1;46906:22:0;46945:23:::2;46906:22:::0;46787:42;46945:23:::2;:::i;:::-;:49;46941:131;;;47046:14;47020:5;:23;;;:40;;;;:::i;:::-;47011:49;;46941:131;47084:22;::::0;;;:13:::2;:22;::::0;;;;:32;;47110:6;;47084:22;:32:::2;::::0;47110:6;;47084:32:::2;:::i;:::-;::::0;;;-1:-1:-1;;47178:76:0::2;::::0;-1:-1:-1;;;47178:76:0;;-1:-1:-1;;;;;47227:15:0::2;7329:32:1::0;;47178:76:0::2;::::0;::::2;7311:51:1::0;-1:-1:-1;;;;47178:7:0::2;:26;::::0;::::2;::::0;7284:18:1;;47178:76:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47157:97;;47265:19;47298:10;-1:-1:-1::0;;;;;47287:31:0::2;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47265:55:::0;-1:-1:-1;47337:16:0;;47333:233:::2;;47382:30;:6:::0;47400:11;47382:17:::2;:30::i;:::-;47370:42:::0;-1:-1:-1;47427:19:0::2;47370:42:::0;47427:19;::::2;:::i;:::-;47500:17;::::0;::::2;::::0;47427:19;;-1:-1:-1;47494:60:0::2;::::0;-1:-1:-1;;;;;47500:17:0::2;47532:10:::0;47544:9;47494:37:::2;:60::i;:::-;47614:17;::::0;::::2;::::0;47608:56:::2;::::0;-1:-1:-1;;;;;47614:17:0::2;47646:9:::0;47657:6;47608:37:::2;:56::i;:::-;47755:7;47723:5;:17;;;;;;;;;;-1:-1:-1::0;;;;;47723:17:0::2;-1:-1:-1::0;;;;;47682:164:0::2;47704:4;-1:-1:-1::0;;;;;47682:164:0::2;;47777:6;47798:9;47822:13;47682:164;;;;;;;15197:25:1::0;;;15253:2;15238:18;;15231:34;;;;15296:2;15281:18;;15274:34;15185:2;15170:18;;14995:319;47682:164:0::2;;;;;;;;45222:2632;;;;;;;;;;36516:1;7248::::0;7239:6;:10;45065:2789;;-1:-1:-1;;;45065:2789:0:o;27350:1529::-;27467:12;27642:4;27636:11;-1:-1:-1;;;27768:17:0;27761:93;27902:2;27898:1;27879:17;27875:25;27868:37;27983:6;27978:2;27959:17;27955:26;27948:42;28795:2;28792:1;28788:2;28769:17;28766:1;28759:5;28752;28747:51;28311:16;28304:24;28298:2;28280:16;28277:24;28273:1;28269;28263:8;28260:15;28256:46;28253:76;28050:763;28039:774;;;28844:7;28836:35;;;;-1:-1:-1;;;28836:35:0;;15521:2:1;28836:35:0;;;15503:21:1;15560:2;15540:18;;;15533:30;-1:-1:-1;;;15579:18:1;;;15572:45;15634:18;;28836:35:0;15319:339:1;28836:35:0;27456:1423;27350:1529;;;:::o;25694:1648::-;25838:12;26013:4;26007:11;-1:-1:-1;;;26139:17:0;26132:93;26273:4;26269:1;26250:17;26246:25;26239:39;26358:2;26353;26334:17;26330:26;26323:38;26439:6;26434:2;26415:17;26411:26;26404:42;27253:2;27250:1;27245:3;27226:17;27223:1;27216:5;27209;27204:52;26767:16;26760:24;26754:2;26736:16;26733:24;26729:1;26725;26719:8;26716:15;26712:46;26709:76;26506:765;26495:776;;;27302:7;27294:40;;;;-1:-1:-1;;;27294:40:0;;15865:2:1;27294:40:0;;;15847:21:1;15904:2;15884:18;;;15877:30;-1:-1:-1;;;15923:18:1;;;15916:50;15983:18;;27294:40:0;15663:344:1;8792:541:0;8912:9;9164:1;-1:-1:-1;;9147:19:0;9144:1;9141:26;9138:1;9134:34;9127:42;9114:11;9110:60;9100:118;;9201:1;9198;9191:12;9100:118;-1:-1:-1;9292:9:0;;9288:27;;8792:541::o;64978:109::-;65036:11;65070:1;65066;:5;:13;;65078:1;65066:13;;;-1:-1:-1;65074:1:0;65060:19;-1:-1:-1;64978:109:0:o;56439:1228::-;56593:17;56657:43;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;56657:43:0;56862:28;;56975:44;;-1:-1:-1;;;56975:44:0;;-1:-1:-1;;;;;16204:32:1;;;56975:44:0;;;16186:51:1;16253:18;;;16246:34;;;56728:13:0;;;;56862:28;;56975:15;:29;;;;16159:18:1;;56975:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:49;;-1:-1:-1;56975:49:0;57037:623;57061:6;57057:1;:10;57037:623;;;57134:15;-1:-1:-1;;;;;57134:32:0;;57185:21;57207:1;57185:24;;;;;;;;:::i;:::-;;;;;;;57228:5;57134:114;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57122:126;;57275:15;-1:-1:-1;;;;;57275:30:0;;57324:21;57346:1;57324:24;;;;;;;;:::i;:::-;;;;;;;57367:5;57275:112;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57263:124;;57415:9;57406:6;:18;57402:156;;;57453:52;57466:9;:15;;;57483:9;:13;;;57498:6;57453:12;:52::i;:::-;57445:60;-1:-1:-1;57524:18:0;57445:60;57524:18;;:::i;:::-;;;57402:156;57630:3;;57037:623;;;;56612:1055;;;;56439:1228;;;;;:::o;65340:279::-;65482:7;65531:11;65506:21;34599:7;65506:13;:21;:::i;:::-;:36;65502:50;;-1:-1:-1;65551:1:0;65544:8;;65502:50;65583:27;65597:13;65583:11;:27;:::i;:::-;65570:41;;:9;:41;:::i;7912:166::-;7977:7;8004:21;8015:1;8018;7861:4;8004:10;:21::i;64739:109::-;64797:11;64831:1;64827;:5;:13;;64839:1;64827:13;;;-1:-1:-1;64835:1:0;;64821:19;-1:-1:-1;64739:109:0:o;47999:1030::-;48062:7;48113:21;;;:12;:21;;;;;48062:7;48171:18;:16;:18::i;:::-;48206:16;;48147:42;;-1:-1:-1;48206:16:0;;:21;:65;;;;;48248:13;:23;;;48231:13;:40;48206:65;48202:399;;;48387:15;;;;:6;:15;;;;;;;:21;48354:55;;-1:-1:-1;;;48354:55:0;;-1:-1:-1;;;;;48387:21:0;;;48354:55;;;7311:51:1;48354:15:0;:32;;;;;;7284:18:1;;48354:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48544:45;48566:7;48575:13;48544:21;:45::i;:::-;34599:7;48664:13;:23;;;:31;;;;:::i;:::-;48645:15;:50;48641:338;;48811:15;;;;:6;:15;;;;;;;:21;48778:55;;-1:-1:-1;;;48778:55:0;;-1:-1:-1;;;;;48811:21:0;;;48778:55;;;7311:51:1;48778:15:0;:32;;;;;;7284:18:1;;48778:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48885:45;48907:7;48916:13;48885:21;:45::i;48641:338::-;-1:-1:-1;48998:23:0;;;;47999:1030;-1:-1:-1;;47999:1030:0:o;51340:548::-;51449:22;;;;:13;:22;;;;;;:27;;51445:436;;51493:17;51548:15;;;:6;:15;;;;;;;;:21;;51588:25;;;;51513:147;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51548:21:0;;;;51513:147;;;51588:25;51513:147;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;51513:147:0;;;;;;;;;;;;;;;;;;;;;51632:13;51513:16;:147::i;:::-;51493:167;-1:-1:-1;51679:14:0;;51675:195;;51739:21;;;;:12;:21;;;;;:59;;;:115;;34705:4;51844:9;51739:92;:115::i;:::-;51714:22;;;;:13;:22;;;;;:140;51675:195;51478:403;51445:436;51340:548;;:::o;49167:2032::-;49272:11;49286:32;49310:7;49286:23;:32::i;:::-;49331:29;49363:26;;;:17;:26;;;;;49457:31;;;;49272:46;;-1:-1:-1;49363:26:0;49457:36;49453:862;;49577:29;;;49543:15;;;:6;:15;;;;;;;;:31;;;;:63;;-1:-1:-1;;;;49543:63:0;49577:29;;;;-1:-1:-1;;;49543:63:0;;;;;;;;-1:-1:-1;49657:31:0;;;49621:33;;;:67;49738:30;;;;49703:32;;;;:65;;;;49814:26;;;;49783:28;;;;:57;;;;49861:23;;:30;:34;49857:126;;49916:15;;;;:6;:15;;;;;49944:23;;;49916:51;;;;:25;;;49944:23;49916:51;:::i;:::-;;49857:126;50071:29;;;50119:31;;;50169:30;;;;50004:210;;;14819:25:1;;;50071:29:0;;;;14875:2:1;14860:18;;14853:45;14914:18;;14907:34;;;;14972:2;14957:18;;14950:34;50004:210:0;;14806:3:1;14791:19;50004:210:0;;;;;;;50277:26;;;;:17;:26;;;;;;;50270:33;;-1:-1:-1;;50270:33:0;;;;;;;;;;;;;;;;;;;;;50277:26;;50270:33;;;;50277:26;50270:33;:::i;:::-;;;49453:862;50327:19;50349:15;;;:6;:15;;;;;;50399:23;50356:7;50399:14;:23::i;:::-;50433;50511:22;;;:13;:22;;;;;;50485:23;;;;50377:45;;-1:-1:-1;50433:23:0;;50485:48;;50511:22;50485:48;:::i;:::-;50467:66;-1:-1:-1;50571:21:0;34599:7;50571:13;:21;:::i;:::-;50550:5;:18;;;:42;:61;;;;;50610:1;50596:11;:15;50550:61;50546:154;;;50646:42;:15;50673:1;50676:11;50646:26;:42::i;:::-;50628:60;;50546:154;50825:11;;50851:15;;;50794:111;;;;;;;;;;;;;;;;;;;50774:17;;50794:111;;-1:-1:-1;;;;;50825:11:0;;;;50794:111;;50851:15;;50794:111;;;50851:15;50794:111;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50794:111:0;;;;;;;;;;;;;;;;;;;;;50881:13;50794:16;:111::i;:::-;50774:131;-1:-1:-1;50943:86:0;:15;34705:4;50774:131;50943:26;:86::i;:::-;50918:22;;;;:13;:22;;;;;;;;:111;;;;51064:45;;;;;;;;;;;;;;;;;;;;;;;;;51040:21;;;:12;:21;;;;;;;:69;;;;;;-1:-1:-1;;51040:69:0;;;;;;;;;;;;;;;;;;51127:64;;;;;50932:7;;51071:5;;51078:13;;51093:15;;14819:25:1;;;14892:4;14880:17;;;;14875:2;14860:18;;14853:45;14929:2;14914:18;;14907:34;14972:2;14957:18;;14950:34;14806:3;14791:19;;14592:398;51127:64:0;;;;;;;;49261:1938;;;;;;49167:2032;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:180:1;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;165:23:1;;14:180;-1:-1:-1;14:180:1:o;388:461::-;441:3;479:5;473:12;506:6;501:3;494:19;532:4;561:2;556:3;552:12;545:19;;598:2;591:5;587:14;619:1;629:195;643:6;640:1;637:13;629:195;;;708:13;;-1:-1:-1;;;;;704:39:1;692:52;;764:12;;;;799:15;;;;740:1;658:9;629:195;;;-1:-1:-1;840:3:1;;388:461;-1:-1:-1;;;;;388:461:1:o;854:959::-;1029:2;1018:9;1011:21;992:4;1068:1;1064;1059:3;1055:11;1051:19;1125:2;1116:6;1110:13;1106:22;1101:2;1090:9;1086:18;1079:50;1193:2;1187;1179:6;1175:15;1169:22;1165:31;1160:2;1149:9;1145:18;1138:59;;1244:2;1236:6;1232:15;1226:22;1257:52;1305:2;1294:9;1290:18;1276:12;-1:-1:-1;;;;;265:31:1;253:44;;199:104;1257:52;-1:-1:-1;1358:2:1;1346:15;;1340:22;375:4;364:16;;1419:3;1404:19;;352:29;1371:53;1479:3;1471:6;1467:16;1461:23;1455:3;1444:9;1440:19;1433:52;1540:3;1532:6;1528:16;1522:23;1516:3;1505:9;1501:19;1494:52;1601:3;1593:6;1589:16;1583:23;1577:3;1566:9;1562:19;1555:52;1656:3;1648:6;1644:16;1638:23;1680:6;1722:2;1717;1706:9;1702:18;1695:30;;1742:65;1802:3;1791:9;1787:19;1771:14;1742:65;:::i;2000:131::-;-1:-1:-1;;;;;2075:31:1;;2065:42;;2055:70;;2121:1;2118;2111:12;2136:315;2204:6;2212;2265:2;2253:9;2244:7;2240:23;2236:32;2233:52;;;2281:1;2278;2271:12;2233:52;2320:9;2307:23;2339:31;2364:5;2339:31;:::i;:::-;2389:5;2441:2;2426:18;;;;2413:32;;-1:-1:-1;;;2136:315:1:o;3161:367::-;3224:8;3234:6;3288:3;3281:4;3273:6;3269:17;3265:27;3255:55;;3306:1;3303;3296:12;3255:55;-1:-1:-1;3329:20:1;;3372:18;3361:30;;3358:50;;;3404:1;3401;3394:12;3358:50;3441:4;3433:6;3429:17;3417:29;;3501:3;3494:4;3484:6;3481:1;3477:14;3469:6;3465:27;3461:38;3458:47;3455:67;;;3518:1;3515;3508:12;3455:67;3161:367;;;;;:::o;3533:437::-;3619:6;3627;3680:2;3668:9;3659:7;3655:23;3651:32;3648:52;;;3696:1;3693;3686:12;3648:52;3736:9;3723:23;3769:18;3761:6;3758:30;3755:50;;;3801:1;3798;3791:12;3755:50;3840:70;3902:7;3893:6;3882:9;3878:22;3840:70;:::i;:::-;3929:8;;3814:96;;-1:-1:-1;3533:437:1;-1:-1:-1;;;;3533:437:1:o;3975:315::-;4043:6;4051;4104:2;4092:9;4083:7;4079:23;4075:32;4072:52;;;4120:1;4117;4110:12;4072:52;4156:9;4143:23;4133:33;;4216:2;4205:9;4201:18;4188:32;4229:31;4254:5;4229:31;:::i;:::-;4279:5;4269:15;;;3975:315;;;;;:::o;4676:658::-;4847:2;4899:21;;;4969:13;;4872:18;;;4991:22;;;4818:4;;4847:2;5070:15;;;;5044:2;5029:18;;;4818:4;5113:195;5127:6;5124:1;5121:13;5113:195;;;5192:13;;-1:-1:-1;;;;;5188:39:1;5176:52;;5283:15;;;;5248:12;;;;5224:1;5142:9;5113:195;;;-1:-1:-1;5325:3:1;;4676:658;-1:-1:-1;;;;;;4676:658:1:o;5339:156::-;5405:20;;5465:4;5454:16;;5444:27;;5434:55;;5485:1;5482;5475:12;5434:55;5339:156;;;:::o;5500:1234::-;5644:6;5652;5660;5668;5676;5684;5692;5700;5708;5761:3;5749:9;5740:7;5736:23;5732:33;5729:53;;;5778:1;5775;5768:12;5729:53;5817:9;5804:23;5836:31;5861:5;5836:31;:::i;:::-;5886:5;-1:-1:-1;5943:2:1;5928:18;;5915:32;5956:33;5915:32;5956:33;:::i;:::-;6008:7;-1:-1:-1;6067:2:1;6052:18;;6039:32;6080:33;6039:32;6080:33;:::i;:::-;6132:7;-1:-1:-1;6158:36:1;6190:2;6175:18;;6158:36;:::i;:::-;6148:46;;6241:3;6230:9;6226:19;6213:33;6203:43;;6293:3;6282:9;6278:19;6265:33;6255:43;;6349:3;6338:9;6334:19;6321:33;6377:18;6369:6;6366:30;6363:50;;;6409:1;6406;6399:12;6363:50;6448:70;6510:7;6501:6;6490:9;6486:22;6448:70;:::i;:::-;6537:8;;-1:-1:-1;6422:96:1;-1:-1:-1;;6624:3:1;6609:19;;6596:33;6667:15;;6660:23;6648:36;;6638:64;;6698:1;6695;6688:12;6638:64;6721:7;6711:17;;;5500:1234;;;;;;;;;;;:::o;8057:602::-;8236:2;8225:9;8218:21;8294:4;8285:6;8279:13;8275:24;8270:2;8259:9;8255:18;8248:52;8354:2;8346:6;8342:15;8336:22;8331:2;8320:9;8316:18;8309:50;8413:2;8405:6;8401:15;8395:22;8390:2;8379:9;8375:18;8368:50;8473:2;8465:6;8461:15;8455:22;8449:3;8438:9;8434:19;8427:51;8199:4;8525:3;8517:6;8513:16;8507:23;8568:4;8561;8550:9;8546:20;8539:34;8590:63;8648:3;8637:9;8633:19;8619:12;8590:63;:::i;8886:572::-;8981:6;8989;8997;9050:2;9038:9;9029:7;9025:23;9021:32;9018:52;;;9066:1;9063;9056:12;9018:52;9105:9;9092:23;9124:31;9149:5;9124:31;:::i;:::-;9174:5;-1:-1:-1;9230:2:1;9215:18;;9202:32;9257:18;9246:30;;9243:50;;;9289:1;9286;9279:12;9243:50;9328:70;9390:7;9381:6;9370:9;9366:22;9328:70;:::i;:::-;8886:572;;9417:8;;-1:-1:-1;9302:96:1;;-1:-1:-1;;;;8886:572:1:o;9463:713::-;9583:6;9591;9599;9607;9615;9623;9676:3;9664:9;9655:7;9651:23;9647:33;9644:53;;;9693:1;9690;9683:12;9644:53;9729:9;9716:23;9706:33;;9758:36;9790:2;9779:9;9775:18;9758:36;:::i;:::-;9748:46;;9841:2;9830:9;9826:18;9813:32;9803:42;;9892:2;9881:9;9877:18;9864:32;9854:42;;9947:3;9936:9;9932:19;9919:33;9975:18;9967:6;9964:30;9961:50;;;10007:1;10004;9997:12;9961:50;10046:70;10108:7;10099:6;10088:9;10084:22;10046:70;:::i;:::-;9463:713;;;;-1:-1:-1;9463:713:1;;-1:-1:-1;9463:713:1;;10135:8;;9463:713;-1:-1:-1;;;9463:713:1:o;10181:127::-;10242:10;10237:3;10233:20;10230:1;10223:31;10273:4;10270:1;10263:15;10297:4;10294:1;10287:15;10313:217;10353:1;10379;10369:132;;10423:10;10418:3;10414:20;10411:1;10404:31;10458:4;10455:1;10448:15;10486:4;10483:1;10476:15;10369:132;-1:-1:-1;10515:9:1;;10313:217::o;10535:168::-;10608:9;;;10639;;10656:15;;;10650:22;;10636:37;10626:71;;10677:18;;:::i;10708:304::-;-1:-1:-1;;;;;10938:15:1;;;10920:34;;10990:15;;10985:2;10970:18;;10963:43;10870:2;10855:18;;10708:304::o;11017:251::-;11087:6;11140:2;11128:9;11119:7;11115:23;11111:32;11108:52;;;11156:1;11153;11146:12;11108:52;11188:9;11182:16;11207:31;11232:5;11207:31;:::i;11273:334::-;11475:2;11457:21;;;11514:2;11494:18;;;11487:30;-1:-1:-1;;;11548:2:1;11533:18;;11526:40;11598:2;11583:18;;11273:334::o;11612:128::-;11679:9;;;11700:11;;;11697:37;;;11714:18;;:::i;11998:127::-;12059:10;12054:3;12050:20;12047:1;12040:31;12090:4;12087:1;12080:15;12114:4;12111:1;12104:15;12338:279;12407:6;12460:2;12448:9;12439:7;12435:23;12431:32;12428:52;;;12476:1;12473;12466:12;12428:52;12508:9;12502:16;12562:5;12558:2;12547:21;12540:5;12537:32;12527:60;;12583:1;12580;12573:12;12622:148;12710:4;12689:12;;;12703;;;12685:31;;12728:13;;12725:39;;;12744:18;;:::i;12775:125::-;12840:9;;;12861:10;;;12858:36;;;12874:18;;:::i;13488:247::-;13547:6;13600:2;13588:9;13579:7;13575:23;13571:32;13568:52;;;13616:1;13613;13606:12;13568:52;13655:9;13642:23;13674:31;13699:5;13674:31;:::i;13740:184::-;13810:6;13863:2;13851:9;13842:7;13838:23;13834:32;13831:52;;;13879:1;13876;13869:12;13831:52;-1:-1:-1;13902:16:1;;13740:184;-1:-1:-1;13740:184:1:o;13929:658::-;14025:6;14078:2;14066:9;14057:7;14053:23;14049:32;14046:52;;;14094:1;14091;14084:12;14046:52;14127:2;14121:9;14169:2;14161:6;14157:15;14238:6;14226:10;14223:22;14202:18;14190:10;14187:34;14184:62;14181:185;;;14288:10;14283:3;14279:20;14276:1;14269:31;14323:4;14320:1;14313:15;14351:4;14348:1;14341:15;14181:185;14386:10;14382:2;14375:22;;14427:9;14421:16;14413:6;14406:32;14492:2;14481:9;14477:18;14471:25;14466:2;14458:6;14454:15;14447:50;14551:2;14540:9;14536:18;14530:25;14525:2;14517:6;14513:15;14506:50;14575:6;14565:16;;;13929:658;;;;:::o;16291:594::-;16382:6;16435:2;16423:9;16414:7;16410:23;16406:32;16403:52;;;16451:1;16448;16441:12;16403:52;16484:2;16478:9;16526:2;16518:6;16514:15;16595:6;16583:10;16580:22;16559:18;16547:10;16544:34;16541:62;16538:185;;;16645:10;16640:3;16636:20;16633:1;16626:31;16680:4;16677:1;16670:15;16708:4;16705:1;16698:15;16538:185;16739:2;16732:22;16778:16;;16763:32;;16849:2;16834:18;;;16828:25;16811:15;;;16804:50;;;;-1:-1:-1;16770:6:1;16291:594;-1:-1:-1;16291:594:1:o
Swarm Source
ipfs://acea1855ea1c703fe155e66a44918f85873963e86ab70c26b0d7928f4c009d46
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.