ETH Price: $3,100.23 (-5.47%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Claim All170217962023-04-11 2:04:47663 days ago1681178687IN
0x7D0F747e...eF7459e1f
0 ETH0.0030242726.09859079
Claim All170165942023-04-10 8:22:23663 days ago1681114943IN
0x7D0F747e...eF7459e1f
0 ETH0.0021869718.87292547
Claim All170131112023-04-09 20:33:59664 days ago1681072439IN
0x7D0F747e...eF7459e1f
0 ETH0.0046459818.63215592
Claim All170097972023-04-09 9:15:35664 days ago1681031735IN
0x7D0F747e...eF7459e1f
0 ETH0.0025581422.07597816
Claim All170033862023-04-08 11:28:23665 days ago1680953303IN
0x7D0F747e...eF7459e1f
0 ETH0.0012052321
Claim All170025122023-04-08 8:30:59665 days ago1680942659IN
0x7D0F747e...eF7459e1f
0 ETH0.0024408321.06369295
Claim All170006742023-04-08 2:15:11666 days ago1680920111IN
0x7D0F747e...eF7459e1f
0 ETH0.0030582126.39142878
Claim169993612023-04-07 21:47:59666 days ago1680904079IN
0x7D0F747e...eF7459e1f
0 ETH0.0020738818
Claim169971552023-04-07 14:18:47666 days ago1680877127IN
0x7D0F747e...eF7459e1f
0 ETH0.0025230821.89870372
Claim169971472023-04-07 14:17:11666 days ago1680877031IN
0x7D0F747e...eF7459e1f
0 ETH0.0026065622.62328215
Claim169969582023-04-07 13:38:59666 days ago1680874739IN
0x7D0F747e...eF7459e1f
0 ETH0.0033267525.14247088
Claim All169959442023-04-07 10:11:23666 days ago1680862283IN
0x7D0F747e...eF7459e1f
0 ETH0.0022373619.30776585
Claim All169959372023-04-07 10:09:59666 days ago1680862199IN
0x7D0F747e...eF7459e1f
0 ETH0.0022420919.34857056
Claim All169955452023-04-07 8:49:47666 days ago1680857387IN
0x7D0F747e...eF7459e1f
0 ETH0.0023175820
Claim All169934182023-04-07 1:36:11667 days ago1680831371IN
0x7D0F747e...eF7459e1f
0 ETH0.0023588320.35598883
Claim All169931192023-04-07 0:34:35667 days ago1680827675IN
0x7D0F747e...eF7459e1f
0 ETH0.002201719
Claim All169931192023-04-07 0:34:35667 days ago1680827675IN
0x7D0F747e...eF7459e1f
0 ETH0.002201719
Claim All169930572023-04-07 0:21:59667 days ago1680826919IN
0x7D0F747e...eF7459e1f
0 ETH0.0023175820
Claim All169925742023-04-06 22:43:35667 days ago1680821015IN
0x7D0F747e...eF7459e1f
0 ETH0.0025854922.31200233
Claim All169925712023-04-06 22:42:47667 days ago1680820967IN
0x7D0F747e...eF7459e1f
0 ETH0.0026218222.62556175
Claim All169904302023-04-06 15:24:47667 days ago1680794687IN
0x7D0F747e...eF7459e1f
0 ETH0.0036626431.60748966
Claim All169901922023-04-06 14:36:23667 days ago1680791783IN
0x7D0F747e...eF7459e1f
0 ETH0.0031287327
Claim169896962023-04-06 12:54:35667 days ago1680785675IN
0x7D0F747e...eF7459e1f
0 ETH0.0032574528.27257946
Claim All169888892023-04-06 10:05:47667 days ago1680775547IN
0x7D0F747e...eF7459e1f
0 ETH0.0032446128
Claim All169883512023-04-06 8:12:11667 days ago1680768731IN
0x7D0F747e...eF7459e1f
0 ETH0.0032746228.25901991
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
163766722023-01-10 13:21:35753 days ago1673356895  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Platform

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv2 license

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

Contract ABI

[{"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"}]

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.