ETH Price: $3,260.88 (-2.15%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Cancel Vault180625952023-09-04 10:43:59506 days ago1693824239IN
0x1356f3b7...85a826674
0 ETH0.0005067811.87102966
Create New Stf180090272023-08-27 22:38:59513 days ago1693175939IN
0x1356f3b7...85a826674
0 ETH0.0017533311.75234759
Cancel Vault180011952023-08-26 20:21:47515 days ago1693081307IN
0x1356f3b7...85a826674
0 ETH0.0007555817.69184365
Create New Stf179910312023-08-25 10:12:23516 days ago1692958343IN
0x1356f3b7...85a826674
0 ETH0.0025616517.17039861
Cancel Vault179730292023-08-22 21:46:47519 days ago1692740807IN
0x1356f3b7...85a826674
0 ETH0.001698239.76324822
Create New Stf179730262023-08-22 21:46:11519 days ago1692740771IN
0x1356f3b7...85a826674
0 ETH0.0053706940.65938328
Claim179692232023-08-22 9:00:59519 days ago1692694859IN
0x1356f3b7...85a826674
0 ETH0.002149721.87264262
Cancel Vault179692152023-08-22 8:59:11519 days ago1692694751IN
0x1356f3b7...85a826674
0 ETH0.0007051116.51659967
Cancel Vault179692102023-08-22 8:58:11519 days ago1692694691IN
0x1356f3b7...85a826674
0 ETH0.0006746115.80216225
Cancel Vault179126632023-08-14 11:03:35527 days ago1692011015IN
0x1356f3b7...85a826674
0 ETH0.000738217.28483067
Create New Stf179126042023-08-14 10:51:47527 days ago1692010307IN
0x1356f3b7...85a826674
0 ETH0.0024423416.37069239
Create New Stf178903312023-08-11 8:03:59530 days ago1691741039IN
0x1356f3b7...85a826674
0 ETH0.002864519.20040403
Create New Stf178816212023-08-10 2:50:23531 days ago1691635823IN
0x1356f3b7...85a826674
0 ETH0.0023116915.49498666
Cancel Vault178151782023-07-31 19:47:47541 days ago1690832867IN
0x1356f3b7...85a826674
0 ETH0.0015620436.58527763
Create New Stf177730272023-07-25 22:17:23546 days ago1690323443IN
0x1356f3b7...85a826674
0 ETH0.0046459531.14121943
Add Token Capaci...176635352023-07-10 13:23:47562 days ago1688995427IN
0x1356f3b7...85a826674
0 ETH0.0008799227.51054085
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
Add Token Capaci...176635342023-07-10 13:23:35562 days ago1688995415IN
0x1356f3b7...85a826674
0 ETH0.0009009728.16862876
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:
Spot

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 15 : Spot.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.15;

import "forge-std/Test.sol";
import {IERC20} from "src/interfaces/external/IERC20.sol";
import {ISpotStorage} from "src/spot/interfaces/ISpotStorage.sol";
import {ISpot} from "src/spot/interfaces/ISpot.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {ISwap} from "src/spot/uni/interfaces/ISwap.sol";
import {ITrade} from "src/spot/uni/interfaces/ITrade.sol";

/*//////////////////////////////////////////////////////////////
                        CUSTOM ERRORS
//////////////////////////////////////////////////////////////*/

error ZeroAddress();
error ZeroAmount();
error NoAccess(address desired, address given);
error StillFundraising(uint256 desired, uint256 given);
error FundraisingComplete();
error BelowMin(uint96 min, uint96 given);
error AboveMax(uint96 max, uint96 given);
error FundExists(address fund);
error NoBaseToken(address token);
error AlreadyOpened();
error CantOpen();
error CantClose();
error AlreadyClaimed();
error NotFinalised();
error NotValidPlugin();

/// @title Spot
/// @author 7811
/// @notice Contract for the investors to deposit and for managers to open and close positions
contract Spot is ISpot, Pausable {
    // owner/deployer of the contract
    address public owner;
    // max fundraising period which can be used by the manager to raise funds (defaults - 1 week)
    uint40 public maxFundraisingPeriod;
    // address used by the backend bot to close/cancel the stfs
    address public admin;
    // address used to collect the protocol fees
    address public treasury;
    // percentage of fees from the profits of the stf to the manager (default - 15e18 (15%))
    uint96 public managerFee;
    // percentage of fees from the profits of the stf to the protocol (default - 5e18 (5%))
    uint96 public protocolFee;
    // min investment amount per investor per stf
    mapping(address => uint96) public minInvestmentAmount;
    // manager's address to indicate if the manager is managing a fund currently
    // manager can only manage one stf per address
    mapping(address => bool) public isManagingFund;
    // mapping to get the details of the stf
    mapping(bytes32 => StfSpotInfo) public stfInfo;
    // mapping to get the manager's current stf
    mapping(address => bytes32) public managerCurrentStf;
    // amount an investor deposits into a particular stf
    mapping(address => mapping(bytes32 => uint96)) public userAmount;
    // amount an investor claims from a particular stf
    mapping(address => mapping(bytes32 => uint96)) public claimAmount;
    // amount an investor claims form an stf if partial amount was used to open a spot position
    mapping(address => mapping(bytes32 => uint96)) public claimPartialAmount;
    // is the base token for opening a spot position eligible
    mapping(address => bool) public isBaseToken;
    // is the deposit token for opening a spot position eligible
    mapping(address => bool) public isDepositToken;
    // capacity of each token which can be fundraised per stf
    mapping(address => mapping(address => uint96)) public tokenCapacity;
    // contracts will can call functions in this contract, `transferToken(), openSpot(), closeSpot)`
    mapping(address => bool) public isPlugin;
    // map the trade contract to the baseToken
    mapping(address => address) public tradeMapping;

    /*//////////////////////////////////////////////////////////////
                            INITIALIZE
    //////////////////////////////////////////////////////////////*/

    constructor(address _admin, address _treasury) {
        owner = msg.sender;
        admin = _admin;
        treasury = _treasury;
        maxFundraisingPeriod = 1 weeks;
        managerFee = 15e18;
        protocolFee = 5e18;

        emit InitializeSpot({
            _maxFundraisingPeriod: 1 weeks,
            _mFee: managerFee,
            _pFee: protocolFee,
            _owner: msg.sender,
            _admin: _admin,
            _treasury: _treasury
        });
    }

    /// @notice initializes the base token for creating an stf
    /// @dev can only be called by the owner
    /// @param _baseToken address of the token which can be used as the base/asset when creating an stf
    /// @param _isBaseToken bool to change if the baseToken is eligible or not
    function changeBaseToken(address _baseToken, bool _isBaseToken) external onlyOwner {
        if (_baseToken == address(0)) revert ZeroAddress();
        isBaseToken[_baseToken] = _isBaseToken;
        emit BaseTokenUpdate(_baseToken, _isBaseToken);
    }

    /// @notice initializes the deposit token for creating an stf
    /// @dev can only be called by the owner
    /// @param _depositToken address of the token which can be used as the deposit when creating an stf
    /// @param _isDepositToken bool to change if the depositToken is eligible or not
    function changeDepositToken(address _depositToken, bool _isDepositToken) external onlyOwner {
        if (_depositToken == address(0)) revert ZeroAddress();
        isDepositToken[_depositToken] = _isDepositToken;
        emit DepositTokenUpdate(_depositToken, _isDepositToken);
    }

    /// @notice adds the total capacity of the deposit token for fundraising per stf
    /// @dev can only be called by the owner
    /// @param baseToken address of the base token
    /// @param depositToken address of the deposit token
    /// @param capacity the total amount of tokens which can be used while fundraising
    function addTokenCapacity(address baseToken, address depositToken, uint96 capacity) external onlyOwner {
        if (baseToken == address(0)) revert ZeroAddress();
        if (depositToken == address(0)) revert ZeroAddress();
        if (capacity < 1) revert ZeroAmount();
        tokenCapacity[baseToken][depositToken] = capacity;
        emit TokenCapacityUpdate(baseToken, depositToken, capacity);
    }

    /// @notice set the min investment of deposit an investor can invest per stf
    /// @dev can only be called by the `owner`
    /// @param _token address of the deposit token
    /// @param _amount min investment of deposit an investor can invest per stf
    function addMinInvestmentAmount(address _token, uint96 _amount) external override onlyOwner {
        if (_amount < 1) revert ZeroAmount();
        minInvestmentAmount[_token] = _amount;
        emit MinInvestmentAmountChanged(_token, _amount);
    }

    /// @notice Updates the plugin addresses
    /// @dev can only be called by the `owner`
    /// @param _plugin address of the plugin which can be used to called `transferToken()`, `openSpot()`, `closeSpot()`
    /// @param _isPlugin bool to determine if the address is a plugin
    function addPlugin(address _plugin, bool _isPlugin) external onlyOwner {
        if (_plugin == address(0)) revert ZeroAddress();
        isPlugin[_plugin] = _isPlugin;
        emit PluginUpdate(_plugin, _isPlugin);
    }

    /// @notice Updates the link of baseToken to the Trade contract of protocols
    /// @dev can only be called by the `owner`
    /// @param _baseToken address of the baseToken
    /// @param _stfxTrade address of the Trade contract of different protocols (uni, sushi, tj)
    function addTradeMapping(address _baseToken, address _stfxTrade) external onlyOwner {
        if (_baseToken == address(0)) revert ZeroAddress();
        tradeMapping[_baseToken] = _stfxTrade;
        emit TradeMappingUpdate(_baseToken, _stfxTrade);
    }

    /*//////////////////////////////////////////////////////////////
                            MODIFIERS
    //////////////////////////////////////////////////////////////*/

    /// @notice modifier for the setters to be called only by the manager
    modifier onlyOwner() {
        if (msg.sender != owner) revert NoAccess(owner, msg.sender);
        _;
    }

    /// @notice modifier for cancel vaults to be called only by the admin
    modifier onlyAdmin() {
        if (msg.sender != admin) revert NoAccess(admin, msg.sender);
        _;
    }

    /// @notice modifier to check if the msg.sender is a plugin
    modifier onlyPlugin() {
        if (!isPlugin[msg.sender]) revert NotValidPlugin();
        _;
    }

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice get the stf details by giving the salt as input
    /// @param _salt the stf salt
    /// @return StfSpotInfo the stf info struct
    function getStfInfo(bytes32 _salt) public view returns (StfSpotInfo memory) {
        return stfInfo[_salt];
    }

    /// @notice get the manager address by giving the salt as input
    /// @param _salt the stf salt
    /// @return manager address
    function getManagerFromSalt(bytes32 _salt) public view returns (address) {
        StfSpotInfo memory _stf = stfInfo[_salt];
        return _stf.manager;
    }

    /// @notice get the stf details by giving the manager address as input
    /// @param _manager address of the manager
    /// @return StfSpotInfo the stf info struct
    function getManagerCurrentStfInfo(address _manager) public view returns (StfSpotInfo memory) {
        bytes32 salt = managerCurrentStf[_manager];
        return stfInfo[salt];
    }

    /// @notice get the stf salt by giving the manager address as input
    /// @param _manager address of the manager
    /// @return salt of the stf
    function getManagerCurrentSalt(address _manager) public view returns (bytes32) {
        bytes32 salt = managerCurrentStf[_manager];
        return salt;
    }

    /// @notice get the pnl of the stf after deducting the fees
    /// @param _salt salt of the stf
    /// @return pnlAfterFees the pnl after the fees has been deducted
    function getPnlAfterFees(bytes32 _salt) external view returns (int96 pnlAfterFees) {
        StfSpotInfo memory _stf = stfInfo[_salt];
        pnlAfterFees = int96(_stf.remainingAfterFees) - int96(_stf.totalRaised);
    }

    /// @notice view function to get the status of the stf
    function getStatusOfStf(bytes32 _salt) public view returns (StfStatus) {
        StfSpotInfo memory _stf = stfInfo[_salt];
        return _stf.status;
    }

    function hasFundraisingPeriodEnded(bytes32 _salt) public view returns (bool) {
        StfSpotInfo memory _stf = stfInfo[_salt];
        if (block.timestamp > _stf.endTime) return true;
        else return false;
    }

    function getIsBaseToken(address _token) external view returns (bool) {
        return isBaseToken[_token];
    }

    function getIsDepositToken(address _token) external view returns (bool) {
        return isDepositToken[_token];
    }

    /// @notice get the capacity of the baseToken per stf
    function getTokenCapacity(address _baseToken, address _depositToken) public view returns (uint96) {
        return tokenCapacity[_baseToken][_depositToken];
    }

    /// @notice get if the manager is managing an stv
    function getIsManagingFund(address _manager) public view returns (bool) {
        return isManagingFund[_manager];
    }

    /// @notice get the deposit amount of the investor per stf
    function getUserAmount(address _investor, bytes32 _salt) external view returns (uint96) {
        return userAmount[_investor][_salt];
    }

    /// @notice get the claim amount of the investor per stf
    function getClaimAmount(address _investor, bytes32 _salt) external view returns (uint96) {
        return claimAmount[_investor][_salt];
    }

    /// @notice get the partial claim amount of the investor per stf
    function getClaimPartialAmount(address _investor, bytes32 _salt) external view returns (uint96) {
        return claimPartialAmount[_investor][_salt];
    }

    /// @notice get the trade contract for the given baseToken
    function getTradeMapping(address _baseToken) external view returns (address) {
        return tradeMapping[_baseToken];
    }

    /// @notice view function to see if the stf has been `DISTRIBUTED`, ie, position is closed
    function isDistributed(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.DISTRIBUTED) return true;
    }

    /// @notice view function to see if the stf has been `OPENED`, ie, spot position was opened
    function isOpened(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.OPENED) return true;
    }

    /// @notice view function to see if the stf has been `CANCELLED_WITH_ZERO_RAISE`, ie, the stf has been cancelled with nothing raised
    function isCancelledWithZeroRaised(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.CANCELLED_WITH_ZERO_RAISE) return true;
    }

    /// @notice view function to see if the stf has been `CANCELLED_WITH_NO_FILL`, ie, the stf has been cancelled without any position
    function isCancelledWithNoFill(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.CANCELLED_WITH_NO_FILL) return true;
    }

    /// @notice view function to see if the stf has been `CANCELLED_BY_MANAGER`, ie, the stf has been cancelled by the manager
    function isCancelledByManager(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.CANCELLED_BY_MANAGER) return true;
    }

    /// @notice view function to see if the stf has been `NOT_OPENED`, ie, no open orders has been created
    function isNotOpened(bytes32 _salt) external view returns (bool) {
        StfStatus _status = getStatusOfStf(_salt);
        if (_status == StfStatus.NOT_OPENED) return true;
    }

    /*//////////////////////////////////////////////////////////////
                          EXTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Create a new Single Trade Fund (STF)
    /// @dev returns the address of the proxy contract with Stfx.sol implementation
    /// @param _stf the fund details, check `ISpotStorage.Stf`
    /// @return salt of the stf
    function createNewStf(StfSpot calldata _stf) external override whenNotPaused returns (bytes32 salt) {
        if (isManagingFund[msg.sender]) revert FundExists(msg.sender);
        if (_stf.fundraisingPeriod < 15 minutes) revert BelowMin(15 minutes, _stf.fundraisingPeriod);
        if (_stf.fundraisingPeriod > maxFundraisingPeriod) {
            revert AboveMax(maxFundraisingPeriod, _stf.fundraisingPeriod);
        }
        if (!isBaseToken[_stf.baseToken] || !isDepositToken[_stf.depositToken]) {
            revert NoBaseToken(_stf.baseToken);
        }

        salt = keccak256(
            abi.encodePacked(
                msg.sender,
                _stf.baseToken,
                _stf.depositToken,
                _stf.fundraisingPeriod,
                block.timestamp,
                block.number,
                block.chainid
            )
        );

        managerCurrentStf[msg.sender] = salt;
        isManagingFund[msg.sender] = true;
        stfInfo[salt].manager = msg.sender;
        stfInfo[salt].baseToken = _stf.baseToken;
        stfInfo[salt].depositToken = _stf.depositToken;
        stfInfo[salt].endTime = uint40(block.timestamp) + _stf.fundraisingPeriod;
        stfInfo[salt].fundDeadline = 72 hours;

        emit NewFundCreated(
            _stf.baseToken,
            _stf.depositToken,
            _stf.fundraisingPeriod,
            msg.sender,
            salt,
            block.chainid,
            tokenCapacity[_stf.baseToken][_stf.depositToken]
        );
    }

    /// @notice deposit a particular amount into an stf for the manager to open a position
    /// @dev `fundraisingPeriod` has to end and the `totalRaised` should not be more than `maxInvestmentPerStf`
    /// @dev amount has to be more than `minInvestmentAmount`
    /// @dev approve has to be called before this method for the investor to transfer usdc to this contract
    /// @param salt the stf salt
    /// @param amount amount the investor wants to deposit
    function depositIntoFund(bytes32 salt, uint96 amount) external whenNotPaused {
        StfSpotInfo memory _stf = getStfInfo(salt);
        uint8 tokenDecimals = IERC20(_stf.depositToken).decimals();
        uint256 balance = IERC20(_stf.depositToken).balanceOf(msg.sender);
        uint96 depositAmount = uint96(amount / (10 ** (18 - tokenDecimals)));

        if (amount < minInvestmentAmount[_stf.depositToken]) {
            revert BelowMin(minInvestmentAmount[_stf.depositToken], amount);
        }
        if (_stf.manager == address(0)) revert ZeroAddress();
        if (uint96(balance) < depositAmount) revert BelowMin(uint96(balance), depositAmount);
        if (uint40(block.timestamp) > _stf.endTime) revert FundraisingComplete();
        if (_stf.status != StfStatus.NOT_OPENED) revert AlreadyOpened();
        if (_stf.totalRaised + amount > tokenCapacity[_stf.baseToken][_stf.depositToken]) {
            revert AboveMax(tokenCapacity[_stf.baseToken][_stf.depositToken], _stf.totalRaised + amount);
        }

        stfInfo[salt].totalRaised += amount;
        userAmount[msg.sender][salt] += amount;

        IERC20(_stf.depositToken).transferFrom(msg.sender, address(this), depositAmount);
        emit DepositIntoFund(msg.sender, amount, salt);
    }

    /// @notice allows the manager to close the fundraising and open a position later
    /// @dev changes the `_stf.endTime` to the current `block.timestamp`
    /// @dev closes fundraising for the current stf managed by the `msg.sender`(manager)
    function closeFundraising() external override whenNotPaused {
        StfSpotInfo memory _stf = getManagerCurrentStfInfo(msg.sender);
        bytes32 salt = managerCurrentStf[msg.sender];

        if (_stf.manager != msg.sender) revert NoAccess(_stf.manager, msg.sender);
        if (_stf.status != StfStatus.NOT_OPENED) revert AlreadyOpened();
        if (_stf.totalRaised < 1) revert ZeroAmount();
        if (block.timestamp >= _stf.endTime) revert CantClose();

        stfInfo[salt].endTime = uint40(block.timestamp);

        emit FundraisingClosed(salt);
    }

    /// @notice transfers an amount of token to the `msg.sender`
    /// @dev can only be called by an approved plugin
    /// @param token address of the token to be transferred
    /// @param amount total amount of tokens to be transferred
    function transferToken(address token, uint256 amount) external override onlyPlugin whenNotPaused {
        IERC20(token).transfer(msg.sender, amount);
    }

    /// @notice Called by the `Trade` contract to change the state after opening a spot position
    /// @dev can only be called by an approved plugin
    /// @param amount the totalAmount which is being used from the stf's `totalRaised`
    /// @param received the total amount of baseToken received after opening a spot position (in baseToken's decimal units)
    /// @param salt the hash of the stf when it was created
    function openSpot(uint96 amount, uint96 received, bytes32 salt) external override onlyPlugin whenNotPaused {
        stfInfo[salt].status = StfStatus.OPENED;
        stfInfo[salt].totalAmountUsed = amount;
        stfInfo[salt].totalReceived = received;
    }

    /// @notice Called by the `Trade` contract to change the state after closing a spot position and distributing the pnl
    /// @dev can only be called by an approved plugin
    /// @param remaining the amount of tokens remaining after closing the spot position (in 1e18 units)
    /// @param salt the hash of the stf when it was created
    function closeSpot(uint96 remaining, bytes32 salt) external override onlyPlugin whenNotPaused {
        stfInfo[salt].status = StfStatus.DISTRIBUTED;
        stfInfo[salt].remainingAfterFees = remaining;
        isManagingFund[stfInfo[salt].manager] = false;
    }

    /// @notice get the `claimableAmount` of the investor from a particular stf
    /// @dev if theres no spot position opened, it'll return the deposited amount
    /// @dev after the spot position is closed, it'll calculate the `claimableAmount` depending on the weightage of the investor
    /// @param _salt the stf salt
    /// @param _investor address of the investor
    /// @return amount which can be claimed by the investor from a particular stf
    function claimableAmount(bytes32 _salt, address _investor) public view override returns (uint256 amount) {
        StfSpotInfo memory _stf = getStfInfo(_salt);

        if ((claimAmount[_investor][_salt] > 0)) {
            // if the investor has already claimed
            amount = 0;
        } else if (_stf.status == StfStatus.OPENED) {
            if (_stf.totalRaised == _stf.totalAmountUsed || claimPartialAmount[_investor][_salt] > 0) {
                // if a spot position is opened and if either the investor has claimed partial amount or if totalRaised is equal to the totalAmountUsed
                amount = 0;
            } else {
                // if a spot position is opened and if the investor can claim the partial amount which was not used by the manager
                uint256 _n =
                    uint256(_stf.totalRaised - _stf.totalAmountUsed) * uint256(userAmount[_investor][_salt]) * 1e18;
                uint256 _d = uint256(_stf.totalRaised) * 1e18;
                amount = _n / _d;
            }
        } else if (_stf.status == StfStatus.DISTRIBUTED) {
            // if the spot position for the stf has been closed and distributed
            uint256 _n = uint256(_stf.remainingAfterFees) * uint256(userAmount[_investor][_salt]) * 1e18;
            uint256 _d = uint256(_stf.totalRaised) * 1e18;
            amount = _n / _d;
        } else {
            // if the stf is either cancelled manually or automatically or if the stf has not been opened
            // valid for NOT_OPENED, CANCELLED_BY_MANAGER, CANCELLED_WITH_ZERO_RAISE, CANCELLED_WITH_NO_FILL
            amount = userAmount[_investor][_salt];
        }
    }

    /// @notice transfers the deposit to the investor depending on the investor's weightage to the totalRaised by the stf
    /// @dev will revert if the investor did not invest in the stf during the fundraisingPeriod
    /// @param _salt the stf salt
    function claim(bytes32 _salt) external override whenNotPaused {
        StfSpotInfo memory _stf = getStfInfo(_salt);
        uint256 amount;

        if (_stf.status == StfStatus.NOT_OPENED) revert NotFinalised();
        if (_stf.status == StfStatus.OPENED) {
            if (_stf.totalAmountUsed == _stf.totalRaised) revert NotFinalised();
            amount = claimableAmount(_salt, msg.sender);
            if (amount < 1) revert ZeroAmount();
            claimPartialAmount[msg.sender][_salt] = uint96(amount);
        } else {
            amount = claimableAmount(_salt, msg.sender);
            if (amount < 1) revert ZeroAmount();
            claimAmount[msg.sender][_salt] = uint96(amount);
        }

        uint8 tokenDecimals = IERC20(_stf.depositToken).decimals();
        uint256 c = amount / (10 ** (18 - tokenDecimals));

        IERC20(_stf.depositToken).transfer(msg.sender, c);
        emit Claimed(msg.sender, amount, _salt);
    }

    /// @notice will change the status of the stf to `CANCELLED` and `isManagingFund(manager)` to false
    /// @dev can be called by the `admin` if there was nothing raised during `fundraisingPeriod`
    /// @dev or if the manager did not open a spot position within the `fundDeadline`
    /// @dev and it can be called by the manager if they want to cancel an stf
    /// @param salt the stf salt
    function cancelVault(bytes32 salt) external override whenNotPaused {
        StfSpotInfo memory _stf = getStfInfo(salt);

        if (_stf.status != StfStatus.NOT_OPENED) revert AlreadyOpened();

        if (msg.sender == admin) {
            if (_stf.totalRaised == 0) {
                if (uint40(block.timestamp) <= _stf.endTime) revert BelowMin(_stf.endTime, uint40(block.timestamp));
                stfInfo[salt].status = StfStatus.CANCELLED_WITH_ZERO_RAISE;
            } else {
                if (uint40(block.timestamp) <= _stf.endTime + _stf.fundDeadline) {
                    revert BelowMin(_stf.endTime + _stf.fundDeadline, uint40(block.timestamp));
                }
                stfInfo[salt].status = StfStatus.CANCELLED_WITH_NO_FILL;
            }
        } else if (msg.sender == _stf.manager) {
            if (_stf.totalRaised == 0) {
                stfInfo[salt].status = StfStatus.CANCELLED_WITH_ZERO_RAISE;
            } else {
                if (uint40(block.timestamp) > _stf.endTime + _stf.fundDeadline) revert CantClose();
                stfInfo[salt].status = StfStatus.CANCELLED_BY_MANAGER;
            }
        } else {
            revert NoAccess(_stf.manager, msg.sender);
        }

        stfInfo[salt].fundDeadline = 0;
        stfInfo[salt].endTime = 0;
        isManagingFund[_stf.manager] = false;

        emit CancelVault(salt);
    }

    function withdraw(address token, uint96 amount) external onlyOwner {
        uint256 balance = IERC20(token).balanceOf(address(this));
        if (balance < amount) revert AboveMax(uint96(balance), amount);
        IERC20(token).transfer(treasury, amount);
        emit Withdraw(token, amount, treasury);
    }

    /*//////////////////////////////////////////////////////////////
                            SETTER FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice set the max fundraising period a manager can use when creating an stf
    /// @dev can only be called by the `owner`
    /// @param _maxFundraisingPeriod max fundraising period a manager can use when creating an stf
    function setMaxFundraisingPeriod(uint40 _maxFundraisingPeriod) external onlyOwner whenNotPaused {
        if (_maxFundraisingPeriod < 15 minutes) revert BelowMin(15 minutes, _maxFundraisingPeriod);
        maxFundraisingPeriod = _maxFundraisingPeriod;
        emit MaxFundraisingPeriodChanged(_maxFundraisingPeriod);
    }

    /// @notice set the manager fee percent to calculate the manager fees on profits depending on the governance
    /// @dev can only be called by the `owner`
    /// @param newManagerFee the percent which is used to calculate the manager fees on profits
    function setManagerFee(uint96 newManagerFee) external override onlyOwner whenNotPaused {
        managerFee = newManagerFee;
        emit ManagerFeeChanged(newManagerFee);
    }

    /// @notice set the protocol fee percent to calculate the protocol fees on profits depending on the governance
    /// @dev can only be called by the `owner`
    /// @param newProtocolFee the percent which is used to calculate the protocol fees on profits
    function setProtocolFee(uint96 newProtocolFee) external override onlyOwner whenNotPaused {
        protocolFee = newProtocolFee;
        emit ProtocolFeeChanged(newProtocolFee);
    }

    /// @notice set the new owner of the StfxVault contract
    /// @dev can only be called by the current `owner`
    /// @param newOwner the new owner of the StfxVault contract
    function setOwner(address newOwner) external override onlyOwner {
        if (newOwner == address(0)) revert ZeroAddress();
        owner = newOwner;
        emit OwnerChanged(newOwner);
    }

    /// @notice set the `fundDeadline` for a particular stf to cancel the vault early if needed
    /// @dev can only be called by the `owner` or the `manager` of the stf
    /// @param salt the stf salt
    /// @param newFundDeadline new fundDeadline
    function setFundDeadline(bytes32 salt, uint40 newFundDeadline) external override whenNotPaused {
        StfSpotInfo memory _stf = getStfInfo(salt);
        if (msg.sender != _stf.manager && msg.sender != owner) revert NoAccess(_stf.manager, msg.sender);
        if (newFundDeadline > 72 hours) revert AboveMax(uint96(72 hours), uint96(newFundDeadline));
        stfInfo[salt].fundDeadline = newFundDeadline;
        emit FundDeadlineChanged(salt, newFundDeadline);
    }

    /// @notice set the admin address
    /// @dev can only be called by the `owner`
    /// @param _admin the admin address
    function setAdmin(address _admin) external onlyOwner {
        if (_admin == address(0)) revert ZeroAddress();
        admin = _admin;
        emit AdminChanged(_admin);
    }

    /// @notice set the treasury address
    /// @dev can only be called by the `owner`
    /// @param _treasury the treasury address
    function setTreasury(address _treasury) external onlyOwner {
        if (_treasury == address(0)) revert ZeroAddress();
        treasury = _treasury;
        emit TreasuryChanged(_treasury);
    }

    /// @notice Set the `isManagingFund` state to true or false depending on the emergency
    /// @dev Can only be called by the owner
    /// @param _manager address of the manager
    /// @param _isManaging true if already managing an stf and false if not managing an stf
    function setIsManagingFund(address _manager, bool _isManaging) external override onlyOwner whenNotPaused {
        isManagingFund[_manager] = _isManaging;
        emit ManagingFundUpdate(_manager, _isManaging);
    }

    /*//////////////////////////////////////////////////////////////
                          PAUSE/UNPAUSE
    //////////////////////////////////////////////////////////////*/

    /// @notice Pause contract
    /// @dev can only be called by the `owner` when the contract is not paused
    function pause() public onlyAdmin whenNotPaused {
        _pause();
    }

    /// @notice Unpause contract
    /// @dev can only be called by the `owner` when the contract is paused
    function unpause() public onlyAdmin whenPaused {
        _unpause();
    }
}

File 2 of 15 : test.sol
// SPDX-License-Identifier: GPL-3.0-or-later

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity >=0.5.0;

contract DSTest {
    event log                    (string);
    event logs                   (bytes);

    event log_address            (address);
    event log_bytes32            (bytes32);
    event log_int                (int);
    event log_uint               (uint);
    event log_bytes              (bytes);
    event log_string             (string);

    event log_named_address      (string key, address val);
    event log_named_bytes32      (string key, bytes32 val);
    event log_named_decimal_int  (string key, int val, uint decimals);
    event log_named_decimal_uint (string key, uint val, uint decimals);
    event log_named_int          (string key, int val);
    event log_named_uint         (string key, uint val);
    event log_named_bytes        (string key, bytes val);
    event log_named_string       (string key, string val);

    bool public IS_TEST = true;
    bool private _failed;

    address constant HEVM_ADDRESS =
        address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));

    modifier mayRevert() { _; }
    modifier testopts(string memory) { _; }

    function failed() public returns (bool) {
        if (_failed) {
            return _failed;
        } else {
            bool globalFailed = false;
            if (hasHEVMContext()) {
                (, bytes memory retdata) = HEVM_ADDRESS.call(
                    abi.encodePacked(
                        bytes4(keccak256("load(address,bytes32)")),
                        abi.encode(HEVM_ADDRESS, bytes32("failed"))
                    )
                );
                globalFailed = abi.decode(retdata, (bool));
            }
            return globalFailed;
        }
    } 

    function fail() internal {
        if (hasHEVMContext()) {
            (bool status, ) = HEVM_ADDRESS.call(
                abi.encodePacked(
                    bytes4(keccak256("store(address,bytes32,bytes32)")),
                    abi.encode(HEVM_ADDRESS, bytes32("failed"), bytes32(uint256(0x01)))
                )
            );
            status; // Silence compiler warnings
        }
        _failed = true;
    }

    function hasHEVMContext() internal view returns (bool) {
        uint256 hevmCodeSize = 0;
        assembly {
            hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)
        }
        return hevmCodeSize > 0;
    }

    modifier logs_gas() {
        uint startGas = gasleft();
        _;
        uint endGas = gasleft();
        emit log_named_uint("gas", startGas - endGas);
    }

    function assertTrue(bool condition) internal {
        if (!condition) {
            emit log("Error: Assertion Failed");
            fail();
        }
    }

    function assertTrue(bool condition, string memory err) internal {
        if (!condition) {
            emit log_named_string("Error", err);
            assertTrue(condition);
        }
    }

    function assertEq(address a, address b) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [address]");
            emit log_named_address("  Expected", b);
            emit log_named_address("    Actual", a);
            fail();
        }
    }
    function assertEq(address a, address b, string memory err) internal {
        if (a != b) {
            emit log_named_string ("Error", err);
            assertEq(a, b);
        }
    }

    function assertEq(bytes32 a, bytes32 b) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [bytes32]");
            emit log_named_bytes32("  Expected", b);
            emit log_named_bytes32("    Actual", a);
            fail();
        }
    }
    function assertEq(bytes32 a, bytes32 b, string memory err) internal {
        if (a != b) {
            emit log_named_string ("Error", err);
            assertEq(a, b);
        }
    }
    function assertEq32(bytes32 a, bytes32 b) internal {
        assertEq(a, b);
    }
    function assertEq32(bytes32 a, bytes32 b, string memory err) internal {
        assertEq(a, b, err);
    }

    function assertEq(int a, int b) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [int]");
            emit log_named_int("  Expected", b);
            emit log_named_int("    Actual", a);
            fail();
        }
    }
    function assertEq(int a, int b, string memory err) internal {
        if (a != b) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }
    function assertEq(uint a, uint b) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [uint]");
            emit log_named_uint("  Expected", b);
            emit log_named_uint("    Actual", a);
            fail();
        }
    }
    function assertEq(uint a, uint b, string memory err) internal {
        if (a != b) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }
    function assertEqDecimal(int a, int b, uint decimals) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [decimal int]");
            emit log_named_decimal_int("  Expected", b, decimals);
            emit log_named_decimal_int("    Actual", a, decimals);
            fail();
        }
    }
    function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {
        if (a != b) {
            emit log_named_string("Error", err);
            assertEqDecimal(a, b, decimals);
        }
    }
    function assertEqDecimal(uint a, uint b, uint decimals) internal {
        if (a != b) {
            emit log("Error: a == b not satisfied [decimal uint]");
            emit log_named_decimal_uint("  Expected", b, decimals);
            emit log_named_decimal_uint("    Actual", a, decimals);
            fail();
        }
    }
    function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {
        if (a != b) {
            emit log_named_string("Error", err);
            assertEqDecimal(a, b, decimals);
        }
    }

    function assertGt(uint a, uint b) internal {
        if (a <= b) {
            emit log("Error: a > b not satisfied [uint]");
            emit log_named_uint("  Value a", a);
            emit log_named_uint("  Value b", b);
            fail();
        }
    }
    function assertGt(uint a, uint b, string memory err) internal {
        if (a <= b) {
            emit log_named_string("Error", err);
            assertGt(a, b);
        }
    }
    function assertGt(int a, int b) internal {
        if (a <= b) {
            emit log("Error: a > b not satisfied [int]");
            emit log_named_int("  Value a", a);
            emit log_named_int("  Value b", b);
            fail();
        }
    }
    function assertGt(int a, int b, string memory err) internal {
        if (a <= b) {
            emit log_named_string("Error", err);
            assertGt(a, b);
        }
    }
    function assertGtDecimal(int a, int b, uint decimals) internal {
        if (a <= b) {
            emit log("Error: a > b not satisfied [decimal int]");
            emit log_named_decimal_int("  Value a", a, decimals);
            emit log_named_decimal_int("  Value b", b, decimals);
            fail();
        }
    }
    function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {
        if (a <= b) {
            emit log_named_string("Error", err);
            assertGtDecimal(a, b, decimals);
        }
    }
    function assertGtDecimal(uint a, uint b, uint decimals) internal {
        if (a <= b) {
            emit log("Error: a > b not satisfied [decimal uint]");
            emit log_named_decimal_uint("  Value a", a, decimals);
            emit log_named_decimal_uint("  Value b", b, decimals);
            fail();
        }
    }
    function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {
        if (a <= b) {
            emit log_named_string("Error", err);
            assertGtDecimal(a, b, decimals);
        }
    }

    function assertGe(uint a, uint b) internal {
        if (a < b) {
            emit log("Error: a >= b not satisfied [uint]");
            emit log_named_uint("  Value a", a);
            emit log_named_uint("  Value b", b);
            fail();
        }
    }
    function assertGe(uint a, uint b, string memory err) internal {
        if (a < b) {
            emit log_named_string("Error", err);
            assertGe(a, b);
        }
    }
    function assertGe(int a, int b) internal {
        if (a < b) {
            emit log("Error: a >= b not satisfied [int]");
            emit log_named_int("  Value a", a);
            emit log_named_int("  Value b", b);
            fail();
        }
    }
    function assertGe(int a, int b, string memory err) internal {
        if (a < b) {
            emit log_named_string("Error", err);
            assertGe(a, b);
        }
    }
    function assertGeDecimal(int a, int b, uint decimals) internal {
        if (a < b) {
            emit log("Error: a >= b not satisfied [decimal int]");
            emit log_named_decimal_int("  Value a", a, decimals);
            emit log_named_decimal_int("  Value b", b, decimals);
            fail();
        }
    }
    function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {
        if (a < b) {
            emit log_named_string("Error", err);
            assertGeDecimal(a, b, decimals);
        }
    }
    function assertGeDecimal(uint a, uint b, uint decimals) internal {
        if (a < b) {
            emit log("Error: a >= b not satisfied [decimal uint]");
            emit log_named_decimal_uint("  Value a", a, decimals);
            emit log_named_decimal_uint("  Value b", b, decimals);
            fail();
        }
    }
    function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {
        if (a < b) {
            emit log_named_string("Error", err);
            assertGeDecimal(a, b, decimals);
        }
    }

    function assertLt(uint a, uint b) internal {
        if (a >= b) {
            emit log("Error: a < b not satisfied [uint]");
            emit log_named_uint("  Value a", a);
            emit log_named_uint("  Value b", b);
            fail();
        }
    }
    function assertLt(uint a, uint b, string memory err) internal {
        if (a >= b) {
            emit log_named_string("Error", err);
            assertLt(a, b);
        }
    }
    function assertLt(int a, int b) internal {
        if (a >= b) {
            emit log("Error: a < b not satisfied [int]");
            emit log_named_int("  Value a", a);
            emit log_named_int("  Value b", b);
            fail();
        }
    }
    function assertLt(int a, int b, string memory err) internal {
        if (a >= b) {
            emit log_named_string("Error", err);
            assertLt(a, b);
        }
    }
    function assertLtDecimal(int a, int b, uint decimals) internal {
        if (a >= b) {
            emit log("Error: a < b not satisfied [decimal int]");
            emit log_named_decimal_int("  Value a", a, decimals);
            emit log_named_decimal_int("  Value b", b, decimals);
            fail();
        }
    }
    function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {
        if (a >= b) {
            emit log_named_string("Error", err);
            assertLtDecimal(a, b, decimals);
        }
    }
    function assertLtDecimal(uint a, uint b, uint decimals) internal {
        if (a >= b) {
            emit log("Error: a < b not satisfied [decimal uint]");
            emit log_named_decimal_uint("  Value a", a, decimals);
            emit log_named_decimal_uint("  Value b", b, decimals);
            fail();
        }
    }
    function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {
        if (a >= b) {
            emit log_named_string("Error", err);
            assertLtDecimal(a, b, decimals);
        }
    }

    function assertLe(uint a, uint b) internal {
        if (a > b) {
            emit log("Error: a <= b not satisfied [uint]");
            emit log_named_uint("  Value a", a);
            emit log_named_uint("  Value b", b);
            fail();
        }
    }
    function assertLe(uint a, uint b, string memory err) internal {
        if (a > b) {
            emit log_named_string("Error", err);
            assertLe(a, b);
        }
    }
    function assertLe(int a, int b) internal {
        if (a > b) {
            emit log("Error: a <= b not satisfied [int]");
            emit log_named_int("  Value a", a);
            emit log_named_int("  Value b", b);
            fail();
        }
    }
    function assertLe(int a, int b, string memory err) internal {
        if (a > b) {
            emit log_named_string("Error", err);
            assertLe(a, b);
        }
    }
    function assertLeDecimal(int a, int b, uint decimals) internal {
        if (a > b) {
            emit log("Error: a <= b not satisfied [decimal int]");
            emit log_named_decimal_int("  Value a", a, decimals);
            emit log_named_decimal_int("  Value b", b, decimals);
            fail();
        }
    }
    function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {
        if (a > b) {
            emit log_named_string("Error", err);
            assertLeDecimal(a, b, decimals);
        }
    }
    function assertLeDecimal(uint a, uint b, uint decimals) internal {
        if (a > b) {
            emit log("Error: a <= b not satisfied [decimal uint]");
            emit log_named_decimal_uint("  Value a", a, decimals);
            emit log_named_decimal_uint("  Value b", b, decimals);
            fail();
        }
    }
    function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {
        if (a > b) {
            emit log_named_string("Error", err);
            assertGeDecimal(a, b, decimals);
        }
    }

    function assertEq(string memory a, string memory b) internal {
        if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {
            emit log("Error: a == b not satisfied [string]");
            emit log_named_string("  Expected", b);
            emit log_named_string("    Actual", a);
            fail();
        }
    }
    function assertEq(string memory a, string memory b, string memory err) internal {
        if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }

    function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {
        ok = true;
        if (a.length == b.length) {
            for (uint i = 0; i < a.length; i++) {
                if (a[i] != b[i]) {
                    ok = false;
                }
            }
        } else {
            ok = false;
        }
    }
    function assertEq0(bytes memory a, bytes memory b) internal {
        if (!checkEq0(a, b)) {
            emit log("Error: a == b not satisfied [bytes]");
            emit log_named_bytes("  Expected", b);
            emit log_named_bytes("    Actual", a);
            fail();
        }
    }
    function assertEq0(bytes memory a, bytes memory b, string memory err) internal {
        if (!checkEq0(a, b)) {
            emit log_named_string("Error", err);
            assertEq0(a, b);
        }
    }
}

File 3 of 15 : Script.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;

import "./console.sol";
import "./console2.sol";
import "./StdJson.sol";

abstract contract Script {
    bool public IS_SCRIPT = true;
    address constant private VM_ADDRESS =
        address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));

    Vm public constant vm = Vm(VM_ADDRESS);

    /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
    /// @notice adapated from Solmate implementation (https://github.com/transmissions11/solmate/blob/main/src/utils/LibRLP.sol)
    function computeCreateAddress(address deployer, uint256 nonce) internal pure returns (address) {
        // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0.
        // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it.
        if (nonce == 0x00)             return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));
        if (nonce <= 0x7f)             return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));

        // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.
        if (nonce <= 2**8 - 1)  return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));
        if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));
        if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));

        // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp
        // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)
        // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
        // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)
        // We assume nobody can have a nonce large enough to require more than 32 bytes.
        return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))));
    }

    function addressFromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {
        return address(uint160(uint256(bytesValue)));
    }
}

File 4 of 15 : StdJson.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;

import "./Vm.sol";

// Helpers for parsing keys into types.
library stdJson {

    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

    function parseRaw(string memory json, string memory key)
        internal
        returns (bytes memory)
    {
        return vm.parseJson(json, key);
    }

    function readUint(string memory json, string memory key)
        internal
        returns (uint256)
    {
        return abi.decode(vm.parseJson(json, key), (uint256));
    }

    function readUintArray(string memory json, string memory key)
        internal
        returns (uint256[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (uint256[]));
    }

    function readInt(string memory json, string memory key)
        internal
        returns (int256)
    {
        return abi.decode(vm.parseJson(json, key), (int256));
    }

    function readIntArray(string memory json, string memory key)
        internal
        returns (int256[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (int256[]));
    }

    function readBytes32(string memory json, string memory key)
        internal
        returns (bytes32)
    {
        return abi.decode(vm.parseJson(json, key), (bytes32));
    }

    function readBytes32Array(string memory json, string memory key)
        internal
        returns (bytes32[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (bytes32[]));
    }

    function readString(string memory json, string memory key)
        internal
        returns (string memory)
    {
        return abi.decode(vm.parseJson(json, key), (string));
    }

    function readStringArray(string memory json, string memory key)
        internal
        returns (string[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (string[]));
    }

    function readAddress(string memory json, string memory key)
        internal
        returns (address)
    {
        return abi.decode(vm.parseJson(json, key), (address));
    }

    function readAddressArray(string memory json, string memory key)
        internal
        returns (address[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (address[]));
    }

    function readBool(string memory json, string memory key)
        internal
        returns (bool)
    {
        return abi.decode(vm.parseJson(json, key), (bool));
    }

    function readBoolArray(string memory json, string memory key)
        internal
        returns (bool[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (bool[]));
    }

    function readBytes(string memory json, string memory key)
        internal
        returns (bytes memory)
    {
        return abi.decode(vm.parseJson(json, key), (bytes));
    }

    function readBytesArray(string memory json, string memory key)
        internal
        returns (bytes[] memory)
    {
        return abi.decode(vm.parseJson(json, key), (bytes[]));
    }


}

File 5 of 15 : Test.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;

import "./Script.sol";
import "../lib/ds-test/src/test.sol";

// Wrappers around Cheatcodes to avoid footguns
abstract contract Test is DSTest, Script {
    using stdStorage for StdStorage;

    uint256 internal constant UINT256_MAX =
        115792089237316195423570985008687907853269984665640564039457584007913129639935;

    StdStorage internal stdstore;

    /*//////////////////////////////////////////////////////////////////////////
                                    STD-LOGS
    //////////////////////////////////////////////////////////////////////////*/

    event log_array(uint256[] val);
    event log_array(int256[] val);
    event log_array(address[] val);
    event log_named_array(string key, uint256[] val);
    event log_named_array(string key, int256[] val);
    event log_named_array(string key, address[] val);

    /*//////////////////////////////////////////////////////////////////////////
                                    STD-CHEATS
    //////////////////////////////////////////////////////////////////////////*/

    // Skip forward or rewind time by the specified number of seconds
    function skip(uint256 time) internal {
        vm.warp(block.timestamp + time);
    }

    function rewind(uint256 time) internal {
        vm.warp(block.timestamp - time);
    }

    // Setup a prank from an address that has some ether
    function hoax(address who) internal {
        vm.deal(who, 1 << 128);
        vm.prank(who);
    }

    function hoax(address who, uint256 give) internal {
        vm.deal(who, give);
        vm.prank(who);
    }

    function hoax(address who, address origin) internal {
        vm.deal(who, 1 << 128);
        vm.prank(who, origin);
    }

    function hoax(address who, address origin, uint256 give) internal {
        vm.deal(who, give);
        vm.prank(who, origin);
    }

    // Start perpetual prank from an address that has some ether
    function startHoax(address who) internal {
        vm.deal(who, 1 << 128);
        vm.startPrank(who);
    }

    function startHoax(address who, uint256 give) internal {
        vm.deal(who, give);
        vm.startPrank(who);
    }

    // Start perpetual prank from an address that has some ether
    // tx.origin is set to the origin parameter
    function startHoax(address who, address origin) internal {
        vm.deal(who, 1 << 128);
        vm.startPrank(who, origin);
    }

    function startHoax(address who, address origin, uint256 give) internal {
        vm.deal(who, give);
        vm.startPrank(who, origin);
    }

    function changePrank(address who) internal {
        vm.stopPrank();
        vm.startPrank(who);
    }

    // creates a labeled address and the corresponding private key
    function makeAddrAndKey(string memory name) internal returns(address addr, uint256 privateKey) {
        privateKey = uint256(keccak256(abi.encodePacked(name)));
        addr = vm.addr(privateKey);
        vm.label(addr, name);
    }

    // creates a labeled address
    function makeAddr(string memory name) internal returns(address addr) {
        (addr,) = makeAddrAndKey(name);
    }

    // DEPRECATED: Use `deal` instead
    function tip(address token, address to, uint256 give) internal {
        emit log_named_string("WARNING", "Test tip(address,address,uint256): The `tip` stdcheat has been deprecated. Use `deal` instead.");
        stdstore
            .target(token)
            .sig(0x70a08231)
            .with_key(to)
            .checked_write(give);
    }

    // The same as Vm's `deal`
    // Use the alternative signature for ERC20 tokens
    function deal(address to, uint256 give) internal {
        vm.deal(to, give);
    }

    // Set the balance of an account for any ERC20 token
    // Use the alternative signature to update `totalSupply`
    function deal(address token, address to, uint256 give) internal {
        deal(token, to, give, false);
    }

    function deal(address token, address to, uint256 give, bool adjust) internal {
        // get current balance
        (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));
        uint256 prevBal = abi.decode(balData, (uint256));

        // update balance
        stdstore
            .target(token)
            .sig(0x70a08231)
            .with_key(to)
            .checked_write(give);

        // update total supply
        if(adjust){
            (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));
            uint256 totSup = abi.decode(totSupData, (uint256));
            if(give < prevBal) {
                totSup -= (prevBal - give);
            } else {
                totSup += (give - prevBal);
            }
            stdstore
                .target(token)
                .sig(0x18160ddd)
                .checked_write(totSup);
        }
    }

    function bound(uint256 x, uint256 min, uint256 max) internal virtual returns (uint256 result) {
        require(min <= max, "Test bound(uint256,uint256,uint256): Max is less than min.");

        uint256 size = max - min;

        if (size == 0)
        {
            result = min;
        }
        else if (size == UINT256_MAX)
        {
            result = x;
        }
        else
        {
            ++size; // make `max` inclusive
            uint256 mod = x % size;
            result = min + mod;
        }

        emit log_named_uint("Bound Result", result);
    }

    // Deploy a contract by fetching the contract bytecode from
    // the artifacts directory
    // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
    function deployCode(string memory what, bytes memory args)
        internal
        returns (address addr)
    {
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
        /// @solidity memory-safe-assembly
        assembly {
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
        }

        require(
            addr != address(0),
            "Test deployCode(string,bytes): Deployment failed."
        );
    }

    function deployCode(string memory what)
        internal
        returns (address addr)
    {
        bytes memory bytecode = vm.getCode(what);
        /// @solidity memory-safe-assembly
        assembly {
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
        }

        require(
            addr != address(0),
            "Test deployCode(string): Deployment failed."
        );
    }

    /// deploy contract with value on construction
    function deployCode(string memory what, bytes memory args, uint256 val)
        internal
        returns (address addr)
    {
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
        /// @solidity memory-safe-assembly
        assembly {
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
        }

        require(
            addr != address(0),
            "Test deployCode(string,bytes,uint256): Deployment failed."
        );
    }

    function deployCode(string memory what, uint256 val)
        internal
        returns (address addr)
    {
        bytes memory bytecode = vm.getCode(what);
        /// @solidity memory-safe-assembly
        assembly {
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
        }

        require(
            addr != address(0),
            "Test deployCode(string,uint256): Deployment failed."
        );
    }

    /*//////////////////////////////////////////////////////////////////////////
                                    STD-ASSERTIONS
    //////////////////////////////////////////////////////////////////////////*/

    function fail(string memory err) internal virtual {
        emit log_named_string("Error", err);
        fail();
    }

    function assertFalse(bool data) internal virtual {
        assertTrue(!data);
    }

    function assertFalse(bool data, string memory err) internal virtual {
        assertTrue(!data, err);
    }

    function assertEq(bool a, bool b) internal {
        if (a != b) {
            emit log                ("Error: a == b not satisfied [bool]");
            emit log_named_string   ("  Expected", b ? "true" : "false");
            emit log_named_string   ("    Actual", a ? "true" : "false");
            fail();
        }
    }

    function assertEq(bool a, bool b, string memory err) internal {
        if (a != b) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }

    function assertEq(bytes memory a, bytes memory b) internal {
        assertEq0(a, b);
    }

    function assertEq(bytes memory a, bytes memory b, string memory err) internal {
        assertEq0(a, b, err);
    }

    function assertEq(uint256[] memory a, uint256[] memory b) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log("Error: a == b not satisfied [uint[]]");
            emit log_named_array("  Expected", b);
            emit log_named_array("    Actual", a);
            fail();
        }
    }

    function assertEq(int256[] memory a, int256[] memory b) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log("Error: a == b not satisfied [int[]]");
            emit log_named_array("  Expected", b);
            emit log_named_array("    Actual", a);
            fail();
        }
    }

    function assertEq(address[] memory a, address[] memory b) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log("Error: a == b not satisfied [address[]]");
            emit log_named_array("  Expected", b);
            emit log_named_array("    Actual", a);
            fail();
        }
    }

    function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }

    function assertEq(int256[] memory a, int256[] memory b, string memory err) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }


    function assertEq(address[] memory a, address[] memory b, string memory err) internal {
        if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {
            emit log_named_string("Error", err);
            assertEq(a, b);
        }
    }

    function assertApproxEqAbs(
        uint256 a,
        uint256 b,
        uint256 maxDelta
    ) internal virtual {
        uint256 delta = stdMath.delta(a, b);

        if (delta > maxDelta) {
            emit log            ("Error: a ~= b not satisfied [uint]");
            emit log_named_uint ("  Expected", b);
            emit log_named_uint ("    Actual", a);
            emit log_named_uint (" Max Delta", maxDelta);
            emit log_named_uint ("     Delta", delta);
            fail();
        }
    }

    function assertApproxEqAbs(
        uint256 a,
        uint256 b,
        uint256 maxDelta,
        string memory err
    ) internal virtual {
        uint256 delta = stdMath.delta(a, b);

        if (delta > maxDelta) {
            emit log_named_string   ("Error", err);
            assertApproxEqAbs(a, b, maxDelta);
        }
    }

    function assertApproxEqAbs(
        int256 a,
        int256 b,
        uint256 maxDelta
    ) internal virtual {
        uint256 delta = stdMath.delta(a, b);

        if (delta > maxDelta) {
            emit log            ("Error: a ~= b not satisfied [int]");
            emit log_named_int  ("  Expected", b);
            emit log_named_int  ("    Actual", a);
            emit log_named_uint (" Max Delta", maxDelta);
            emit log_named_uint ("     Delta", delta);
            fail();
        }
    }

    function assertApproxEqAbs(
        int256 a,
        int256 b,
        uint256 maxDelta,
        string memory err
    ) internal virtual {
        uint256 delta = stdMath.delta(a, b);

        if (delta > maxDelta) {
            emit log_named_string   ("Error", err);
            assertApproxEqAbs(a, b, maxDelta);
        }
    }

    function assertApproxEqRel(
        uint256 a,
        uint256 b,
        uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
    ) internal virtual {
        if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

        uint256 percentDelta = stdMath.percentDelta(a, b);

        if (percentDelta > maxPercentDelta) {
            emit log                    ("Error: a ~= b not satisfied [uint]");
            emit log_named_uint         ("    Expected", b);
            emit log_named_uint         ("      Actual", a);
            emit log_named_decimal_uint (" Max % Delta", maxPercentDelta, 18);
            emit log_named_decimal_uint ("     % Delta", percentDelta, 18);
            fail();
        }
    }

    function assertApproxEqRel(
        uint256 a,
        uint256 b,
        uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
        string memory err
    ) internal virtual {
        if (b == 0) return assertEq(a, b, err); // If the expected is 0, actual must be too.

        uint256 percentDelta = stdMath.percentDelta(a, b);

        if (percentDelta > maxPercentDelta) {
            emit log_named_string       ("Error", err);
            assertApproxEqRel(a, b, maxPercentDelta);
        }
    }

    function assertApproxEqRel(
        int256 a,
        int256 b,
        uint256 maxPercentDelta
    ) internal virtual {
        if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

        uint256 percentDelta = stdMath.percentDelta(a, b);

        if (percentDelta > maxPercentDelta) {
            emit log                   ("Error: a ~= b not satisfied [int]");
            emit log_named_int         ("    Expected", b);
            emit log_named_int         ("      Actual", a);
            emit log_named_decimal_uint(" Max % Delta", maxPercentDelta, 18);
            emit log_named_decimal_uint("     % Delta", percentDelta, 18);
            fail();
        }
    }

    function assertApproxEqRel(
        int256 a,
        int256 b,
        uint256 maxPercentDelta,
        string memory err
    ) internal virtual {
        if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

        uint256 percentDelta = stdMath.percentDelta(a, b);

        if (percentDelta > maxPercentDelta) {
            emit log_named_string      ("Error", err);
            assertApproxEqRel(a, b, maxPercentDelta);
        }
    }

    /*//////////////////////////////////////////////////////////////
                              JSON PARSING
    //////////////////////////////////////////////////////////////*/

   // Data structures to parse Transaction objects from the broadcast artifact
   // that conform to EIP1559. The Raw structs is what is parsed from the JSON
   // and then converted to the one that is used by the user for better UX.

   struct RawTx1559 {
        string[] arguments;
        address contractAddress;
        string contractName;
        // json value name = function
        string functionSig;
        bytes32 hash;
        // json value name = tx
        RawTx1559Detail txDetail;
        // json value name = type
        string opcode;
    }

    struct RawTx1559Detail {
        AccessList[] accessList;
        bytes data;
        address from;
        bytes gas;
        bytes nonce;
        address to;
        bytes txType;
        bytes value;
    }

    struct Tx1559 {
        string[] arguments;
        address contractAddress;
        string contractName;
        string functionSig;
        bytes32 hash;
        Tx1559Detail txDetail;
        string opcode;
    }

    struct Tx1559Detail {
        AccessList[] accessList;
        bytes data;
        address from;
        uint256 gas;
        uint256 nonce;
        address to;
        uint256 txType;
        uint256 value;
    }

   // Data structures to parse Transaction objects from the broadcast artifact
   // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
   // and then converted to the one that is used by the user for better UX.

    struct TxLegacy{
        string[] arguments;
        address contractAddress;
        string contractName;
        string functionSig;
        string hash;
        string opcode;
        TxDetailLegacy transaction;
    }

    struct TxDetailLegacy{
        AccessList[] accessList;
        uint256 chainId;
        bytes data;
        address from;
        uint256 gas;
        uint256 gasPrice;
        bytes32 hash;
        uint256 nonce;
        bytes1 opcode;
        bytes32 r;
        bytes32 s;
        uint256 txType;
        address to;
        uint8 v;
        uint256 value;
    }

    struct AccessList{
        address accessAddress;
        bytes32[] storageKeys;
    }

    // Data structures to parse Receipt objects from the broadcast artifact.
    // The Raw structs is what is parsed from the JSON
    // and then converted to the one that is used by the user for better UX.

    struct RawReceipt {
        bytes32 blockHash;
        bytes blockNumber;
        address contractAddress;
        bytes cumulativeGasUsed;
        bytes effectiveGasPrice;
        address from;
        bytes gasUsed;
        RawReceiptLog[] logs;
        bytes logsBloom;
        bytes status;
        address to;
        bytes32 transactionHash;
        bytes transactionIndex;
    }

    struct Receipt {
        bytes32 blockHash;
        uint256 blockNumber;
        address contractAddress;
        uint256 cumulativeGasUsed;
        uint256 effectiveGasPrice;
        address from;
        uint256 gasUsed;
        ReceiptLog[] logs;
        bytes logsBloom;
        uint256 status;
        address to;
        bytes32 transactionHash;
        uint256 transactionIndex;
    }

    // Data structures to parse the entire broadcast artifact, assuming the
    // transactions conform to EIP1559.

    struct EIP1559ScriptArtifact {
        string[] libraries;
        string path;
        string[] pending;
        Receipt[] receipts;
        uint256 timestamp;
        Tx1559[] transactions;
        TxReturn[] txReturns;
    }

    struct RawEIP1559ScriptArtifact {
        string[] libraries;
        string path;
        string[] pending;
        RawReceipt[] receipts;
        TxReturn[] txReturns;
        uint256 timestamp;
        RawTx1559[] transactions;
    }

    struct RawReceiptLog {
        // json value = address
        address logAddress;
        bytes32 blockHash;
        bytes blockNumber;
        bytes data;
        bytes logIndex;
        bool removed;
        bytes32[] topics;
        bytes32 transactionHash;
        bytes transactionIndex;
        bytes transactionLogIndex;
    }

    struct ReceiptLog {
        // json value = address
        address logAddress;
        bytes32 blockHash;
        uint256 blockNumber;
        bytes data;
        uint256 logIndex;
        bytes32[] topics;
        uint256 transactionIndex;
        uint256 transactionLogIndex;
        bool removed;
    }

    struct TxReturn {
        string internalType;
        string value;
    }


    function readEIP1559ScriptArtifact(string memory path)
        internal
        returns(EIP1559ScriptArtifact memory)
    {
        string memory data = vm.readFile(path);
        bytes memory parsedData = vm.parseJson(data);
        RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
        EIP1559ScriptArtifact memory artifact;
        artifact.libraries = rawArtifact.libraries;
        artifact.path = rawArtifact.path;
        artifact.timestamp = rawArtifact.timestamp;
        artifact.pending = rawArtifact.pending;
        artifact.txReturns = rawArtifact.txReturns;
        artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
        artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
        return artifact;
    }

    function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs)
        internal pure
        returns (Tx1559[] memory)
    {
        Tx1559[] memory txs = new Tx1559[](rawTxs.length);
        for (uint i; i < rawTxs.length; i++) {
            txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
        }
        return txs;
    }

    function rawToConvertedEIPTx1559(RawTx1559 memory rawTx)
        internal pure
        returns (Tx1559 memory)
    {
        Tx1559 memory transaction;
        transaction.arguments = rawTx.arguments;
        transaction.contractName = rawTx.contractName;
        transaction.functionSig = rawTx.functionSig;
        transaction.hash= rawTx.hash;
        transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
        transaction.opcode= rawTx.opcode;
        return transaction;
    }

    function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
        internal pure
        returns (Tx1559Detail memory)
    {
        Tx1559Detail memory txDetail;
        txDetail.data = rawDetail.data;
        txDetail.from = rawDetail.from;
        txDetail.to = rawDetail.to;
        txDetail.nonce = bytesToUint(rawDetail.nonce);
        txDetail.txType = bytesToUint(rawDetail.txType);
        txDetail.value = bytesToUint(rawDetail.value);
        txDetail.gas = bytesToUint(rawDetail.gas);
        txDetail.accessList = rawDetail.accessList;
        return txDetail;

    }

    function readTx1559s(string memory path)
        internal
        returns (Tx1559[] memory)
    {
        string memory deployData = vm.readFile(path);
        bytes memory parsedDeployData =
            vm.parseJson(deployData, ".transactions");
        RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
        return rawToConvertedEIPTx1559s(rawTxs);
    }


    function readTx1559(string memory path, uint256 index)
        internal
        returns (Tx1559 memory)
    {
        string memory deployData = vm.readFile(path);
        string memory key = string(abi.encodePacked(".transactions[",vm.toString(index), "]"));
        bytes memory parsedDeployData =
            vm.parseJson(deployData, key);
        RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
        return rawToConvertedEIPTx1559(rawTx);
    }


    // Analogous to readTransactions, but for receipts.
    function readReceipts(string memory path)
        internal
        returns (Receipt[] memory)
    {
        string memory deployData = vm.readFile(path);
        bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
        RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
        return rawToConvertedReceipts(rawReceipts);
    }

    function readReceipt(string memory path, uint index)
        internal
        returns (Receipt memory)
    {
        string memory deployData = vm.readFile(path);
        string memory key = string(abi.encodePacked(".receipts[",vm.toString(index), "]"));
        bytes memory parsedDeployData = vm.parseJson(deployData, key);
        RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
        return rawToConvertedReceipt(rawReceipt);
    }

    function rawToConvertedReceipts(RawReceipt[] memory rawReceipts)
        internal pure
        returns(Receipt[] memory)
    {
        Receipt[] memory receipts = new Receipt[](rawReceipts.length);
        for (uint i; i < rawReceipts.length; i++) {
            receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
        }
        return receipts;
    }

    function rawToConvertedReceipt(RawReceipt memory rawReceipt)
        internal pure
        returns(Receipt memory)
    {
        Receipt memory receipt;
        receipt.blockHash = rawReceipt.blockHash;
        receipt.to = rawReceipt.to;
        receipt.from = rawReceipt.from;
        receipt.contractAddress = rawReceipt.contractAddress;
        receipt.effectiveGasPrice = bytesToUint(rawReceipt.effectiveGasPrice);
        receipt.cumulativeGasUsed= bytesToUint(rawReceipt.cumulativeGasUsed);
        receipt.gasUsed = bytesToUint(rawReceipt.gasUsed);
        receipt.status = bytesToUint(rawReceipt.status);
        receipt.transactionIndex = bytesToUint(rawReceipt.transactionIndex);
        receipt.blockNumber = bytesToUint(rawReceipt.blockNumber);
        receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
        receipt.logsBloom = rawReceipt.logsBloom;
        receipt.transactionHash = rawReceipt.transactionHash;
        return receipt;
    }

    function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
        internal pure
        returns (ReceiptLog[] memory)
    {
        ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
        for (uint i; i < rawLogs.length; i++) {
            logs[i].logAddress = rawLogs[i].logAddress;
            logs[i].blockHash = rawLogs[i].blockHash;
            logs[i].blockNumber = bytesToUint(rawLogs[i].blockNumber);
            logs[i].data = rawLogs[i].data;
            logs[i].logIndex = bytesToUint(rawLogs[i].logIndex);
            logs[i].topics = rawLogs[i].topics;
            logs[i].transactionIndex = bytesToUint(rawLogs[i].transactionIndex);
            logs[i].transactionLogIndex = bytesToUint(rawLogs[i].transactionLogIndex);
            logs[i].removed = rawLogs[i].removed;
        }
        return logs;

    }

    function bytesToUint(bytes memory b) internal pure returns (uint256){
            uint256 number;
            for (uint i=0; i < b.length; i++) {
                number = number + uint(uint8(b[i]))*(2**(8*(b.length-(i+1))));
            }
        return number;
    }

}

/*//////////////////////////////////////////////////////////////////////////
                                STD-ERRORS
//////////////////////////////////////////////////////////////////////////*/

library stdError {
    bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
    bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
    bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
    bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
    bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
    bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
    bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
    bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
    bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
    // DEPRECATED: Use Vm's `expectRevert` without any arguments instead
    bytes public constant lowLevelError = bytes(""); // `0x`
}

/*//////////////////////////////////////////////////////////////////////////
                                STD-STORAGE
//////////////////////////////////////////////////////////////////////////*/

struct StdStorage {
    mapping (address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;
    mapping (address => mapping(bytes4 =>  mapping(bytes32 => bool))) finds;

    bytes32[] _keys;
    bytes4 _sig;
    uint256 _depth;
    address _target;
    bytes32 _set;
}

library stdStorage {
    event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint slot);
    event WARNING_UninitedSlot(address who, uint slot);

    uint256 private constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
    int256 private constant INT256_MAX = 57896044618658097711785492504343953926634992332820282019728792003956564819967;

    Vm private constant vm_std_store = Vm(address(uint160(uint256(keccak256('hevm cheat code')))));

    function sigs(
        string memory sigStr
    )
        internal
        pure
        returns (bytes4)
    {
        return bytes4(keccak256(bytes(sigStr)));
    }

    /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
    // slot complexity:
    //  if flat, will be bytes32(uint256(uint));
    //  if map, will be keccak256(abi.encode(key, uint(slot)));
    //  if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
    //  if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
    function find(
        StdStorage storage self
    )
        internal
        returns (uint256)
    {
        address who = self._target;
        bytes4 fsig = self._sig;
        uint256 field_depth = self._depth;
        bytes32[] memory ins = self._keys;

        // calldata to test against
        if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
            return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
        }
        bytes memory cald = abi.encodePacked(fsig, flatten(ins));
        vm_std_store.record();
        bytes32 fdat;
        {
            (, bytes memory rdat) = who.staticcall(cald);
            fdat = bytesToBytes32(rdat, 32*field_depth);
        }

        (bytes32[] memory reads, ) = vm_std_store.accesses(address(who));
        if (reads.length == 1) {
            bytes32 curr = vm_std_store.load(who, reads[0]);
            if (curr == bytes32(0)) {
                emit WARNING_UninitedSlot(who, uint256(reads[0]));
            }
            if (fdat != curr) {
                require(false, "stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.");
            }
            emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));
            self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);
            self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;
        } else if (reads.length > 1) {
            for (uint256 i = 0; i < reads.length; i++) {
                bytes32 prev = vm_std_store.load(who, reads[i]);
                if (prev == bytes32(0)) {
                    emit WARNING_UninitedSlot(who, uint256(reads[i]));
                }
                // store
                vm_std_store.store(who, reads[i], bytes32(hex"1337"));
                bool success;
                bytes memory rdat;
                {
                    (success, rdat) = who.staticcall(cald);
                    fdat = bytesToBytes32(rdat, 32*field_depth);
                }

                if (success && fdat == bytes32(hex"1337")) {
                    // we found which of the slots is the actual one
                    emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));
                    self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);
                    self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;
                    vm_std_store.store(who, reads[i], prev);
                    break;
                }
                vm_std_store.store(who, reads[i], prev);
            }
        } else {
            require(false, "stdStorage find(StdStorage): No storage use detected for target.");
        }

        require(self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))], "stdStorage find(StdStorage): Slot(s) not found.");

        delete self._target;
        delete self._sig;
        delete self._keys;
        delete self._depth;

        return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
    }

    function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
        self._target = _target;
        return self;
    }

    function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
        self._sig = _sig;
        return self;
    }

    function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
        self._sig = sigs(_sig);
        return self;
    }

    function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
        self._keys.push(bytes32(uint256(uint160(who))));
        return self;
    }

    function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
        self._keys.push(bytes32(amt));
        return self;
    }
    function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
        self._keys.push(key);
        return self;
    }

    function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
        self._depth = _depth;
        return self;
    }

    function checked_write(StdStorage storage self, address who) internal {
        checked_write(self, bytes32(uint256(uint160(who))));
    }

    function checked_write(StdStorage storage self, uint256 amt) internal {
        checked_write(self, bytes32(amt));
    }

    function checked_write(StdStorage storage self, bool write) internal {
        bytes32 t;
        /// @solidity memory-safe-assembly
        assembly {
            t := write
        }
        checked_write(self, t);
    }

    function checked_write(
        StdStorage storage self,
        bytes32 set
    ) internal {
        address who = self._target;
        bytes4 fsig = self._sig;
        uint256 field_depth = self._depth;
        bytes32[] memory ins = self._keys;

        bytes memory cald = abi.encodePacked(fsig, flatten(ins));
        if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
            find(self);
        }
        bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);

        bytes32 fdat;
        {
            (, bytes memory rdat) = who.staticcall(cald);
            fdat = bytesToBytes32(rdat, 32*field_depth);
        }
        bytes32 curr = vm_std_store.load(who, slot);

        if (fdat != curr) {
            require(false, "stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.");
        }
        vm_std_store.store(who, slot, set);
        delete self._target;
        delete self._sig;
        delete self._keys;
        delete self._depth;
    }

    function read(StdStorage storage self) private returns (bytes memory) {
        address t = self._target;
        uint256 s = find(self);
        return abi.encode(vm_std_store.load(t, bytes32(s)));
    }

    function read_bytes32(StdStorage storage self) internal returns (bytes32) {
        return abi.decode(read(self), (bytes32));
    }


    function read_bool(StdStorage storage self) internal returns (bool) {
        int256 v = read_int(self);
        if (v == 0) return false;
        if (v == 1) return true;
        revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
    }

    function read_address(StdStorage storage self) internal returns (address) {
        return abi.decode(read(self), (address));
    }

    function read_uint(StdStorage storage self) internal returns (uint256) {
        return abi.decode(read(self), (uint256));
    }

    function read_int(StdStorage storage self) internal returns (int256) {
        return abi.decode(read(self), (int256));
    }

    function bytesToBytes32(bytes memory b, uint offset) public pure returns (bytes32) {
        bytes32 out;

        uint256 max = b.length > 32 ? 32 : b.length;
        for (uint i = 0; i < max; i++) {
            out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
        }
        return out;
    }

    function flatten(bytes32[] memory b) private pure returns (bytes memory)
    {
        bytes memory result = new bytes(b.length * 32);
        for (uint256 i = 0; i < b.length; i++) {
            bytes32 k = b[i];
            /// @solidity memory-safe-assembly
            assembly {
                mstore(add(result, add(32, mul(32, i))), k)
            }
        }

        return result;
    }



}


/*//////////////////////////////////////////////////////////////////////////
                                STD-MATH
//////////////////////////////////////////////////////////////////////////*/

library stdMath {
    int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;

    function abs(int256 a) internal pure returns (uint256) {
        // Required or it will fail when `a = type(int256).min`
        if (a == INT256_MIN)
            return 57896044618658097711785492504343953926634992332820282019728792003956564819968;

        return uint256(a > 0 ? a : -a);
    }

    function delta(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b
            ? a - b
            : b - a;
    }

    function delta(int256 a, int256 b) internal pure returns (uint256) {
        // a and b are of the same sign
        // this works thanks to two's complement, the left-most bit is the sign bit
        if ((a ^ b) > -1) {
            return delta(abs(a), abs(b));
        }

        // a and b are of opposite signs
        return abs(a) + abs(b);
    }

    function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 absDelta = delta(a, b);

        return absDelta * 1e18 / b;
    }

    function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
        uint256 absDelta = delta(a, b);
        uint256 absB = abs(b);

        return absDelta * 1e18 / absB;
    }
}

File 6 of 15 : Vm.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
pragma experimental ABIEncoderV2;

interface Vm {
    struct Log {
        bytes32[] topics;
        bytes data;
    }

    // Sets block.timestamp (newTimestamp)
    function warp(uint256) external;
    // Sets block.height (newHeight)
    function roll(uint256) external;
    // Sets block.basefee (newBasefee)
    function fee(uint256) external;
    // Sets block.difficulty (newDifficulty)
    function difficulty(uint256) external;
    // Sets block.chainid
    function chainId(uint256) external;
    // Loads a storage slot from an address (who, slot)
    function load(address,bytes32) external returns (bytes32);
    // Stores a value to an address' storage slot, (who, slot, value)
    function store(address,bytes32,bytes32) external;
    // Signs data, (privateKey, digest) => (v, r, s)
    function sign(uint256,bytes32) external returns (uint8,bytes32,bytes32);
    // Gets the address for a given private key, (privateKey) => (address)
    function addr(uint256) external returns (address);
    // Gets the nonce of an account
    function getNonce(address) external returns (uint64);
    // Sets the nonce of an account; must be higher than the current nonce of the account
    function setNonce(address, uint64) external;
    // Performs a foreign function call via the terminal, (stringInputs) => (result)
    function ffi(string[] calldata) external returns (bytes memory);
    // Sets environment variables, (name, value)
    function setEnv(string calldata, string calldata) external;
    // Reads environment variables, (name) => (value)
    function envBool(string calldata) external returns (bool);
    function envUint(string calldata) external returns (uint256);
    function envInt(string calldata) external returns (int256);
    function envAddress(string calldata) external returns (address);
    function envBytes32(string calldata) external returns (bytes32);
    function envString(string calldata) external returns (string memory);
    function envBytes(string calldata) external returns (bytes memory);
    // Reads environment variables as arrays, (name, delim) => (value[])
    function envBool(string calldata, string calldata) external returns (bool[] memory);
    function envUint(string calldata, string calldata) external returns (uint256[] memory);
    function envInt(string calldata, string calldata) external returns (int256[] memory);
    function envAddress(string calldata, string calldata) external returns (address[] memory);
    function envBytes32(string calldata, string calldata) external returns (bytes32[] memory);
    function envString(string calldata, string calldata) external returns (string[] memory);
    function envBytes(string calldata, string calldata) external returns (bytes[] memory);
    // Sets the *next* call's msg.sender to be the input address
    function prank(address) external;
    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
    function startPrank(address) external;
    // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
    function prank(address,address) external;
    // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
    function startPrank(address,address) external;
    // Resets subsequent calls' msg.sender to be `address(this)`
    function stopPrank() external;
    // Sets an address' balance, (who, newBalance)
    function deal(address, uint256) external;
    // Sets an address' code, (who, newCode)
    function etch(address, bytes calldata) external;
    // Expects an error on next call
    function expectRevert(bytes calldata) external;
    function expectRevert(bytes4) external;
    function expectRevert() external;
    // Records all storage reads and writes
    function record() external;
    // Gets all accessed reads and write slot from a recording session, for a given address
    function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes);
    // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
    // Call this function, then emit an event, then call a function. Internally after the call, we check if
    // logs were emitted in the expected order with the expected topics and data (as specified by the booleans)
    function expectEmit(bool,bool,bool,bool) external;
    function expectEmit(bool,bool,bool,bool,address) external;
    // Mocks a call to an address, returning specified data.
    // Calldata can either be strict or a partial match, e.g. if you only
    // pass a Solidity selector to the expected calldata, then the entire Solidity
    // function will be mocked.
    function mockCall(address,bytes calldata,bytes calldata) external;
    // Mocks a call to an address with a specific msg.value, returning specified data.
    // Calldata match takes precedence over msg.value in case of ambiguity.
    function mockCall(address,uint256,bytes calldata,bytes calldata) external;
    // Clears all mocked calls
    function clearMockedCalls() external;
    // Expects a call to an address with the specified calldata.
    // Calldata can either be a strict or a partial match
    function expectCall(address,bytes calldata) external;
    // Expects a call to an address with the specified msg.value and calldata
    function expectCall(address,uint256,bytes calldata) external;
    // Gets the code from an artifact file. Takes in the relative path to the json file
    function getCode(string calldata) external returns (bytes memory);
    // Labels an address in call traces
    function label(address, string calldata) external;
    // If the condition is false, discard this run's fuzz inputs and generate new ones
    function assume(bool) external;
    // Sets block.coinbase (who)
    function coinbase(address) external;
    // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain
    function broadcast() external;
    // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain
    function broadcast(address) external;
    // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
    function startBroadcast() external;
    // Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
    function startBroadcast(address) external;
    // Stops collecting onchain transactions
    function stopBroadcast() external;

    // Reads the entire content of file to string, (path) => (data)
    function readFile(string calldata) external returns (string memory);
    // Get the path of the current project root
    function projectRoot() external returns (string memory);
    // Reads next line of file to string, (path) => (line)
    function readLine(string calldata) external returns (string memory);
    // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
    // (path, data) => ()
    function writeFile(string calldata, string calldata) external;
    // Writes line to file, creating a file if it does not exist.
    // (path, data) => ()
    function writeLine(string calldata, string calldata) external;
    // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
    // (path) => ()
    function closeFile(string calldata) external;
    // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:
    // - Path points to a directory.
    // - The file doesn't exist.
    // - The user lacks permissions to remove the file.
    // (path) => ()
    function removeFile(string calldata) external;

    // Convert values to a string, (value) => (stringified value)
    function toString(address) external returns(string memory);
    function toString(bytes calldata) external returns(string memory);
    function toString(bytes32) external returns(string memory);
    function toString(bool) external returns(string memory);
    function toString(uint256) external returns(string memory);
    function toString(int256) external returns(string memory);

    // Convert values from a string, (string) => (parsed value)
    function parseBytes(string calldata) external returns (bytes memory);
    function parseAddress(string calldata) external returns (address);
    function parseUint(string calldata) external returns (uint256);
    function parseInt(string calldata) external returns (int256);
    function parseBytes32(string calldata) external returns (bytes32);
    function parseBool(string calldata) external returns (bool);

    // Record all the transaction logs
    function recordLogs() external;
    // Gets all the recorded logs, () => (logs)
    function getRecordedLogs() external returns (Log[] memory);
    // Snapshot the current state of the evm.
    // Returns the id of the snapshot that was created.
    // To revert a snapshot use `revertTo`
    function snapshot() external returns(uint256);
    // Revert the state of the evm to a previous snapshot
    // Takes the snapshot id to revert to.
    // This deletes the snapshot and all snapshots taken after the given snapshot id.
    function revertTo(uint256) external returns(bool);

    // Creates a new fork with the given endpoint and block and returns the identifier of the fork
    function createFork(string calldata,uint256) external returns(uint256);
    // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork
    function createFork(string calldata) external returns(uint256);
    // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork
    function createSelectFork(string calldata,uint256) external returns(uint256);
    // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork
    function createSelectFork(string calldata) external returns(uint256);
    // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
    function selectFork(uint256) external;
    /// Returns the currently active fork
    /// Reverts if no fork is currently active
    function activeFork() external returns(uint256);
    // Updates the currently active fork to given block number
    // This is similar to `roll` but for the currently active fork
    function rollFork(uint256) external;
    // Updates the given fork to given block number
    function rollFork(uint256 forkId, uint256 blockNumber) external;

    // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
    // Meaning, changes made to the state of this account will be kept when switching forks
    function makePersistent(address) external;
    function makePersistent(address, address) external;
    function makePersistent(address, address, address) external;
    function makePersistent(address[] calldata) external;
    // Revokes persistent status from the address, previously added via `makePersistent`
    function revokePersistent(address) external;
    function revokePersistent(address[] calldata) external;
    // Returns true if the account is marked as persistent
    function isPersistent(address) external returns (bool);

    // Returns the RPC url for the given alias
    function rpcUrl(string calldata) external returns(string memory);
    // Returns all rpc urls and their aliases `[alias, url][]`
    function rpcUrls() external returns(string[2][] memory);

    // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}
    function deriveKey(string calldata, uint32) external returns (uint256);
    // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path {path}{index}
    function deriveKey(string calldata, string calldata, uint32) external returns (uint256);
    // parseJson

    // Given a string of JSON, return the ABI-encoded value of provided key
    // (stringified json, key) => (ABI-encoded data)
    // Read the note below!
    function parseJson(string calldata, string calldata) external returns(bytes memory);

    // Given a string of JSON, return it as ABI-encoded, (stringified json, key) => (ABI-encoded data)
    // Read the note below!
    function parseJson(string calldata) external returns(bytes memory);

    // Note:
    // ----
    // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects
    // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in
    // ALPHABETICAL ordser. That means that in order to succesfully decode the tuple, we need to define a tuple that
    // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded
    // as tuples, with the attributes in the order in which they are defined.
    // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}
    // a: uint256
    // b: address
    // To decode that json, we need to define a struct or a tuple as follows:
    // struct json = { uint256 a; address b; }
    // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to
    // decode the tuple in that order, and thus fail.

}

File 7 of 15 : 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 8 of 15 : console2.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

// The orignal console.sol uses `int` and `uint` for computing function selectors, but it should
// use `int256` and `uint256`. This modified version fixes that. This version is recommended
// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in
// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.
// Reference: https://github.com/NomicFoundation/hardhat/issues/2178

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

    function _sendLogPayload(bytes memory payload) private view {
        uint256 payloadLength = payload.length;
        address consoleAddress = CONSOLE_ADDRESS;
        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(int256 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
    }

    function logUint(uint256 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", 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(uint256 p0) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint256)", 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(uint256 p0, uint256 p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
    }

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

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

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

    function log(string memory p0, uint256 p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", 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, uint256 p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", 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, uint256 p1) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", 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(uint256 p0, uint256 p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function log(string memory p0, string memory p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", 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, uint256 p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
    }

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

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

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

    function log(bool p0, string memory p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", 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, uint256 p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
    }

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

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

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

    function log(address p0, string memory p1, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", 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, uint256 p2) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", 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(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", 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, uint256 p1, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", 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, uint256 p1, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", 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, uint256 p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
    }

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

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

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

    function log(address p0, address p1, string memory p2, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", 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, uint256 p3) internal view {
        _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", 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 9 of 15 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 10 of 15 : 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;
    }
}

File 11 of 15 : 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);

    function decimals() external view returns (uint8);
}

File 12 of 15 : ISpot.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {ISpotStorage} from "src/spot/interfaces/ISpotStorage.sol";

interface ISpot is ISpotStorage {
    event InitializeSpot(
        uint256 _maxFundraisingPeriod,
        uint256 _mFee,
        uint256 _pFee,
        address indexed _owner,
        address indexed _admin,
        address indexed _treasury
    );
    event NewFundCreated(
        address indexed baseToken,
        address indexed depositToken,
        uint256 fundraisingPeriod,
        address indexed manager,
        bytes32 salt,
        uint256 chainId,
        uint96 capacity
    );
    event BaseTokenUpdate(address indexed baseToken, bool isBaseToken);
    event DepositTokenUpdate(address indexed depositToken, bool isDepositToken);
    event StfxSwapUpdate(address indexed swap);
    event StfxTradeUpdate(address indexed trade);
    event PluginUpdate(address indexed plugin, bool _isPlugin);
    event DepositIntoFund(address indexed investor, uint256 amount, bytes32 indexed salt);
    event FundraisingClosed(bytes32 stf);
    event Claimed(address indexed investor, uint256 amount, bytes32 indexed salt);
    event CancelVault(bytes32 indexed salt);
    event TokenCapacityUpdate(address indexed baseToken, address indexed depositToken, uint96 capacity);
    event MinInvestmentAmountChanged(address indexed depositToken, uint96 minAmount);
    event MaxFundraisingPeriodChanged(uint40 maxFundraisingPeriod);
    event ManagerFeeChanged(uint96 managerFee);
    event ProtocolFeeChanged(uint96 protocolFee);
    event OwnerChanged(address indexed newOwner);
    event FundDeadlineChanged(bytes32 indexed salt, uint256 fundDeadline);
    event AdminChanged(address indexed admin);
    event TreasuryChanged(address indexed treasury);
    event ManagingFundUpdate(address indexed manager, bool isManaging);
    event TradeMappingUpdate(address indexed baseToken, address indexed stfxTrade);
    event Withdraw(address indexed token, uint96 amount, address indexed to);

    function owner() external view returns (address);

    function managerCurrentStf(address) external returns (bytes32);

    function managerFee() external view returns (uint96);

    function protocolFee() external view returns (uint96);

    function admin() external view returns (address);

    function treasury() external view returns (address);

    function getTradeMapping(address _baseToken) external view returns (address);

    function getManagerCurrentStfInfo(address) external returns (StfSpotInfo memory);

    function getStfInfo(bytes32) external returns (StfSpotInfo memory);

    function createNewStf(StfSpot calldata _fund) external returns (bytes32);

    function closeFundraising() external;

    function transferToken(address token, uint256 amount) external;

    function openSpot(uint96 amount, uint96 received, bytes32 salt) external;

    function closeSpot(uint96 remaining, bytes32 salt) external;

    function claimableAmount(bytes32 salt, address investor) external view returns (uint256);

    function claim(bytes32) external;

    function cancelVault(bytes32) external;

    function addMinInvestmentAmount(address _token, uint96 _amount) external;

    function setManagerFee(uint96 _managerFee) external;

    function setProtocolFee(uint96 _protocolFee) external;

    function setOwner(address _owner) external;

    function setFundDeadline(bytes32 salt, uint40 _fundDeadline) external;

    function setIsManagingFund(address _manager, bool _isManaging) external;
}

File 13 of 15 : ISpotStorage.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface ISpotStorage {
    /// @notice Enum to describe the trading status of the vault
    /// @dev NOT_OPENED - Not open
    /// @dev OPENED - opened position
    /// @dev CANCELLED_WITH_ZERO_RAISE - cancelled without any raise
    /// @dev CANCELLED_WITH_NO_FILL - cancelled with raise but not opening a position
    /// @dev CANCELLED_BY_MANAGER - cancelled by the manager after raising
    /// @dev DISTRIBUTED - closed position and distributed fees
    enum StfStatus {
        NOT_OPENED,
        OPENED,
        CANCELLED_WITH_ZERO_RAISE,
        CANCELLED_WITH_NO_FILL,
        CANCELLED_BY_MANAGER,
        DISTRIBUTED
    }

    struct StfSpot {
        address baseToken;
        address depositToken;
        uint40 fundraisingPeriod;
    }

    struct StfSpotInfo {
        StfStatus status;
        address manager;
        uint40 endTime;
        uint40 fundDeadline;
        uint96 totalRaised;
        uint96 totalAmountUsed;
        uint96 totalReceived;
        uint96 remainingAfterFees;
        address baseToken;
        address depositToken;
    }
}

File 14 of 15 : ISwap.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {ISpotStorage} from "src/spot/interfaces/ISpotStorage.sol";

interface ISwap is ISpotStorage {
    function swapUniversalRouter(
        address token0,
        address token1,
        uint160 amount,
        bytes calldata commands,
        bytes[] calldata inputs,
        uint256 deadline,
        address receiver
    ) external returns (uint96);
}

File 15 of 15 : ITrade.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import {ISpotStorage} from "src/spot/interfaces/ISpotStorage.sol";

interface ITrade is ISpotStorage {
    event OpenSpot(
        bytes32 indexed salt,
        uint96 amount,
        uint256 swapAmount,
        uint96 received,
        bytes commands,
        bytes[] inputs,
        uint256 deadline
    );

    event CloseSpot(
        bytes32 indexed salt,
        uint96 remainingAfterClose,
        uint96 managerFee,
        uint96 protocolFee,
        bytes commands,
        bytes[] inputs,
        uint256 deadline
    );

    function openSpot(uint96 amount, bytes calldata commands, bytes[] calldata inputs, uint256 deadline)
        external
        returns (uint96 received);

    function closeSpot(bytes calldata commands, bytes[] calldata inputs, uint256 deadline)
        external
        returns (uint96 remaining);

    function closeSpotByAdmin(bytes calldata commands, bytes[] calldata inputs, bytes32 salt)
        external
        returns (uint96 remaining);
}

Settings
{
  "remappings": [
    "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "permit2/=lib/permit2/src/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint96","name":"max","type":"uint96"},{"internalType":"uint96","name":"given","type":"uint96"}],"name":"AboveMax","type":"error"},{"inputs":[],"name":"AlreadyOpened","type":"error"},{"inputs":[{"internalType":"uint96","name":"min","type":"uint96"},{"internalType":"uint96","name":"given","type":"uint96"}],"name":"BelowMin","type":"error"},{"inputs":[],"name":"CantClose","type":"error"},{"inputs":[{"internalType":"address","name":"fund","type":"address"}],"name":"FundExists","type":"error"},{"inputs":[],"name":"FundraisingComplete","type":"error"},{"inputs":[{"internalType":"address","name":"desired","type":"address"},{"internalType":"address","name":"given","type":"address"}],"name":"NoAccess","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"NoBaseToken","type":"error"},{"inputs":[],"name":"NotFinalised","type":"error"},{"inputs":[],"name":"NotValidPlugin","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isBaseToken","type":"bool"}],"name":"BaseTokenUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"CancelVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"investor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"investor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"DepositIntoFund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isDepositToken","type":"bool"}],"name":"DepositTokenUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"salt","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"fundDeadline","type":"uint256"}],"name":"FundDeadlineChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"stf","type":"bytes32"}],"name":"FundraisingClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_maxFundraisingPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_mFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_pFee","type":"uint256"},{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_admin","type":"address"},{"indexed":true,"internalType":"address","name":"_treasury","type":"address"}],"name":"InitializeSpot","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"managerFee","type":"uint96"}],"name":"ManagerFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"manager","type":"address"},{"indexed":false,"internalType":"bool","name":"isManaging","type":"bool"}],"name":"ManagingFundUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"maxFundraisingPeriod","type":"uint40"}],"name":"MaxFundraisingPeriodChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":false,"internalType":"uint96","name":"minAmount","type":"uint96"}],"name":"MinInvestmentAmountChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fundraisingPeriod","type":"uint256"},{"indexed":true,"internalType":"address","name":"manager","type":"address"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"capacity","type":"uint96"}],"name":"NewFundCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"plugin","type":"address"},{"indexed":false,"internalType":"bool","name":"_isPlugin","type":"bool"}],"name":"PluginUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"protocolFee","type":"uint96"}],"name":"ProtocolFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"swap","type":"address"}],"name":"StfxSwapUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trade","type":"address"}],"name":"StfxTradeUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":false,"internalType":"uint96","name":"capacity","type":"uint96"}],"name":"TokenCapacityUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"stfxTrade","type":"address"}],"name":"TradeMappingUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"treasury","type":"address"}],"name":"TreasuryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint96","name":"_amount","type":"uint96"}],"name":"addMinInvestmentAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_plugin","type":"address"},{"internalType":"bool","name":"_isPlugin","type":"bool"}],"name":"addPlugin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint96","name":"capacity","type":"uint96"}],"name":"addTokenCapacity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_baseToken","type":"address"},{"internalType":"address","name":"_stfxTrade","type":"address"}],"name":"addTradeMapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"cancelVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_baseToken","type":"address"},{"internalType":"bool","name":"_isBaseToken","type":"bool"}],"name":"changeBaseToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_depositToken","type":"address"},{"internalType":"bool","name":"_isDepositToken","type":"bool"}],"name":"changeDepositToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"claimAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"claimPartialAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"},{"internalType":"address","name":"_investor","type":"address"}],"name":"claimableAmount","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFundraising","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"remaining","type":"uint96"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"closeSpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"depositToken","type":"address"},{"internalType":"uint40","name":"fundraisingPeriod","type":"uint40"}],"internalType":"struct ISpotStorage.StfSpot","name":"_stf","type":"tuple"}],"name":"createNewStf","outputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"depositIntoFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_investor","type":"address"},{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getClaimAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_investor","type":"address"},{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getClaimPartialAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getIsBaseToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getIsDepositToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"getIsManagingFund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"getManagerCurrentSalt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"getManagerCurrentStfInfo","outputs":[{"components":[{"internalType":"enum ISpotStorage.StfStatus","name":"status","type":"uint8"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint40","name":"endTime","type":"uint40"},{"internalType":"uint40","name":"fundDeadline","type":"uint40"},{"internalType":"uint96","name":"totalRaised","type":"uint96"},{"internalType":"uint96","name":"totalAmountUsed","type":"uint96"},{"internalType":"uint96","name":"totalReceived","type":"uint96"},{"internalType":"uint96","name":"remainingAfterFees","type":"uint96"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"depositToken","type":"address"}],"internalType":"struct ISpotStorage.StfSpotInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getManagerFromSalt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getPnlAfterFees","outputs":[{"internalType":"int96","name":"pnlAfterFees","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getStatusOfStf","outputs":[{"internalType":"enum ISpotStorage.StfStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getStfInfo","outputs":[{"components":[{"internalType":"enum ISpotStorage.StfStatus","name":"status","type":"uint8"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint40","name":"endTime","type":"uint40"},{"internalType":"uint40","name":"fundDeadline","type":"uint40"},{"internalType":"uint96","name":"totalRaised","type":"uint96"},{"internalType":"uint96","name":"totalAmountUsed","type":"uint96"},{"internalType":"uint96","name":"totalReceived","type":"uint96"},{"internalType":"uint96","name":"remainingAfterFees","type":"uint96"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"depositToken","type":"address"}],"internalType":"struct ISpotStorage.StfSpotInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_baseToken","type":"address"},{"internalType":"address","name":"_depositToken","type":"address"}],"name":"getTokenCapacity","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_baseToken","type":"address"}],"name":"getTradeMapping","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_investor","type":"address"},{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"getUserAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"hasFundraisingPeriodEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBaseToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isCancelledByManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isCancelledWithNoFill","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isCancelledWithZeroRaised","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isDepositToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isDistributed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isManagingFund","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isNotOpened","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"isOpened","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isPlugin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"managerCurrentStf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerFee","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxFundraisingPeriod","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minInvestmentAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint96","name":"received","type":"uint96"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"openSpot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint40","name":"newFundDeadline","type":"uint40"}],"name":"setFundDeadline","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"bool","name":"_isManaging","type":"bool"}],"name":"setIsManagingFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"newManagerFee","type":"uint96"}],"name":"setManagerFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"_maxFundraisingPeriod","type":"uint40"}],"name":"setMaxFundraisingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"newProtocolFee","type":"uint96"}],"name":"setProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"stfInfo","outputs":[{"internalType":"enum ISpotStorage.StfStatus","name":"status","type":"uint8"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"uint40","name":"endTime","type":"uint40"},{"internalType":"uint40","name":"fundDeadline","type":"uint40"},{"internalType":"uint96","name":"totalRaised","type":"uint96"},{"internalType":"uint96","name":"totalAmountUsed","type":"uint96"},{"internalType":"uint96","name":"totalReceived","type":"uint96"},{"internalType":"uint96","name":"remainingAfterFees","type":"uint96"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"depositToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenCapacity","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tradeMapping","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"userAmount","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162003dc138038062003dc183398101604081905262000034916200012f565b60008054600180546001600160a01b0319166001600160a01b038681169182179092556001600160d01b03199092166101003390810264ffffffffff60a81b19169190911761127560af1b17909355831665340aad21b3b760b21b8117600281905560038054674563918244f400006001600160601b031990911681179091556040805162093a8081526001600160601b03600160a01b9094049390931660208401528201529092907fd50b4f1e09064b28c3a9151b6a86cb9809835dda24ec84d530d6d1f2e37d4a5e9060600160405180910390a4505062000167565b80516001600160a01b03811681146200012a57600080fd5b919050565b600080604083850312156200014357600080fd5b6200014e8362000112565b91506200015e6020840162000112565b90509250929050565b613c4a80620001776000396000f3fe608060405234801561001057600080fd5b50600436106103e65760003560e01c806385bb6a3c1161020a578063b89e45b311610125578063e9d977c0116100b8578063f071372a11610087578063f071372a14610b85578063f0f4426014610b98578063f5eb3db814610bab578063f851a44014610bbe578063fa57cb0e14610bd157600080fd5b8063e9d977c014610b20578063ea5c942814610b4c578063eb0a5a2d14610b5f578063eb600f7414610b7257600080fd5b8063d3126817116100f4578063d312681714610abe578063d951b3a514610af2578063e2879a1014610b05578063e34c333314610b0d57600080fd5b8063b89e45b3146109d1578063bd66528a146109f4578063c845201714610a07578063ccc923fa14610aab57600080fd5b806394e20bb11161019d578063a3cb57341161016c578063a3cb573414610964578063acce01f914610998578063aef8a03c146109ab578063b0e21e8a146109be57600080fd5b806394e20bb1146108ab57806396153ae8146108ed57806399c07fb4146109165780639c7632fc1461094a57600080fd5b806389a9a7ee116101d957806389a9a7ee1461085a5780638c8c3c9d1461086d5780638da5cb5b14610880578063925c9bbd1461089857600080fd5b806385bb6a3c146107bc57806385bf9435146107df5780638657f9f11461081e578063876428401461083157600080fd5b80635c943880116103055780636b6dccfe116102985780637629e26c116102675780637629e26c146107585780637ac7c7fe1461076b5780637d1096471461077e5780637e06c0dc146107a15780638456cb59146107b457600080fd5b80636b6dccfe146106f3578063704b6c021461070657806370bdefc1146107195780637592ce0f1461072c57600080fd5b806361d027b3116102d457806361d027b31461065957806363f0e3c914610684578063671469b9146106a757806368d1e264146106c757600080fd5b80635c943880146105fa5780635c975abb146106285780635e33d715146106335780635f5794f11461064657600080fd5b80633a6ac96a1161037d578063444920eb1161034c578063444920eb14610569578063567b9b0f146105a05780635826b2e8146105d45780635b81b123146105e757600080fd5b80633a6ac96a146104ef5780633f4ba83a1461050257806340735dc41461050a5780634380d0a51461052a57600080fd5b806313af4035116103b957806313af40351461045f578063181d5c06146104725780631c0069391461049d57806331ae7a65146104c957600080fd5b806301ed5861146103eb5780630d00472e146104145780631072cbea14610437578063138f29be1461044c575b600080fd5b6103fe6103f936600461351b565b610be4565b60405161040b919061356c565b60405180910390f35b61042761042236600461351b565b610ccb565b604051901515815260200161040b565b61044a610445366004613681565b610d02565b005b61044a61045a3660046136c0565b610db0565b61044a61046d3660046136ec565b610ed4565b610485610480366004613681565b610f8f565b6040516001600160601b03909116815260200161040b565b6104276104ab3660046136ec565b6001600160a01b031660009081526005602052604090205460ff1690565b6104dc6104d736600461351b565b610fc3565b604051600b9190910b815260200161040b565b6104276104fd36600461351b565b6110c4565b61044a6110d9565b61051d61051836600461351b565b611125565b60405161040b9190613707565b610485610538366004613681565b6001600160a01b0391909116600090815260096020908152604080832093835292905220546001600160601b031690565b6105926105773660046136ec565b6001600160a01b031660009081526007602052604090205490565b60405190815260200161040b565b6104856105ae366004613681565b60096020908152600092835260408084209091529082529020546001600160601b031681565b61044a6105e236600461372c565b611209565b6105926105f536600461374f565b6116ba565b60005461061290600160a81b900464ffffffffff1681565b60405164ffffffffff909116815260200161040b565b60005460ff16610427565b61044a610641366004613772565b611b43565b61042761065436600461351b565b611c0e565b60025461066c906001600160a01b031681565b6040516001600160a01b03909116815260200161040b565b6104276106923660046136ec565b600e6020526000908152604090205460ff1681565b6105926106b53660046136ec565b60076020526000908152604090205481565b6104276106d53660046136ec565b6001600160a01b03166000908152600b602052604090205460ff1690565b61044a6107013660046137a9565b611c23565b61044a6107143660046136ec565b611cc4565b6105926107273660046137c4565b611d79565b61042761073a3660046136ec565b6001600160a01b03166000908152600c602052604090205460ff1690565b61044a610766366004613772565b611f71565b6103fe6107793660046136ec565b612034565b61042761078c3660046136ec565b60056020526000908152604090205460ff1681565b61044a6107af36600461351b565b612137565b61044a6123d8565b6104276107ca3660046136ec565b600b6020526000908152604090205460ff1681565b6104856107ed366004613681565b6001600160a01b0391909116600090815260086020908152604080832093835292905220546001600160601b031690565b61042761082c36600461351b565b612422565b61048561083f3660046136ec565b6004602052600090815260409020546001600160601b031681565b61044a610868366004613772565b612523565b61044a61087b3660046137e7565b6125c7565b60005461066c9061010090046001600160a01b031681565b6104276108a636600461351b565b612789565b6104856108b9366004613811565b6001600160a01b039182166000908152600d602090815260408083209390941682529190915220546001600160601b031690565b61066c6108fb3660046136ec565b600f602052600090815260409020546001600160a01b031681565b610485610924366004613681565b600a6020908152600092835260408084209091529082529020546001600160601b031681565b60025461048590600160a01b90046001600160601b031681565b610485610972366004613681565b60086020908152600092835260408084209091529082529020546001600160601b031681565b61044a6109a636600461383b565b61279e565b61044a6109b93660046137a9565b612834565b600354610485906001600160601b031681565b6104276109df3660046136ec565b600c6020526000908152604090205460ff1681565b61044a610a0236600461351b565b6128d6565b610a95610a1536600461351b565b6006602052600090815260409020805460018201546002830154600384015460049094015460ff8416946001600160a01b03610100860481169564ffffffffff600160a81b8204811696600160d01b90920416946001600160601b0380831695600160601b9384900482169583831695949093049091169291821691168a565b60405161040b9a99989796959493929190613877565b61044a610ab93660046138ed565b612b80565b610485610acc366004613811565b600d6020908152600092835260408084209091529082529020546001600160601b031681565b610427610b0036600461351b565b612caf565b61044a612cc4565b61044a610b1b366004613930565b612e12565b61066c610b2e3660046136ec565b6001600160a01b039081166000908152600f60205260409020541690565b61044a610b5a3660046137e7565b612eef565b61066c610b6d36600461351b565b612fc3565b61044a610b80366004613772565b6130aa565b61044a610b9336600461394b565b61316d565b61044a610ba63660046136ec565b61321b565b610427610bb936600461351b565b6132d0565b60015461066c906001600160a01b031681565b61044a610bdf366004613811565b6132e5565b610bec6134c5565b60008281526006602052604090819020815161014081019092528054829060ff166005811115610c1e57610c1e613534565b6005811115610c2f57610c2f613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e084015260038401548216908301526004909201549091166101209091015292915050565b600080610cd783611125565b905060055b816005811115610cee57610cee613534565b03610cfc5750600192915050565b50919050565b336000908152600e602052604090205460ff16610d325760405163418954f760e11b815260040160405180910390fd5b610d3a6133a7565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303816000875af1158015610d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dab9190613967565b505050565b610db86133a7565b6000610dc383610be4565b905080602001516001600160a01b0316336001600160a01b031614158015610dfb575060005461010090046001600160a01b03163314155b15610e2a57806020015133604051630150a30b60e21b8152600401610e21929190613984565b60405180910390fd5b6203f4808264ffffffffff161115610e67576040516305f0e94360e01b81526203f480600482015264ffffffffff83166024820152604401610e21565b600083815260066020908152604091829020805464ffffffffff60d01b1916600160d01b64ffffffffff871690810291909117909155915191825284917fb711cf4c951c83a618ff2370aada0beb10e68bd204a1c7b6cc2dc25ef3e169d7910160405180910390a2505050565b60005461010090046001600160a01b03163314610f1857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038116610f3f5760405163d92e233d60e01b815260040160405180910390fd5b60008054610100600160a81b0319166101006001600160a01b03841690810291909117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b6001600160a01b0382166000908152600a602090815260408083208484529091529020546001600160601b03165b92915050565b60008181526006602052604080822081516101408101909252805483929190829060ff166005811115610ff857610ff8613534565b600581111561100957611009613534565b815281546001600160a01b036101008083048216602085015264ffffffffff600160a81b840481166040860152600160d01b909304909216606084015260018401546001600160601b03808216608080870191909152600160601b92839004821660a0870152600287015480831660c0880152929092041660e0808601919091526003860154831693850193909352600490940154166101209092019190915290820151908201519192506110bd916139b4565b9392505050565b6000806110d083611125565b90506003610cdc565b6001546001600160a01b0316331461111357600154604051630150a30b60e21b8152610e21916001600160a01b0316903390600401613984565b61111b6133ed565b611123613436565b565b60008181526006602052604080822081516101408101909252805483929190829060ff16600581111561115a5761115a613534565b600581111561116b5761116b613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e0840152600384015482169083015260049092015490911661012090910152519392505050565b6112116133a7565b600061121c83610be4565b905060008161012001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190613a0e565b6101208301516040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156112d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fc9190613a31565b9050600061130b836012613a4a565b61131690600a613b51565b611329906001600160601b038716613b60565b6101208501516001600160a01b03166000908152600460205260409020549091506001600160601b0390811690861610156113ae576101208401516001600160a01b0316600090815260046020819052604091829020549151635b7892d160e11b81526001600160601b03928316918101919091529086166024820152604401610e21565b60208401516001600160a01b03166113d95760405163d92e233d60e01b815260040160405180910390fd5b806001600160601b0316826001600160601b0316101561141f57604051635b7892d160e11b81526001600160601b03808416600483015282166024820152604401610e21565b836040015164ffffffffff164264ffffffffff1611156114525760405163780c89c560e01b815260040160405180910390fd5b60008451600581111561146757611467613534565b1461148557604051630ed2159360e11b815260040160405180910390fd5b6101008401516001600160a01b039081166000908152600d602090815260408083206101208901519094168352929052205460808501516001600160601b03909116906114d3908790613b82565b6001600160601b0316111561155c576101008401516001600160a01b039081166000908152600d602090815260408083206101208901519094168352929052205460808501516001600160601b0390911690611530908790613b82565b6040516305f0e94360e01b81526001600160601b03928316600482015291166024820152604401610e21565b600086815260066020526040812060010180548792906115869084906001600160601b0316613b82565b82546101009290920a6001600160601b038181021990931691831602179091553360009081526008602090815260408083208b84529091528120805489945090926115d391859116613b82565b82546101009290920a6001600160601b038181021990931691831602179091556101208601516040516323b872dd60e01b815233600482015230602482015291841660448301526001600160a01b031691506323b872dd906064016020604051808303816000875af115801561164d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116719190613967565b506040516001600160601b0386168152869033907f9096e481393af38e01008317b0d2fc664c1608cd8f693072d73b6b78539c40079060200160405180910390a3505050505050565b60006116c46133a7565b3360009081526005602052604090205460ff16156116f7576040516326e90db160e21b8152336004820152602401610e21565b61038461170a6060840160408501613930565b64ffffffffff16101561175b5761038461172a6060840160408501613930565b604051635b7892d160e11b81526001600160601b03909216600483015264ffffffffff166024820152604401610e21565b600054600160a81b900464ffffffffff1661177c6060840160408501613930565b64ffffffffff1611156117d457600054600160a81b900464ffffffffff166117aa6060840160408501613930565b6040516305f0e94360e01b815264ffffffffff928316600482015291166024820152604401610e21565b600b60006117e560208501856136ec565b6001600160a01b0316815260208101919091526040016000205460ff16158061183c5750600c600061181d60408501602086016136ec565b6001600160a01b0316815260208101919091526040016000205460ff16155b156118735761184e60208301836136ec565b60405163b4d5d76960e01b81526001600160a01b039091166004820152602401610e21565b3361188160208401846136ec565b61189160408501602086016136ec565b6118a16060860160408701613930565b604051606094851b6001600160601b0319908116602083015293851b841660348201529190931b909116604882015260d89190911b6001600160d81b031916605c8201524260618201524360818201524660a182015260c10160408051601f1981840301815291815281516020928301203360008181526007855283812083905560058552838120805460ff1916600117905582815260068552929092208054610100909302610100600160a81b0319909316929092179091559150611969908301836136ec565b60008281526006602090815260409182902060030180546001600160a01b0319166001600160a01b0394909416939093179092556119ac919084019084016136ec565b6000828152600660205260409081902060040180546001600160a01b0319166001600160a01b0393909316929092179091556119ee9060608401908401613930565b6119f89042613bad565b600082815260066020908152604091829020805469ffffffffffffffffffff60a81b1916600160a81b64ffffffffff959095169490940264ffffffffff60d01b1916939093176107e960d71b179092553391611a589185019085016136ec565b6001600160a01b0316611a6e60208501856136ec565b6001600160a01b03167fa07b4dffdd3f3212ccd1996d518cf9c5794d30e236c6f0731ba837f1888bfb8b611aa86060870160408801613930565b8546600d6000611abb60208c018c6136ec565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a6020016020810190611af091906136ec565b6001600160a01b03168152602080820192909252604090810160002054815164ffffffffff909616865291850193909352918301526001600160601b0316606082015260800160405180910390a4919050565b60005461010090046001600160a01b03163314611b8757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038216611bae5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600e6020908152604091829020805460ff191685151590811790915591519182527fde858fc156736efe839b339a993c27ade12e9091c50ba57c78e21ef99b266bb491015b60405180910390a25050565b600080611c1a83611125565b90506001610cdc565b60005461010090046001600160a01b03163314611c6757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b611c6f6133a7565b600380546001600160601b0319166001600160601b0383169081179091556040519081527f287e82d7e96f9ef638407255ed4fc3d476cfcc6067b6e621efb1ebea72fd5782906020015b60405180910390a150565b60005461010090046001600160a01b03163314611d0857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038116611d2f5760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c90600090a250565b600080611d8584610be4565b6001600160a01b03841660009081526009602090815260408083208884529091529020549091506001600160601b031615611dc35760009150611f6a565b600181516005811115611dd857611dd8613534565b03611ee1578060a001516001600160601b031681608001516001600160601b03161480611e3057506001600160a01b0383166000908152600a602090815260408083208784529091529020546001600160601b031615155b15611e3e5760009150611f6a565b6001600160a01b038316600090815260086020908152604080832087845290915281205460a083015160808401516001600160601b0390921691611e829190613bcd565b6001600160601b0316611e959190613bf5565b611ea790670de0b6b3a7640000613bf5565b9050600082608001516001600160601b0316670de0b6b3a7640000611ecc9190613bf5565b9050611ed88183613b60565b93505050611f6a565b600581516005811115611ef657611ef6613534565b03611f3a576001600160a01b038316600090815260086020908152604080832087845290915281205460e0830151611e95916001600160601b039081169116613bf5565b6001600160a01b03831660009081526008602090815260408083208784529091529020546001600160601b031691505b5092915050565b60005461010090046001600160a01b03163314611fb557600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038216611fdc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600c6020908152604091829020805460ff191685151590811790915591519182527f4328be84b11f78e9419014af97164f1c1133d5505c551ea4285cf180db3388909101611c02565b61203c6134c5565b6001600160a01b038216600090815260076020908152604080832054808452600690925291829020825161014081019093528054919291829060ff16600581111561208957612089613534565b600581111561209a5761209a613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e08401526003840154821690830152600490920154909116610120909101529392505050565b61213f6133a7565b600061214a82610be4565b905060008151600581111561216157612161613534565b1461217f57604051630ed2159360e11b815260040160405180910390fd5b6001546001600160a01b0316330361229e5780608001516001600160601b031660000361221657806040015164ffffffffff164264ffffffffff16116121f0576040818101519051635b7892d160e11b815264ffffffffff9182166004820152429091166024820152604401610e21565b600082815260066020526040902080546002919060ff19166001835b021790555061236a565b8060600151816040015161222a9190613bad565b64ffffffffff164264ffffffffff161161227e57806060015181604001516122529190613bad565b604051635b7892d160e11b815264ffffffffff9182166004820152429091166024820152604401610e21565b600082815260066020526040902080546003919060ff191660018361220c565b60208101516001600160a01b031633036123495780608001516001600160601b03166000036122e757600082815260066020526040902080546002919060ff191660018361220c565b806060015181604001516122fb9190613bad565b64ffffffffff164264ffffffffff1611156123295760405163f9202d0b60e01b815260040160405180910390fd5b600082815260066020526040902080546004919060ff191660018361220c565b806020015133604051630150a30b60e21b8152600401610e21929190613984565b6000828152600660209081526040808320805469ffffffffffffffffffff60a81b19169055838201516001600160a01b031683526005909152808220805460ff191690555183917f630dec10c667c85b46c86fa3a23d5710c2ec0c247043c1f9ec2433226f5adfcc91a25050565b6001546001600160a01b0316331461241257600154604051630150a30b60e21b8152610e21916001600160a01b0316903390600401613984565b61241a6133a7565b611123613488565b60008181526006602052604080822081516101408101909252805483929190829060ff16600581111561245757612457613534565b600581111561246857612468613534565b815281546001600160a01b036101008083048216602085015264ffffffffff600160a81b84048116604080870191909152600160d01b9094048116606086015260018601546001600160601b038082166080880152600160601b91829004811660a0880152600288015480821660c0890152919091041660e0860152600386015483169185019190915260049094015416610120909201919091528201519192501642111561251a5750600192915050565b50600092915050565b60005461010090046001600160a01b0316331461256757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b61256f6133a7565b6001600160a01b038216600081815260056020908152604091829020805460ff191685151590811790915591519182527f449e12f29fe41627ebd01011c719955667b4df5c9c72d148fe27e0ff6dfdf0ef9101611c02565b60005461010090046001600160a01b0316331461260b57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612652573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126769190613a31565b9050816001600160601b03168110156126b5576040516305f0e94360e01b81526001600160601b03808316600483015283166024820152604401610e21565b60025460405163a9059cbb60e01b81526001600160a01b0391821660048201526001600160601b03841660248201529084169063a9059cbb906044016020604051808303816000875af1158015612710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127349190613967565b506002546040516001600160601b03841681526001600160a01b03918216918516907f9fccd62c17ef896e78b4f9ac51bdb97dd8529f658cf5f16ee2639ac8111fe32a906020015b60405180910390a3505050565b60008061279583611125565b90506002610cdc565b336000908152600e602052604090205460ff166127ce5760405163418954f760e11b815260040160405180910390fd5b6127d66133a7565b60009081526006602052604090208054600160ff1990911681178255810180546bffffffffffffffffffffffff60601b1916600160601b6001600160601b039586160217905560020180546001600160601b03191691909216179055565b60005461010090046001600160a01b0316331461287857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6128806133a7565b600280546001600160a01b0316600160a01b6001600160601b038416908102919091179091556040519081527fcb3786bb21602dee80b97c08027ae6bc5d44994af952ee703d8979d120fd4a4e90602001611cb9565b6128de6133a7565b60006128e982610be4565b90506000808251600581111561290157612901613534565b0361291f576040516306e85c8160e21b815260040160405180910390fd5b60018251600581111561293457612934613534565b036129d95781608001516001600160601b03168260a001516001600160601b031603612973576040516306e85c8160e21b815260040160405180910390fd5b61297d8333611d79565b905060018110156129a157604051631f2a200560e01b815260040160405180910390fd5b336000908152600a60209081526040808320868452909152902080546001600160601b0319166001600160601b038316179055612a3b565b6129e38333611d79565b90506001811015612a0757604051631f2a200560e01b815260040160405180910390fd5b336000908152600960209081526040808320868452909152902080546001600160601b0319166001600160601b0383161790555b60008261012001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa49190613a0e565b90506000612ab3826012613a4a565b612abe90600a613b51565b612ac89084613b60565b61012085015160405163a9059cbb60e01b8152336004820152602481018390529192506001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015612b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b419190613967565b50604051838152859033907fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d579060200160405180910390a35050505050565b60005461010090046001600160a01b03163314612bc457600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038316612beb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216612c125760405163d92e233d60e01b815260040160405180910390fd5b6001816001600160601b03161015612c3d57604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b038381166000818152600d602090815260408083209487168084529482529182902080546001600160601b0319166001600160601b03871690811790915591519182527f2055f2233e159548ffdee099764f9077b42e619cc18cfb4e13866451e7a274a3910161277c565b600080612cbb83611125565b90506004610cdc565b612ccc6133a7565b6000612cd733612034565b3360008181526007602090815260409091205490830151929350916001600160a01b031614612d2157816020015133604051630150a30b60e21b8152600401610e21929190613984565b600082516005811115612d3657612d36613534565b14612d5457604051630ed2159360e11b815260040160405180910390fd5b600182608001516001600160601b03161015612d8357604051631f2a200560e01b815260040160405180910390fd5b816040015164ffffffffff164210612dae5760405163f9202d0b60e01b815260040160405180910390fd5b600081815260066020908152604091829020805464ffffffffff60a81b1916600160a81b4264ffffffffff160217905590518281527f0e4dc79b81ed8d026b924a69a0974b0907468daaefe94b82cd635fbfa1545a5b910160405180910390a15050565b60005461010090046001600160a01b03163314612e5657600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b612e5e6133a7565b6103848164ffffffffff161015612e9957604051635b7892d160e11b8152610384600482015264ffffffffff82166024820152604401610e21565b6000805464ffffffffff60a81b1916600160a81b64ffffffffff8416908102919091179091556040519081527f0b88071bc4a6802bc22db02d81577eff416fc2650a28a04d3e00763f493b77a790602001611cb9565b60005461010090046001600160a01b03163314612f3357600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001816001600160601b03161015612f5e57604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b03821660008181526004602090815260409182902080546001600160601b0319166001600160601b03861690811790915591519182527f2fd80d6d7fe26893b03e52b1d79bcdc27efa1ae9fbfe157a8b7f3728be623c089101611c02565b60008181526006602052604080822081516101408101909252805483929190829060ff166005811115612ff857612ff8613534565b600581111561300957613009613534565b815281546001600160a01b03610100808304821660208086019190915264ffffffffff600160a81b850481166040870152600160d01b909404909316606085015260018501546001600160601b038082166080870152600160601b91829004811660a0870152600287015480821660c0880152919091041660e085015260038501548216908401526004909301549092166101209091015201519392505050565b60005461010090046001600160a01b031633146130ee57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0382166131155760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600b6020908152604091829020805460ff191685151590811790915591519182527f5926168bbdf56f6c4d84af71d7a5ea30e1f913592bca60635781989f29d371539101611c02565b336000908152600e602052604090205460ff1661319d5760405163418954f760e11b815260040160405180910390fd5b6131a56133a7565b6000908152600660209081526040808320805460ff199081166005908117808455600290930180546bffffffffffffffffffffffff60601b1916600160601b6001600160601b039990991698909802979097179096556101009091046001600160a01b0316845293909152902080549091169055565b60005461010090046001600160a01b0316331461325f57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0381166132865760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517fc714d22a2f08b695f81e7c707058db484aa5b4d6b4c9fd64beb10fe85832f60890600090a250565b6000806132dc83611125565b90506000610cdc565b60005461010090046001600160a01b0316331461332957600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0382166133505760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038281166000818152600f602052604080822080546001600160a01b0319169486169485179055517f670ad79f87ce8ed7baef7f6d287a9c03389c829bc2a55c15bf7c88c6f5be6f249190a35050565b60005460ff16156111235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e21565b60005460ff166111235760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e21565b61343e6133ed565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6134906133a7565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861346b3390565b604080516101408101909152806000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101209091015290565b60006020828403121561352d57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6006811061356857634e487b7160e01b600052602160045260246000fd5b9052565b60006101408201905061358082845161354a565b602083015161359a60208401826001600160a01b03169052565b5060408301516135b3604084018264ffffffffff169052565b5060608301516135cc606084018264ffffffffff169052565b5060808301516135e760808401826001600160601b03169052565b5060a083015161360260a08401826001600160601b03169052565b5060c083015161361d60c08401826001600160601b03169052565b5060e083015161363860e08401826001600160601b03169052565b50610100838101516001600160a01b03908116918401919091526101209384015116929091019190915290565b80356001600160a01b038116811461367c57600080fd5b919050565b6000806040838503121561369457600080fd5b61369d83613665565b946020939093013593505050565b803564ffffffffff8116811461367c57600080fd5b600080604083850312156136d357600080fd5b823591506136e3602084016136ab565b90509250929050565b6000602082840312156136fe57600080fd5b6110bd82613665565b60208101610fbd828461354a565b80356001600160601b038116811461367c57600080fd5b6000806040838503121561373f57600080fd5b823591506136e360208401613715565b600060608284031215610cfc57600080fd5b801515811461376f57600080fd5b50565b6000806040838503121561378557600080fd5b61378e83613665565b9150602083013561379e81613761565b809150509250929050565b6000602082840312156137bb57600080fd5b6110bd82613715565b600080604083850312156137d757600080fd5b823591506136e360208401613665565b600080604083850312156137fa57600080fd5b61380383613665565b91506136e360208401613715565b6000806040838503121561382457600080fd5b61382d83613665565b91506136e360208401613665565b60008060006060848603121561385057600080fd5b61385984613715565b925061386760208501613715565b9150604084013590509250925092565b6101408101613886828d61354a565b6001600160a01b039a8b16602083015264ffffffffff998a1660408301529790981660608901526001600160601b03958616608089015293851660a088015291841660c087015290921660e085015290841661010084015290921661012090910152919050565b60008060006060848603121561390257600080fd5b61390b84613665565b925061391960208501613665565b915061392760408501613715565b90509250925092565b60006020828403121561394257600080fd5b6110bd826136ab565b6000806040838503121561395e57600080fd5b61369d83613715565b60006020828403121561397957600080fd5b81516110bd81613761565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b600081600b0b83600b0b60008112816b7fffffffffffffffffffffff19018312811516156139e4576139e461399e565b816b7fffffffffffffffffffffff018313811615613a0457613a0461399e565b5090039392505050565b600060208284031215613a2057600080fd5b815160ff811681146110bd57600080fd5b600060208284031215613a4357600080fd5b5051919050565b600060ff821660ff841680821015613a6457613a6461399e565b90039392505050565b600181815b80851115613aa8578160001904821115613a8e57613a8e61399e565b80851615613a9b57918102915b93841c9390800290613a72565b509250929050565b600082613abf57506001610fbd565b81613acc57506000610fbd565b8160018114613ae25760028114613aec57613b08565b6001915050610fbd565b60ff841115613afd57613afd61399e565b50506001821b610fbd565b5060208310610133831016604e8410600b8410161715613b2b575081810a610fbd565b613b358383613a6d565b8060001904821115613b4957613b4961399e565b029392505050565b60006110bd60ff841683613ab0565b600082613b7d57634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160601b03808316818516808303821115613ba457613ba461399e565b01949350505050565b600064ffffffffff808316818516808303821115613ba457613ba461399e565b60006001600160601b0383811690831681811015613bed57613bed61399e565b039392505050565b6000816000190483118215151615613c0f57613c0f61399e565b50029056fea2646970667358221220221f08419005744fdb5ce3562d878e2db19a5cd77b4b75f4e1360a1eea367c0964736f6c634300080f00330000000000000000000000004e72ca122b586a622f456a45db849f95adef4e8b0000000000000000000000005695e33b0b9d0cf89cffd10ec7365d4722de90a3

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103e65760003560e01c806385bb6a3c1161020a578063b89e45b311610125578063e9d977c0116100b8578063f071372a11610087578063f071372a14610b85578063f0f4426014610b98578063f5eb3db814610bab578063f851a44014610bbe578063fa57cb0e14610bd157600080fd5b8063e9d977c014610b20578063ea5c942814610b4c578063eb0a5a2d14610b5f578063eb600f7414610b7257600080fd5b8063d3126817116100f4578063d312681714610abe578063d951b3a514610af2578063e2879a1014610b05578063e34c333314610b0d57600080fd5b8063b89e45b3146109d1578063bd66528a146109f4578063c845201714610a07578063ccc923fa14610aab57600080fd5b806394e20bb11161019d578063a3cb57341161016c578063a3cb573414610964578063acce01f914610998578063aef8a03c146109ab578063b0e21e8a146109be57600080fd5b806394e20bb1146108ab57806396153ae8146108ed57806399c07fb4146109165780639c7632fc1461094a57600080fd5b806389a9a7ee116101d957806389a9a7ee1461085a5780638c8c3c9d1461086d5780638da5cb5b14610880578063925c9bbd1461089857600080fd5b806385bb6a3c146107bc57806385bf9435146107df5780638657f9f11461081e578063876428401461083157600080fd5b80635c943880116103055780636b6dccfe116102985780637629e26c116102675780637629e26c146107585780637ac7c7fe1461076b5780637d1096471461077e5780637e06c0dc146107a15780638456cb59146107b457600080fd5b80636b6dccfe146106f3578063704b6c021461070657806370bdefc1146107195780637592ce0f1461072c57600080fd5b806361d027b3116102d457806361d027b31461065957806363f0e3c914610684578063671469b9146106a757806368d1e264146106c757600080fd5b80635c943880146105fa5780635c975abb146106285780635e33d715146106335780635f5794f11461064657600080fd5b80633a6ac96a1161037d578063444920eb1161034c578063444920eb14610569578063567b9b0f146105a05780635826b2e8146105d45780635b81b123146105e757600080fd5b80633a6ac96a146104ef5780633f4ba83a1461050257806340735dc41461050a5780634380d0a51461052a57600080fd5b806313af4035116103b957806313af40351461045f578063181d5c06146104725780631c0069391461049d57806331ae7a65146104c957600080fd5b806301ed5861146103eb5780630d00472e146104145780631072cbea14610437578063138f29be1461044c575b600080fd5b6103fe6103f936600461351b565b610be4565b60405161040b919061356c565b60405180910390f35b61042761042236600461351b565b610ccb565b604051901515815260200161040b565b61044a610445366004613681565b610d02565b005b61044a61045a3660046136c0565b610db0565b61044a61046d3660046136ec565b610ed4565b610485610480366004613681565b610f8f565b6040516001600160601b03909116815260200161040b565b6104276104ab3660046136ec565b6001600160a01b031660009081526005602052604090205460ff1690565b6104dc6104d736600461351b565b610fc3565b604051600b9190910b815260200161040b565b6104276104fd36600461351b565b6110c4565b61044a6110d9565b61051d61051836600461351b565b611125565b60405161040b9190613707565b610485610538366004613681565b6001600160a01b0391909116600090815260096020908152604080832093835292905220546001600160601b031690565b6105926105773660046136ec565b6001600160a01b031660009081526007602052604090205490565b60405190815260200161040b565b6104856105ae366004613681565b60096020908152600092835260408084209091529082529020546001600160601b031681565b61044a6105e236600461372c565b611209565b6105926105f536600461374f565b6116ba565b60005461061290600160a81b900464ffffffffff1681565b60405164ffffffffff909116815260200161040b565b60005460ff16610427565b61044a610641366004613772565b611b43565b61042761065436600461351b565b611c0e565b60025461066c906001600160a01b031681565b6040516001600160a01b03909116815260200161040b565b6104276106923660046136ec565b600e6020526000908152604090205460ff1681565b6105926106b53660046136ec565b60076020526000908152604090205481565b6104276106d53660046136ec565b6001600160a01b03166000908152600b602052604090205460ff1690565b61044a6107013660046137a9565b611c23565b61044a6107143660046136ec565b611cc4565b6105926107273660046137c4565b611d79565b61042761073a3660046136ec565b6001600160a01b03166000908152600c602052604090205460ff1690565b61044a610766366004613772565b611f71565b6103fe6107793660046136ec565b612034565b61042761078c3660046136ec565b60056020526000908152604090205460ff1681565b61044a6107af36600461351b565b612137565b61044a6123d8565b6104276107ca3660046136ec565b600b6020526000908152604090205460ff1681565b6104856107ed366004613681565b6001600160a01b0391909116600090815260086020908152604080832093835292905220546001600160601b031690565b61042761082c36600461351b565b612422565b61048561083f3660046136ec565b6004602052600090815260409020546001600160601b031681565b61044a610868366004613772565b612523565b61044a61087b3660046137e7565b6125c7565b60005461066c9061010090046001600160a01b031681565b6104276108a636600461351b565b612789565b6104856108b9366004613811565b6001600160a01b039182166000908152600d602090815260408083209390941682529190915220546001600160601b031690565b61066c6108fb3660046136ec565b600f602052600090815260409020546001600160a01b031681565b610485610924366004613681565b600a6020908152600092835260408084209091529082529020546001600160601b031681565b60025461048590600160a01b90046001600160601b031681565b610485610972366004613681565b60086020908152600092835260408084209091529082529020546001600160601b031681565b61044a6109a636600461383b565b61279e565b61044a6109b93660046137a9565b612834565b600354610485906001600160601b031681565b6104276109df3660046136ec565b600c6020526000908152604090205460ff1681565b61044a610a0236600461351b565b6128d6565b610a95610a1536600461351b565b6006602052600090815260409020805460018201546002830154600384015460049094015460ff8416946001600160a01b03610100860481169564ffffffffff600160a81b8204811696600160d01b90920416946001600160601b0380831695600160601b9384900482169583831695949093049091169291821691168a565b60405161040b9a99989796959493929190613877565b61044a610ab93660046138ed565b612b80565b610485610acc366004613811565b600d6020908152600092835260408084209091529082529020546001600160601b031681565b610427610b0036600461351b565b612caf565b61044a612cc4565b61044a610b1b366004613930565b612e12565b61066c610b2e3660046136ec565b6001600160a01b039081166000908152600f60205260409020541690565b61044a610b5a3660046137e7565b612eef565b61066c610b6d36600461351b565b612fc3565b61044a610b80366004613772565b6130aa565b61044a610b9336600461394b565b61316d565b61044a610ba63660046136ec565b61321b565b610427610bb936600461351b565b6132d0565b60015461066c906001600160a01b031681565b61044a610bdf366004613811565b6132e5565b610bec6134c5565b60008281526006602052604090819020815161014081019092528054829060ff166005811115610c1e57610c1e613534565b6005811115610c2f57610c2f613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e084015260038401548216908301526004909201549091166101209091015292915050565b600080610cd783611125565b905060055b816005811115610cee57610cee613534565b03610cfc5750600192915050565b50919050565b336000908152600e602052604090205460ff16610d325760405163418954f760e11b815260040160405180910390fd5b610d3a6133a7565b60405163a9059cbb60e01b8152336004820152602481018290526001600160a01b0383169063a9059cbb906044016020604051808303816000875af1158015610d87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dab9190613967565b505050565b610db86133a7565b6000610dc383610be4565b905080602001516001600160a01b0316336001600160a01b031614158015610dfb575060005461010090046001600160a01b03163314155b15610e2a57806020015133604051630150a30b60e21b8152600401610e21929190613984565b60405180910390fd5b6203f4808264ffffffffff161115610e67576040516305f0e94360e01b81526203f480600482015264ffffffffff83166024820152604401610e21565b600083815260066020908152604091829020805464ffffffffff60d01b1916600160d01b64ffffffffff871690810291909117909155915191825284917fb711cf4c951c83a618ff2370aada0beb10e68bd204a1c7b6cc2dc25ef3e169d7910160405180910390a2505050565b60005461010090046001600160a01b03163314610f1857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038116610f3f5760405163d92e233d60e01b815260040160405180910390fd5b60008054610100600160a81b0319166101006001600160a01b03841690810291909117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b6001600160a01b0382166000908152600a602090815260408083208484529091529020546001600160601b03165b92915050565b60008181526006602052604080822081516101408101909252805483929190829060ff166005811115610ff857610ff8613534565b600581111561100957611009613534565b815281546001600160a01b036101008083048216602085015264ffffffffff600160a81b840481166040860152600160d01b909304909216606084015260018401546001600160601b03808216608080870191909152600160601b92839004821660a0870152600287015480831660c0880152929092041660e0808601919091526003860154831693850193909352600490940154166101209092019190915290820151908201519192506110bd916139b4565b9392505050565b6000806110d083611125565b90506003610cdc565b6001546001600160a01b0316331461111357600154604051630150a30b60e21b8152610e21916001600160a01b0316903390600401613984565b61111b6133ed565b611123613436565b565b60008181526006602052604080822081516101408101909252805483929190829060ff16600581111561115a5761115a613534565b600581111561116b5761116b613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e0840152600384015482169083015260049092015490911661012090910152519392505050565b6112116133a7565b600061121c83610be4565b905060008161012001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112879190613a0e565b6101208301516040516370a0823160e01b81523360048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156112d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fc9190613a31565b9050600061130b836012613a4a565b61131690600a613b51565b611329906001600160601b038716613b60565b6101208501516001600160a01b03166000908152600460205260409020549091506001600160601b0390811690861610156113ae576101208401516001600160a01b0316600090815260046020819052604091829020549151635b7892d160e11b81526001600160601b03928316918101919091529086166024820152604401610e21565b60208401516001600160a01b03166113d95760405163d92e233d60e01b815260040160405180910390fd5b806001600160601b0316826001600160601b0316101561141f57604051635b7892d160e11b81526001600160601b03808416600483015282166024820152604401610e21565b836040015164ffffffffff164264ffffffffff1611156114525760405163780c89c560e01b815260040160405180910390fd5b60008451600581111561146757611467613534565b1461148557604051630ed2159360e11b815260040160405180910390fd5b6101008401516001600160a01b039081166000908152600d602090815260408083206101208901519094168352929052205460808501516001600160601b03909116906114d3908790613b82565b6001600160601b0316111561155c576101008401516001600160a01b039081166000908152600d602090815260408083206101208901519094168352929052205460808501516001600160601b0390911690611530908790613b82565b6040516305f0e94360e01b81526001600160601b03928316600482015291166024820152604401610e21565b600086815260066020526040812060010180548792906115869084906001600160601b0316613b82565b82546101009290920a6001600160601b038181021990931691831602179091553360009081526008602090815260408083208b84529091528120805489945090926115d391859116613b82565b82546101009290920a6001600160601b038181021990931691831602179091556101208601516040516323b872dd60e01b815233600482015230602482015291841660448301526001600160a01b031691506323b872dd906064016020604051808303816000875af115801561164d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116719190613967565b506040516001600160601b0386168152869033907f9096e481393af38e01008317b0d2fc664c1608cd8f693072d73b6b78539c40079060200160405180910390a3505050505050565b60006116c46133a7565b3360009081526005602052604090205460ff16156116f7576040516326e90db160e21b8152336004820152602401610e21565b61038461170a6060840160408501613930565b64ffffffffff16101561175b5761038461172a6060840160408501613930565b604051635b7892d160e11b81526001600160601b03909216600483015264ffffffffff166024820152604401610e21565b600054600160a81b900464ffffffffff1661177c6060840160408501613930565b64ffffffffff1611156117d457600054600160a81b900464ffffffffff166117aa6060840160408501613930565b6040516305f0e94360e01b815264ffffffffff928316600482015291166024820152604401610e21565b600b60006117e560208501856136ec565b6001600160a01b0316815260208101919091526040016000205460ff16158061183c5750600c600061181d60408501602086016136ec565b6001600160a01b0316815260208101919091526040016000205460ff16155b156118735761184e60208301836136ec565b60405163b4d5d76960e01b81526001600160a01b039091166004820152602401610e21565b3361188160208401846136ec565b61189160408501602086016136ec565b6118a16060860160408701613930565b604051606094851b6001600160601b0319908116602083015293851b841660348201529190931b909116604882015260d89190911b6001600160d81b031916605c8201524260618201524360818201524660a182015260c10160408051601f1981840301815291815281516020928301203360008181526007855283812083905560058552838120805460ff1916600117905582815260068552929092208054610100909302610100600160a81b0319909316929092179091559150611969908301836136ec565b60008281526006602090815260409182902060030180546001600160a01b0319166001600160a01b0394909416939093179092556119ac919084019084016136ec565b6000828152600660205260409081902060040180546001600160a01b0319166001600160a01b0393909316929092179091556119ee9060608401908401613930565b6119f89042613bad565b600082815260066020908152604091829020805469ffffffffffffffffffff60a81b1916600160a81b64ffffffffff959095169490940264ffffffffff60d01b1916939093176107e960d71b179092553391611a589185019085016136ec565b6001600160a01b0316611a6e60208501856136ec565b6001600160a01b03167fa07b4dffdd3f3212ccd1996d518cf9c5794d30e236c6f0731ba837f1888bfb8b611aa86060870160408801613930565b8546600d6000611abb60208c018c6136ec565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008a6020016020810190611af091906136ec565b6001600160a01b03168152602080820192909252604090810160002054815164ffffffffff909616865291850193909352918301526001600160601b0316606082015260800160405180910390a4919050565b60005461010090046001600160a01b03163314611b8757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038216611bae5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600e6020908152604091829020805460ff191685151590811790915591519182527fde858fc156736efe839b339a993c27ade12e9091c50ba57c78e21ef99b266bb491015b60405180910390a25050565b600080611c1a83611125565b90506001610cdc565b60005461010090046001600160a01b03163314611c6757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b611c6f6133a7565b600380546001600160601b0319166001600160601b0383169081179091556040519081527f287e82d7e96f9ef638407255ed4fc3d476cfcc6067b6e621efb1ebea72fd5782906020015b60405180910390a150565b60005461010090046001600160a01b03163314611d0857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038116611d2f5760405163d92e233d60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f7ce7ec0b50378fb6c0186ffb5f48325f6593fcb4ca4386f21861af3129188f5c90600090a250565b600080611d8584610be4565b6001600160a01b03841660009081526009602090815260408083208884529091529020549091506001600160601b031615611dc35760009150611f6a565b600181516005811115611dd857611dd8613534565b03611ee1578060a001516001600160601b031681608001516001600160601b03161480611e3057506001600160a01b0383166000908152600a602090815260408083208784529091529020546001600160601b031615155b15611e3e5760009150611f6a565b6001600160a01b038316600090815260086020908152604080832087845290915281205460a083015160808401516001600160601b0390921691611e829190613bcd565b6001600160601b0316611e959190613bf5565b611ea790670de0b6b3a7640000613bf5565b9050600082608001516001600160601b0316670de0b6b3a7640000611ecc9190613bf5565b9050611ed88183613b60565b93505050611f6a565b600581516005811115611ef657611ef6613534565b03611f3a576001600160a01b038316600090815260086020908152604080832087845290915281205460e0830151611e95916001600160601b039081169116613bf5565b6001600160a01b03831660009081526008602090815260408083208784529091529020546001600160601b031691505b5092915050565b60005461010090046001600160a01b03163314611fb557600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038216611fdc5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600c6020908152604091829020805460ff191685151590811790915591519182527f4328be84b11f78e9419014af97164f1c1133d5505c551ea4285cf180db3388909101611c02565b61203c6134c5565b6001600160a01b038216600090815260076020908152604080832054808452600690925291829020825161014081019093528054919291829060ff16600581111561208957612089613534565b600581111561209a5761209a613534565b815281546101008082046001600160a01b039081166020850152600160a81b830464ffffffffff9081166040860152600160d01b909304909216606084015260018401546001600160601b038082166080860152600160601b91829004811660a0860152600286015480821660c0870152919091041660e08401526003840154821690830152600490920154909116610120909101529392505050565b61213f6133a7565b600061214a82610be4565b905060008151600581111561216157612161613534565b1461217f57604051630ed2159360e11b815260040160405180910390fd5b6001546001600160a01b0316330361229e5780608001516001600160601b031660000361221657806040015164ffffffffff164264ffffffffff16116121f0576040818101519051635b7892d160e11b815264ffffffffff9182166004820152429091166024820152604401610e21565b600082815260066020526040902080546002919060ff19166001835b021790555061236a565b8060600151816040015161222a9190613bad565b64ffffffffff164264ffffffffff161161227e57806060015181604001516122529190613bad565b604051635b7892d160e11b815264ffffffffff9182166004820152429091166024820152604401610e21565b600082815260066020526040902080546003919060ff191660018361220c565b60208101516001600160a01b031633036123495780608001516001600160601b03166000036122e757600082815260066020526040902080546002919060ff191660018361220c565b806060015181604001516122fb9190613bad565b64ffffffffff164264ffffffffff1611156123295760405163f9202d0b60e01b815260040160405180910390fd5b600082815260066020526040902080546004919060ff191660018361220c565b806020015133604051630150a30b60e21b8152600401610e21929190613984565b6000828152600660209081526040808320805469ffffffffffffffffffff60a81b19169055838201516001600160a01b031683526005909152808220805460ff191690555183917f630dec10c667c85b46c86fa3a23d5710c2ec0c247043c1f9ec2433226f5adfcc91a25050565b6001546001600160a01b0316331461241257600154604051630150a30b60e21b8152610e21916001600160a01b0316903390600401613984565b61241a6133a7565b611123613488565b60008181526006602052604080822081516101408101909252805483929190829060ff16600581111561245757612457613534565b600581111561246857612468613534565b815281546001600160a01b036101008083048216602085015264ffffffffff600160a81b84048116604080870191909152600160d01b9094048116606086015260018601546001600160601b038082166080880152600160601b91829004811660a0880152600288015480821660c0890152919091041660e0860152600386015483169185019190915260049094015416610120909201919091528201519192501642111561251a5750600192915050565b50600092915050565b60005461010090046001600160a01b0316331461256757600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b61256f6133a7565b6001600160a01b038216600081815260056020908152604091829020805460ff191685151590811790915591519182527f449e12f29fe41627ebd01011c719955667b4df5c9c72d148fe27e0ff6dfdf0ef9101611c02565b60005461010090046001600160a01b0316331461260b57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612652573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126769190613a31565b9050816001600160601b03168110156126b5576040516305f0e94360e01b81526001600160601b03808316600483015283166024820152604401610e21565b60025460405163a9059cbb60e01b81526001600160a01b0391821660048201526001600160601b03841660248201529084169063a9059cbb906044016020604051808303816000875af1158015612710573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127349190613967565b506002546040516001600160601b03841681526001600160a01b03918216918516907f9fccd62c17ef896e78b4f9ac51bdb97dd8529f658cf5f16ee2639ac8111fe32a906020015b60405180910390a3505050565b60008061279583611125565b90506002610cdc565b336000908152600e602052604090205460ff166127ce5760405163418954f760e11b815260040160405180910390fd5b6127d66133a7565b60009081526006602052604090208054600160ff1990911681178255810180546bffffffffffffffffffffffff60601b1916600160601b6001600160601b039586160217905560020180546001600160601b03191691909216179055565b60005461010090046001600160a01b0316331461287857600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6128806133a7565b600280546001600160a01b0316600160a01b6001600160601b038416908102919091179091556040519081527fcb3786bb21602dee80b97c08027ae6bc5d44994af952ee703d8979d120fd4a4e90602001611cb9565b6128de6133a7565b60006128e982610be4565b90506000808251600581111561290157612901613534565b0361291f576040516306e85c8160e21b815260040160405180910390fd5b60018251600581111561293457612934613534565b036129d95781608001516001600160601b03168260a001516001600160601b031603612973576040516306e85c8160e21b815260040160405180910390fd5b61297d8333611d79565b905060018110156129a157604051631f2a200560e01b815260040160405180910390fd5b336000908152600a60209081526040808320868452909152902080546001600160601b0319166001600160601b038316179055612a3b565b6129e38333611d79565b90506001811015612a0757604051631f2a200560e01b815260040160405180910390fd5b336000908152600960209081526040808320868452909152902080546001600160601b0319166001600160601b0383161790555b60008261012001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa49190613a0e565b90506000612ab3826012613a4a565b612abe90600a613b51565b612ac89084613b60565b61012085015160405163a9059cbb60e01b8152336004820152602481018390529192506001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015612b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b419190613967565b50604051838152859033907fd95107f4584744c6c893a04c43058aadd1ce8aac8ca5d64140eaf277de6c1d579060200160405180910390a35050505050565b60005461010090046001600160a01b03163314612bc457600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b038316612beb5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216612c125760405163d92e233d60e01b815260040160405180910390fd5b6001816001600160601b03161015612c3d57604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b038381166000818152600d602090815260408083209487168084529482529182902080546001600160601b0319166001600160601b03871690811790915591519182527f2055f2233e159548ffdee099764f9077b42e619cc18cfb4e13866451e7a274a3910161277c565b600080612cbb83611125565b90506004610cdc565b612ccc6133a7565b6000612cd733612034565b3360008181526007602090815260409091205490830151929350916001600160a01b031614612d2157816020015133604051630150a30b60e21b8152600401610e21929190613984565b600082516005811115612d3657612d36613534565b14612d5457604051630ed2159360e11b815260040160405180910390fd5b600182608001516001600160601b03161015612d8357604051631f2a200560e01b815260040160405180910390fd5b816040015164ffffffffff164210612dae5760405163f9202d0b60e01b815260040160405180910390fd5b600081815260066020908152604091829020805464ffffffffff60a81b1916600160a81b4264ffffffffff160217905590518281527f0e4dc79b81ed8d026b924a69a0974b0907468daaefe94b82cd635fbfa1545a5b910160405180910390a15050565b60005461010090046001600160a01b03163314612e5657600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b612e5e6133a7565b6103848164ffffffffff161015612e9957604051635b7892d160e11b8152610384600482015264ffffffffff82166024820152604401610e21565b6000805464ffffffffff60a81b1916600160a81b64ffffffffff8416908102919091179091556040519081527f0b88071bc4a6802bc22db02d81577eff416fc2650a28a04d3e00763f493b77a790602001611cb9565b60005461010090046001600160a01b03163314612f3357600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001816001600160601b03161015612f5e57604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b03821660008181526004602090815260409182902080546001600160601b0319166001600160601b03861690811790915591519182527f2fd80d6d7fe26893b03e52b1d79bcdc27efa1ae9fbfe157a8b7f3728be623c089101611c02565b60008181526006602052604080822081516101408101909252805483929190829060ff166005811115612ff857612ff8613534565b600581111561300957613009613534565b815281546001600160a01b03610100808304821660208086019190915264ffffffffff600160a81b850481166040870152600160d01b909404909316606085015260018501546001600160601b038082166080870152600160601b91829004811660a0870152600287015480821660c0880152919091041660e085015260038501548216908401526004909301549092166101209091015201519392505050565b60005461010090046001600160a01b031633146130ee57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0382166131155760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382166000818152600b6020908152604091829020805460ff191685151590811790915591519182527f5926168bbdf56f6c4d84af71d7a5ea30e1f913592bca60635781989f29d371539101611c02565b336000908152600e602052604090205460ff1661319d5760405163418954f760e11b815260040160405180910390fd5b6131a56133a7565b6000908152600660209081526040808320805460ff199081166005908117808455600290930180546bffffffffffffffffffffffff60601b1916600160601b6001600160601b039990991698909802979097179096556101009091046001600160a01b0316845293909152902080549091169055565b60005461010090046001600160a01b0316331461325f57600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0381166132865760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517fc714d22a2f08b695f81e7c707058db484aa5b4d6b4c9fd64beb10fe85832f60890600090a250565b6000806132dc83611125565b90506000610cdc565b60005461010090046001600160a01b0316331461332957600054604051630150a30b60e21b8152610e219161010090046001600160a01b0316903390600401613984565b6001600160a01b0382166133505760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038281166000818152600f602052604080822080546001600160a01b0319169486169485179055517f670ad79f87ce8ed7baef7f6d287a9c03389c829bc2a55c15bf7c88c6f5be6f249190a35050565b60005460ff16156111235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e21565b60005460ff166111235760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e21565b61343e6133ed565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6134906133a7565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861346b3390565b604080516101408101909152806000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101209091015290565b60006020828403121561352d57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6006811061356857634e487b7160e01b600052602160045260246000fd5b9052565b60006101408201905061358082845161354a565b602083015161359a60208401826001600160a01b03169052565b5060408301516135b3604084018264ffffffffff169052565b5060608301516135cc606084018264ffffffffff169052565b5060808301516135e760808401826001600160601b03169052565b5060a083015161360260a08401826001600160601b03169052565b5060c083015161361d60c08401826001600160601b03169052565b5060e083015161363860e08401826001600160601b03169052565b50610100838101516001600160a01b03908116918401919091526101209384015116929091019190915290565b80356001600160a01b038116811461367c57600080fd5b919050565b6000806040838503121561369457600080fd5b61369d83613665565b946020939093013593505050565b803564ffffffffff8116811461367c57600080fd5b600080604083850312156136d357600080fd5b823591506136e3602084016136ab565b90509250929050565b6000602082840312156136fe57600080fd5b6110bd82613665565b60208101610fbd828461354a565b80356001600160601b038116811461367c57600080fd5b6000806040838503121561373f57600080fd5b823591506136e360208401613715565b600060608284031215610cfc57600080fd5b801515811461376f57600080fd5b50565b6000806040838503121561378557600080fd5b61378e83613665565b9150602083013561379e81613761565b809150509250929050565b6000602082840312156137bb57600080fd5b6110bd82613715565b600080604083850312156137d757600080fd5b823591506136e360208401613665565b600080604083850312156137fa57600080fd5b61380383613665565b91506136e360208401613715565b6000806040838503121561382457600080fd5b61382d83613665565b91506136e360208401613665565b60008060006060848603121561385057600080fd5b61385984613715565b925061386760208501613715565b9150604084013590509250925092565b6101408101613886828d61354a565b6001600160a01b039a8b16602083015264ffffffffff998a1660408301529790981660608901526001600160601b03958616608089015293851660a088015291841660c087015290921660e085015290841661010084015290921661012090910152919050565b60008060006060848603121561390257600080fd5b61390b84613665565b925061391960208501613665565b915061392760408501613715565b90509250925092565b60006020828403121561394257600080fd5b6110bd826136ab565b6000806040838503121561395e57600080fd5b61369d83613715565b60006020828403121561397957600080fd5b81516110bd81613761565b6001600160a01b0392831681529116602082015260400190565b634e487b7160e01b600052601160045260246000fd5b600081600b0b83600b0b60008112816b7fffffffffffffffffffffff19018312811516156139e4576139e461399e565b816b7fffffffffffffffffffffff018313811615613a0457613a0461399e565b5090039392505050565b600060208284031215613a2057600080fd5b815160ff811681146110bd57600080fd5b600060208284031215613a4357600080fd5b5051919050565b600060ff821660ff841680821015613a6457613a6461399e565b90039392505050565b600181815b80851115613aa8578160001904821115613a8e57613a8e61399e565b80851615613a9b57918102915b93841c9390800290613a72565b509250929050565b600082613abf57506001610fbd565b81613acc57506000610fbd565b8160018114613ae25760028114613aec57613b08565b6001915050610fbd565b60ff841115613afd57613afd61399e565b50506001821b610fbd565b5060208310610133831016604e8410600b8410161715613b2b575081810a610fbd565b613b358383613a6d565b8060001904821115613b4957613b4961399e565b029392505050565b60006110bd60ff841683613ab0565b600082613b7d57634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160601b03808316818516808303821115613ba457613ba461399e565b01949350505050565b600064ffffffffff808316818516808303821115613ba457613ba461399e565b60006001600160601b0383811690831681811015613bed57613bed61399e565b039392505050565b6000816000190483118215151615613c0f57613c0f61399e565b50029056fea2646970667358221220221f08419005744fdb5ce3562d878e2db19a5cd77b4b75f4e1360a1eea367c0964736f6c634300080f0033

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

0000000000000000000000004e72ca122b586a622f456a45db849f95adef4e8b0000000000000000000000005695e33b0b9d0cf89cffd10ec7365d4722de90a3

-----Decoded View---------------
Arg [0] : _admin (address): 0x4e72Ca122B586a622F456a45dB849F95Adef4e8B
Arg [1] : _treasury (address): 0x5695e33B0b9D0Cf89cFFD10EC7365d4722De90A3

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e72ca122b586a622f456a45db849f95adef4e8b
Arg [1] : 0000000000000000000000005695e33b0b9d0cf89cffd10ec7365d4722de90a3


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.