ETH Price: $2,676.26 (-0.77%)

Contract

0xd027Ef82dB658805C9Ba8053196cD6ED1Dd407E4
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw207893772024-09-20 4:20:478 days ago1726806047IN
unshETH: vdUSH
0 ETH0.0062701415.07660481
Withdraw207422532024-09-13 14:20:5915 days ago1726237259IN
unshETH: vdUSH
0 ETH0.000906962.45158013
Withdraw206810942024-09-05 1:26:3523 days ago1725499595IN
unshETH: vdUSH
0 ETH0.0045388210.32548621
Withdraw205847352024-08-22 14:27:1137 days ago1724336831IN
unshETH: vdUSH
0 ETH0.000634391.38917158
Withdraw205104252024-08-12 5:24:1147 days ago1723440251IN
unshETH: vdUSH
0 ETH0.000795032.05408874
Withdraw204754772024-08-07 8:23:3552 days ago1723019015IN
unshETH: vdUSH
0 ETH0.001121983.01648208
Withdraw204274042024-07-31 15:23:1159 days ago1722439391IN
unshETH: vdUSH
0 ETH0.0039763612.44851665
Withdraw204085242024-07-29 0:05:2361 days ago1722211523IN
unshETH: vdUSH
0 ETH0.001248651.87613052
Withdraw201471272024-06-22 12:04:4798 days ago1719057887IN
unshETH: vdUSH
0 ETH0.001205832.89944047
Withdraw201056952024-06-16 16:57:59104 days ago1718557079IN
unshETH: vdUSH
0 ETH0.002066516.46949847
Withdraw201015342024-06-16 3:02:35104 days ago1718506955IN
unshETH: vdUSH
0 ETH0.001030813.22710818
Withdraw200920352024-06-14 19:07:35106 days ago1718392055IN
unshETH: vdUSH
0 ETH0.0037212212.30870462
Withdraw200920312024-06-14 19:06:47106 days ago1718392007IN
unshETH: vdUSH
0 ETH0.0037871912.52689396
Withdraw200822492024-06-13 10:17:11107 days ago1718273831IN
unshETH: vdUSH
0 ETH0.0028547412.35297367
Withdraw200799722024-06-13 2:38:23107 days ago1718246303IN
unshETH: vdUSH
0 ETH0.005202913.63138359
Withdraw200695212024-06-11 15:36:11109 days ago1718120171IN
unshETH: vdUSH
0 ETH0.0121931931.91024938
Withdraw199967522024-06-01 11:44:47119 days ago1717242287IN
unshETH: vdUSH
0 ETH0.00161884.88827286
Withdraw199929052024-05-31 22:50:47120 days ago1717195847IN
unshETH: vdUSH
0 ETH0.001321786
Withdraw199929052024-05-31 22:50:47120 days ago1717195847IN
unshETH: vdUSH
0 ETH0.001894936
Withdraw199684792024-05-28 12:51:11123 days ago1716900671IN
unshETH: vdUSH
0 ETH0.0074843922.60048394
Withdraw199325772024-05-23 12:26:47128 days ago1716467207IN
unshETH: vdUSH
0 ETH0.0050579316.79562362
Withdraw199174212024-05-21 9:34:47130 days ago1716284087IN
unshETH: vdUSH
0 ETH0.002644378.2785543
Withdraw198953742024-05-18 7:34:11133 days ago1716017651IN
unshETH: vdUSH
0 ETH0.000976713.10994553
Withdraw198953432024-05-18 7:27:59133 days ago1716017279IN
unshETH: vdUSH
0 ETH0.000954143.01231757
Withdraw198800252024-05-16 4:02:35135 days ago1715832155IN
unshETH: vdUSH
0 ETH0.001785094.67685902
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VotingEscrow

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 9999 runs

Other Settings:
default evmVersion
File 1 of 10 : VotingEscrow.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

//Modified Multiple Token VotingEscrow Contract
//The following changes have been made:
//1. Users can lock either 80-20 USH-unshETH BPT, Uniswapv2 style pool2 token, or single-sided USH
//2. Make sure deposit() and withdraw() funcs are correctly updated for the multi token model
//3. Give owner ability to update boost weight of BPT and Pool2 tokens
//4. Price everything in USH terms - this means pricing the BPT and Pool2 tokens in USH terms
//5. Make 1 USH = 1vdUSH max locked for single-sided.
//6. Pool2 included for easy migration of existing liquidity + enable locking in chains where BPT is not supported

/// basically, where tokenAmount is used, we need to use scaledtokenAmount1+weight*tokenAmount2
/**
@title Multi-Token Weighted Voting Escrow
@author @EIP_Alta1r, Original: Curve Finance, Solidity Rewrite: Stargate Finance
@license MIT
@notice Votes have a weight depending on time, so that users are
        committed to the future of (whatever they are voting for)
@dev Vote weight decays linearly over time. Lock time cannot be
     more than `MAXTIME` (1 years).

# Voting escrow to have time-weighted votes
# Votes have a weight depending on time, so that users are committed
# to the future of (whatever they are voting for).
# The weight in this implementation is linear, and lock cannot be more than maxtime:
# w ^
# 1 +        /
#   |      /
#   |    /
#   |  /
#   |/
# 0 +--------+------> time
#       maxtime (1 years?)
*/

import "openzeppelin-contracts/contracts/access/Ownable.sol";
import "openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import "forge-std/console.sol";

struct Point {
    int128 bias;
    int128 slope; // # -dweight / dt
    uint ts;
    uint blk; // block
}
/* We cannot really do block numbers per se b/c slope is per time, not per block
 * and per block could be fairly bad b/c Ethereum changes blocktimes.
 * What we can do is to extrapolate ***At functions */

struct LockedBalance {
    int128 amount; //weightedAmount
    uint256 amountA;
    uint256 amountB;
    uint256 amountC;
    uint end;
}

interface IPool2 {
    function getReserves() external view returns (uint112 _reserveA, uint112 _reserveB, uint32 _blockTimestampLast);
    function getPoolId() external view returns (bytes32);
}

interface IBPT {
    function getVault() external view returns (address);
    function getPoolId() external view returns (bytes32);
}

interface IBPTVault {
    function getPoolTokenInfo(
        bytes32 poolId,
        address token
    ) external view returns (uint256, uint256, uint256, address);
}

contract VotingEscrow is Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;

    enum DepositType {
        DEPOSIT_FOR_TYPE,
        CREATE_LOCK_TYPE,
        INCREASE_LOCK_AMOUNT,
        INCREASE_UNLOCK_TIME
    }

    event Deposit(
        address indexed provider,
        uint valueA,
        uint valueB,
        uint valueC,
        uint indexed locktime,
        DepositType deposit_type,
        uint ts
    );
    event Withdraw(address indexed provider, uint valueA, uint valueB, uint valueC, uint ts);
    event Supply(uint prevSupply, uint supply);

    uint internal constant WEEK = 1 weeks;
    uint public constant MAXTIME = 53 weeks; //max lock 1 year
    int128 internal constant iMAXTIME = 53 weeks;
    uint public constant MINTIME = 4 weeks;
    uint internal constant MULTIPLIER = 1 ether;

    //a dynamic boost weight that is configurable
    uint256 public bpt_boost_weight;
    uint256 public pool2_boost_weight;

    address public immutable tokenA; //BPT
    address public immutable tokenB; //Pool2 LP Token
    address public immutable tokenC; //Single-sided USH Token
    uint public supply;
    bool public unlocked;

    mapping(address => LockedBalance) public locked; //weighted locked balance

    uint public epoch;
    mapping(uint => Point) public point_history; // epoch -> unsigned point
    mapping(address => Point[1000000000]) public user_point_history; // user -> Point[user_epoch]
    mapping(address => uint) public user_point_epoch;
    mapping(uint => int128) public slope_changes; // time -> signed slope change

    // Aragon's view methods for compatibility
    address public controller;
    bool public transfersEnabled;

    string public constant name = "vdUSH";
    string public constant symbol = "vdUSH";
    string public constant version = "1.0.0";
    uint8 public constant decimals = 18;

    // Whitelisted (smart contract) wallets which are allowed to deposit
    // The goal is to prevent tokenizing the escrow
    mapping(address => bool) public contracts_whitelist;

    /// @notice Contract constructor
    /// @param tokenA_addr BPT
    /// @param tokenB_addr Pool2 LP token
    /// @param tokenC_addr USH token
    constructor(address tokenA_addr, address tokenB_addr, address tokenC_addr) {
        tokenA = tokenA_addr;
        tokenB = tokenB_addr;
        tokenC = tokenC_addr;
        bpt_boost_weight = 2.5 ether;
        pool2_boost_weight = 3.5 ether;
        point_history[0].blk = block.number;
        point_history[0].ts = block.timestamp;
        controller = msg.sender;
        transfersEnabled = true;
    }

    modifier onlyUserOrWhitelist() {
        if (msg.sender != tx.origin) {
            require(contracts_whitelist[msg.sender], "Smart contract not allowed");
        }
        _;
    }

    modifier notUnlocked() {
        require(!unlocked, "unlocked globally");
        _;
    }

    //helper unit conversion funcs
    function bpt_amount_to_ush_units(uint256 amount) internal view returns (uint256) {
        //get the contract address of the BPT pool token
        address bpt_address = tokenA;
        //get vault and pool info
        address balancer_vault = IBPT(bpt_address).getVault();
        bytes32 pool_id = IBPT(bpt_address).getPoolId();
        //get the balance of token A in the BPT pool
        (uint256 ush_balance, , , ) = IBPTVault(balancer_vault).getPoolTokenInfo(pool_id, tokenC);
        //get the total supply of the BPT pool
        uint256 total_supply = IERC20(bpt_address).totalSupply();
        //calculate the amount of token C units
        return (amount * ush_balance) / total_supply;
    }

    function pool2_amount_to_ush_units(uint256 amount) internal view returns (uint256) {
        //get the contract address of the BPT pool token
        address pool2_address = tokenB;
        //get vault and pool info
        (, uint256 ush_balance, ) = IPool2(pool2_address).getReserves();

        console.log(ush_balance);
        //get the total supply of the pool2
        uint256 total_supply = IERC20(pool2_address).totalSupply();
        console.log(total_supply);
        //calculate the amount of token C units
        return (amount * ush_balance) / total_supply;
    }

    function update_bpt_boost_weight(uint256 weight) external onlyOwner {
        require(weight > 0, "Cannot set zero boost weight!");
        bpt_boost_weight = weight;
    }

    function update_pool2_boost_weight(uint256 weight) external onlyOwner {
        require(weight > 0, "Cannot set zero boost weight!");
        pool2_boost_weight = weight;
    }

    function weighted_amount(uint256 bptAmount, uint256 pool2Amount, uint256 tokenAmount) public view returns (uint256) {

        uint256 scaled_bpt_amount = tokenA == address(0) ? 0 : bpt_amount_to_ush_units(bptAmount);

        uint256 scaled_pool2_amount = pool2_amount_to_ush_units(pool2Amount);

        return (scaled_bpt_amount * bpt_boost_weight) / 1e18 + (scaled_pool2_amount * pool2_boost_weight) / 1e18 + tokenAmount;
    }

    function int_weighted_amount(uint256 _valueA, uint256 _valueB, uint256 _valueC) internal view returns (int128) {
        return int128(int(weighted_amount(_valueA, _valueB, _valueC)));
    }

    /// @notice Add address to whitelist smart contract depositors `addr`
    /// @param addr Address to be whitelisted
    function add_to_whitelist(address addr) external onlyOwner {
        require(!contracts_whitelist[addr], "Address already whitelisted");
        contracts_whitelist[addr] = true;
    }

    /// @notice Remove a smart contract address from whitelist
    /// @param addr Address to be removed from whitelist
    function remove_from_whitelist(address addr) external onlyOwner {
        require(contracts_whitelist[addr], "Address not whitelisted");
        contracts_whitelist[addr] = false;
    }

    /// @notice Unlock all locked balances
    function unlock() external onlyOwner {
        unlocked = true;
    }

    /// @notice Get the most recently recorded rate of voting power decrease for `_addr`
    /// @param addr Address of the user wallet
    /// @return Value of the slope
    function get_last_user_slope(address addr) external view returns (int128) {
        uint uepoch = user_point_epoch[addr];
        return user_point_history[addr][uepoch].slope;
    }

    /// @notice Get the timestamp for checkpoint `_idx` for `_addr`
    /// @param _addr User wallet address
    /// @param _idx User epoch number
    /// @return Epoch time of the checkpoint
    function user_point_history__ts(address _addr, uint _idx) external view returns (uint) {
        return user_point_history[_addr][_idx].ts;
    }

    /// @notice Get timestamp when `_addr`'s lock finishes
    /// @param _addr User wallet address
    /// @return Epoch time of the lock end
    function locked__end(address _addr) external view returns (uint) {
        return locked[_addr].end;
    }

    function locked__amountA(address user) external view returns (uint) {
        return locked[user].amountA;
    }

    function locked__amountB(address user) external view returns (uint) {
        return locked[user].amountB;
    }

    function locked__amountC(address user) external view returns (uint) {
        return locked[user].amountC;
    }

    /// @notice Record global and per-user data to checkpoint
    /// @param _addr User's wallet address. No user checkpoint if 0x0
    /// @param old_locked Pevious locked amount / end lock time for the user
    /// @param new_locked New locked amount / end lock time for the user
    function _checkpoint(
        address _addr,
        LockedBalance memory old_locked,
        LockedBalance memory new_locked
    ) internal {
        Point memory u_old;
        Point memory u_new;
        int128 old_dslope = 0;
        int128 new_dslope = 0;
        uint _epoch = epoch;

        //make sure we are using the most current BPT boost weights
        //and then make sure the new_locked that was passed in has had the most current boost weights applied (do that elsewhere)
        old_locked.amount = int_weighted_amount(old_locked.amountA, old_locked.amountB, old_locked.amountC);

        if (_addr != address(0x0)) {
            // Calculate slopes and biases
            // Kept at zero when they have to
            if (old_locked.end > block.timestamp && old_locked.amount > 0) {
                u_old.slope = old_locked.amount / iMAXTIME;
                u_old.bias = u_old.slope * int128(int(old_locked.end - block.timestamp));
            }
            if (new_locked.end > block.timestamp && new_locked.amount > 0) {
                u_new.slope = new_locked.amount / iMAXTIME;
                u_new.bias = u_new.slope * int128(int(new_locked.end - block.timestamp));
            }

            // Read values of scheduled changes in the slope
            // old_locked.end can be in the past and in the future
            // new_locked.end can ONLY by in the FUTURE unless everything expired: than zeros
            old_dslope = slope_changes[old_locked.end];
            if (new_locked.end != 0) {
                if (new_locked.end == old_locked.end) {
                    new_dslope = old_dslope;
                } else {
                    new_dslope = slope_changes[new_locked.end];
                }
            }
        }

        Point memory last_point = Point({ bias: 0, slope: 0, ts: block.timestamp, blk: block.number });
        if (_epoch > 0) {
            last_point = point_history[_epoch];
        }
        uint last_checkpoint = last_point.ts;
        // initial_last_point is used for extrapolation to calculate block number
        // (approximately, for *At methods) and save them
        // as we cannot figure that out exactly from inside the contract

        uint initial_last_point_ts = last_point.ts;
        uint initial_last_point_blk = last_point.blk;

        uint block_slope = 0; // dblock/dt
        if (block.timestamp > last_point.ts) {
            block_slope = (MULTIPLIER * (block.number - last_point.blk)) / (block.timestamp - last_point.ts);
        }
        // If last point is already recorded in this block, slope=0
        // But that's ok b/c we know the block in such case

        // Go over weeks to fill history and calculate what the current point is
        uint t_i = (last_checkpoint / WEEK) * WEEK;
        for (uint i = 0; i < 255; ++i) {
            // Hopefully it won't happen that this won't get used in 5 years!
            // If it does, users will be able to withdraw but vote weight will be broken
            t_i += WEEK;
            int128 d_slope = 0;
            if (t_i > block.timestamp) {
                t_i = block.timestamp;
            } else {
                d_slope = slope_changes[t_i];
            }
            last_point.bias -= last_point.slope * int128(int(t_i - last_checkpoint));
            last_point.slope += d_slope;
            if (last_point.bias < 0) {
                // This can happen
                last_point.bias = 0;
            }
            if (last_point.slope < 0) {
                // This cannot happen - just in case
                last_point.slope = 0;
            }
            last_checkpoint = t_i;
            last_point.ts = t_i;
            last_point.blk =
                initial_last_point_blk +
                (block_slope * (t_i - initial_last_point_ts)) /
                MULTIPLIER;

            _epoch += 1;
            if (t_i == block.timestamp) {
                last_point.blk = block.number;
                break;
            } else {
                point_history[_epoch] = last_point;
            }
        }

        epoch = _epoch;
        // Now point_history is filled until t=now

        if (_addr != address(0x0)) {
            // If last point was in this block, the slope change has been applied already
            // But in such case we have 0 slope(s)
            last_point.slope += (u_new.slope - u_old.slope);
            last_point.bias += (u_new.bias - u_old.bias);
            if (last_point.slope < 0) {
                last_point.slope = 0;
            }
            if (last_point.bias < 0) {
                last_point.bias = 0;
            }
        }

        // Record the changed point into history
        point_history[_epoch] = last_point;

        if (_addr != address(0x0)) {
            // Schedule the slope changes (slope is going down)
            // We subtract new_user_slope from [new_locked.end]
            // and add old_user_slope to [old_locked.end]
            if (old_locked.end > block.timestamp) {
                // old_dslope was <something> - u_old.slope, so we cancel that
                old_dslope += u_old.slope;
                if (new_locked.end == old_locked.end) {
                    old_dslope -= u_new.slope; // It was a new deposit, not extension
                }
                slope_changes[old_locked.end] = old_dslope;
            }

            if (new_locked.end > block.timestamp) {
                if (new_locked.end > old_locked.end) {
                    new_dslope -= u_new.slope; // old slope disappeared at this point
                    slope_changes[new_locked.end] = new_dslope;
                }
                // else: we recorded it already in old_dslope
            }
            // Now handle user history
            address addr = _addr;
            uint user_epoch = user_point_epoch[addr] + 1;

            user_point_epoch[addr] = user_epoch;
            u_new.ts = block.timestamp;
            u_new.blk = block.number;
            user_point_history[addr][user_epoch] = u_new;
        }
    }

    /// @notice Record global data to checkpoint
    function checkpoint() external notUnlocked {
        _checkpoint(
            address(0x0),
            LockedBalance(int_weighted_amount(0, 0, 0), 0, 0, 0, 0),
            LockedBalance(int_weighted_amount(0, 0, 0), 0, 0, 0, 0)
        );
    }

    function deposit_for(address _addr, uint _valueA, uint _valueB, uint _valueC) external nonReentrant {
        LockedBalance memory _locked = locked[_addr];

        require(_valueA > 0 || _valueB > 0 || _valueC > 0); // dev: need non-zero value
        require(_locked.amount > 0, "No existing lock found");
        require(_locked.end > block.timestamp, "Cannot add to expired lock. Withdraw");
        _deposit_for(_addr, _valueA, _valueB, _valueC, 0, _locked, DepositType.DEPOSIT_FOR_TYPE);
    }

    function _deposit_for(
        address _addr,
        uint _valueA,
        uint _valueB,
        uint _valueC,
        uint unlock_time,
        LockedBalance memory locked_balance,
        DepositType deposit_type
    ) internal {
        LockedBalance memory _locked = locked_balance;
        uint supply_before = supply;

        supply = supply_before + weighted_amount(_valueA, _valueB, _valueC);
        LockedBalance memory old_locked;
        //NOTE: need to be checked
        _locked.amount = int128(int(weighted_amount(_locked.amountA, _locked.amountB, _locked.amountC)));
        // old_locked.amount = int128(int(weighted_amount(old_locked.amountA, old_locked.amountB)));
        (old_locked.amount, old_locked.end) = (_locked.amount, _locked.end);
        // Adding to existing lock, or if a lock is expired - creating a new one
        _locked.amount += int128(int(weighted_amount(_valueA, _valueB, _valueC)));
        _locked.amountA += _valueA;
        _locked.amountB += _valueB;
        _locked.amountC += _valueC;

        if (unlock_time != 0) {
            _locked.end = unlock_time;
        }
        locked[_addr] = _locked;

        // Possibilities:
        // Both old_locked.end could be current or expired (>/< block.timestamp)
        // value == 0 (extend lock) or value > 0 (add to lock or extend lock)
        // _locked.end > block.timestamp (always)
        _checkpoint(_addr, old_locked, _locked);

        if (_valueA != 0) {
            IERC20(tokenA).safeTransferFrom(msg.sender, address(this), _valueA);
        }

        if (_valueB != 0) {
            IERC20(tokenB).safeTransferFrom(msg.sender, address(this), _valueB);
        }

        if (_valueC != 0) {
            IERC20(tokenC).safeTransferFrom(msg.sender, address(this), _valueC);
        }

        emit Deposit(_addr, _valueA, _valueB, _valueC, _locked.end, deposit_type, block.timestamp);
        emit Supply(supply_before, supply_before + weighted_amount(_valueA, _valueB, _valueC));
    }

    /// @notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time`
    /// @param _valueA Amount to deposit of BPT
    /// @param _valueB amount to deposit of pool2
    /// @param _valueC amount to deposit of token
    /// @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
    function _create_lock(uint _valueA, uint _valueB, uint _valueC, uint _unlock_time) internal {
        require(_valueA > 0 || _valueB > 0 || _valueC > 0); // dev: need non-zero value

        LockedBalance memory _locked = locked[msg.sender];
        require(_locked.amount == 0, "Withdraw old tokens first");

        require(_unlock_time >= block.timestamp + MINTIME, "Voting lock must be at least MINTIME");
        //NOTE:MAXTIME is set to 1 year, may be changed to 3 years
        require(_unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 1 year max");
        //NOTE: calc only if valid time to save on gas
        uint unlock_time = (_unlock_time / WEEK) * WEEK; // Locktime is rounded down to weeks

        _deposit_for(msg.sender, _valueA, _valueB, _valueC, unlock_time, _locked, DepositType.CREATE_LOCK_TYPE);
    }

    /// @notice External function for _create_lock
    /// @param _valueA Amount to deposit of BPT
    /// @param _valueB amount to deposit of pool2
    /// @param _valueC amount to deposit of token
    /// @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
    function create_lock(
        uint _valueA,
        uint _valueB,
        uint _valueC,
        uint _unlock_time
    ) external nonReentrant onlyUserOrWhitelist notUnlocked {
        _create_lock(_valueA, _valueB, _valueC, _unlock_time);
    }

    /// @notice Deposit `_value` additional tokens for `msg.sender` without modifying the unlock time
    /// @param _valueA Amount to deposit of BPT
    /// @param _valueB amount to deposit of pool2
    /// @param _valueC amount to deposit of token
    function increase_amount(
        uint _valueA,
        uint _valueB,
        uint _valueC
    ) external nonReentrant onlyUserOrWhitelist notUnlocked {
        _increase_amount(_valueA, _valueB, _valueC);
    }

    function _increase_amount(uint _valueA, uint _valueB, uint _valueC) internal {
        LockedBalance memory _locked = locked[msg.sender];

        require(_valueA > 0 || _valueB > 0 || _valueC > 0); // dev: need non-zero value
        require(_locked.amount > 0, "No existing lock found");
        require(_locked.end > block.timestamp, "Cannot add to expired lock. Withdraw");

        _deposit_for(msg.sender, _valueA, _valueB, _valueC, 0, _locked, DepositType.INCREASE_LOCK_AMOUNT);
    }

    /// @notice Extend the unlock time for `msg.sender` to `_unlock_time`
    /// @param _unlock_time New epoch time for unlocking
    function increase_unlock_time(uint _unlock_time) external nonReentrant onlyUserOrWhitelist notUnlocked {
        _increase_unlock_time(_unlock_time);
    }

    function _increase_unlock_time(uint _unlock_time) internal {
        LockedBalance memory _locked = locked[msg.sender];
        uint unlock_time = (_unlock_time / WEEK) * WEEK; // Locktime is rounded down to weeks

        require(_locked.end > block.timestamp, "Lock expired");
        require(_locked.amount > 0, "Nothing is locked");
        require(unlock_time > _locked.end, "Can only increase lock duration");
        require(unlock_time <= block.timestamp + MAXTIME, "Voting lock can be 3 years max");

        _deposit_for(msg.sender, 0, 0, 0, unlock_time, _locked, DepositType.INCREASE_UNLOCK_TIME);
    }

    /// @notice Extend the unlock time and/or for `msg.sender` to `_unlock_time`
    /// @param _unlock_time New epoch time for unlocking
    function increase_amount_and_time(
        uint _valueA,
        uint _valueB,
        uint _valueC,
        uint _unlock_time
    ) external nonReentrant onlyUserOrWhitelist notUnlocked {
        require((_valueA > 0 || _valueB > 0 || _valueC > 0) || _unlock_time > 0, "Value and Unlock cannot both be 0");
        if ((_valueA > 0 || _valueB > 0 || _valueC > 0) && _unlock_time > 0) {
            _increase_amount(_valueA, _valueB, _valueC);
            _increase_unlock_time(_unlock_time);
        } else if ((_valueA > 0 || _valueB > 0 || _valueC > 0) && _unlock_time == 0) {
            _increase_amount(_valueA, _valueB, _valueC);
        } else {
            _increase_unlock_time(_unlock_time);
        }
    }

    /// @notice Withdraw all tokens for `msg.sender`
    /// @dev Only possible if the lock has expired
    function _withdraw() internal {
        LockedBalance memory _locked = locked[msg.sender];
        uint256 token_a_balance = _locked.amountA;
        uint256 token_b_balance = _locked.amountB;
        uint256 token_c_balance = _locked.amountC;
        uint value = uint(int(_locked.amount));

        if (!unlocked) {
            require(block.timestamp >= _locked.end, "The lock didn't expire");
        }

        locked[msg.sender] = LockedBalance(0, 0, 0, 0, 0);
        uint supply_before = supply;
        supply = supply_before - value;

        // old_locked can have either expired <= timestamp or zero end
        // _locked has only 0 end
        // Both can have >= 0 amount
        _checkpoint(msg.sender, _locked, LockedBalance(0, 0, 0, 0, 0));

        if(token_a_balance > 0) {
            IERC20(tokenA).safeTransfer(msg.sender, token_a_balance);
        }
        if(token_b_balance > 0) {
            IERC20(tokenB).safeTransfer(msg.sender, token_b_balance);
        }
        if(token_c_balance > 0) {
            IERC20(tokenC).safeTransfer(msg.sender, token_c_balance);
        }
        emit Withdraw(msg.sender, token_a_balance, token_b_balance, token_c_balance, block.timestamp);
        emit Supply(supply_before, supply_before - value);
    }

    function withdraw() external nonReentrant {
        _withdraw();
    }

    /// @notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time`
    /// @param _valueA Amount to deposit of BPT
    /// @param _valueB amount to deposit of pool2
    /// @param _valueC amount to deposit of token
    /// @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
    function withdraw_and_create_lock(
        uint _valueA,
        uint _valueB,
        uint _valueC,
        uint _unlock_time
    ) external nonReentrant onlyUserOrWhitelist notUnlocked {
        _withdraw();
        _create_lock(_valueA, _valueB, _valueC, _unlock_time);
    }

    // The following ERC20/minime-compatible methods are not real balanceOf and supply!
    // They measure the weights for the purpose of voting, so they don't represent
    // real coins.

    /// @notice Binary search to estimate timestamp for block number
    /// @param _block Block to find
    /// @param max_epoch Don't go beyond this epoch
    /// @return Approximate timestamp for block
    function _find_block_epoch(uint _block, uint max_epoch) internal view returns (uint) {
        // Binary search
        uint _min = 0;
        uint _max = max_epoch;
        for (uint i = 0; i < 128; ++i) {
            // Will be always enough for 128-bit numbers
            if (_min >= _max) {
                break;
            }
            uint _mid = (_min + _max + 1) / 2;
            if (point_history[_mid].blk <= _block) {
                _min = _mid;
            } else {
                _max = _mid - 1;
            }
        }
        return _min;
    }

    /// @notice Get the current voting power for `msg.sender`
    /// @dev Adheres to the ERC20 `balanceOf` interface for Aragon compatibility
    /// @param addr User wallet address
    /// @param _t Epoch time to return voting power at
    /// @return User voting power
    function _balanceOf(address addr, uint _t) internal view returns (uint) {
        uint _epoch = user_point_epoch[addr];
        if (_epoch == 0) {
            return 0;
        } else {
            Point memory last_point = user_point_history[addr][_epoch];
            last_point.bias -= last_point.slope * int128(int(_t) - int(last_point.ts));
            if (last_point.bias < 0) {
                last_point.bias = 0;
            }
            return uint(int(last_point.bias));
        }
    }

    function balanceOfAtT(address addr, uint _t) external view returns (uint) {
        return _balanceOf(addr, _t);
    }

    function balanceOf(address addr) external view returns (uint) {
        return _balanceOf(addr, block.timestamp);
    }

    /// @notice Measure voting power of `addr` at block height `_block`
    /// @dev Adheres to MiniMe `balanceOfAt` interface: https://github.com/Giveth/minime
    /// @param addr User's wallet address
    /// @param _block Block to calculate the voting power at
    /// @return Voting power
    function balanceOfAt(address addr, uint _block) external view returns (uint) {
        // Copying and pasting totalSupply code because Vyper cannot pass by
        // reference yet
        require(_block <= block.number);

        // Binary search
        uint _min = 0;
        uint _max = user_point_epoch[addr];
        for (uint i = 0; i < 128; ++i) {
            // Will be always enough for 128-bit numbers
            if (_min >= _max) {
                break;
            }
            uint _mid = (_min + _max + 1) / 2;
            if (user_point_history[addr][_mid].blk <= _block) {
                _min = _mid;
            } else {
                _max = _mid - 1;
            }
        }

        Point memory upoint = user_point_history[addr][_min];

        uint max_epoch = epoch;
        uint _epoch = _find_block_epoch(_block, max_epoch);
        Point memory point_0 = point_history[_epoch];
        uint d_block = 0;
        uint d_t = 0;
        if (_epoch < max_epoch) {
            Point memory point_1 = point_history[_epoch + 1];
            d_block = point_1.blk - point_0.blk;
            d_t = point_1.ts - point_0.ts;
        } else {
            d_block = block.number - point_0.blk;
            d_t = block.timestamp - point_0.ts;
        }
        uint block_time = point_0.ts;
        if (d_block != 0) {
            block_time += (d_t * (_block - point_0.blk)) / d_block;
        }

        upoint.bias -= upoint.slope * int128(int(block_time - upoint.ts));
        if (upoint.bias >= 0) {
            return uint(uint128(upoint.bias));
        } else {
            return 0;
        }
    }

    /// @notice Calculate total voting power at some point in the past
    /// @param point The point (bias/slope) to start search from
    /// @param t Time to calculate the total voting power at
    /// @return Total voting power at that time
    function _supply_at(Point memory point, uint t) internal view returns (uint) {
        Point memory last_point = point;
        uint t_i = (last_point.ts / WEEK) * WEEK;
        for (uint i = 0; i < 255; ++i) {
            t_i += WEEK;
            int128 d_slope = 0;
            if (t_i > t) {
                t_i = t;
            } else {
                d_slope = slope_changes[t_i];
            }
            last_point.bias -= last_point.slope * int128(int(t_i - last_point.ts));
            if (t_i == t) {
                break;
            }
            last_point.slope += d_slope;
            last_point.ts = t_i;
        }

        if (last_point.bias < 0) {
            last_point.bias = 0;
        }
        return uint(uint128(last_point.bias));
    }

    /// @notice Calculate total voting power
    /// @dev Adheres to the ERC20 `totalSupply` interface for Aragon compatibility
    /// @return Total voting power
    function _totalSupply(uint t) internal view returns (uint) {
        uint _epoch = epoch;
        Point memory last_point = point_history[_epoch];
        return _supply_at(last_point, t);
    }

    function totalSupplyAtT(uint t) external view returns (uint) {
        return _totalSupply(t);
    }

    function totalSupply() external view returns (uint) {
        return _totalSupply(block.timestamp);
    }

    /// @notice Calculate total voting power at some point in the past
    /// @param _block Block to calculate the total voting power at
    /// @return Total voting power at `_block`
    function totalSupplyAt(uint _block) external view returns (uint) {
        require(_block <= block.number);
        uint _epoch = epoch;
        uint target_epoch = _find_block_epoch(_block, _epoch);

        Point memory point = point_history[target_epoch];
        uint dt = 0;
        if (target_epoch < _epoch) {
            Point memory point_next = point_history[target_epoch + 1];
            if (point.blk != point_next.blk) {
                dt = ((_block - point.blk) * (point_next.ts - point.ts)) / (point_next.blk - point.blk);
            }
        } else {
            if (point.blk != block.number) {
                dt = ((_block - point.blk) * (block.timestamp - point.ts)) / (block.number - point.blk);
            }
        }
        // Now dt contains info on how far are we beyond point
        return _supply_at(point, point.ts + dt);
    }

    // Dummy methods for compatibility with Aragon
    function changeController(address _newController) external {
        require(msg.sender == controller);
        controller = _newController;
    }
}

File 2 of 10 : console.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

library console {
    address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);

    function _sendLogPayload(bytes memory payload) private view {
        uint256 payloadLength = payload.length;
        address consoleAddress = CONSOLE_ADDRESS;
        /// @solidity memory-safe-assembly
        assembly {
            let payloadStart := add(payload, 32)
            let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
        }
    }

    function log() internal view {
        _sendLogPayload(abi.encodeWithSignature("log()"));
    }

    function logInt(int p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(int)", p0));
    }

    function logUint(uint p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
    }

    function logString(string memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function logBool(bool p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function logAddress(address p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function logBytes(bytes memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
    }

    function logBytes1(bytes1 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
    }

    function logBytes2(bytes2 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
    }

    function logBytes3(bytes3 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
    }

    function logBytes4(bytes4 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
    }

    function logBytes5(bytes5 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
    }

    function logBytes6(bytes6 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
    }

    function logBytes7(bytes7 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
    }

    function logBytes8(bytes8 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
    }

    function logBytes9(bytes9 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
    }

    function logBytes10(bytes10 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
    }

    function logBytes11(bytes11 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
    }

    function logBytes12(bytes12 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
    }

    function logBytes13(bytes13 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
    }

    function logBytes14(bytes14 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
    }

    function logBytes15(bytes15 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
    }

    function logBytes16(bytes16 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
    }

    function logBytes17(bytes17 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
    }

    function logBytes18(bytes18 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
    }

    function logBytes19(bytes19 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
    }

    function logBytes20(bytes20 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
    }

    function logBytes21(bytes21 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
    }

    function logBytes22(bytes22 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
    }

    function logBytes23(bytes23 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
    }

    function logBytes24(bytes24 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
    }

    function logBytes25(bytes25 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
    }

    function logBytes26(bytes26 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
    }

    function logBytes27(bytes27 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
    }

    function logBytes28(bytes28 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
    }

    function logBytes29(bytes29 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
    }

    function logBytes30(bytes30 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
    }

    function logBytes31(bytes31 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
    }

    function logBytes32(bytes32 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
    }

    function log(uint p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
    }

    function log(string memory p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
    }

    function log(bool p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
    }

    function log(address p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
    }

    function log(uint p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
    }

    function log(uint p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
    }

    function log(uint p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
    }

    function log(uint p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
    }

    function log(string memory p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
    }

    function log(string memory p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
    }

    function log(string memory p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
    }

    function log(string memory p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
    }

    function log(bool p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
    }

    function log(bool p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
    }

    function log(bool p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
    }

    function log(bool p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
    }

    function log(address p0, uint p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
    }

    function log(address p0, string memory p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
    }

    function log(address p0, bool p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
    }

    function log(address p0, address p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
    }

    function log(uint p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
    }

    function log(uint p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
    }

    function log(uint p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
    }

    function log(uint p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
    }

    function log(uint p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
    }

    function log(uint p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
    }

    function log(uint p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
    }

    function log(uint p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
    }

    function log(uint p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
    }

    function log(uint p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
    }

    function log(uint p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
    }

    function log(uint p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
    }

    function log(uint p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
    }

    function log(string memory p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
    }

    function log(string memory p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
    }

    function log(string memory p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
    }

    function log(string memory p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
    }

    function log(string memory p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
    }

    function log(string memory p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
    }

    function log(string memory p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
    }

    function log(bool p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
    }

    function log(bool p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
    }

    function log(bool p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
    }

    function log(bool p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
    }

    function log(bool p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
    }

    function log(bool p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
    }

    function log(bool p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
    }

    function log(bool p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
    }

    function log(bool p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
    }

    function log(bool p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
    }

    function log(bool p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
    }

    function log(bool p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
    }

    function log(bool p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
    }

    function log(address p0, uint p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
    }

    function log(address p0, uint p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
    }

    function log(address p0, uint p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
    }

    function log(address p0, uint p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
    }

    function log(address p0, string memory p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
    }

    function log(address p0, string memory p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
    }

    function log(address p0, string memory p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
    }

    function log(address p0, string memory p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
    }

    function log(address p0, bool p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
    }

    function log(address p0, bool p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
    }

    function log(address p0, bool p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
    }

    function log(address p0, bool p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
    }

    function log(address p0, address p1, uint p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
    }

    function log(address p0, address p1, string memory p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
    }

    function log(address p0, address p1, bool p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
    }

    function log(address p0, address p1, address p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
    }

    function log(uint p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
    }

    function log(uint p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
    }

    function log(string memory p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
    }

    function log(bool p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, uint p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, string memory p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, bool p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, uint p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, string memory p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, bool p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, uint p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, string memory p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, bool p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
    }

    function log(address p0, address p1, address p2, address p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
    }

}

File 3 of 10 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 4 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";

File 5 of 10 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 6 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 7 of 10 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 8 of 10 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 9 of 10 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 10 of 10 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "remappings": [
    "@ensdomains/=node_modules/@ensdomains/",
    "@ethereum-waffle/=node_modules/@ethereum-waffle/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@pancakeswap/=node_modules/@pancakeswap/",
    "@prb/math/=lib/prb-math/src/",
    "@prb/test/=lib/prb-test/src/",
    "@uniswap/=node_modules/@uniswap/",
    "Common/=lib/Common/",
    "ERC20/=lib/ERC20/",
    "Governance/=lib/Governance/",
    "Math/=lib/Math/",
    "Staking/=lib/Staking/",
    "Utils/=lib/Utils/",
    "base64-sol/=node_modules/base64-sol/",
    "communal/=lib/communal/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "layerzerolabs/=lib/solidity-examples/",
    "local/=src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin/",
    "prb-math/=lib/prb-math/src/",
    "prb-test/=lib/prb-math/lib/prb-test/src/",
    "solidity-examples/=lib/solidity-examples/contracts/",
    "solmate/=lib/solmate/src/",
    "src/=lib/prb-math/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 9999
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"tokenA_addr","type":"address"},{"internalType":"address","name":"tokenB_addr","type":"address"},{"internalType":"address","name":"tokenC_addr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"valueA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueC","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"locktime","type":"uint256"},{"indexed":false,"internalType":"enum VotingEscrow.DepositType","name":"deposit_type","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"prevSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"valueA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueB","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"valueC","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"MAXTIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"add_to_whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"_t","type":"uint256"}],"name":"balanceOfAtT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bpt_boost_weight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newController","type":"address"}],"name":"changeController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"contracts_whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_valueA","type":"uint256"},{"internalType":"uint256","name":"_valueB","type":"uint256"},{"internalType":"uint256","name":"_valueC","type":"uint256"},{"internalType":"uint256","name":"_unlock_time","type":"uint256"}],"name":"create_lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_valueA","type":"uint256"},{"internalType":"uint256","name":"_valueB","type":"uint256"},{"internalType":"uint256","name":"_valueC","type":"uint256"}],"name":"deposit_for","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"get_last_user_slope","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_valueA","type":"uint256"},{"internalType":"uint256","name":"_valueB","type":"uint256"},{"internalType":"uint256","name":"_valueC","type":"uint256"}],"name":"increase_amount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_valueA","type":"uint256"},{"internalType":"uint256","name":"_valueB","type":"uint256"},{"internalType":"uint256","name":"_valueC","type":"uint256"},{"internalType":"uint256","name":"_unlock_time","type":"uint256"}],"name":"increase_amount_and_time","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlock_time","type":"uint256"}],"name":"increase_unlock_time","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"amountC","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"locked__amountA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"locked__amountB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"locked__amountC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"locked__end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool2_boost_weight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"remove_from_whitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slope_changes","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_block","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"t","type":"uint256"}],"name":"totalSupplyAtT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transfersEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"weight","type":"uint256"}],"name":"update_bpt_boost_weight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"weight","type":"uint256"}],"name":"update_pool2_boost_weight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"user_point_epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"user_point_history__ts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bptAmount","type":"uint256"},{"internalType":"uint256","name":"pool2Amount","type":"uint256"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"weighted_amount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_valueA","type":"uint256"},{"internalType":"uint256","name":"_valueB","type":"uint256"},{"internalType":"uint256","name":"_valueC","type":"uint256"},{"internalType":"uint256","name":"_unlock_time","type":"uint256"}],"name":"withdraw_and_create_lock","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e034620001b357601f6200445f38819003918201601f19168301916001600160401b03831184841017620001b857808492606094604052833981010312620001b35760406200004f82620001ce565b916200006b826200006360208401620001ce565b9201620001ce565b60008054336001600160a01b0319821681178355855196929492916001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08680a36001805560805260a05260c0526722b1c8c1227a00006002556730927f74c9de0000600355808052600860205220436002820155600142910155600c54600160a01b9060ff60a01b1933169060018060a81b0319161717600c5561427b9081620001e482396080518181816116bc0152818161180901528181611bbf0152818161202a0152818161337a015281816137640152613d0c015260a051818181610fca0152818161168001528181611bef0152818161205b015281816133400152818161372a0152613cd3015260c05181818161055c0152818161164401528181611e520152818161229201528181613306015281816136f00152613c9a0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001b35756fe608080604052600436101561001357600080fd5b60003560e01c908163010ae7571461186457508063047fc9aa1461184657806306fdde0314610c8c578063082ccd2d1461182d5780630fc63d10146117e957806313c71fd2146117bd57806318160ddd1461178e5780631df23cc2146117515780631df60b69146116fc578063289381dc1461138657806328d09d471461130957806329d8d00e1461117f578063313ce567146111635780633617a2041461112457806337c0850e146111065780633ccfd60b146110e55780633cebb823146110895780634ee2cd7e1461106257806354fd4d501461100c5780635b51c30814610fee5780635f64b55b14610faa57806365003a1314610f7e5780636a5e265014610f5b57806370a0823114610f365780637116c60c14610f005780637119748414610ed1578063715018a614610e605780637c74a17414610e0d578063842a7ebd14610dd05780638da5cb5b14610da9578063900cf0cf14610d8b57806390fad1e614610cce5780639493128414610c9157806395d89b4114610c8c578063981b24d014610b51578063a1a2c30c14610afe578063a58d08e214610ae0578063a69df4b514610a9a578063a80f67fb14610a3a578063ac25f2661461097b578063adc635891461093e578063bef97c8714610918578063c2c4c5c114610580578063c483a3081461053c578063cbf9fe5f146104d3578063d07b705f146104a4578063d1febfb91461043f578063da020a18146103f6578063ee00ef3a146103d7578063eff7a61214610377578063f2fde38b146102875763f77c47911461025b57600080fd5b346102825760006003193601126102825760206001600160a01b03600c5416604051908152f35b600080fd5b34610282576020600319360112610282576102a061189a565b6102a8611aae565b6001600160a01b0380911690811561030d57600054827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b608460405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b3461028257602060031936011261028257610390612d66565b3233036103b8575b6103a760ff60055416156124bf565b6103b26004356137a4565b60018055005b33600052600d6020526103d260ff60406000205416613032565b610398565b346102825760006003193601126102825760206040516301e91c808152f35b34610282576040600319360112610282576001600160a01b0361041761189a565b166000526009602052602060016104346024356040600020611a4a565b500154604051908152f35b34610282576020600319360112610282576004356000526008602052604060002080546104a0600260018401549301546040519383859460801d90600f0b85909493926060926080830196600f0b8352600f0b602083015260408201520152565b0390f35b346102825760406003193601126102825760206104cb6104c261189a565b60243590613dd3565b604051908152f35b34610282576020600319360112610282576001600160a01b036104f461189a565b16600052600660205260a060406000208054600f0b90600181015490600281015460046003830154920154926040519485526020850152604084015260608301526080820152f35b346102825760006003193601126102825760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610282576000600319360112610282576105a060ff60055416156124bf565b6105a8611bb4565b604051906105b5826118b0565b600f0b81526020810190600082526106306040820160008152606083016000815260006080850152600060806105e9611bb4565b600f0b604051906105f9826118b0565b8152826020820152826040820152826060820152015261061761250a565b5061062061250a565b506007549451915190519161201e565b600f0b9052604051610641816118fb565b6000815260006020820152426040820152436060820152816108fc575b6040810151806060830151906000918342116108bd575b62093a80840462093a8081029080820462093a80149015171561085557936000945b60ff861061070b575b6107098789806007556000526008602052604060002090606060029180516fffffffffffffffffffffffffffffffff1980865416916fffffffffffffffffffffffffffffffff168092178655602083015160801b16178455604081015160018501550151910155565b005b62093a80810180911161085557600090804281111561089857505061076c60009161075a61075042955b61074760208d0151600f0b918861252f565b600f0b9061253c565b8a51600f0b6125b7565b600f0b89526020890151600f0b6125fe565b600f0b806020890152818851600f0b12610890575b12610884575b80948160408801526107b5670de0b6b3a76400006107ae6107a8878661252f565b88611b51565b0484611ba7565b60608801526001880180981161085557874283036107e95750505050505050610709914360608301529183808080806106a0565b6000908152600860209081526040918290208951918a015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909216919091178155908801516001820155606088015160029091015561084e9061258a565b9490610697565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006020870152610787565b818852610781565b600092509261076c91938352600b60205261075a6107506040852054600f0b92610735565b91506108c9824361252f565b670de0b6b3a76400009080820291820403610855576108f6906108f060408701514261252f565b90611b9d565b91610675565b508060005260086020526109136040600020612553565b61065e565b3461028257600060031936011261028257602060ff600c5460a01c166040519015158152f35b34610282576020600319360112610282576001600160a01b0361095f61189a565b1660005260066020526020600460406000200154604051908152f35b34610282576020600319360112610282576001600160a01b0361099c61189a565b6109a4611aae565b1680600052600d60205260ff604060002054166109f657600052600d602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055600080f35b606460405162461bcd60e51b815260206004820152601b60248201527f4164647265737320616c72656164792077686974656c697374656400000000006044820152fd5b34610282576103b2610a4b36611a90565b92610a57929192612d66565b323303610a7b575b610a6e60ff60055416156124bf565b610a76613af6565b61307d565b33600052600d602052610a9560ff60406000205416613032565b610a5f565b3461028257600060031936011261028257610ab3611aae565b600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055005b34610282576000600319360112610282576020600254604051908152f35b34610282576103b2610b0f36611a90565b92610b1b929192612d66565b323303610b32575b610a7660ff60055416156124bf565b33600052600d602052610b4c60ff60406000205416613032565b610b23565b34610282576020600319360112610282576004354381116102825760075490610b7a82826140a7565b806000526008602052610b906040600020612553565b906000938110600014610c365760018101809111610855576020936104cb93610bec9260005260088652610bc76040600020612553565b60608501908151606082019384518203610bf2575b50505050505b6040830151611ba7565b9061414b565b610c2c955091610c1c6040610c0e610c22946108f0979661252f565b92015160408a01519061252f565b90611b51565b925190519061252f565b8580808080610bdc565b50610bec6020936104cb936060840190815190438203610c59575b505050610be2565b610c849350610c6e6108f092610c7c9261252f565b610c1c60408801514261252f565b91514361252f565b858080610c51565b6119da565b34610282576020600319360112610282576001600160a01b03610cb261189a565b1660005260066020526020600160406000200154604051908152f35b34610282576020600319360112610282576001600160a01b03610cef61189a565b610cf7611aae565b1680600052600d60205260ff6040600020541615610d4757600052600d60205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055600080f35b606460405162461bcd60e51b815260206004820152601760248201527f41646472657373206e6f742077686974656c69737465640000000000000000006044820152fd5b34610282576000600319360112610282576020600754604051908152f35b346102825760006003193601126102825760206001600160a01b0360005416604051908152f35b34610282576020600319360112610282576001600160a01b03610df161189a565b1660005260066020526020600360406000200154604051908152f35b34610282576020600319360112610282576001600160a01b03610e2e61189a565b16600052600a6020526020610e50604060002054600983526040600020611a4a565b505460801d60405190600f0b8152f35b3461028257600060031936011261028257610e79611aae565b60006001600160a01b0381547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461028257602060031936011261028257600435600052600b6020526020604060002054600f0b604051908152f35b3461028257602060031936011261028257600754600052600860205260206104cb600435610f316040600020612553565b61414b565b346102825760206003193601126102825760206104cb610f5461189a565b4290613dd3565b3461028257600060031936011261028257602060ff600554166040519015158152f35b3461028257602060031936011261028257600435610f9a611aae565b610fa5811515611b06565b600255005b346102825760006003193601126102825760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102825760006003193601126102825760206040516224ea008152f35b34610282576000600319360112610282576104a060405161102c81611917565b600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015260405191829182611974565b346102825760406003193601126102825760206104cb61108061189a565b60243590613e9c565b34610282576020600319360112610282576110a261189a565b600c54906001600160a01b038083163303610282577fffffffffffffffffffffffff00000000000000000000000000000000000000009116911617600c55600080f35b34610282576000600319360112610282576110fe612d66565b6103b2613af6565b34610282576000600319360112610282576020600354604051908152f35b34610282576020600319360112610282576001600160a01b0361114561189a565b16600052600d602052602060ff604060002054166040519015158152f35b3461028257600060031936011261028257602060405160128152f35b346102825761118d36611a90565b92611199929192612d66565b3233036112ea575b6111b060ff60055416156124bf565b8015801580826112e1575b80156112d8575b80156112cf575b1561126557808261125c575b8015611253575b8061124a575b156111fd575050916111f8916103b294936134b3565b6137a4565b90611241575b8015611238575b80611230575b156112245761121f93506134b3565b6103b2565b50505061121f906137a4565b508315611210565b5082151561120a565b50811515611203565b508515156111e2565b508415156111dc565b508315156111d5565b608460405162461bcd60e51b815260206004820152602160248201527f56616c756520616e6420556e6c6f636b2063616e6e6f7420626f74682062652060448201527f30000000000000000000000000000000000000000000000000000000000000006064820152fd5b508515156111c9565b508415156111c2565b508315156111bb565b33600052600d60205261130460ff60406000205416613032565b6111a1565b346102825760406003193601126102825761132261189a565b6001600160a01b0360243591166000526009602052604060002090633b9aca008110156102825761135291611a4a565b508054600182015460029092015460408051600f84810b8252608094851d900b602082015290810193909352606083015290f35b346102825760806003193601126102825761139f61189a565b6113a7612d66565b6001600160a01b0381166000526006602052604060002090604051906113cc826118b0565b60048354600f0b93848452600181015460208501526002810154604085015260038101546060850152015460808301526024351590811580926116f1575b80156116e6575b1561028257608060409361144860007f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9713612cab565b611456828201514210612cf6565b6004549361147461146e60643560443560243561201e565b86611ba7565b60045561159d828751611486816118b0565b600081526000602082015260008982015260006060820152858101600081526114bc60208401518b85015160608601519161201e565b600f0b9081845287840151905281526114ec6114df60643560443560243561201e565b600f0b8351600f0b6125fe565b600f0b82526115016024356020840151611ba7565b60208301526115156044358a840151611ba7565b898301526115296064356060840151611ba7565b60608301526001600160a01b03871660005260066020528860002082516fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16178155602083015160018201558983015160028201556060830151600382015560048784015191015586612645565b6116aa575b60443561166e575b606435611632575b0151907fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a06001600160a01b038651936024358552604435602086015260643588860152600060608601524260808601521692a361162161161b60643560443560243561201e565b82611ba7565b82519182526020820152a160018055005b61166960643530336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b6115b2565b6116a560443530336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b6115aa565b6116e160243530336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b6115a2565b506064351515611411565b50604435151561140a565b34610282576103b261170d36611a30565b91611716612d66565b323303611732575b61172d60ff60055416156124bf565b6134b3565b33600052600d60205261174c60ff60406000205416613032565b61171e565b34610282576020600319360112610282576001600160a01b0361177261189a565b1660005260066020526020600260406000200154604051908152f35b3461028257600060031936011261028257600754600052600860205260206104cb42610f316040600020612553565b34610282576020600319360112610282576004356117d9611aae565b6117e4811515611b06565b600355005b346102825760006003193601126102825760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102825760206104cb61184036611a30565b9161201e565b34610282576000600319360112610282576020600454604051908152f35b34610282576020600319360112610282576020906001600160a01b0361188861189a565b16600052600a82526040600020548152f35b600435906001600160a01b038216820361028257565b60a0810190811067ffffffffffffffff8211176118cc57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176118cc57604052565b6040810190811067ffffffffffffffff8211176118cc57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176118cc57604052565b60208082528251818301819052939260005b8581106119c6575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b818101830151848201604001528201611986565b34610282576000600319360112610282576104a06040516119fa81611917565b600581527f7664555348000000000000000000000000000000000000000000000000000000602082015260405191829182611974565b600319606091011261028257600435906024359060443590565b90633b9aca00811015611a61576003020190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60031960809101126102825760043590602435906044359060643590565b6001600160a01b03600054163303611ac257565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15611b0d57565b606460405162461bcd60e51b815260206004820152601d60248201527f43616e6e6f7420736574207a65726f20626f6f737420776569676874210000006044820152fd5b8181029291811591840414171561085557565b15611b6e57600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115611b6e570490565b9190820180921161085557565b6001600160a01b03907f00000000000000000000000000000000000000000000000000000000000000008216600081611d955750506000915b7f00000000000000000000000000000000000000000000000000000000000000001691604051927f0902f1ac000000000000000000000000000000000000000000000000000000008452606084600481845afa938415611d3157600094611d3d575b5060206dffffffffffffffffffffffffffff600494951691611c7083612457565b604051948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa928315611d3157600093611cfb575b50611cb583612457565b156001171561085557611ce6611cf1611cd0611cf894611b64565b92670de0b6b3a764000092839160025490611b51565b049260035490611b51565b0490611ba7565b90565b90926020823d8211611d29575b81611d1560209383611933565b81010312611d265750519138611cab565b80fd5b3d9150611d08565b6040513d6000823e3d90fd5b936060853d8211611d8d575b81611d5660609383611933565b81010312611d2657611d678561243c565b506040611d766020870161243c565b95015163ffffffff811603611d2657506020611c4f565b3d9150611d49565b6040918251907f8d928af80000000000000000000000000000000000000000000000000000000082526020918281600481855afa908115611f99578491611fe9575b5084517f38fff2d00000000000000000000000000000000000000000000000000000000081528381600481865afa908115611fdf579088949392918691611fa3575b50906044608092885196879384927fb05f8e480000000000000000000000000000000000000000000000000000000084526004840152817f0000000000000000000000000000000000000000000000000000000000000000166024840152165afa928315611f99578493611f4d575b5090806004928651938480927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa948515611f4457508394611f10575b50501560011715611ee35750611edd90611b64565b91611bed565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b9080929450813d8311611f3d575b611f288183611933565b81010312611f395751913880611ec8565b5080fd5b503d611f1e565b513d85823e3d90fd5b9092506080813d8211611f91575b81611f6860809383611933565b81010312611f8d57908082611f836060600495519201612428565b5093919250611e88565b8380fd5b3d9150611f5b565b85513d86823e3d90fd5b848096508193949592503d8311611fd8575b611fbf8183611933565b81010312611fd4575187939291906044611e19565b8480fd5b503d611fb5565b86513d87823e3d90fd5b90508281813d8311612017575b6120008183611933565b81010312611f8d5761201190612428565b38611dd7565b503d611ff6565b6001600160a01b0391907f000000000000000000000000000000000000000000000000000000000000000083166000816121d4575050506000915b7f000000000000000000000000000000000000000000000000000000000000000016906040517f0902f1ac000000000000000000000000000000000000000000000000000000008152606081600481865afa908115611d315760009161217c575b509060206dffffffffffffffffffffffffffff6004949316926120dc84612457565b604051948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa928315611d3157600093612147575b50611cf1611cd08461213d611cf8989795611ce69561213861214299612457565b611b51565b611b9d565b611ba7565b90926020823d8211612174575b8161216160209383611933565b81010312611d2657505191611cf1612117565b3d9150612154565b906060823d82116121cc575b8161219560609383611933565b81010312611d26576121a68261243c565b5060406121b56020840161243c565b92015163ffffffff811603611d26575060206120ba565b3d9150612188565b6040918251907f8d928af80000000000000000000000000000000000000000000000000000000082526020918281600481855afa908115611f995784916123f3575b5084517f38fff2d00000000000000000000000000000000000000000000000000000000081528381600481865afa908115611fdf579085949392918a96916123b9575b50906044608092885197889384927fb05f8e480000000000000000000000000000000000000000000000000000000084526004840152817f0000000000000000000000000000000000000000000000000000000000000000166024840152165afa9384156123af578394612361575b509080600493928651948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa9485156123565750819461231f575b50505061213d9061231993611b51565b91612059565b909180939450813d831161234f575b6123388183611933565b81010312611d26575051908061231961213d612309565b503d61232e565b51913d9150823e3d90fd5b9093506080813d82116123a7575b8161237c60809383611933565b810103126123a357908082612398606060049695519201612428565b5094919293506122c8565b8280fd5b3d915061236f565b85513d85823e3d90fd5b84809697508193949592503d83116123ec575b6123d68183611933565b81010312611fd457518894939291906044612259565b503d6123cc565b90508281813d8311612421575b61240a8183611933565b81010312611f8d5761241b90612428565b38612216565b503d612400565b51906001600160a01b038216820361028257565b51906dffffffffffffffffffffffffffff8216820361028257565b6040519060208201907ff5b1bba9000000000000000000000000000000000000000000000000000000008252602483015260248252606082019082821067ffffffffffffffff8311176118cc57600092839260405251906a636f6e736f6c652e6c6f675afa50565b156124c657565b606460405162461bcd60e51b815260206004820152601160248201527f756e6c6f636b656420676c6f62616c6c790000000000000000000000000000006044820152fd5b60405190612517826118fb565b60006060838281528260208201528260408201520152565b9190820391821161085557565b90600f0b90600f0b029081600f0b91820361085557565b90604051612560816118fb565b606060028294805480600f0b855260801d600f0b6020850152600181015460408501520154910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146108555760010190565b90600f0b90600f0b03906f7fffffffffffffffffffffffffffffff82137fffffffffffffffffffffffffffffffff8000000000000000000000000000000083121761085557565b90600f0b90600f0b01907fffffffffffffffffffffffffffffffff8000000000000000000000000000000082126f7fffffffffffffffffffffffffffffff83131761085557565b909161264f61250a565b61265761250a565b9360009283926007546126786020850151604086015160608701519161201e565b600f0b8085526001600160a01b038816612bc6575b5060405161269a816118fb565b60008152600060208201524260408201524360608201529080612ba8575b604082015180606084015191600092824211612b67575b62093a809283810484810290808204861490151715610855576000915b60ff83106129f2575b505050505050509081612774926007556001600160a01b038916612974575b6000526008602052604060002090606060029180516fffffffffffffffffffffffffffffffff1980865416916fffffffffffffffffffffffffffffffff168092178655602083015160801b16178455604081015160018501550151910155565b6001600160a01b03861661278c575b50505050505050565b608080930194428651116128fa575b50500191825190428211612898575b505050506001600160a01b038116600052600a60205260406000205460018101809111610855576001600160a01b03828161280e9416600052600a602052826040600020554260408601524360608601521660005260096020526040600020611a4a565b919091612869578051602082015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909116178255604081015160018301556060015160029091015538808080808080612783565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b51106128a6575b80806127aa565b6128b8906020850151600f0b906125b7565b9051600052600b6020526040600020906fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16179055388061289f565b602061290b920151600f0b906125fe565b808383015186511461295b575b508451600052600b6020526040600020906fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16179055388061279b565b61296e91506020880151600f0b906125b7565b38612918565b600061298f60208c0151600f0b6020870151600f0b906125b7565b6129a160208501918251600f0b6125fe565b600f0b81526129c66129bc8d51600f0b8851600f0b906125b7565b8551600f0b6125fe565b600f0b90818552828151600f0b126129e9575b5012156127145760008252612714565b829052386129d9565b8582018092116108555788916000908042811115612b43575050612a47600091612a38612a2e602042975b01956107478751600f0b918961252f565b8d51600f0b6125b7565b600f0b8c528351600f0b6125fe565b600f0b808352818b51600f0b12612b3b575b12612b31575b5080918160408a0152612a8e670de0b6b3a7640000612a87612a81888661252f565b8a611b51565b0485611ba7565b60608a0152600188018098116108555787428303612ac6575050505050505050906127749143606083015290913880808080806126f5565b6000908152600860209081526040918290208b51918c015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909216919091178155908a0151600182015560608a0151600290910155612b2b9061258a565b916126ec565b6000905238612a5f565b818b52612a59565b93612a38612a2e6020604086612a47969960009852600b83522054600f0b93612a1d565b92612b72844361252f565b670de0b6b3a76400009182828102048203611ee3575090612ba291612b9b60408901514261252f565b9102611b9d565b926126cf565b8091506000526008602052612bc06040600020612553565b906126b8565b95604091966080860151421080612ca2575b612c76575b504260808501511180612c69575b612c3a575b60808501518152600b6020522054600f0b946080830151801561268d5790945060808401518114600014612c28575084935b3861268d565b600052604060002054600f0b93612c22565b612c5f6301e91c808551600f0b05600f0b8060208c015261074742608088015161252f565b600f0b8952612bf0565b50808451600f0b13612beb565b6301e91c80612c979105600f0b80602086015261074742608089015161252f565b600f0b835238612bdd565b50818113612bd8565b15612cb257565b606460405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152fd5b15612cfd57565b608460405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152fd5b600260015414612d77576002600155565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b9092612e1893604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b038092166024860152166044840152606483015260648252612e13826118b0565b612e1a565b565b6001600160a01b031690604051612e3081611917565b6020928382527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564848301526000808486829651910182855af13d15612f94573d9167ffffffffffffffff8311612f675790612ec993929160405192612ebc887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160185611933565b83523d868885013e612f9e565b805180612ed7575b50505050565b81849181010312611f395782015190811591821503611d265750612efd57808080612ed1565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b90612ec992916060915b91929015612fff5750815115612fb2575090565b3b15612fbb5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156130125750805190602001fd5b61302e9060405191829162461bcd60e51b835260048301611974565b0390fd5b1561303957565b606460405162461bcd60e51b815260206004820152601a60248201527f536d61727420636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152fd5b9290918315801580916134aa575b80156134a1575b1561028257336000526006602052604060002091604051926130b3846118b0565b60048154600f0b918286526001810154602087015260028101546040870152600381015460608701520154608085015261345d576224ea0042018042116108555784106133f4576301e91c8042018042116108555784116133b05762093a80809404948585810204851486151715610855577f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9660808561161b9561328e6132e99860409b6004549b6131718d61316b8c8c8c61201e565b90611ba7565b6004558d5191613180836118b0565b600083526000602084015260008f84015260006060840152878301600081526131b76020860151604087015160608801519161201e565b600f0b9081865289860151905283526131e16131d48c8c8c61201e565b600f0b8551600f0b6125fe565b600f0b84526131f4896020860151611ba7565b60208501526132078f8b90860151611ba7565b8f8501526132198b6060860151611ba7565b60608501528181026133a4575b50503360005260066020528c60002082516fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16178155602083015160018201558d83015160028201556060830151600382015560048784015191015533612645565b61336a575b83613330575b846132f6575b015187518281528360208201528489820152600160608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a361201e565b82519182526020820152a1565b61332b8530336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b61329f565b6133658430336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b613299565b61339f8330336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b613293565b02868301523880613226565b606460405162461bcd60e51b815260206004820152601d60248201527f566f74696e67206c6f636b2063616e20626520312079656172206d61780000006044820152fd5b608460405162461bcd60e51b8152602060048201526024808201527f566f74696e67206c6f636b206d757374206265206174206c65617374204d494e60448201527f54494d45000000000000000000000000000000000000000000000000000000006064820152fd5b606460405162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006044820152fd5b50811515613092565b5083151561308b565b9160009033825260209060068252604093848420918551916134d4836118b0565b8354600f0b928381526001850154868201908152600286015495898301968752600460038201549160608501928352015496608084019788528b15968715809861379b575b8015613792575b1561378e57908a8d959493921361353690612cab565b8851421061354390612cf6565b8b6004549b8c6135548a8a8a61201e565b61355d91611ba7565b60045581519661356c886118b0565b818852818d890152818389015281606089015260808801828152865185518751906135969261201e565b600f0b908189528d51905288526135ae8a8a8361201e565b600f0b8751600f0b906135c0916125fe565b600f0b87528551906135d191611ba7565b8552878351906135e091611ba7565b8352888451906135ef91611ba7565b845233815260068c522092845184546fffffffffffffffffffffffffffffffff1916906fffffffffffffffffffffffffffffffff1617845551600184015551600283015551600382015586519060040155339161364b92612645565b7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c976136d4946136ce94613754575b8261371a575b836136e0575b5188518281528388820152848a820152600260608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a361201e565b83611ba7565b908351928352820152a1565b6137158430336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b613686565b61374f8330336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b613680565b6137898230336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612dbb565b61367a565b8a80fd5b50861515613520565b50851515613519565b600033815260209060068252604092838220908451906137c3826118b0565b825492600f93840b8352600181015491868401928352600282015488850190815260038301549160608601928352600480940154966080870197885262093a80809204828102928184041490151715613aca578751421015613a8857888751820b1315613a46578751821115613a04576301e91c8042018042116139d857821161399657938896938a989692938c9b9461393f976138899c7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9f86549e8f61316b611bb4565b8755818151996138988b6118b0565b818b528a01528801528a6060880152608087018b81526138bd8751855187519161201e565b820b90818a528b51905287526138df6138d4611bb4565b820b8951830b6125fe565b900b87528061398e575b5033895260068a528b89209386516fffffffffffffffffffffffffffffffff19865416906fffffffffffffffffffffffffffffffff16178555516001850155516002840155516003830155855191015533612645565b5190845190808252808483015285820152600360608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a36136d46136ce611bb4565b8852386138e9565b6064858b8d519162461bcd60e51b8352820152601e60248201527f566f74696e67206c6f636b2063616e2062652033207965617273206d617800006044820152fd5b60248a6011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6064858b8d519162461bcd60e51b8352820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152fd5b6064858b8d519162461bcd60e51b8352820152601160248201527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006044820152fd5b6064858b8d519162461bcd60e51b8352820152600c60248201527f4c6f636b206578706972656400000000000000000000000000000000000000006044820152fd5b6024896011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6000903382526020916006835260409081812093825191613b16836118b0565b8554600f0b95868452600181015491828486015260028201549081878701526004600384015493846060890152015480608088015260ff6005541615613d36575b50916136d49391613c3a7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c999a948951613b90816118b0565b8181526004898c81840185815281850190868252606086019287845260066080880195898752338a5252872095516fffffffffffffffffffffffffffffffff19875416906fffffffffffffffffffffffffffffffff161786555160018601555160028501555160038401555191015560045498613c0d878b61252f565b6004558a5191613c1c836118b0565b808352808a840152808c840152806060840152608083015233612645565b82613cfd575b80613cc4575b81613c8b575b875192835285830152868201524260608201527fe08737ac48a1dab4b1a46c7dc9398bd5bfc6d7ad6fabb7cd8caa254de14def3560803392a28361252f565b613cbf82336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613d85565b613c4c565b613cf881336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613d85565b613c46565b613d3183336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613d85565b613c40565b4210613d425738613b57565b60648588519062461bcd60e51b82526004820152601660248201527f546865206c6f636b206469646e277420657870697265000000000000000000006044820152fd5b612e18926001600160a01b03604051937fa9059cbb000000000000000000000000000000000000000000000000000000006020860152166024840152604483015260448252612e13826118fb565b6001600160a01b03166000908152600a602052604081205480613df65750905090565b613e0b613e1191600960205260408420611a4a565b50612553565b91602083015190604084015190838282039212818312811691831390151617613e6f57613e498392613e5392600f0b90600f0b61253c565b8451600f0b6125b7565b600f0b80845212613e67575b5051600f0b90565b815238613e5f565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b438211610282576001600160a01b036000911690818152602090600a82526040928382205482905b60808210614017575b5050613ee791613e0b916000526009845284600020611a4a565b9260075492613ef684836140a7565b8060005260088452613f0a82600020612553565b94811015613fe6576001810180911161085557600094613f9694613f8c94613f8093885260088252613f3d858920612553565b90613f6286613f55606085015160608801519061252f565b930151878601519061252f565b905b868501519483613fc0575b50505050870151928701519061252f565b600f0b90600f0b61253c565b8351600f0b6125b7565b600f81900b928390529112613fba576fffffffffffffffffffffffffffffffff1690565b50600090565b61316b92610c1c613fdc96979593606061213d9401519061252f565b9038808080613f6f565b50613f8084613f9694613f8c94614003606060009901514361252f565b90614011868501514261252f565b90613f64565b9092818110156140a15761402b8282611ba7565b6001808201809211610855571c908360005260098652876002614051848a600020611a4a565b5001541161406a5750614064909361258a565b90613ec4565b9391507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161085557614064909161258a565b92613ecd565b6000919082915b608083106140bd575b50505090565b90919281811015614145576140d28282611ba7565b6001808201809211610855571c9081600052600860205283600260406000200154111560001461410e5750614107909361258a565b91906140ae565b9391507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161085557614107909161258a565b926140b7565b91909160409283820162093a80918282510483810290808204851490151715610855579560005b60ff81106141ae575b50505050506fffffffffffffffffffffffffffffffff91925060008151600f0b126141a557511690565b60008152511690565b84880180981161085557600097808481111561423157505082975b60208701908151906141fa6141f16141e38d8a519061252f565b93600f94850b90850b61253c565b8a51840b6125b7565b820b8952858b1461422957906142188392614224959451830b6125fe565b900b905288855261258a565b614172565b50505061417b565b8952600b6020529782902054600f0b6141c956fea2646970667358221220a645b8a50c69df54434d9c8b100309c5fbb7e648d57f7b5e42b9e566dbf6eecc64736f6c63430008120033000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f312000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c908163010ae7571461186457508063047fc9aa1461184657806306fdde0314610c8c578063082ccd2d1461182d5780630fc63d10146117e957806313c71fd2146117bd57806318160ddd1461178e5780631df23cc2146117515780631df60b69146116fc578063289381dc1461138657806328d09d471461130957806329d8d00e1461117f578063313ce567146111635780633617a2041461112457806337c0850e146111065780633ccfd60b146110e55780633cebb823146110895780634ee2cd7e1461106257806354fd4d501461100c5780635b51c30814610fee5780635f64b55b14610faa57806365003a1314610f7e5780636a5e265014610f5b57806370a0823114610f365780637116c60c14610f005780637119748414610ed1578063715018a614610e605780637c74a17414610e0d578063842a7ebd14610dd05780638da5cb5b14610da9578063900cf0cf14610d8b57806390fad1e614610cce5780639493128414610c9157806395d89b4114610c8c578063981b24d014610b51578063a1a2c30c14610afe578063a58d08e214610ae0578063a69df4b514610a9a578063a80f67fb14610a3a578063ac25f2661461097b578063adc635891461093e578063bef97c8714610918578063c2c4c5c114610580578063c483a3081461053c578063cbf9fe5f146104d3578063d07b705f146104a4578063d1febfb91461043f578063da020a18146103f6578063ee00ef3a146103d7578063eff7a61214610377578063f2fde38b146102875763f77c47911461025b57600080fd5b346102825760006003193601126102825760206001600160a01b03600c5416604051908152f35b600080fd5b34610282576020600319360112610282576102a061189a565b6102a8611aae565b6001600160a01b0380911690811561030d57600054827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b608460405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b3461028257602060031936011261028257610390612d66565b3233036103b8575b6103a760ff60055416156124bf565b6103b26004356137a4565b60018055005b33600052600d6020526103d260ff60406000205416613032565b610398565b346102825760006003193601126102825760206040516301e91c808152f35b34610282576040600319360112610282576001600160a01b0361041761189a565b166000526009602052602060016104346024356040600020611a4a565b500154604051908152f35b34610282576020600319360112610282576004356000526008602052604060002080546104a0600260018401549301546040519383859460801d90600f0b85909493926060926080830196600f0b8352600f0b602083015260408201520152565b0390f35b346102825760406003193601126102825760206104cb6104c261189a565b60243590613dd3565b604051908152f35b34610282576020600319360112610282576001600160a01b036104f461189a565b16600052600660205260a060406000208054600f0b90600181015490600281015460046003830154920154926040519485526020850152604084015260608301526080820152f35b346102825760006003193601126102825760206040516001600160a01b037f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48168152f35b34610282576000600319360112610282576105a060ff60055416156124bf565b6105a8611bb4565b604051906105b5826118b0565b600f0b81526020810190600082526106306040820160008152606083016000815260006080850152600060806105e9611bb4565b600f0b604051906105f9826118b0565b8152826020820152826040820152826060820152015261061761250a565b5061062061250a565b506007549451915190519161201e565b600f0b9052604051610641816118fb565b6000815260006020820152426040820152436060820152816108fc575b6040810151806060830151906000918342116108bd575b62093a80840462093a8081029080820462093a80149015171561085557936000945b60ff861061070b575b6107098789806007556000526008602052604060002090606060029180516fffffffffffffffffffffffffffffffff1980865416916fffffffffffffffffffffffffffffffff168092178655602083015160801b16178455604081015160018501550151910155565b005b62093a80810180911161085557600090804281111561089857505061076c60009161075a61075042955b61074760208d0151600f0b918861252f565b600f0b9061253c565b8a51600f0b6125b7565b600f0b89526020890151600f0b6125fe565b600f0b806020890152818851600f0b12610890575b12610884575b80948160408801526107b5670de0b6b3a76400006107ae6107a8878661252f565b88611b51565b0484611ba7565b60608801526001880180981161085557874283036107e95750505050505050610709914360608301529183808080806106a0565b6000908152600860209081526040918290208951918a015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909216919091178155908801516001820155606088015160029091015561084e9061258a565b9490610697565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006020870152610787565b818852610781565b600092509261076c91938352600b60205261075a6107506040852054600f0b92610735565b91506108c9824361252f565b670de0b6b3a76400009080820291820403610855576108f6906108f060408701514261252f565b90611b9d565b91610675565b508060005260086020526109136040600020612553565b61065e565b3461028257600060031936011261028257602060ff600c5460a01c166040519015158152f35b34610282576020600319360112610282576001600160a01b0361095f61189a565b1660005260066020526020600460406000200154604051908152f35b34610282576020600319360112610282576001600160a01b0361099c61189a565b6109a4611aae565b1680600052600d60205260ff604060002054166109f657600052600d602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055600080f35b606460405162461bcd60e51b815260206004820152601b60248201527f4164647265737320616c72656164792077686974656c697374656400000000006044820152fd5b34610282576103b2610a4b36611a90565b92610a57929192612d66565b323303610a7b575b610a6e60ff60055416156124bf565b610a76613af6565b61307d565b33600052600d602052610a9560ff60406000205416613032565b610a5f565b3461028257600060031936011261028257610ab3611aae565b600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055005b34610282576000600319360112610282576020600254604051908152f35b34610282576103b2610b0f36611a90565b92610b1b929192612d66565b323303610b32575b610a7660ff60055416156124bf565b33600052600d602052610b4c60ff60406000205416613032565b610b23565b34610282576020600319360112610282576004354381116102825760075490610b7a82826140a7565b806000526008602052610b906040600020612553565b906000938110600014610c365760018101809111610855576020936104cb93610bec9260005260088652610bc76040600020612553565b60608501908151606082019384518203610bf2575b50505050505b6040830151611ba7565b9061414b565b610c2c955091610c1c6040610c0e610c22946108f0979661252f565b92015160408a01519061252f565b90611b51565b925190519061252f565b8580808080610bdc565b50610bec6020936104cb936060840190815190438203610c59575b505050610be2565b610c849350610c6e6108f092610c7c9261252f565b610c1c60408801514261252f565b91514361252f565b858080610c51565b6119da565b34610282576020600319360112610282576001600160a01b03610cb261189a565b1660005260066020526020600160406000200154604051908152f35b34610282576020600319360112610282576001600160a01b03610cef61189a565b610cf7611aae565b1680600052600d60205260ff6040600020541615610d4757600052600d60205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055600080f35b606460405162461bcd60e51b815260206004820152601760248201527f41646472657373206e6f742077686974656c69737465640000000000000000006044820152fd5b34610282576000600319360112610282576020600754604051908152f35b346102825760006003193601126102825760206001600160a01b0360005416604051908152f35b34610282576020600319360112610282576001600160a01b03610df161189a565b1660005260066020526020600360406000200154604051908152f35b34610282576020600319360112610282576001600160a01b03610e2e61189a565b16600052600a6020526020610e50604060002054600983526040600020611a4a565b505460801d60405190600f0b8152f35b3461028257600060031936011261028257610e79611aae565b60006001600160a01b0381547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461028257602060031936011261028257600435600052600b6020526020604060002054600f0b604051908152f35b3461028257602060031936011261028257600754600052600860205260206104cb600435610f316040600020612553565b61414b565b346102825760206003193601126102825760206104cb610f5461189a565b4290613dd3565b3461028257600060031936011261028257602060ff600554166040519015158152f35b3461028257602060031936011261028257600435610f9a611aae565b610fa5811515611b06565b600255005b346102825760006003193601126102825760206040516001600160a01b037f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f312168152f35b346102825760006003193601126102825760206040516224ea008152f35b34610282576000600319360112610282576104a060405161102c81611917565b600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015260405191829182611974565b346102825760406003193601126102825760206104cb61108061189a565b60243590613e9c565b34610282576020600319360112610282576110a261189a565b600c54906001600160a01b038083163303610282577fffffffffffffffffffffffff00000000000000000000000000000000000000009116911617600c55600080f35b34610282576000600319360112610282576110fe612d66565b6103b2613af6565b34610282576000600319360112610282576020600354604051908152f35b34610282576020600319360112610282576001600160a01b0361114561189a565b16600052600d602052602060ff604060002054166040519015158152f35b3461028257600060031936011261028257602060405160128152f35b346102825761118d36611a90565b92611199929192612d66565b3233036112ea575b6111b060ff60055416156124bf565b8015801580826112e1575b80156112d8575b80156112cf575b1561126557808261125c575b8015611253575b8061124a575b156111fd575050916111f8916103b294936134b3565b6137a4565b90611241575b8015611238575b80611230575b156112245761121f93506134b3565b6103b2565b50505061121f906137a4565b508315611210565b5082151561120a565b50811515611203565b508515156111e2565b508415156111dc565b508315156111d5565b608460405162461bcd60e51b815260206004820152602160248201527f56616c756520616e6420556e6c6f636b2063616e6e6f7420626f74682062652060448201527f30000000000000000000000000000000000000000000000000000000000000006064820152fd5b508515156111c9565b508415156111c2565b508315156111bb565b33600052600d60205261130460ff60406000205416613032565b6111a1565b346102825760406003193601126102825761132261189a565b6001600160a01b0360243591166000526009602052604060002090633b9aca008110156102825761135291611a4a565b508054600182015460029092015460408051600f84810b8252608094851d900b602082015290810193909352606083015290f35b346102825760806003193601126102825761139f61189a565b6113a7612d66565b6001600160a01b0381166000526006602052604060002090604051906113cc826118b0565b60048354600f0b93848452600181015460208501526002810154604085015260038101546060850152015460808301526024351590811580926116f1575b80156116e6575b1561028257608060409361144860007f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9713612cab565b611456828201514210612cf6565b6004549361147461146e60643560443560243561201e565b86611ba7565b60045561159d828751611486816118b0565b600081526000602082015260008982015260006060820152858101600081526114bc60208401518b85015160608601519161201e565b600f0b9081845287840151905281526114ec6114df60643560443560243561201e565b600f0b8351600f0b6125fe565b600f0b82526115016024356020840151611ba7565b60208301526115156044358a840151611ba7565b898301526115296064356060840151611ba7565b60608301526001600160a01b03871660005260066020528860002082516fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16178155602083015160018201558983015160028201556060830151600382015560048784015191015586612645565b6116aa575b60443561166e575b606435611632575b0151907fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a06001600160a01b038651936024358552604435602086015260643588860152600060608601524260808601521692a361162161161b60643560443560243561201e565b82611ba7565b82519182526020820152a160018055005b61166960643530336001600160a01b037f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec4816612dbb565b6115b2565b6116a560443530336001600160a01b037f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f31216612dbb565b6115aa565b6116e160243530336001600160a01b037f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd16612dbb565b6115a2565b506064351515611411565b50604435151561140a565b34610282576103b261170d36611a30565b91611716612d66565b323303611732575b61172d60ff60055416156124bf565b6134b3565b33600052600d60205261174c60ff60406000205416613032565b61171e565b34610282576020600319360112610282576001600160a01b0361177261189a565b1660005260066020526020600260406000200154604051908152f35b3461028257600060031936011261028257600754600052600860205260206104cb42610f316040600020612553565b34610282576020600319360112610282576004356117d9611aae565b6117e4811515611b06565b600355005b346102825760006003193601126102825760206040516001600160a01b037f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd168152f35b346102825760206104cb61184036611a30565b9161201e565b34610282576000600319360112610282576020600454604051908152f35b34610282576020600319360112610282576020906001600160a01b0361188861189a565b16600052600a82526040600020548152f35b600435906001600160a01b038216820361028257565b60a0810190811067ffffffffffffffff8211176118cc57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6080810190811067ffffffffffffffff8211176118cc57604052565b6040810190811067ffffffffffffffff8211176118cc57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176118cc57604052565b60208082528251818301819052939260005b8581106119c6575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b818101830151848201604001528201611986565b34610282576000600319360112610282576104a06040516119fa81611917565b600581527f7664555348000000000000000000000000000000000000000000000000000000602082015260405191829182611974565b600319606091011261028257600435906024359060443590565b90633b9aca00811015611a61576003020190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60031960809101126102825760043590602435906044359060643590565b6001600160a01b03600054163303611ac257565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b15611b0d57565b606460405162461bcd60e51b815260206004820152601d60248201527f43616e6e6f7420736574207a65726f20626f6f737420776569676874210000006044820152fd5b8181029291811591840414171561085557565b15611b6e57600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8115611b6e570490565b9190820180921161085557565b6001600160a01b03907f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd8216600081611d955750506000915b7f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f3121691604051927f0902f1ac000000000000000000000000000000000000000000000000000000008452606084600481845afa938415611d3157600094611d3d575b5060206dffffffffffffffffffffffffffff600494951691611c7083612457565b604051948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa928315611d3157600093611cfb575b50611cb583612457565b156001171561085557611ce6611cf1611cd0611cf894611b64565b92670de0b6b3a764000092839160025490611b51565b049260035490611b51565b0490611ba7565b90565b90926020823d8211611d29575b81611d1560209383611933565b81010312611d265750519138611cab565b80fd5b3d9150611d08565b6040513d6000823e3d90fd5b936060853d8211611d8d575b81611d5660609383611933565b81010312611d2657611d678561243c565b506040611d766020870161243c565b95015163ffffffff811603611d2657506020611c4f565b3d9150611d49565b6040918251907f8d928af80000000000000000000000000000000000000000000000000000000082526020918281600481855afa908115611f99578491611fe9575b5084517f38fff2d00000000000000000000000000000000000000000000000000000000081528381600481865afa908115611fdf579088949392918691611fa3575b50906044608092885196879384927fb05f8e480000000000000000000000000000000000000000000000000000000084526004840152817f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48166024840152165afa928315611f99578493611f4d575b5090806004928651938480927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa948515611f4457508394611f10575b50501560011715611ee35750611edd90611b64565b91611bed565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b9080929450813d8311611f3d575b611f288183611933565b81010312611f395751913880611ec8565b5080fd5b503d611f1e565b513d85823e3d90fd5b9092506080813d8211611f91575b81611f6860809383611933565b81010312611f8d57908082611f836060600495519201612428565b5093919250611e88565b8380fd5b3d9150611f5b565b85513d86823e3d90fd5b848096508193949592503d8311611fd8575b611fbf8183611933565b81010312611fd4575187939291906044611e19565b8480fd5b503d611fb5565b86513d87823e3d90fd5b90508281813d8311612017575b6120008183611933565b81010312611f8d5761201190612428565b38611dd7565b503d611ff6565b6001600160a01b0391907f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd83166000816121d4575050506000915b7f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f31216906040517f0902f1ac000000000000000000000000000000000000000000000000000000008152606081600481865afa908115611d315760009161217c575b509060206dffffffffffffffffffffffffffff6004949316926120dc84612457565b604051948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa928315611d3157600093612147575b50611cf1611cd08461213d611cf8989795611ce69561213861214299612457565b611b51565b611b9d565b611ba7565b90926020823d8211612174575b8161216160209383611933565b81010312611d2657505191611cf1612117565b3d9150612154565b906060823d82116121cc575b8161219560609383611933565b81010312611d26576121a68261243c565b5060406121b56020840161243c565b92015163ffffffff811603611d26575060206120ba565b3d9150612188565b6040918251907f8d928af80000000000000000000000000000000000000000000000000000000082526020918281600481855afa908115611f995784916123f3575b5084517f38fff2d00000000000000000000000000000000000000000000000000000000081528381600481865afa908115611fdf579085949392918a96916123b9575b50906044608092885197889384927fb05f8e480000000000000000000000000000000000000000000000000000000084526004840152817f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48166024840152165afa9384156123af578394612361575b509080600493928651948580927f18160ddd0000000000000000000000000000000000000000000000000000000082525afa9485156123565750819461231f575b50505061213d9061231993611b51565b91612059565b909180939450813d831161234f575b6123388183611933565b81010312611d26575051908061231961213d612309565b503d61232e565b51913d9150823e3d90fd5b9093506080813d82116123a7575b8161237c60809383611933565b810103126123a357908082612398606060049695519201612428565b5094919293506122c8565b8280fd5b3d915061236f565b85513d85823e3d90fd5b84809697508193949592503d83116123ec575b6123d68183611933565b81010312611fd457518894939291906044612259565b503d6123cc565b90508281813d8311612421575b61240a8183611933565b81010312611f8d5761241b90612428565b38612216565b503d612400565b51906001600160a01b038216820361028257565b51906dffffffffffffffffffffffffffff8216820361028257565b6040519060208201907ff5b1bba9000000000000000000000000000000000000000000000000000000008252602483015260248252606082019082821067ffffffffffffffff8311176118cc57600092839260405251906a636f6e736f6c652e6c6f675afa50565b156124c657565b606460405162461bcd60e51b815260206004820152601160248201527f756e6c6f636b656420676c6f62616c6c790000000000000000000000000000006044820152fd5b60405190612517826118fb565b60006060838281528260208201528260408201520152565b9190820391821161085557565b90600f0b90600f0b029081600f0b91820361085557565b90604051612560816118fb565b606060028294805480600f0b855260801d600f0b6020850152600181015460408501520154910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146108555760010190565b90600f0b90600f0b03906f7fffffffffffffffffffffffffffffff82137fffffffffffffffffffffffffffffffff8000000000000000000000000000000083121761085557565b90600f0b90600f0b01907fffffffffffffffffffffffffffffffff8000000000000000000000000000000082126f7fffffffffffffffffffffffffffffff83131761085557565b909161264f61250a565b61265761250a565b9360009283926007546126786020850151604086015160608701519161201e565b600f0b8085526001600160a01b038816612bc6575b5060405161269a816118fb565b60008152600060208201524260408201524360608201529080612ba8575b604082015180606084015191600092824211612b67575b62093a809283810484810290808204861490151715610855576000915b60ff83106129f2575b505050505050509081612774926007556001600160a01b038916612974575b6000526008602052604060002090606060029180516fffffffffffffffffffffffffffffffff1980865416916fffffffffffffffffffffffffffffffff168092178655602083015160801b16178455604081015160018501550151910155565b6001600160a01b03861661278c575b50505050505050565b608080930194428651116128fa575b50500191825190428211612898575b505050506001600160a01b038116600052600a60205260406000205460018101809111610855576001600160a01b03828161280e9416600052600a602052826040600020554260408601524360608601521660005260096020526040600020611a4a565b919091612869578051602082015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909116178255604081015160018301556060015160029091015538808080808080612783565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b51106128a6575b80806127aa565b6128b8906020850151600f0b906125b7565b9051600052600b6020526040600020906fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16179055388061289f565b602061290b920151600f0b906125fe565b808383015186511461295b575b508451600052600b6020526040600020906fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16179055388061279b565b61296e91506020880151600f0b906125b7565b38612918565b600061298f60208c0151600f0b6020870151600f0b906125b7565b6129a160208501918251600f0b6125fe565b600f0b81526129c66129bc8d51600f0b8851600f0b906125b7565b8551600f0b6125fe565b600f0b90818552828151600f0b126129e9575b5012156127145760008252612714565b829052386129d9565b8582018092116108555788916000908042811115612b43575050612a47600091612a38612a2e602042975b01956107478751600f0b918961252f565b8d51600f0b6125b7565b600f0b8c528351600f0b6125fe565b600f0b808352818b51600f0b12612b3b575b12612b31575b5080918160408a0152612a8e670de0b6b3a7640000612a87612a81888661252f565b8a611b51565b0485611ba7565b60608a0152600188018098116108555787428303612ac6575050505050505050906127749143606083015290913880808080806126f5565b6000908152600860209081526040918290208b51918c015160801b6fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff909216919091178155908a0151600182015560608a0151600290910155612b2b9061258a565b916126ec565b6000905238612a5f565b818b52612a59565b93612a38612a2e6020604086612a47969960009852600b83522054600f0b93612a1d565b92612b72844361252f565b670de0b6b3a76400009182828102048203611ee3575090612ba291612b9b60408901514261252f565b9102611b9d565b926126cf565b8091506000526008602052612bc06040600020612553565b906126b8565b95604091966080860151421080612ca2575b612c76575b504260808501511180612c69575b612c3a575b60808501518152600b6020522054600f0b946080830151801561268d5790945060808401518114600014612c28575084935b3861268d565b600052604060002054600f0b93612c22565b612c5f6301e91c808551600f0b05600f0b8060208c015261074742608088015161252f565b600f0b8952612bf0565b50808451600f0b13612beb565b6301e91c80612c979105600f0b80602086015261074742608089015161252f565b600f0b835238612bdd565b50818113612bd8565b15612cb257565b606460405162461bcd60e51b815260206004820152601660248201527f4e6f206578697374696e67206c6f636b20666f756e64000000000000000000006044820152fd5b15612cfd57565b608460405162461bcd60e51b8152602060048201526024808201527f43616e6e6f742061646420746f2065787069726564206c6f636b2e205769746860448201527f64726177000000000000000000000000000000000000000000000000000000006064820152fd5b600260015414612d77576002600155565b606460405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b9092612e1893604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b038092166024860152166044840152606483015260648252612e13826118b0565b612e1a565b565b6001600160a01b031690604051612e3081611917565b6020928382527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564848301526000808486829651910182855af13d15612f94573d9167ffffffffffffffff8311612f675790612ec993929160405192612ebc887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160185611933565b83523d868885013e612f9e565b805180612ed7575b50505050565b81849181010312611f395782015190811591821503611d265750612efd57808080612ed1565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b90612ec992916060915b91929015612fff5750815115612fb2575090565b3b15612fbb5790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156130125750805190602001fd5b61302e9060405191829162461bcd60e51b835260048301611974565b0390fd5b1561303957565b606460405162461bcd60e51b815260206004820152601a60248201527f536d61727420636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152fd5b9290918315801580916134aa575b80156134a1575b1561028257336000526006602052604060002091604051926130b3846118b0565b60048154600f0b918286526001810154602087015260028101546040870152600381015460608701520154608085015261345d576224ea0042018042116108555784106133f4576301e91c8042018042116108555784116133b05762093a80809404948585810204851486151715610855577f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9660808561161b9561328e6132e99860409b6004549b6131718d61316b8c8c8c61201e565b90611ba7565b6004558d5191613180836118b0565b600083526000602084015260008f84015260006060840152878301600081526131b76020860151604087015160608801519161201e565b600f0b9081865289860151905283526131e16131d48c8c8c61201e565b600f0b8551600f0b6125fe565b600f0b84526131f4896020860151611ba7565b60208501526132078f8b90860151611ba7565b8f8501526132198b6060860151611ba7565b60608501528181026133a4575b50503360005260066020528c60002082516fffffffffffffffffffffffffffffffff19825416906fffffffffffffffffffffffffffffffff16178155602083015160018201558d83015160028201556060830151600382015560048784015191015533612645565b61336a575b83613330575b846132f6575b015187518281528360208201528489820152600160608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a361201e565b82519182526020820152a1565b61332b8530336001600160a01b037f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec4816612dbb565b61329f565b6133658430336001600160a01b037f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f31216612dbb565b613299565b61339f8330336001600160a01b037f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd16612dbb565b613293565b02868301523880613226565b606460405162461bcd60e51b815260206004820152601d60248201527f566f74696e67206c6f636b2063616e20626520312079656172206d61780000006044820152fd5b608460405162461bcd60e51b8152602060048201526024808201527f566f74696e67206c6f636b206d757374206265206174206c65617374204d494e60448201527f54494d45000000000000000000000000000000000000000000000000000000006064820152fd5b606460405162461bcd60e51b815260206004820152601960248201527f5769746864726177206f6c6420746f6b656e73206669727374000000000000006044820152fd5b50811515613092565b5083151561308b565b9160009033825260209060068252604093848420918551916134d4836118b0565b8354600f0b928381526001850154868201908152600286015495898301968752600460038201549160608501928352015496608084019788528b15968715809861379b575b8015613792575b1561378e57908a8d959493921361353690612cab565b8851421061354390612cf6565b8b6004549b8c6135548a8a8a61201e565b61355d91611ba7565b60045581519661356c886118b0565b818852818d890152818389015281606089015260808801828152865185518751906135969261201e565b600f0b908189528d51905288526135ae8a8a8361201e565b600f0b8751600f0b906135c0916125fe565b600f0b87528551906135d191611ba7565b8552878351906135e091611ba7565b8352888451906135ef91611ba7565b845233815260068c522092845184546fffffffffffffffffffffffffffffffff1916906fffffffffffffffffffffffffffffffff1617845551600184015551600283015551600382015586519060040155339161364b92612645565b7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c976136d4946136ce94613754575b8261371a575b836136e0575b5188518281528388820152848a820152600260608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a361201e565b83611ba7565b908351928352820152a1565b6137158430336001600160a01b037f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec4816612dbb565b613686565b61374f8330336001600160a01b037f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f31216612dbb565b613680565b6137898230336001600160a01b037f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd16612dbb565b61367a565b8a80fd5b50861515613520565b50851515613519565b600033815260209060068252604092838220908451906137c3826118b0565b825492600f93840b8352600181015491868401928352600282015488850190815260038301549160608601928352600480940154966080870197885262093a80809204828102928184041490151715613aca578751421015613a8857888751820b1315613a46578751821115613a04576301e91c8042018042116139d857821161399657938896938a989692938c9b9461393f976138899c7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c9f86549e8f61316b611bb4565b8755818151996138988b6118b0565b818b528a01528801528a6060880152608087018b81526138bd8751855187519161201e565b820b90818a528b51905287526138df6138d4611bb4565b820b8951830b6125fe565b900b87528061398e575b5033895260068a528b89209386516fffffffffffffffffffffffffffffffff19865416906fffffffffffffffffffffffffffffffff16178555516001850155516002840155516003830155855191015533612645565b5190845190808252808483015285820152600360608201524260808201527fad59145baaefcfeae3913393b4960a2d3fdd71bebf6f8223399868099b57bc8b60a03392a36136d46136ce611bb4565b8852386138e9565b6064858b8d519162461bcd60e51b8352820152601e60248201527f566f74696e67206c6f636b2063616e2062652033207965617273206d617800006044820152fd5b60248a6011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6064858b8d519162461bcd60e51b8352820152601f60248201527f43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e006044820152fd5b6064858b8d519162461bcd60e51b8352820152601160248201527f4e6f7468696e67206973206c6f636b65640000000000000000000000000000006044820152fd5b6064858b8d519162461bcd60e51b8352820152600c60248201527f4c6f636b206578706972656400000000000000000000000000000000000000006044820152fd5b6024896011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6000903382526020916006835260409081812093825191613b16836118b0565b8554600f0b95868452600181015491828486015260028201549081878701526004600384015493846060890152015480608088015260ff6005541615613d36575b50916136d49391613c3a7f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c999a948951613b90816118b0565b8181526004898c81840185815281850190868252606086019287845260066080880195898752338a5252872095516fffffffffffffffffffffffffffffffff19875416906fffffffffffffffffffffffffffffffff161786555160018601555160028501555160038401555191015560045498613c0d878b61252f565b6004558a5191613c1c836118b0565b808352808a840152808c840152806060840152608083015233612645565b82613cfd575b80613cc4575b81613c8b575b875192835285830152868201524260608201527fe08737ac48a1dab4b1a46c7dc9398bd5bfc6d7ad6fabb7cd8caa254de14def3560803392a28361252f565b613cbf82336001600160a01b037f000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec4816613d85565b613c4c565b613cf881336001600160a01b037f000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f31216613d85565b613c46565b613d3183336001600160a01b037f000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd16613d85565b613c40565b4210613d425738613b57565b60648588519062461bcd60e51b82526004820152601660248201527f546865206c6f636b206469646e277420657870697265000000000000000000006044820152fd5b612e18926001600160a01b03604051937fa9059cbb000000000000000000000000000000000000000000000000000000006020860152166024840152604483015260448252612e13826118fb565b6001600160a01b03166000908152600a602052604081205480613df65750905090565b613e0b613e1191600960205260408420611a4a565b50612553565b91602083015190604084015190838282039212818312811691831390151617613e6f57613e498392613e5392600f0b90600f0b61253c565b8451600f0b6125b7565b600f0b80845212613e67575b5051600f0b90565b815238613e5f565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b438211610282576001600160a01b036000911690818152602090600a82526040928382205482905b60808210614017575b5050613ee791613e0b916000526009845284600020611a4a565b9260075492613ef684836140a7565b8060005260088452613f0a82600020612553565b94811015613fe6576001810180911161085557600094613f9694613f8c94613f8093885260088252613f3d858920612553565b90613f6286613f55606085015160608801519061252f565b930151878601519061252f565b905b868501519483613fc0575b50505050870151928701519061252f565b600f0b90600f0b61253c565b8351600f0b6125b7565b600f81900b928390529112613fba576fffffffffffffffffffffffffffffffff1690565b50600090565b61316b92610c1c613fdc96979593606061213d9401519061252f565b9038808080613f6f565b50613f8084613f9694613f8c94614003606060009901514361252f565b90614011868501514261252f565b90613f64565b9092818110156140a15761402b8282611ba7565b6001808201809211610855571c908360005260098652876002614051848a600020611a4a565b5001541161406a5750614064909361258a565b90613ec4565b9391507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161085557614064909161258a565b92613ecd565b6000919082915b608083106140bd575b50505090565b90919281811015614145576140d28282611ba7565b6001808201809211610855571c9081600052600860205283600260406000200154111560001461410e5750614107909361258a565b91906140ae565b9391507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811161085557614107909161258a565b926140b7565b91909160409283820162093a80918282510483810290808204851490151715610855579560005b60ff81106141ae575b50505050506fffffffffffffffffffffffffffffffff91925060008151600f0b126141a557511690565b60008152511690565b84880180981161085557600097808481111561423157505082975b60208701908151906141fa6141f16141e38d8a519061252f565b93600f94850b90850b61253c565b8a51840b6125b7565b820b8952858b1461422957906142188392614224959451830b6125fe565b900b905288855261258a565b614172565b50505061417b565b8952600b6020529782902054600f0b6141c956fea2646970667358221220a645b8a50c69df54434d9c8b100309c5fbb7e648d57f7b5e42b9e566dbf6eecc64736f6c63430008120033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f312000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48

-----Decoded View---------------
Arg [0] : tokenA_addr (address): 0xd689ABc77B82803F22c49dE5C8A0049Cc74D11fD
Arg [1] : tokenB_addr (address): 0xAAF448d30F01b429FB6e7F9AF6A8FF66e694F312
Arg [2] : tokenC_addr (address): 0xE60779CC1b2c1d0580611c526a8DF0E3f870EC48

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000d689abc77b82803f22c49de5c8a0049cc74d11fd
Arg [1] : 000000000000000000000000aaf448d30f01b429fb6e7f9af6a8ff66e694f312
Arg [2] : 000000000000000000000000e60779cc1b2c1d0580611c526a8df0e3f870ec48


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  ]

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.