Address Details
contract

0xf0e764Da1E61Bd5421692e5d02bdad9f3B09f825

Contract Name
BiPoolManager
Creator
0x56fd3f–9b8d81 at 0xfb2a45–2061ae
Balance
0 CELO
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
1 Transactions
Transfers
0 Transfers
Gas Used
28,909
Last Balance Update
25562063
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
BiPoolManager




Optimization enabled
true
Compiler version
v0.5.17+commit.d19bba13




Optimization runs
10000
Verified at
2024-02-16T23:14:53.010878Z

lib/mento-core-2.2.0/contracts/swap/BiPoolManager.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma experimental ABIEncoderV2;

import { Ownable } from "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol";

import { IERC20Metadata } from "../common/interfaces/IERC20Metadata.sol";
import { IExchangeProvider } from "../interfaces/IExchangeProvider.sol";
import { IBiPoolManager } from "../interfaces/IBiPoolManager.sol";
import { IReserve } from "../interfaces/IReserve.sol";
import { IPricingModule } from "../interfaces/IPricingModule.sol";
import { ISortedOracles } from "../interfaces/ISortedOracles.sol";
import { IBreakerBox } from "../interfaces/IBreakerBox.sol";

import { Initializable } from "../common/Initializable.sol";
import { FixidityLib } from "../common/FixidityLib.sol";
import { console2 } from "forge-std/Script.sol";

/**
 * @title BiPoolExchangeManager
 * @notice An exchange manager that manages asset exchanges consisting of two assets
 */
contract BiPoolManager is IExchangeProvider, IBiPoolManager, Initializable, Ownable {
  using FixidityLib for FixidityLib.Fraction;
  using SafeMath for uint256;

  /* ==================== State Variables ==================== */

  // Address of the broker contract.
  address public broker;

  // Maps an exchange id to the corresponding PoolExchange struct.
  // exchangeId is in the format "asset0Symbol:asset1Symbol:pricingModuleName"
  mapping(bytes32 => PoolExchange) public exchanges;
  bytes32[] public exchangeIds;

  uint256 private constant TRADING_MODE_BIDIRECTIONAL = 0;

  // Address of the Mento Reserve contract
  IReserve public reserve;

  // Address of the Mento BreakerBox contract
  IBreakerBox public breakerBox;

  // Address of the Mento SortedOracles contract
  ISortedOracles public sortedOracles;

  // Token precision multiplier used to normalize values to the
  // same precision when calculating vAMM bucket sizes.
  mapping(address => uint256) public tokenPrecisionMultipliers;

  bytes32 public constant CONSTANT_SUM = keccak256(abi.encodePacked("ConstantSum"));
  bytes32 public constant CONSTANT_PRODUCT = keccak256(abi.encodePacked("ConstantProduct"));

  // Maps a pricing module identifier to the address of the pricing module contract.
  mapping(bytes32 => address) public pricingModules;

  /* ==================== Constructor ==================== */

  /**
   * @notice Sets initialized == true on implementation contracts.
   * @param test Set to true to skip implementation initialization.
   */
  // solhint-disable-next-line no-empty-blocks
  constructor(bool test) public Initializable(test) {}

  /**
   * @notice Allows the contract to be upgradable via the proxy.
   * @param _broker The address of the broker contract.
   * @param _reserve The address of the reserve contract.
   * @param _sortedOracles The address of the sorted oracles contract.
   * @param _breakerBox The address of the breaker box contract.
   */
  function initialize(
    address _broker,
    IReserve _reserve,
    ISortedOracles _sortedOracles,
    IBreakerBox _breakerBox
  ) external initializer {
    _transferOwnership(msg.sender);
    setBroker(_broker);
    setReserve(_reserve);
    setSortedOracles(_sortedOracles);
    setBreakerBox(_breakerBox);
  }

  /* ==================== Modifiers ==================== */

  modifier onlyBroker() {
    require(msg.sender == broker, "Caller is not the Broker");
    _;
  }

  modifier verifyExchangeTokens(
    address tokenIn,
    address tokenOut,
    PoolExchange memory exchange
  ) {
    require(
      (tokenIn == exchange.asset0 && tokenOut == exchange.asset1) ||
        (tokenIn == exchange.asset1 && tokenOut == exchange.asset0),
      "tokenIn and tokenOut must match exchange"
    );
    _;
  }

  /* ==================== View Functions ==================== */

  /**
   * @notice Get a PoolExchange from storage.
   * @param exchangeId the exchange id
   */
  function getPoolExchange(bytes32 exchangeId) public view returns (PoolExchange memory exchange) {
    exchange = exchanges[exchangeId];
    require(exchange.asset0 != address(0), "An exchange with the specified id does not exist");
  }

  /**
   * @notice Get all exchange IDs.
   * @return exchangeIds List of the exchangeIds.
   */
  function getExchangeIds() external view returns (bytes32[] memory) {
    return exchangeIds;
  }

  /**
   * @notice Get all exchanges (used by interfaces)
   * @dev We don't expect the number of exchanges to grow to
   * astronomical values so this is safe gas-wise as is.
   */
  function getExchanges() public view returns (Exchange[] memory _exchanges) {
    uint256 numExchanges = exchangeIds.length;
    _exchanges = new Exchange[](numExchanges);
    for (uint256 i = 0; i < numExchanges; i++) {
      _exchanges[i].exchangeId = exchangeIds[i];
      _exchanges[i].assets = new address[](2);
      _exchanges[i].assets[0] = exchanges[exchangeIds[i]].asset0;
      _exchanges[i].assets[1] = exchanges[exchangeIds[i]].asset1;
    }
  }

  /**
   * @notice Calculate amountOut of tokenOut received for a given amountIn of tokenIn
   * @param exchangeId The id of the exchange i.e PoolExchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountIn The amount of tokenIn to be sold
   * @return amountOut The amount of tokenOut to be bought
   */
  function getAmountOut(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountIn
  ) external view returns (uint256 amountOut) {
    PoolExchange memory exchange = getPoolExchange(exchangeId);
    uint256 scaledAmountIn = amountIn.mul(tokenPrecisionMultipliers[tokenIn]);
    (uint256 scaledAmountOut, ) = _getAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);
    amountOut = scaledAmountOut.div(tokenPrecisionMultipliers[tokenOut]);
    return amountOut;
  }

  /**
   * @notice Calculate amountIn of tokenIn for a given amountOut of tokenOut
   * @param exchangeId The id of the exchange i.e PoolExchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountOut The amount of tokenOut to be bought
   * @return amountIn The amount of tokenIn to be sold
   */
  function getAmountIn(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountOut
  ) external view returns (uint256 amountIn) {
    PoolExchange memory exchange = getPoolExchange(exchangeId);
    uint256 scaledAmountOut = amountOut.mul(tokenPrecisionMultipliers[tokenOut]);
    (uint256 scaledAmountIn, ) = _getAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);
    amountIn = scaledAmountIn.div(tokenPrecisionMultipliers[tokenIn]);
    return amountIn;
  }

  /* ==================== Mutative Functions ==================== */

  /**
   * @notice Sets the address of the broker contract.
   * @param _broker The new address of the broker contract.
   */
  function setBroker(address _broker) public onlyOwner {
    require(_broker != address(0), "Broker address must be set");
    broker = _broker;
    emit BrokerUpdated(_broker);
  }

  /**
   * @notice Sets the address of the reserve contract.
   * @param _reserve The new address of the reserve contract.
   */
  function setReserve(IReserve _reserve) public onlyOwner {
    require(address(_reserve) != address(0), "Reserve address must be set");
    reserve = _reserve;
    emit ReserveUpdated(address(_reserve));
  }

  /**
   * @notice Sets the address of the BreakerBox.
   * @param _breakerBox The new BreakerBox address.
   */
  function setBreakerBox(IBreakerBox _breakerBox) public onlyOwner {
    require(address(_breakerBox) != address(0), "BreakerBox address must be set");
    breakerBox = _breakerBox;
    emit BreakerBoxUpdated(address(_breakerBox));
  }

  /**
   * @notice Sets the address of the sortedOracles contract.
   * @param _sortedOracles The new address of the sorted oracles contract.
   */
  function setSortedOracles(ISortedOracles _sortedOracles) public onlyOwner {
    require(address(_sortedOracles) != address(0), "SortedOracles address must be set");
    sortedOracles = _sortedOracles;
    emit SortedOraclesUpdated(address(_sortedOracles));
  }

  /**
   * @notice Updates the pricing modules for a list of identifiers
   * @dev This function can only be called by the owner of the contract.
   *      The number of identifiers and modules provided must be the same.
   * @param identifiers An array of identifiers for which the pricing modules are to be set.
   * @param modules An array of module addresses corresponding to each identifier.
   */
  function setPricingModules(bytes32[] calldata identifiers, address[] calldata modules) external onlyOwner {
    require(identifiers.length == modules.length, "identifiers and modules must be the same length");
    for (uint256 i = 0; i < identifiers.length; i++) {
      pricingModules[identifiers[i]] = modules[i];
    }
    emit PricingModulesUpdated(identifiers, modules);
  }

  /**
   * @notice Creates a new exchange using the given parameters.
   * @param _exchange the PoolExchange to create.
   * @return exchangeId The id of the newly created exchange.
   */
  function createExchange(PoolExchange calldata _exchange) external onlyOwner returns (bytes32 exchangeId) {
    PoolExchange memory exchange = _exchange;
    require(address(exchange.pricingModule) != address(0), "pricingModule must be set");
    require(exchange.asset0 != address(0), "asset0 must be set");
    require(exchange.asset1 != address(0), "asset1 must be set");
    require(exchange.asset0 != exchange.asset1, "exchange assets can't be identical");
    require(
      pricingModules[pricingModuleIdentifier(exchange)] == address(exchange.pricingModule),
      "invalid pricingModule"
    );

    exchangeId = keccak256(
      abi.encodePacked(
        IERC20Metadata(exchange.asset0).symbol(),
        IERC20Metadata(exchange.asset1).symbol(),
        exchange.pricingModule.name()
      )
    );
    require(exchanges[exchangeId].asset0 == address(0), "An exchange with the specified assets and exchange exists");

    validate(exchange);
    (uint256 bucket0, uint256 bucket1) = getUpdatedBuckets(exchange);

    exchange.bucket0 = bucket0;
    exchange.bucket1 = bucket1;

    uint256 asset0Decimals = IERC20Metadata(exchange.asset0).decimals();
    uint256 asset1Decimals = IERC20Metadata(exchange.asset1).decimals();

    require(asset0Decimals <= 18, "asset0 decimals must be <= 18");
    require(asset1Decimals <= 18, "asset1 decimals must be <= 18");

    tokenPrecisionMultipliers[exchange.asset0] = 10**(18 - uint256(asset0Decimals));
    tokenPrecisionMultipliers[exchange.asset1] = 10**(18 - uint256(asset1Decimals));

    exchanges[exchangeId] = exchange;
    exchangeIds.push(exchangeId);

    emit ExchangeCreated(exchangeId, exchange.asset0, exchange.asset1, address(exchange.pricingModule));
  }

  /**
   * @notice Destroys a exchange with the given parameters if it exists and frees up
   *         the collateral and stable allocation it was using.
   * @param exchangeId the id of the exchange to destroy
   * @param exchangeIdIndex The index of the exchangeId in the ids array
   * @return destroyed A boolean indicating whether or not the exchange was successfully destroyed.
   */
  function destroyExchange(bytes32 exchangeId, uint256 exchangeIdIndex) external onlyOwner returns (bool destroyed) {
    require(exchangeIdIndex < exchangeIds.length, "exchangeIdIndex not in range");
    require(exchangeIds[exchangeIdIndex] == exchangeId, "exchangeId at index doesn't match");
    PoolExchange memory exchange = exchanges[exchangeId];

    delete exchanges[exchangeId];
    exchangeIds[exchangeIdIndex] = exchangeIds[exchangeIds.length.sub(1)];
    exchangeIds.pop();
    destroyed = true;

    emit ExchangeDestroyed(exchangeId, exchange.asset0, exchange.asset1, address(exchange.pricingModule));
  }

  /**
   * @notice Execute a token swap with fixed amountIn
   * @param exchangeId The id of exchange, i.e. PoolExchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountIn The amount of tokenIn to be sold
   * @return amountOut The amount of tokenOut to be bought
   */
  function swapIn(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountIn
  ) external onlyBroker returns (uint256 amountOut) {
    PoolExchange memory exchange = getPoolExchange(exchangeId);
    require(
      breakerBox.getRateFeedTradingMode(exchange.config.referenceRateFeedID) == TRADING_MODE_BIDIRECTIONAL,
      "Trading is suspended for this reference rate"
    );

    uint256 scaledAmountIn = amountIn.mul(tokenPrecisionMultipliers[tokenIn]);
    (uint256 scaledAmountOut, bool bucketsUpdated) = _getAmountOut(exchange, tokenIn, tokenOut, scaledAmountIn);
    executeSwap(exchangeId, exchange, tokenIn, scaledAmountIn, scaledAmountOut, bucketsUpdated);

    amountOut = scaledAmountOut.div(tokenPrecisionMultipliers[tokenOut]);
    return amountOut;
  }

  /**
   * @notice Execute a token swap with fixed amountOut
   * @param exchangeId The id of exchange, i.e. PoolExchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountOut The amount of tokenOut to be bought
   * @return amountIn The amount of tokenIn to be sold
   */
  function swapOut(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountOut
  ) external onlyBroker returns (uint256 amountIn) {
    PoolExchange memory exchange = getPoolExchange(exchangeId);
    require(
      breakerBox.getRateFeedTradingMode(exchange.config.referenceRateFeedID) == TRADING_MODE_BIDIRECTIONAL,
      "Trading is suspended for this reference rate"
    );

    uint256 scaledAmountOut = amountOut.mul(tokenPrecisionMultipliers[tokenOut]);
    (uint256 scaledAmountIn, bool bucketsUpdated) = _getAmountIn(exchange, tokenIn, tokenOut, scaledAmountOut);
    executeSwap(exchangeId, exchange, tokenIn, scaledAmountIn, scaledAmountOut, bucketsUpdated);

    amountIn = scaledAmountIn.div(tokenPrecisionMultipliers[tokenIn]);
    return amountIn;
  }

  /* ==================== Private Functions ==================== */

  /**
   * @notice Execute a swap against the in memory exchange and write
   *         the new bucket sizes to storage.
   * @dev In constant sum exchanges, the virtual bucket ratio serve as the reference price
   *      and should remain constant between bucket updates.
   *      Thats why the amounts of a swap are only applied for constant product exchanges.
   * @param exchangeId The id of the exchange
   * @param exchange The exchange to operate on
   * @param tokenIn The token to be sold
   * @param scaledAmountIn The amount of tokenIn to be sold scaled to 18 decimals
   * @param scaledAmountOut The amount of tokenOut to be bought scaled to 18 decimals
   * @param bucketsUpdated whether the buckets updated during the swap
   */
  function executeSwap(
    bytes32 exchangeId,
    PoolExchange memory exchange,
    address tokenIn,
    uint256 scaledAmountIn,
    uint256 scaledAmountOut,
    bool bucketsUpdated
  ) internal {
    if (bucketsUpdated) {
      // solhint-disable-next-line not-rely-on-time
      exchanges[exchangeId].lastBucketUpdate = now;
      emit BucketsUpdated(exchangeId, exchange.bucket0, exchange.bucket1);
    }

    if (isConstantProduct(exchange)) {
      if (tokenIn == exchange.asset0) {
        exchange.bucket0 = exchange.bucket0.add(scaledAmountIn);
        exchange.bucket1 = exchange.bucket1.sub(scaledAmountOut);
      } else {
        exchange.bucket0 = exchange.bucket0.sub(scaledAmountOut);
        exchange.bucket1 = exchange.bucket1.add(scaledAmountIn);
      }
    }

    exchanges[exchangeId].bucket0 = exchange.bucket0;
    exchanges[exchangeId].bucket1 = exchange.bucket1;
  }

  /**
   * @notice Calculate amountOut of tokenOut received for a given amountIn of tokenIn
   * @param exchange The exchange to operate on
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param scaledAmountIn The amount of tokenIn to be sold scaled to 18 decimals
   * @return scaledAmountOut The amount of tokenOut to be bought scaled to 18 decimals
   * @return bucketsUpdated Wether the buckets were updated during the quote
   */
  function _getAmountOut(
    PoolExchange memory exchange,
    address tokenIn,
    address tokenOut,
    uint256 scaledAmountIn
  )
    internal
    view
    verifyExchangeTokens(tokenIn, tokenOut, exchange)
    returns (uint256 scaledAmountOut, bool bucketsUpdated)
  {
    (exchange, bucketsUpdated) = updateBucketsIfNecessary(exchange);

    if (tokenIn == exchange.asset0) {
      scaledAmountOut = exchange.pricingModule.getAmountOut(
        exchange.bucket0,
        exchange.bucket1,
        exchange.config.spread.unwrap(),
        scaledAmountIn
      );
    } else {
      scaledAmountOut = exchange.pricingModule.getAmountOut(
        exchange.bucket1,
        exchange.bucket0,
        exchange.config.spread.unwrap(),
        scaledAmountIn
      );
    }
  }

  /**
   * @notice Calculate amountIn of tokenIn for a given amountOut of tokenOut
   * @param exchange The exchange to operate on
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param scaledAmountOut The amount of tokenOut to be bought scaled to 18 decimals
   * @return scaledAmountIn The amount of tokenIn to be sold scaled to 18 decimals
   * @return bucketsUpdated Whether the buckets were updated during the quote
   */
  function _getAmountIn(
    PoolExchange memory exchange,
    address tokenIn,
    address tokenOut,
    uint256 scaledAmountOut
  )
    internal
    view
    verifyExchangeTokens(tokenIn, tokenOut, exchange)
    returns (uint256 scaledAmountIn, bool bucketsUpdated)
  {
    (exchange, bucketsUpdated) = updateBucketsIfNecessary(exchange);

    if (tokenIn == exchange.asset0) {
      scaledAmountIn = exchange.pricingModule.getAmountIn(
        exchange.bucket0,
        exchange.bucket1,
        exchange.config.spread.unwrap(),
        scaledAmountOut
      );
    } else {
      scaledAmountIn = exchange.pricingModule.getAmountIn(
        exchange.bucket1,
        exchange.bucket0,
        exchange.config.spread.unwrap(),
        scaledAmountOut
      );
    }
  }

  /**
   * @notice If conditions are met, update the exchange bucket sizes.
   * @dev This doesn't checkpoint the exchange, just updates the in-memory one
   * so it should be used in a context that then checkpoints the exchange.
   * @param exchange The exchange being updated.
   * @return exchangeAfter The updated exchange.
   */
  function updateBucketsIfNecessary(PoolExchange memory exchange)
    internal
    view
    returns (PoolExchange memory, bool updated)
  {
    if (shouldUpdateBuckets(exchange)) {
      (exchange.bucket0, exchange.bucket1) = getUpdatedBuckets(exchange);
      updated = true;
    }
    return (exchange, updated);
  }

  /**
   * @notice Determine if a exchange's buckets should be updated
   * based on staleness of buckets and oracle rates.
   * @param exchange The PoolExchange.
   * @return shouldUpdate
   */
  function shouldUpdateBuckets(PoolExchange memory exchange) internal view returns (bool) {
    bool hasValidMedian = oracleHasValidMedian(exchange);
    if (isConstantSum(exchange)) {
      require(hasValidMedian, "no valid median");
    }
    // solhint-disable-next-line not-rely-on-time
    bool timePassed = now >= exchange.lastBucketUpdate.add(exchange.config.referenceRateResetFrequency);
    return timePassed && hasValidMedian;
  }

  /**
   * @notice Determine if the median is valid based on the current oracle rates.
   * @param exchange The PoolExchange.
   * @return HasValidMedian.
   */
  function oracleHasValidMedian(PoolExchange memory exchange) internal view returns (bool) {
    // solhint-disable-next-line not-rely-on-time
    (bool isReportExpired, ) = sortedOracles.isOldestReportExpired(exchange.config.referenceRateFeedID);
    bool enoughReports = (sortedOracles.numRates(exchange.config.referenceRateFeedID) >=
      exchange.config.minimumReports);
    // solhint-disable-next-line not-rely-on-time
    bool medianReportRecent = sortedOracles.medianTimestamp(exchange.config.referenceRateFeedID) >
      now.sub(exchange.config.referenceRateResetFrequency);
    return !isReportExpired && enoughReports && medianReportRecent;
  }

  /**
   * @notice Calculate the new bucket sizes for a exchange.
   * @param exchange The PoolExchange in context.
   * @return bucket0 The size of bucket0.
   * @return bucket1 The size of bucket1.
   */
  function getUpdatedBuckets(PoolExchange memory exchange) internal view returns (uint256 bucket0, uint256 bucket1) {
    bucket0 = exchange.config.stablePoolResetSize;
    uint256 exchangeRateNumerator;
    uint256 exchangeRateDenominator;
    (exchangeRateNumerator, exchangeRateDenominator) = getOracleExchangeRate(exchange.config.referenceRateFeedID);

    bucket1 = exchangeRateDenominator.mul(bucket0).div(exchangeRateNumerator);
  }

  /**
   * @notice Get the exchange rate as numerator,denominator from sorted oracles
   * and protect in case of a 0-denominator.
   * @param target the reportTarget to read from SortedOracles
   * @return rateNumerator
   * @return rateDenominator
   */
  function getOracleExchangeRate(address target)
    internal
    view
    returns (uint256 rateNumerator, uint256 rateDenominator)
  {
    (rateNumerator, rateDenominator) = sortedOracles.medianRate(target);
    require(rateDenominator > 0, "exchange rate denominator must be greater than 0");
  }

  /**
   * @notice Valitates a PoolExchange's parameters and configuration
   * @dev Reverts if not valid
   * @param exchange The PoolExchange to validate
   */
  function validate(PoolExchange memory exchange) private view {
    require(reserve.isStableAsset(exchange.asset0), "asset0 must be a stable registered with the reserve");
    require(
      reserve.isStableAsset(exchange.asset1) || reserve.isCollateralAsset(exchange.asset1),
      "asset1 must be a stable or collateral"
    );
    require(FixidityLib.lte(exchange.config.spread, FixidityLib.fixed1()), "spread must be less than or equal to 1");
    require(exchange.config.referenceRateFeedID != address(0), "referenceRateFeedID must be set");
  }

  /**
   * @notice Get the identifier of the pricing module used by a exchange
   * @param exchange The exchange to get the pricing module identifier for
   * @return The encoded and hashed identifier of the pricing module
   */
  function pricingModuleIdentifier(PoolExchange memory exchange) internal view returns (bytes32) {
    return keccak256(abi.encodePacked(exchange.pricingModule.name()));
  }

  /**
   * @notice Determine whether an exchange is using a constant sum pricing module
   * @param exchange The exchange to check
   * @return bool indicating if the exchange is using a constant sum pricing module
   */
  function isConstantSum(PoolExchange memory exchange) internal view returns (bool) {
    return pricingModuleIdentifier(exchange) == CONSTANT_SUM;
  }

  /**
   * @notice Determine whether an exchange is using a constant product pricing module
   * @param exchange The exchange to check
   * @return bool indicating if the exchange is using a constant product pricing module
   */
  function isConstantProduct(PoolExchange memory exchange) internal view returns (bool) {
    return pricingModuleIdentifier(exchange) == CONSTANT_PRODUCT;
  }
}
        

/lib/mento-core-2.2.0/contracts/interfaces/ISortedOracles.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "../common/linkedlists/SortedLinkedListWithMedian.sol";

interface ISortedOracles {
  function addOracle(address, address) external;

  function removeOracle(
    address,
    address,
    uint256
  ) external;

  function report(
    address,
    uint256,
    address,
    address
  ) external;

  function removeExpiredReports(address, uint256) external;

  function isOldestReportExpired(address token) external view returns (bool, address);

  function numRates(address) external view returns (uint256);

  function medianRate(address) external view returns (uint256, uint256);

  function numTimestamps(address) external view returns (uint256);

  function medianTimestamp(address) external view returns (uint256);

  function getOracles(address) external view returns (address[] memory);

  function getTimestamps(address token)
    external
    view
    returns (
      address[] memory,
      uint256[] memory,
      SortedLinkedListWithMedian.MedianRelation[] memory
    );
}
          

/lib/mento-core-2.2.0/contracts/interfaces/IReserve.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

interface IReserve {
  function setTobinTaxStalenessThreshold(uint256) external;

  function addToken(address) external returns (bool);

  function removeToken(address, uint256) external returns (bool);

  function transferGold(address payable, uint256) external returns (bool);

  function transferExchangeGold(address payable, uint256) external returns (bool);

  function transferCollateralAsset(
    address collateralAsset,
    address payable to,
    uint256 value
  ) external returns (bool);

  function getReserveGoldBalance() external view returns (uint256);

  function getUnfrozenReserveGoldBalance() external view returns (uint256);

  function getOrComputeTobinTax() external returns (uint256, uint256);

  function getTokens() external view returns (address[] memory);

  function getReserveRatio() external view returns (uint256);

  function addExchangeSpender(address) external;

  function removeExchangeSpender(address, uint256) external;

  function addSpender(address) external;

  function removeSpender(address) external;

  function isStableAsset(address) external view returns (bool);

  function isCollateralAsset(address) external view returns (bool);

  function getDailySpendingRatioForCollateralAsset(address collateralAsset) external view returns (uint256);

  function isExchangeSpender(address exchange) external view returns (bool);

  function addCollateralAsset(address asset) external returns (bool);

  function transferExchangeCollateralAsset(
    address collateralAsset,
    address payable to,
    uint256 value
  ) external returns (bool);
}
          

/lib/mento-core-2.2.0/contracts/interfaces/IPricingModule.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

/**
 * @title Interface for a Mento Pricing Module.
 * @notice A Mento pricing module represents an exchange relation between a pair of ERC20 assets.
 */
interface IPricingModule {
  /**
   * @notice Returns the output amount and new bucket sizes for a given input amount.
   * @param tokenInBucketSize Size of the tokenIn bucket.
   * @param tokenOutBucketSize Size of the tokenOut bucket.
   * @param spread Spread charged on exchanges.
   * @param amountIn Amount of tokenIn being paid in.
   * @return amountOut Amount of tokenOut that will be paid out.
   */
  function getAmountOut(
    uint256 tokenInBucketSize,
    uint256 tokenOutBucketSize,
    uint256 spread,
    uint256 amountIn
  ) external view returns (uint256 amountOut);

  /**
   * @notice Returns the input amount necessary for a given output amount.
   * @param tokenInBucketSize Size of the tokenIn bucket.
   * @param tokenOutBucketSize Size of the tokenOut bucket.
   * @param spread Spread charged on exchanges.
   * @param amountOut Amount of tokenIn being paid out.
   * @return amountIn Amount of tokenOut that would have to be paid in.
   */
  function getAmountIn(
    uint256 tokenInBucketSize,
    uint256 tokenOutBucketSize,
    uint256 spread,
    uint256 amountOut
  ) external view returns (uint256 amountIn);

  /**
   * @notice Retrieve the name of this pricing module.
   * @return exchangeName The name of the pricing module.
   */
  function name() external view returns (string memory pricingModuleName);
}
          

/lib/mento-core-2.2.0/contracts/interfaces/IExchangeProvider.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma experimental ABIEncoderV2;

/**
 * @title ExchangeProvider interface
 * @notice The IExchangeProvider interface is the interface that the Broker uses
 * to communicate with different exchange manager implementations like the BiPoolManager
 */
interface IExchangeProvider {
  /**
   * @notice Exchange - a struct that's used only by UIs (frontends/CLIs)
   * in order to discover what asset swaps are possible within an
   * exchange provider.
   * It's up to the specific exchange provider to convert its internal
   * representation to this universal struct. This conversion should
   * only happen in view calls used for discovery.
   * @param exchangeId The ID of the exchange, used to initiate swaps or get quotes.
   * @param assets An array of addresses of ERC20 tokens that can be swapped.
   */
  struct Exchange {
    bytes32 exchangeId;
    address[] assets;
  }

  /**
   * @notice Get all exchanges supported by the ExchangeProvider.
   * @return exchanges An array of Exchange structs.
   */
  function getExchanges() external view returns (Exchange[] memory exchanges);

  /**
   * @notice Execute a token swap with fixed amountIn
   * @param exchangeId The id of the exchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountIn The amount of tokenIn to be sold
   * @return amountOut The amount of tokenOut to be bought
   */
  function swapIn(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountIn
  ) external returns (uint256 amountOut);

  /**
   * @notice Execute a token swap with fixed amountOut
   * @param exchangeId The id of the exchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountOut The amount of tokenOut to be bought
   * @return amountIn The amount of tokenIn to be sold
   */
  function swapOut(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountOut
  ) external returns (uint256 amountIn);

  /**
   * @notice Calculate amountOut of tokenOut received for a given amountIn of tokenIn
   * @param exchangeId The id of the exchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountIn The amount of tokenIn to be sold
   * @return amountOut The amount of tokenOut to be bought
   */
  function getAmountOut(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountIn
  ) external view returns (uint256 amountOut);

  /**
   * @notice Calculate amountIn of tokenIn needed for a given amountOut of tokenOut
   * @param exchangeId The id of the exchange to use
   * @param tokenIn The token to be sold
   * @param tokenOut The token to be bought
   * @param amountOut The amount of tokenOut to be bought
   * @return amountIn The amount of tokenIn to be sold
   */
  function getAmountIn(
    bytes32 exchangeId,
    address tokenIn,
    address tokenOut,
    uint256 amountOut
  ) external view returns (uint256 amountIn);
}
          

/lib/mento-core-2.2.0/contracts/interfaces/IBreakerBox.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

/**
 * @title Breaker Box Interface
 * @notice Defines the basic interface for the Breaker Box
 */
interface IBreakerBox {
  /**
   * @dev Used to keep track of the status of a breaker for a specific rate feed.
   *
   * - TradingMode: Represents the trading mode the breaker is in for a rate feed.
   *                This uses a bitmask approach, meaning each bit represents a
   *                different trading mode. The final trading mode of the rate feed
   *                is obtained by applying a logical OR operation to the TradingMode
   *                of all breakers associated with that rate feed. This allows multiple
   *                breakers to contribute to the final trading mode simultaneously.
   *                Possible values:
   *                0: bidirectional trading.
   *                1: inflow only.
   *                2: outflow only.
   *                3: trading halted.
   *
   * - LastUpdatedTime: Records the last time the breaker status was updated. This is
   *                    used to manage cooldown periods before the breaker can be reset.
   *
   * - Enabled:     Indicates whether the breaker is enabled for the associated rate feed.
   */
  struct BreakerStatus {
    uint8 tradingMode;
    uint64 lastUpdatedTime;
    bool enabled;
  }

  /**
   * @notice Emitted when a new breaker is added to the breaker box.
   * @param breaker The address of the breaker.
   */
  event BreakerAdded(address indexed breaker);

  /**
   * @notice Emitted when a breaker is removed from the breaker box.
   * @param breaker The address of the breaker.
   */
  event BreakerRemoved(address indexed breaker);

  /**
   * @notice Emitted when a breaker is tripped by a rate feed.
   * @param breaker The address of the breaker.
   * @param rateFeedID The address of the rate feed.
   */
  event BreakerTripped(address indexed breaker, address indexed rateFeedID);

  /**
   * @notice Emitted when a new rate feed is added to the breaker box.
   * @param rateFeedID The address of the rate feed.
   */
  event RateFeedAdded(address indexed rateFeedID);

  /**
   * @notice Emitted when dependencies for a rate feed are set.
   * @param rateFeedID The address of the rate feed.
   * @param dependencies The addresses of the dependendent rate feeds.
   */
  event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies);

  /**
   * @notice Emitted when a rate feed is removed from the breaker box.
   * @param rateFeedID The address of the rate feed.
   */
  event RateFeedRemoved(address indexed rateFeedID);

  /**
   * @notice Emitted when the trading mode for a rate feed is updated
   * @param rateFeedID The address of the rate feed.
   * @param tradingMode The new trading mode.
   */
  event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode);

  /**
   * @notice Emitted after a reset attempt is successful.
   * @param rateFeedID The address of the rate feed.
   * @param breaker The address of the breaker.
   */
  event ResetSuccessful(address indexed rateFeedID, address indexed breaker);

  /**
   * @notice  Emitted after a reset attempt fails when the
   *          rate feed fails the breakers reset criteria.
   * @param rateFeedID The address of the rate feed.
   * @param breaker The address of the breaker.
   */
  event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker);

  /**
   * @notice Emitted after a reset attempt fails when cooldown time has not elapsed.
   * @param rateFeedID The address of the rate feed.
   * @param breaker The address of the breaker.
   */
  event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker);

  /**
   * @notice Emitted when the sortedOracles address is updated.
   * @param newSortedOracles The address of the new sortedOracles.
   */
  event SortedOraclesUpdated(address indexed newSortedOracles);

  /**
   * @notice Emitted when the breaker is enabled or disabled for a rate feed.
   * @param breaker The address of the breaker.
   * @param rateFeedID The address of the rate feed.
   * @param status Indicating the status.
   */
  event BreakerStatusUpdated(address breaker, address rateFeedID, bool status);

  /**
   * @notice Retrives an array of all breaker addresses.
   */
  function getBreakers() external view returns (address[] memory);

  /**
   * @notice Checks if a breaker with the specified address has been added to the breaker box.
   * @param breaker The address of the breaker to check;
   * @return A bool indicating whether or not the breaker has been added.
   */
  function isBreaker(address breaker) external view returns (bool);

  /**
   * @notice Checks breakers for the rateFeedID and sets correct trading mode
   * if any breakers are tripped or need to be reset.
   * @param rateFeedID The address of the rate feed to run checks for.
   */
  function checkAndSetBreakers(address rateFeedID) external;

  /**
   * @notice Gets the trading mode for the specified rateFeedID.
   * @param rateFeedID The address of the rate feed to retrieve the trading mode for.
   */
  function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode);
}
          

/lib/mento-core-2.2.0/contracts/interfaces/IBiPoolManager.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;
pragma experimental ABIEncoderV2;

import { IPricingModule } from "./IPricingModule.sol";
import { FixidityLib } from "../common/FixidityLib.sol";

/**
 * @title BiPool Manager interface
 * @notice The two asset pool manager is responsible for
 * managing the state of all two-asset virtual pools.
 */
interface IBiPoolManager {
  /**
   * @title PoolExchange
   * @notice The PoolExchange is a type of asset exchange that
   * that implements an AMM with two virtual buckets.
   */
  struct PoolExchange {
    address asset0;
    address asset1;
    IPricingModule pricingModule;
    uint256 bucket0;
    uint256 bucket1;
    uint256 lastBucketUpdate;
    PoolConfig config;
  }

  /**
   * @notice Variables related to bucket updates and sizing.
   * @dev Broken down into a separate struct because the compiler
   * version doesn't support structs with too many members.
   * Sad reacts only.
   */
  struct PoolConfig {
    FixidityLib.Fraction spread;
    address referenceRateFeedID; // rateFeedID of the price that this pool follows (i.e. it's reference rate)
    uint256 referenceRateResetFrequency;
    uint256 minimumReports;
    uint256 stablePoolResetSize;
  }

  /**
   * @notice Emitted when a new PoolExchange has been created.
   * @param exchangeId The id of the new PoolExchange
   * @param asset0 The address of asset0
   * @param asset1 The address of asset1
   * @param pricingModule the address of the pricingModule
   */
  event ExchangeCreated(
    bytes32 indexed exchangeId,
    address indexed asset0,
    address indexed asset1,
    address pricingModule
  );

  /**
   * @notice Emitted when a PoolExchange has been destroyed.
   * @param exchangeId The id of the PoolExchange
   * @param asset0 The address of asset0
   * @param asset1 The address of asset1
   * @param pricingModule the address of the pricingModule
   */
  event ExchangeDestroyed(
    bytes32 indexed exchangeId,
    address indexed asset0,
    address indexed asset1,
    address pricingModule
  );

  /**
   * @notice Emitted when the broker address is updated.
   * @param newBroker The address of the new broker.
   */
  event BrokerUpdated(address indexed newBroker);

  /**
   * @notice Emitted when the reserve address is updated.
   * @param newReserve The address of the new reserve.
   */
  event ReserveUpdated(address indexed newReserve);

  /**
   * @notice Emitted when the breakerBox address is updated.
   * @param newBreakerBox The address of the new breakerBox.
   */
  event BreakerBoxUpdated(address newBreakerBox);

  /**
   * @notice Emitted when the sortedOracles address is updated.
   * @param newSortedOracles The address of the new sortedOracles.
   */
  event SortedOraclesUpdated(address indexed newSortedOracles);

  /**
   * @notice Emitted when the buckets for a specified exchange are updated.
   * @param exchangeId The id of the exchange
   * @param bucket0 The new bucket0 size
   * @param bucket1 The new bucket1 size
   */
  event BucketsUpdated(bytes32 indexed exchangeId, uint256 bucket0, uint256 bucket1);

  /**
   * @notice Emitted when the pricing modules have been updated.
   * @param newIdentifiers The new identifiers.
   * @param newAddresses The new pricing module addresses.
   */
  event PricingModulesUpdated(bytes32[] newIdentifiers, address[] newAddresses);

  /**
   * @notice Retrieves the pool with the specified exchangeId.
   * @param exchangeId The id of the pool to be retrieved.
   * @return exchange The PoolExchange with that ID.
   */
  function getPoolExchange(bytes32 exchangeId) external view returns (PoolExchange memory exchange);

  /**
   * @notice Get all exchange IDs.
   * @return exchangeIds List of the exchangeIds.
   */
  function getExchangeIds() external view returns (bytes32[] memory exchangeIds);

  /**
   * @notice Create a PoolExchange with the provided data.
   * @param exchange The PoolExchange to be created.
   * @return exchangeId The id of the exchange.
   */
  function createExchange(PoolExchange calldata exchange) external returns (bytes32 exchangeId);

  /**
   * @notice Delete a PoolExchange.
   * @param exchangeId The PoolExchange to be created.
   * @param exchangeIdIndex The index of the exchangeId in the exchangeIds array.
   * @return destroyed - true on successful delition.
   */
  function destroyExchange(bytes32 exchangeId, uint256 exchangeIdIndex) external returns (bool destroyed);
}
          

/lib/mento-core-2.2.0/contracts/common/linkedlists/SortedLinkedListWithMedian.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./LinkedList.sol";
import "./SortedLinkedList.sol";

/**
 * @title Maintains a sorted list of unsigned ints keyed by bytes32.
 */
library SortedLinkedListWithMedian {
  using SafeMath for uint256;
  using SortedLinkedList for SortedLinkedList.List;

  enum MedianAction {
    None,
    Lesser,
    Greater
  }

  enum MedianRelation {
    Undefined,
    Lesser,
    Greater,
    Equal
  }

  struct List {
    SortedLinkedList.List list;
    bytes32 median;
    mapping(bytes32 => MedianRelation) relation;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param value The element value.
   * @param lesserKey The key of the element less than the element to insert.
   * @param greaterKey The key of the element greater than the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    list.list.insert(key, value, lesserKey, greaterKey);
    LinkedList.Element storage element = list.list.list.elements[key];

    MedianAction action = MedianAction.None;
    if (list.list.list.numElements == 1) {
      list.median = key;
      list.relation[key] = MedianRelation.Equal;
    } else if (list.list.list.numElements % 2 == 1) {
      // When we have an odd number of elements, and the element that we inserted is less than
      // the previous median, we need to slide the median down one element, since we had previously
      // selected the greater of the two middle elements.
      if (element.previousKey == bytes32(0) || list.relation[element.previousKey] == MedianRelation.Lesser) {
        action = MedianAction.Lesser;
        list.relation[key] = MedianRelation.Lesser;
      } else {
        list.relation[key] = MedianRelation.Greater;
      }
    } else {
      // When we have an even number of elements, and the element that we inserted is greater than
      // the previous median, we need to slide the median up one element, since we always select
      // the greater of the two middle elements.
      if (element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater) {
        action = MedianAction.Greater;
        list.relation[key] = MedianRelation.Greater;
      } else {
        list.relation[key] = MedianRelation.Lesser;
      }
    }
    updateMedian(list, action);
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    MedianAction action = MedianAction.None;
    if (list.list.list.numElements == 0) {
      list.median = bytes32(0);
    } else if (list.list.list.numElements % 2 == 0) {
      // When we have an even number of elements, we always choose the higher of the two medians.
      // Thus, if the element we're removing is greaterKey than or equal to the median we need to
      // slide the median left by one.
      if (list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal) {
        action = MedianAction.Lesser;
      }
    } else {
      // When we don't have an even number of elements, we just choose the median value.
      // Thus, if the element we're removing is less than or equal to the median, we need to slide
      // median right by one.
      if (list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal) {
        action = MedianAction.Greater;
      }
    }
    updateMedian(list, action);

    list.list.remove(key);
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param value The element value.
   * @param lesserKey The key of the element will be just left of `key` after the update.
   * @param greaterKey The key of the element will be just right of `key` after the update.
   * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction.
   */
  function update(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    remove(list, key);
    insert(list, key, value, lesserKey, greaterKey);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, 0, bytes32(0), list.list.list.tail);
  }

  /**
   * @notice Removes N elements from the head of the list and returns their keys.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to pop.
   * @return The keys of the popped elements.
   */
  function popN(List storage list, uint256 n) internal returns (bytes32[] memory) {
    require(n <= list.list.list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    for (uint256 i = 0; i < n; i = i.add(1)) {
      bytes32 key = list.list.list.head;
      keys[i] = key;
      remove(list, key);
    }
    return keys;
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.list.contains(key);
  }

  /**
   * @notice Returns the value for a particular key in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return The element value.
   */
  function getValue(List storage list, bytes32 key) internal view returns (uint256) {
    return list.list.values[key];
  }

  /**
   * @notice Returns the median value of the sorted list.
   * @param list A storage pointer to the underlying list.
   * @return The median value.
   */
  function getMedianValue(List storage list) internal view returns (uint256) {
    return getValue(list, list.median);
  }

  /**
   * @notice Returns the key of the first element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the first element in the list.
   */
  function getHead(List storage list) internal view returns (bytes32) {
    return list.list.list.head;
  }

  /**
   * @notice Returns the key of the median element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the median element in the list.
   */
  function getMedian(List storage list) internal view returns (bytes32) {
    return list.median;
  }

  /**
   * @notice Returns the key of the last element in the list.
   * @param list A storage pointer to the underlying list.
   * @return The key of the last element in the list.
   */
  function getTail(List storage list) internal view returns (bytes32) {
    return list.list.list.tail;
  }

  /**
   * @notice Returns the number of elements in the list.
   * @param list A storage pointer to the underlying list.
   * @return The number of elements in the list.
   */
  function getNumElements(List storage list) internal view returns (uint256) {
    return list.list.list.numElements;
  }

  /**
   * @notice Gets all elements from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return Array of all keys in the list.
   * @return Values corresponding to keys, which will be ordered largest to smallest.
   * @return Array of relations to median of corresponding list elements.
   */
  function getElements(List storage list)
    internal
    view
    returns (
      bytes32[] memory,
      uint256[] memory,
      MedianRelation[] memory
    )
  {
    bytes32[] memory keys = getKeys(list);
    uint256[] memory values = new uint256[](keys.length);
    MedianRelation[] memory relations = new MedianRelation[](keys.length);
    for (uint256 i = 0; i < keys.length; i = i.add(1)) {
      values[i] = list.list.values[keys[i]];
      relations[i] = list.relation[keys[i]];
    }
    return (keys, values, relations);
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return list.list.getKeys();
  }

  /**
   * @notice Moves the median pointer right or left of its current value.
   * @param list A storage pointer to the underlying list.
   * @param action Which direction to move the median pointer.
   */
  function updateMedian(List storage list, MedianAction action) private {
    LinkedList.Element storage previousMedian = list.list.list.elements[list.median];
    if (action == MedianAction.Lesser) {
      list.relation[list.median] = MedianRelation.Greater;
      list.median = previousMedian.previousKey;
    } else if (action == MedianAction.Greater) {
      list.relation[list.median] = MedianRelation.Lesser;
      list.median = previousMedian.nextKey;
    }
    list.relation[list.median] = MedianRelation.Equal;
  }
}
          

/lib/mento-core-2.2.0/contracts/common/linkedlists/SortedLinkedList.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./LinkedList.sol";

/**
 * @title Maintains a sorted list of unsigned ints keyed by bytes32.
 */
library SortedLinkedList {
  using SafeMath for uint256;
  using LinkedList for LinkedList.List;

  struct List {
    LinkedList.List list;
    mapping(bytes32 => uint256) values;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param value The element value.
   * @param lesserKey The key of the element less than the element to insert.
   * @param greaterKey The key of the element greater than the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    require(key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key), "invalid key");
    require(
      (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0,
      "greater and lesser key zero"
    );
    require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key");
    require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key");
    (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey);
    list.list.insert(key, lesserKey, greaterKey);
    list.values[key] = value;
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    list.list.remove(key);
    list.values[key] = 0;
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param value The element value.
   * @param lesserKey The key of the element will be just left of `key` after the update.
   * @param greaterKey The key of the element will be just right of `key` after the update.
   * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction.
   */
  function update(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) internal {
    remove(list, key);
    insert(list, key, value, lesserKey, greaterKey);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, 0, bytes32(0), list.list.tail);
  }

  /**
   * @notice Removes N elements from the head of the list and returns their keys.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to pop.
   * @return The keys of the popped elements.
   */
  function popN(List storage list, uint256 n) internal returns (bytes32[] memory) {
    require(n <= list.list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    for (uint256 i = 0; i < n; i = i.add(1)) {
      bytes32 key = list.list.head;
      keys[i] = key;
      remove(list, key);
    }
    return keys;
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.list.contains(key);
  }

  /**
   * @notice Returns the value for a particular key in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return The element value.
   */
  function getValue(List storage list, bytes32 key) internal view returns (uint256) {
    return list.values[key];
  }

  /**
   * @notice Gets all elements from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return Array of all keys in the list.
   * @return Values corresponding to keys, which will be ordered largest to smallest.
   */
  function getElements(List storage list) internal view returns (bytes32[] memory, uint256[] memory) {
    bytes32[] memory keys = getKeys(list);
    uint256[] memory values = new uint256[](keys.length);
    for (uint256 i = 0; i < keys.length; i = i.add(1)) {
      values[i] = list.values[keys[i]];
    }
    return (keys, values);
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return list.list.getKeys();
  }

  /**
   * @notice Returns first N greatest elements of the list.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to return.
   * @return The keys of the first n elements.
   * @dev Reverts if n is greater than the number of elements in the list.
   */
  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {
    return list.list.headN(n);
  }

  /**
   * @notice Returns the keys of the elements greaterKey than and less than the provided value.
   * @param list A storage pointer to the underlying list.
   * @param value The element value.
   * @param lesserKey The key of the element which could be just left of the new value.
   * @param greaterKey The key of the element which could be just right of the new value.
   * @return The correct lesserKey keys.
   * @return The correct greaterKey keys.
   */
  function getLesserAndGreater(
    List storage list,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) private view returns (bytes32, bytes32) {
    // Check for one of the following conditions and fail if none are met:
    //   1. The value is less than the current lowest value
    //   2. The value is greater than the current greatest value
    //   3. The value is just greater than the value for `lesserKey`
    //   4. The value is just less than the value for `greaterKey`
    if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) {
      return (lesserKey, list.list.tail);
    } else if (greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)) {
      return (list.list.head, greaterKey);
    } else if (
      lesserKey != bytes32(0) && isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey)
    ) {
      return (lesserKey, list.list.elements[lesserKey].nextKey);
    } else if (
      greaterKey != bytes32(0) && isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey)
    ) {
      return (list.list.elements[greaterKey].previousKey, greaterKey);
    } else {
      require(false, "get lesser and greater failure");
    }
  }

  /**
   * @notice Returns whether or not a given element is between two other elements.
   * @param list A storage pointer to the underlying list.
   * @param value The element value.
   * @param lesserKey The key of the element whose value should be lesserKey.
   * @param greaterKey The key of the element whose value should be greaterKey.
   * @return True if the given element is between the two other elements.
   */
  function isValueBetween(
    List storage list,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) private view returns (bool) {
    bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value;
    bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value;
    return isLesser && isGreater;
  }
}
          

/lib/mento-core-2.2.0/contracts/common/linkedlists/LinkedList.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @title Maintains a doubly linked list keyed by bytes32.
 * @dev Following the `next` pointers will lead you to the head, rather than the tail.
 */
library LinkedList {
  using SafeMath for uint256;

  struct Element {
    bytes32 previousKey;
    bytes32 nextKey;
    bool exists;
  }

  struct List {
    bytes32 head;
    bytes32 tail;
    uint256 numElements;
    mapping(bytes32 => Element) elements;
  }

  /**
   * @notice Inserts an element into a doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   * @param previousKey The key of the element that comes before the element to insert.
   * @param nextKey The key of the element that comes after the element to insert.
   */
  function insert(
    List storage list,
    bytes32 key,
    bytes32 previousKey,
    bytes32 nextKey
  ) internal {
    require(key != bytes32(0), "Key must be defined");
    require(!contains(list, key), "Can't insert an existing element");
    require(previousKey != key && nextKey != key, "Key cannot be the same as previousKey or nextKey");

    Element storage element = list.elements[key];
    element.exists = true;

    if (list.numElements == 0) {
      list.tail = key;
      list.head = key;
    } else {
      require(previousKey != bytes32(0) || nextKey != bytes32(0), "Either previousKey or nextKey must be defined");

      element.previousKey = previousKey;
      element.nextKey = nextKey;

      if (previousKey != bytes32(0)) {
        require(contains(list, previousKey), "If previousKey is defined, it must exist in the list");
        Element storage previousElement = list.elements[previousKey];
        require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey");
        previousElement.nextKey = key;
      } else {
        list.tail = key;
      }

      if (nextKey != bytes32(0)) {
        require(contains(list, nextKey), "If nextKey is defined, it must exist in the list");
        Element storage nextElement = list.elements[nextKey];
        require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey");
        nextElement.previousKey = key;
      } else {
        list.head = key;
      }
    }

    list.numElements = list.numElements.add(1);
  }

  /**
   * @notice Inserts an element at the tail of the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to insert.
   */
  function push(List storage list, bytes32 key) internal {
    insert(list, key, bytes32(0), list.tail);
  }

  /**
   * @notice Removes an element from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @param key The key of the element to remove.
   */
  function remove(List storage list, bytes32 key) internal {
    Element storage element = list.elements[key];
    require(key != bytes32(0) && contains(list, key), "key not in list");
    if (element.previousKey != bytes32(0)) {
      Element storage previousElement = list.elements[element.previousKey];
      previousElement.nextKey = element.nextKey;
    } else {
      list.tail = element.nextKey;
    }

    if (element.nextKey != bytes32(0)) {
      Element storage nextElement = list.elements[element.nextKey];
      nextElement.previousKey = element.previousKey;
    } else {
      list.head = element.previousKey;
    }

    delete list.elements[key];
    list.numElements = list.numElements.sub(1);
  }

  /**
   * @notice Updates an element in the list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @param previousKey The key of the element that comes before the updated element.
   * @param nextKey The key of the element that comes after the updated element.
   */
  function update(
    List storage list,
    bytes32 key,
    bytes32 previousKey,
    bytes32 nextKey
  ) internal {
    require(key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key), "key on in list");
    remove(list, key);
    insert(list, key, previousKey, nextKey);
  }

  /**
   * @notice Returns whether or not a particular key is present in the sorted list.
   * @param list A storage pointer to the underlying list.
   * @param key The element key.
   * @return Whether or not the key is in the sorted list.
   */
  function contains(List storage list, bytes32 key) internal view returns (bool) {
    return list.elements[key].exists;
  }

  /**
   * @notice Returns the keys of the N elements at the head of the list.
   * @param list A storage pointer to the underlying list.
   * @param n The number of elements to return.
   * @return The keys of the N elements at the head of the list.
   * @dev Reverts if n is greater than the number of elements in the list.
   */
  function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) {
    require(n <= list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    bytes32 key = list.head;
    for (uint256 i = 0; i < n; i = i.add(1)) {
      keys[i] = key;
      key = list.elements[key].previousKey;
    }
    return keys;
  }

  /**
   * @notice Gets all element keys from the doubly linked list.
   * @param list A storage pointer to the underlying list.
   * @return All element keys from head to tail.
   */
  function getKeys(List storage list) internal view returns (bytes32[] memory) {
    return headN(list, list.numElements);
  }
}
          

/lib/mento-core-2.2.0/contracts/common/interfaces/IERC20Metadata.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

interface IERC20Metadata {
  /**
   * @dev Returns the name of the token.
   */
  function name() external view returns (string memory);

  /**
   * @dev Returns the symbol of the token.
   */
  function symbol() external view returns (string memory);

  /**
   * @dev Returns the decimals places of the token.
   */
  function decimals() external view returns (uint8);

  /**
   * @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 `recipient`.
   *
   * Returns a boolean value indicating whether the operation succeeded.
   *
   * Emits a {Transfer} event.
   */
  function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
    address recipient,
    uint256 amount
  ) external returns (bool);

  /**
   * @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);
}
          

/lib/mento-core-2.2.0/contracts/common/Initializable.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.5.13;

contract Initializable {
  bool public initialized;

  constructor(bool testingDeployment) public {
    if (!testingDeployment) {
      initialized = true;
    }
  }

  modifier initializer() {
    require(!initialized, "contract already initialized");
    initialized = true;
    _;
  }
}
          

/lib/mento-core-2.2.0/contracts/common/FixidityLib.sol

pragma solidity ^0.5.13;

/**
 * @title FixidityLib
 * @author Gadi Guy, Alberto Cuesta Canada
 * @notice This library provides fixed point arithmetic with protection against
 * overflow.
 * All operations are done with uint256 and the operands must have been created
 * with any of the newFrom* functions, which shift the comma digits() to the
 * right and check for limits, or with wrap() which expects a number already
 * in the internal representation of a fraction.
 * When using this library be sure to use maxNewFixed() as the upper limit for
 * creation of fixed point numbers.
 * @dev All contained functions are pure and thus marked internal to be inlined
 * on consuming contracts at compile time for gas efficiency.
 */
library FixidityLib {
  struct Fraction {
    uint256 value;
  }

  /**
   * @notice Number of positions that the comma is shifted to the right.
   */
  function digits() internal pure returns (uint8) {
    return 24;
  }

  uint256 private constant FIXED1_UINT = 1000000000000000000000000;

  /**
   * @notice This is 1 in the fixed point units used in this library.
   * @dev Test fixed1() equals 10^digits()
   * Hardcoded to 24 digits.
   */
  function fixed1() internal pure returns (Fraction memory) {
    return Fraction(FIXED1_UINT);
  }

  /**
   * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction
   * struct.
   * @param x Number that already represents a 24-decimal fraction.
   * @return A Fraction struct with contents x.
   */
  function wrap(uint256 x) internal pure returns (Fraction memory) {
    return Fraction(x);
  }

  /**
   * @notice Unwraps the uint256 inside of a Fraction struct.
   */
  function unwrap(Fraction memory x) internal pure returns (uint256) {
    return x.value;
  }

  /**
   * @notice The amount of decimals lost on each multiplication operand.
   * @dev Test mulPrecision() equals sqrt(fixed1)
   */
  function mulPrecision() internal pure returns (uint256) {
    return 1000000000000;
  }

  /**
   * @notice Maximum value that can be converted to fixed point. Optimize for deployment.
   * @dev
   * Test maxNewFixed() equals maxUint256() / fixed1()
   */
  function maxNewFixed() internal pure returns (uint256) {
    return 115792089237316195423570985008687907853269984665640564;
  }

  /**
   * @notice Converts a uint256 to fixed point Fraction
   * @dev Test newFixed(0) returns 0
   * Test newFixed(1) returns fixed1()
   * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1()
   * Test newFixed(maxNewFixed()+1) fails
   */
  function newFixed(uint256 x) internal pure returns (Fraction memory) {
    require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()");
    return Fraction(x * FIXED1_UINT);
  }

  /**
   * @notice Converts a uint256 in the fixed point representation of this
   * library to a non decimal. All decimal digits will be truncated.
   */
  function fromFixed(Fraction memory x) internal pure returns (uint256) {
    return x.value / FIXED1_UINT;
  }

  /**
   * @notice Converts two uint256 representing a fraction to fixed point units,
   * equivalent to multiplying dividend and divisor by 10^digits().
   * @param numerator numerator must be <= maxNewFixed()
   * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0
   * @dev
   * Test newFixedFraction(1,0) fails
   * Test newFixedFraction(0,1) returns 0
   * Test newFixedFraction(1,1) returns fixed1()
   * Test newFixedFraction(1,fixed1()) returns 1
   */
  function newFixedFraction(uint256 numerator, uint256 denominator) internal pure returns (Fraction memory) {
    Fraction memory convertedNumerator = newFixed(numerator);
    Fraction memory convertedDenominator = newFixed(denominator);
    return divide(convertedNumerator, convertedDenominator);
  }

  /**
   * @notice Returns the integer part of a fixed point number.
   * @dev
   * Test integer(0) returns 0
   * Test integer(fixed1()) returns fixed1()
   * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()
   */
  function integer(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
  }

  /**
   * @notice Returns the fractional part of a fixed point number.
   * In the case of a negative number the fractional is also negative.
   * @dev
   * Test fractional(0) returns 0
   * Test fractional(fixed1()) returns 0
   * Test fractional(fixed1()-1) returns 10^24-1
   */
  function fractional(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
  }

  /**
   * @notice x+y.
   * @dev The maximum value that can be safely used as an addition operator is defined as
   * maxFixedAdd = maxUint256()-1 / 2, or
   * 57896044618658097711785492504343953926634992332820282019728792003956564819967.
   * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd
   * Test add(maxFixedAdd+1,maxFixedAdd+1) throws
   */
  function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    uint256 z = x.value + y.value;
    require(z >= x.value, "add overflow detected");
    return Fraction(z);
  }

  /**
   * @notice x-y.
   * @dev
   * Test subtract(6, 10) fails
   */
  function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(x.value >= y.value, "substraction underflow detected");
    return Fraction(x.value - y.value);
  }

  /**
   * @notice x*y. If any of the operators is higher than the max multiplier value it
   * might overflow.
   * @dev The maximum value that can be safely used as a multiplication operator
   * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()),
   * or 340282366920938463463374607431768211455999999999999
   * Test multiply(0,0) returns 0
   * Test multiply(maxFixedMul,0) returns 0
   * Test multiply(0,maxFixedMul) returns 0
   * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1()
   * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256()
   * Test multiply(maxFixedMul+1,maxFixedMul+1) fails
   */
  // solhint-disable-next-line code-complexity
  function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    if (x.value == 0 || y.value == 0) return Fraction(0);
    if (y.value == FIXED1_UINT) return x;
    if (x.value == FIXED1_UINT) return y;

    // Separate into integer and fractional parts
    // x = x1 + x2, y = y1 + y2
    uint256 x1 = integer(x).value / FIXED1_UINT;
    uint256 x2 = fractional(x).value;
    uint256 y1 = integer(y).value / FIXED1_UINT;
    uint256 y2 = fractional(y).value;

    // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2)
    uint256 x1y1 = x1 * y1;
    if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected");

    // x1y1 needs to be multiplied back by fixed1
    // solhint-disable-next-line var-name-mixedcase
    uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;
    if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected");
    x1y1 = fixed_x1y1;

    uint256 x2y1 = x2 * y1;
    if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected");

    uint256 x1y2 = x1 * y2;
    if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected");

    x2 = x2 / mulPrecision();
    y2 = y2 / mulPrecision();
    uint256 x2y2 = x2 * y2;
    if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected");

    // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1();
    Fraction memory result = Fraction(x1y1);
    result = add(result, Fraction(x2y1)); // Add checks for overflow
    result = add(result, Fraction(x1y2)); // Add checks for overflow
    result = add(result, Fraction(x2y2)); // Add checks for overflow
    return result;
  }

  /**
   * @notice 1/x
   * @dev
   * Test reciprocal(0) fails
   * Test reciprocal(fixed1()) returns fixed1()
   * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated
   * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated
   * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24)
   */
  function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {
    require(x.value != 0, "can't call reciprocal(0)");
    return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow
  }

  /**
   * @notice x/y. If the dividend is higher than the max dividend value, it
   * might overflow. You can use multiply(x,reciprocal(y)) instead.
   * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as
   * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256().
   * This yields the value 115792089237316195423570985008687907853269984665640564.
   * Test maxNewFixed equals maxUint256()/fixed1()
   * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1)
   * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws
   * Test divide(fixed1(),0) fails
   * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits())
   * Test divide(maxNewFixed+1,1) throws
   */
  function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(y.value != 0, "can't divide by 0");
    // solhint-disable-next-line var-name-mixedcase
    uint256 X = x.value * FIXED1_UINT;
    require(X / FIXED1_UINT == x.value, "overflow at divide");
    return Fraction(X / y.value);
  }

  /**
   * @notice x > y
   */
  function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value > y.value;
  }

  /**
   * @notice x >= y
   */
  function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value >= y.value;
  }

  /**
   * @notice x < y
   */
  function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value < y.value;
  }

  /**
   * @notice x <= y
   */
  function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value <= y.value;
  }

  /**
   * @notice x == y
   */
  function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value == y.value;
  }

  /**
   * @notice x <= 1
   */
  function isProperFraction(Fraction memory x) internal pure returns (bool) {
    return lte(x, fixed1());
  }
}
          

/lib/mento-core-2.0.0/lib/openzeppelin-contracts/contracts/ownership/Ownable.sol

pragma solidity ^0.5.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}
          

/lib/mento-core-2.0.0/lib/openzeppelin-contracts/contracts/math/SafeMath.sol

pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}
          

/lib/mento-core-2.0.0/lib/openzeppelin-contracts/contracts/GSN/Context.sol

pragma solidity ^0.5.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 GSN 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.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}
          

/lib/celo-foundry/lib/forge-std/src/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));
    }

}
          

/lib/celo-foundry/lib/forge-std/src/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));
    }

}
          

/lib/celo-foundry/lib/forge-std/src/Vm.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.13 <0.9.0;

pragma experimental ABIEncoderV2;

// Cheatcodes are marked as view/pure/none using the following rules:
// 0. A call's observable behaviour includes its return value, logs, reverts and state writes.
// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure` (you are modifying some state be it the EVM, interpreter, filesystem, etc),
// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,
// 3. Otherwise you're `pure`.

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

    struct Rpc {
        string key;
        string url;
    }

    // Loads a storage slot from an address (who, slot)
    function load(address, bytes32) external view returns (bytes32);
    // Signs data, (privateKey, digest) => (v, r, s)
    function sign(uint256, bytes32) external pure returns (uint8, bytes32, bytes32);
    // Gets the address for a given private key, (privateKey) => (address)
    function addr(uint256) external pure returns (address);
    // Gets the nonce of an account
    function getNonce(address) external view returns (uint64);
    // 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 view returns (bool);
    function envUint(string calldata) external view returns (uint256);
    function envInt(string calldata) external view returns (int256);
    function envAddress(string calldata) external view returns (address);
    function envBytes32(string calldata) external view returns (bytes32);
    function envString(string calldata) external view returns (string memory);
    function envBytes(string calldata) external view returns (bytes memory);
    // Reads environment variables as arrays, (name, delim) => (value[])
    function envBool(string calldata, string calldata) external view returns (bool[] memory);
    function envUint(string calldata, string calldata) external view returns (uint256[] memory);
    function envInt(string calldata, string calldata) external view returns (int256[] memory);
    function envAddress(string calldata, string calldata) external view returns (address[] memory);
    function envBytes32(string calldata, string calldata) external view returns (bytes32[] memory);
    function envString(string calldata, string calldata) external view returns (string[] memory);
    function envBytes(string calldata, string calldata) external view returns (bytes[] memory);
    // 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);
    // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file
    function getCode(string calldata) external view returns (bytes memory);
    // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file
    function getDeployedCode(string calldata) external view returns (bytes memory);
    // Labels an address in call traces
    function label(address, string calldata) 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;
    // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain
    function broadcast(uint256) 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 with the address provided that can later be signed and sent onchain
    function startBroadcast(address) external;
    // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain
    function startBroadcast(uint256) external;
    // Stops collecting onchain transactions
    function stopBroadcast() external;
    // Reads the entire content of file to string, (path) => (data)
    function readFile(string calldata) external view returns (string memory);
    // Reads the entire content of file as binary. Path is relative to the project root. (path) => (data)
    function readFileBinary(string calldata) external view returns (bytes memory);
    // Get the path of the current project root
    function projectRoot() external view returns (string memory);
    // Reads next line of file to string, (path) => (line)
    function readLine(string calldata) external view 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 binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
    // Path is relative to the project root. (path, data) => ()
    function writeFileBinary(string calldata, bytes 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 pure returns (string memory);
    function toString(bytes calldata) external pure returns (string memory);
    function toString(bytes32) external pure returns (string memory);
    function toString(bool) external pure returns (string memory);
    function toString(uint256) external pure returns (string memory);
    function toString(int256) external pure returns (string memory);
    // Convert values from a string, (string) => (parsed value)
    function parseBytes(string calldata) external pure returns (bytes memory);
    function parseAddress(string calldata) external pure returns (address);
    function parseUint(string calldata) external pure returns (uint256);
    function parseInt(string calldata) external pure returns (int256);
    function parseBytes32(string calldata) external pure returns (bytes32);
    function parseBool(string calldata) external pure returns (bool);
    // Record all the transaction logs
    function recordLogs() external;
    // Gets all the recorded logs, () => (logs)
    function getRecordedLogs() external returns (Log[] 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 pure 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 pure returns (uint256);
    // Adds a private key to the local forge wallet and returns the address
    function rememberKey(uint256) external returns (address);
    //
    // parseJson
    //
    // ----
    // 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.
    // ----
    // Given a string of JSON, return it as ABI-encoded, (stringified json, key) => (ABI-encoded data)
    function parseJson(string calldata, string calldata) external pure returns (bytes memory);
    function parseJson(string calldata) external pure returns (bytes memory);
    //
    // writeJson
    //
    // ----
    // Let's assume we want to write the following JSON to a file:
    //
    // { "boolean": true, "number": 342, "object": { "title": "finally json serialization" } }
    //
    // ```
    //  string memory json1 = "some key";
    //  vm.serializeBool(json1, "boolean", true);
    //  vm.serializeBool(json1, "number", uint256(342));
    //  json2 = "some other key";
    //  string memory output = vm.serializeString(json2, "title", "finally json serialization");
    //  string memory finalJson = vm.serialize(json1, "object", output);
    //  vm.writeJson(finalJson, "./output/example.json");
    // ```
    //  The critical insight is that every invocation of serialization will return the stringified version of the JSON
    // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version
    // to serialize them as values to another JSON object.
    //
    //  json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)
    //  will find the object in-memory that is keyed by "some key".   // writeJson
    // ----
    // Serialize a key and value to a JSON object stored in-memory that can be latery written to a file
    // It returns the stringified version of the specific JSON file up to that moment.
    // (object_key, value_key, value) => (stringified JSON)
    function serializeBool(string calldata, string calldata, bool) external returns (string memory);
    function serializeUint(string calldata, string calldata, uint256) external returns (string memory);
    function serializeInt(string calldata, string calldata, int256) external returns (string memory);
    function serializeAddress(string calldata, string calldata, address) external returns (string memory);
    function serializeBytes32(string calldata, string calldata, bytes32) external returns (string memory);
    function serializeString(string calldata, string calldata, string calldata) external returns (string memory);
    function serializeBytes(string calldata, string calldata, bytes calldata) external returns (string memory);

    function serializeBool(string calldata, string calldata, bool[] calldata) external returns (string memory);
    function serializeUint(string calldata, string calldata, uint256[] calldata) external returns (string memory);
    function serializeInt(string calldata, string calldata, int256[] calldata) external returns (string memory);
    function serializeAddress(string calldata, string calldata, address[] calldata) external returns (string memory);
    function serializeBytes32(string calldata, string calldata, bytes32[] calldata) external returns (string memory);
    function serializeString(string calldata, string calldata, string[] calldata) external returns (string memory);
    function serializeBytes(string calldata, string calldata, bytes[] calldata) external returns (string memory);
    // Write a serialized JSON object to a file. If the file exists, it will be overwritten.
    // (stringified_json, path)
    function writeJson(string calldata, string calldata) external;
    // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key>
    // This is useful to replace a specific value of a JSON file, without having to parse the entire thing
    // (stringified_json, path, value_key)
    function writeJson(string calldata, string calldata, string calldata) external;
    // Returns the RPC url for the given alias
    function rpcUrl(string calldata) external view returns (string memory);
    // Returns all rpc urls and their aliases `[alias, url][]`
    function rpcUrls() external view returns (string[2][] memory);
    // Returns all rpc urls and their aliases as structs.
    function rpcUrlStructs() external view returns (Rpc[] memory);
    // If the condition is false, discard this run's fuzz inputs and generate new ones.
    function assume(bool) external pure;

    // 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;
    // Stores a value to an address' storage slot, (who, slot, value)
    function store(address, bytes32, bytes32) external;
    // Sets the nonce of an account; must be higher than the current nonce of the account
    function setNonce(address, uint64) external;
    // 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;
    // 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;
    // Sets block.coinbase (who)
    function coinbase(address) external;
    // 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 a new fork with the given endpoint and at the block the given transaction was mined in, and replays all transaction mined in the block before the transaction
    function createFork(string calldata, bytes32) 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 new fork with the given endpoint and at the block the given transaction was mined in, and replays all transaction mined in the block before the transaction
    function createSelectFork(string calldata, bytes32) 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 view 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 currently active fork to given transaction
    // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block
    function rollFork(bytes32) external;
    // Updates the given fork to given block number
    function rollFork(uint256 forkId, uint256 blockNumber) external;
    // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block
    function rollFork(uint256 forkId, bytes32 transaction) 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 view returns (bool);
    // In forking mode, explicitly grant the given address cheatcode access
    function allowCheatcodes(address) external;
    // Fetches the given transaction from the active fork and executes it on the current state
    function transact(bytes32 txHash) external;
    // Fetches the given transaction from the given fork and executes it on the current state
    function transact(uint256 forkId, bytes32 txHash) external;
}
          

/lib/celo-foundry/lib/forge-std/src/Script.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.13 <0.9.0;

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

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)));
    }
}
          

Compiler Settings

{"remappings":[":celo-foundry/=lib/celo-foundry/src/",":contracts/=contracts/",":ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/",":forge-std-next/=lib/mento-core-2.2.0/lib/forge-std-next/src/",":forge-std/=lib/celo-foundry/lib/forge-std/src/",":mento-core-2.0.0/=lib/mento-core-2.0.0/contracts/",":mento-core-2.1.0/=lib/mento-core-2.1.0/contracts/",":mento-core-2.2.0/=lib/mento-core-2.2.0/contracts/",":mento-core/=lib/mento-core/contracts/",":openzeppelin-contracts-next/=lib/mento-core-2.2.0/lib/openzeppelin-contracts-next/",":openzeppelin-contracts-upgradeable/=lib/mento-core-2.2.0/lib/openzeppelin-contracts-upgradeable/",":openzeppelin-contracts/=lib/mento-core-2.0.0/lib/openzeppelin-contracts/contracts/",":openzeppelin-solidity/=lib/mento-core-2.0.0/lib/openzeppelin-contracts/",":test/=lib/mento-core-2.0.0/test/"],"optimizer":{"runs":10000,"enabled":true},"libraries":{"AddressSortedLinkedListWithMedian":"0x99edce8143ff8aefa1fbb6c2103b349add2b9519","AddressLinkedList":"0x3e2cc57f83093ce1ee03482c1590e3b5f4225bd7"},"compilationTarget":{"lib/mento-core-2.2.0/contracts/swap/BiPoolManager.sol":"BiPoolManager"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"bool","name":"test","internalType":"bool"}]},{"type":"event","name":"BreakerBoxUpdated","inputs":[{"type":"address","name":"newBreakerBox","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BrokerUpdated","inputs":[{"type":"address","name":"newBroker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BucketsUpdated","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32","indexed":true},{"type":"uint256","name":"bucket0","internalType":"uint256","indexed":false},{"type":"uint256","name":"bucket1","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExchangeCreated","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32","indexed":true},{"type":"address","name":"asset0","internalType":"address","indexed":true},{"type":"address","name":"asset1","internalType":"address","indexed":true},{"type":"address","name":"pricingModule","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ExchangeDestroyed","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32","indexed":true},{"type":"address","name":"asset0","internalType":"address","indexed":true},{"type":"address","name":"asset1","internalType":"address","indexed":true},{"type":"address","name":"pricingModule","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PricingModulesUpdated","inputs":[{"type":"bytes32[]","name":"newIdentifiers","internalType":"bytes32[]","indexed":false},{"type":"address[]","name":"newAddresses","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"ReserveUpdated","inputs":[{"type":"address","name":"newReserve","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SortedOraclesUpdated","inputs":[{"type":"address","name":"newSortedOracles","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"CONSTANT_PRODUCT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"CONSTANT_SUM","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IBreakerBox"}],"name":"breakerBox","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"broker","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"}],"name":"createExchange","inputs":[{"type":"tuple","name":"_exchange","internalType":"struct IBiPoolManager.PoolExchange","components":[{"type":"address","name":"asset0","internalType":"address"},{"type":"address","name":"asset1","internalType":"address"},{"type":"address","name":"pricingModule","internalType":"contract IPricingModule"},{"type":"uint256","name":"bucket0","internalType":"uint256"},{"type":"uint256","name":"bucket1","internalType":"uint256"},{"type":"uint256","name":"lastBucketUpdate","internalType":"uint256"},{"type":"tuple","name":"config","internalType":"struct IBiPoolManager.PoolConfig","components":[{"type":"tuple","name":"spread","internalType":"struct FixidityLib.Fraction","components":[{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"address","name":"referenceRateFeedID","internalType":"address"},{"type":"uint256","name":"referenceRateResetFrequency","internalType":"uint256"},{"type":"uint256","name":"minimumReports","internalType":"uint256"},{"type":"uint256","name":"stablePoolResetSize","internalType":"uint256"}]}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"destroyed","internalType":"bool"}],"name":"destroyExchange","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"uint256","name":"exchangeIdIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"exchangeIds","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"asset0","internalType":"address"},{"type":"address","name":"asset1","internalType":"address"},{"type":"address","name":"pricingModule","internalType":"contract IPricingModule"},{"type":"uint256","name":"bucket0","internalType":"uint256"},{"type":"uint256","name":"bucket1","internalType":"uint256"},{"type":"uint256","name":"lastBucketUpdate","internalType":"uint256"},{"type":"tuple","name":"config","internalType":"struct IBiPoolManager.PoolConfig","components":[{"type":"tuple","name":"spread","internalType":"struct FixidityLib.Fraction","components":[{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"address","name":"referenceRateFeedID","internalType":"address"},{"type":"uint256","name":"referenceRateResetFrequency","internalType":"uint256"},{"type":"uint256","name":"minimumReports","internalType":"uint256"},{"type":"uint256","name":"stablePoolResetSize","internalType":"uint256"}]}],"name":"exchanges","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"}],"name":"getAmountIn","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"getAmountOut","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getExchangeIds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"_exchanges","internalType":"struct IExchangeProvider.Exchange[]","components":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"address[]","name":"assets","internalType":"address[]"}]}],"name":"getExchanges","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"exchange","internalType":"struct IBiPoolManager.PoolExchange","components":[{"type":"address","name":"asset0","internalType":"address"},{"type":"address","name":"asset1","internalType":"address"},{"type":"address","name":"pricingModule","internalType":"contract IPricingModule"},{"type":"uint256","name":"bucket0","internalType":"uint256"},{"type":"uint256","name":"bucket1","internalType":"uint256"},{"type":"uint256","name":"lastBucketUpdate","internalType":"uint256"},{"type":"tuple","name":"config","internalType":"struct IBiPoolManager.PoolConfig","components":[{"type":"tuple","name":"spread","internalType":"struct FixidityLib.Fraction","components":[{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"address","name":"referenceRateFeedID","internalType":"address"},{"type":"uint256","name":"referenceRateResetFrequency","internalType":"uint256"},{"type":"uint256","name":"minimumReports","internalType":"uint256"},{"type":"uint256","name":"stablePoolResetSize","internalType":"uint256"}]}]}],"name":"getPoolExchange","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","name":"initialize","inputs":[{"type":"address","name":"_broker","internalType":"address"},{"type":"address","name":"_reserve","internalType":"contract IReserve"},{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"},{"type":"address","name":"_breakerBox","internalType":"contract IBreakerBox"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"initialized","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pricingModules","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IReserve"}],"name":"reserve","inputs":[]},{"type":"function","stateMutability":"nonpayable","name":"setBreakerBox","inputs":[{"type":"address","name":"_breakerBox","internalType":"contract IBreakerBox"}]},{"type":"function","stateMutability":"nonpayable","name":"setBroker","inputs":[{"type":"address","name":"_broker","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"setPricingModules","inputs":[{"type":"bytes32[]","name":"identifiers","internalType":"bytes32[]"},{"type":"address[]","name":"modules","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","name":"setReserve","inputs":[{"type":"address","name":"_reserve","internalType":"contract IReserve"}]},{"type":"function","stateMutability":"nonpayable","name":"setSortedOracles","inputs":[{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ISortedOracles"}],"name":"sortedOracles","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"swapIn","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountIn","internalType":"uint256"}],"name":"swapOut","inputs":[{"type":"bytes32","name":"exchangeId","internalType":"bytes32"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenPrecisionMultipliers","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b5060405162004241380380620042418339810160408190526200003491620000cf565b808062000049576000805460ff191660011790555b5060006200005f6001600160e01b03620000b816565b60008054610100600160a81b0319166101006001600160a01b038416908102919091178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3505062000117565b3390565b8051620000c981620000fd565b92915050565b600060208284031215620000e257600080fd5b6000620000f08484620000bc565b949350505050565b151590565b6200010881620000f8565b81146200011457600080fd5b50565b61411a80620001276000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c8063abff011011610104578063d482dda6116100a2578063f2fde38b11610071578063f2fde38b146103cd578063f414c5e4146103e0578063f670dde1146103e8578063f8c8765e146103fb576101da565b8063d482dda61461036c578063dc162e3614610392578063e46eb5b6146103a7578063eaaba701146103ba576101da565b8063c0ad52d5116100de578063c0ad52d514610341578063cd3293de14610349578063cd8513ba14610351578063d3385d0514610359576101da565b8063abff011014610313578063b08986911461031b578063bf0d02131461032e576101da565b8063450154211161017c5780638da5cb5b1161014b5780638da5cb5b146102d05780638f32d59b146102e557806393c7e3bc146102ed5780639cecc80a14610300576101da565b8063450154211461028f57806345b2b467146102a25780634afb215e146102b5578063715018a6146102c8576101da565b80631e2e3a6b116101b85780631e2e3a6b14610227578063278488a41461023c57806338b1e9f71461025c57806342bfc99c1461027c576101da565b8063040bbd35146101df578063132e8aa7146101f4578063158ef93e14610212575b600080fd5b6101f26101ed366004612e82565b61040e565b005b6101fc6104cf565b6040516102099190613d62565b60405180910390f35b61021a6104de565b6040516102099190613d46565b61022f6104e7565b6040516102099190613d35565b61024f61024a366004612ddf565b6106b0565b6040516102099190613f61565b61026f61026a366004612ddf565b610793565b6040516102099190613d54565b61026f61028a366004612dfd565b6107b1565b6101f261029d366004612d17565b610939565b61026f6102b0366004612c98565b610a53565b6101f26102c3366004612e82565b610a65565b6101f2610b11565b6102d8610b9b565b6040516102099190613c88565b61021a610baf565b61026f6102fb366004612dfd565b610bd8565b6101f261030e366004612e82565b610c63565b6102d8610d0f565b61026f610329366004612ed5565b610d1e565b6101f261033c366004612c98565b6113b4565b61026f611460565b6101fc611488565b61026f611497565b61026f610367366004612dfd565b6114a6565b61037f61037a366004612ddf565b611621565b6040516102099796959493929190613c96565b61039a6116ad565b6040516102099190613d24565b61021a6103b5366004612e52565b611705565b6102d86103c8366004612ddf565b611a65565b6101f26103db366004612c98565b611a80565b6101fc611ab0565b61026f6103f6366004612dfd565b611abf565b6101f2610409366004612cb6565b611b3e565b610416610baf565b61043b5760405162461bcd60e51b815260040161043290613ea1565b60405180910390fd5b6001600160a01b0381166104615760405162461bcd60e51b815260040161043290613f21565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383161790556040517f21921b3b46ef2c939e85d6a14410c6e3b9ce132b66e944357ff4f789f68e00e2906104c4908390613c88565b60405180910390a150565b6006546001600160a01b031681565b60005460ff1681565b6003546040805182815260208084028201019091526060919081801561052757816020015b61051461296d565b81526020019060019003908161050c5790505b50915060005b818110156106ab576003818154811061054257fe5b906000526020600020015483828151811061055957fe5b60209081029190910101515260408051600280825260608201909252908160200160208202803883390190505083828151811061059257fe5b60200260200101516020018190525060026000600383815481106105b257fe5b9060005260206000200154815260200190815260200160002060000160009054906101000a90046001600160a01b03168382815181106105ee57fe5b60200260200101516020015160008151811061060657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600260006003838154811061063757fe5b9060005260206000200154815260200190815260200160002060010160009054906101000a90046001600160a01b031683828151811061067357fe5b60200260200101516020015160018151811061068b57fe5b6001600160a01b039092166020928302919091019091015260010161052d565b505090565b6106b8612985565b50600081815260026020818152604092839020835160e08101855281546001600160a01b03908116825260018301548116828501529382015484168186015260038201546060808301919091526004830154608080840191909152600584015460a080850191909152875160c08181018a5260068701549282019283529181526007860154881696810196909652600885015497860197909752600984015491850191909152600a90920154918301919091529283015281511661078e5760405162461bcd60e51b815260040161043290613ef1565b919050565b600381815481106107a057fe5b600091825260209091200154905081565b6001546000906001600160a01b031633146107de5760405162461bcd60e51b815260040161043290613e31565b6107e6612985565b6107ef866106b0565b60055460c0820151602001516040517fc0b05da00000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039092169163c0b05da09161084591600401613c88565b60206040518083038186803b15801561085d57600080fd5b505afa158015610871573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108959190810190612f61565b60ff16146108b55760405162461bcd60e51b815260040161043290613d81565b6001600160a01b0385166000908152600760205260408120546108df90859063ffffffff611bbf16565b90506000806108f084898986611c02565b9150915061090289858a868686611e0a565b6001600160a01b03871660009081526007602052604090205461092c90839063ffffffff611f2b16565b9998505050505050505050565b610941610baf565b61095d5760405162461bcd60e51b815260040161043290613ea1565b82811461097c5760405162461bcd60e51b815260040161043290613f51565b60005b83811015610a0f5782828281811061099357fe5b90506020020160206109a89190810190612c98565b600860008787858181106109b857fe5b6020908102929092013583525081019190915260400160002080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905560010161097f565b507f84557d458d60fcb29d9a10a8f28861c76847f7ef6450a9266a228a6f3a590baa84848484604051610a459493929190613cf3565b60405180910390a150505050565b60076020526000908152604090205481565b610a6d610baf565b610a895760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b038116610aaf5760405162461bcd60e51b815260040161043290613f01565b600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b610b19610baf565b610b355760405162461bcd60e51b815260040161043290613ea1565b600080546040516101009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b60005461010090046001600160a01b031690565b6000805461010090046001600160a01b0316610bc9611f6d565b6001600160a01b031614905090565b6000610be2612985565b610beb866106b0565b6001600160a01b03861660009081526007602052604081205491925090610c1990859063ffffffff611bbf16565b90506000610c2983888885611c02565b506001600160a01b038716600090815260076020526040902054909150610c5790829063ffffffff611f2b16565b98975050505050505050565b610c6b610baf565b610c875760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b038116610cad5760405162461bcd60e51b815260040161043290613f11565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f0b248ab246a87e452fbedee8dc12dfc53e3f3bfdc6920999062c56dea4ab522a90600090a250565b6001546001600160a01b031681565b6000610d28610baf565b610d445760405162461bcd60e51b815260040161043290613ea1565b610d4c612985565b610d5b36849003840184612ef4565b60408101519091506001600160a01b0316610d885760405162461bcd60e51b815260040161043290613e71565b80516001600160a01b0316610daf5760405162461bcd60e51b815260040161043290613dd1565b60208101516001600160a01b0316610dd95760405162461bcd60e51b815260040161043290613ec1565b80602001516001600160a01b031681600001516001600160a01b03161415610e135760405162461bcd60e51b815260040161043290613eb1565b80604001516001600160a01b031660086000610e2e84611f71565b81526020810191909152604001600020546001600160a01b031614610e655760405162461bcd60e51b815260040161043290613e91565b80600001516001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610ea257600080fd5b505afa158015610eb6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ede9190810190612ea0565b81602001516001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610f1b57600080fd5b505afa158015610f2f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f579190810190612ea0565b82604001516001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015610f9457600080fd5b505afa158015610fa8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fd09190810190612ea0565b604051602001610fe293929190613c4e565b60408051601f198184030181529181528151602092830120600081815260029093529120549092506001600160a01b0316156110305760405162461bcd60e51b815260040161043290613e01565b61103981612019565b60008061104583612289565b915091508183606001818152505080836080018181525050600083600001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561109c57600080fd5b505afa1580156110b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110d49190810190612f61565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561111857600080fd5b505afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111509190810190612f61565b60ff16905060128211156111765760405162461bcd60e51b815260040161043290613e11565b60128111156111975760405162461bcd60e51b815260040161043290613e51565b81601203600a0a6007600087600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555080601203600a0a6007600087602001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550846002600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160008201518160000160008201518160000155505060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002015560608201518160030155608082015181600401555050905050600386908060018154018082558091505090600182039060005260206000200160009091929091909150555084602001516001600160a01b031685600001516001600160a01b0316877fb374789237d43aed0f75b4c50a45793fd70e354bb96eecd573f35f5d509d78a188604001516040516113a29190613c88565b60405180910390a45050505050919050565b6113bc610baf565b6113d85760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b0381166113fe5760405162461bcd60e51b815260040161043290613f41565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f865dab7821134b6eb27cba259b40e33bbc1b898e970a535a18a83147f380a51f90600090a250565b60405160200161146f90613c7d565b6040516020818303038152906040528051906020012081565b6004546001600160a01b031681565b60405160200161146f90613c72565b6001546000906001600160a01b031633146114d35760405162461bcd60e51b815260040161043290613e31565b6114db612985565b6114e4866106b0565b60055460c0820151602001516040517fc0b05da00000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039092169163c0b05da09161153a91600401613c88565b60206040518083038186803b15801561155257600080fd5b505afa158015611566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061158a9190810190612f61565b60ff16146115aa5760405162461bcd60e51b815260040161043290613d81565b6001600160a01b0384166000908152600760205260408120546115d490859063ffffffff611bbf16565b90506000806115e5848989866122d9565b915091506115f789858a858786611e0a565b6001600160a01b03881660009081526007602052604090205461092c90839063ffffffff611f2b16565b6002602081815260009283526040928390208054600182015493820154600383015460048401546005850154885160c081018a52600687015460a08201908152815260078701546001600160a01b0390811698820198909852600887015499810199909952600986015460608a0152600a90950154608089015292851696958516959190941693929087565b606060038054806020026020016040519081016040528092919081815260200182805480156116fb57602002820191906000526020600020905b8154815260200190600101908083116116e7575b5050505050905090565b600061170f610baf565b61172b5760405162461bcd60e51b815260040161043290613ea1565b600354821061174c5760405162461bcd60e51b815260040161043290613de1565b826003838154811061175a57fe5b9060005260206000200154146117825760405162461bcd60e51b815260040161043290613ed1565b61178a612985565b600260008581526020019081526020016000206040518060e00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600382015481526020016004820154815260200160058201548152602001600682016040518060a00160405290816000820160405180602001604052908160008201548152505081526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600282015481526020016003820154815260200160048201548152505081525050905060026000858152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556001820160006101000a8154906001600160a01b0302191690556002820160006101000a8154906001600160a01b03021916905560038201600090556004820160009055600582016000905560068201600080820160008082016000905550506001820160006101000a8154906001600160a01b0302191690556002820160009055600382016000905560048201600090555050505060036119b360016003805490506123eb90919063ffffffff16565b815481106119bd57fe5b9060005260206000200154600384815481106119d557fe5b60009182526020909120015560038054806119ec57fe5b600190038181906000526020600020016000905590556001915080602001516001600160a01b031681600001516001600160a01b0316857fadbbec6c203cb0248e89fe6d15ad651061a9d5203a1ab0273256e2b7decffa898460400151604051611a569190613c88565b60405180910390a45092915050565b6008602052600090815260409020546001600160a01b031681565b611a88610baf565b611aa45760405162461bcd60e51b815260040161043290613ea1565b611aad8161242d565b50565b6005546001600160a01b031681565b6000611ac9612985565b611ad2866106b0565b6001600160a01b03851660009081526007602052604081205491925090611b0090859063ffffffff611bbf16565b90506000611b10838888856122d9565b506001600160a01b038816600090815260076020526040902054909150610c5790829063ffffffff611f2b16565b60005460ff1615611b615760405162461bcd60e51b815260040161043290613da1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611b953361242d565b611b9e846113b4565b611ba783610c63565b611bb082610a65565b611bb98161040e565b50505050565b600082611bce57506000611bfc565b82820282848281611bdb57fe5b0414611bf95760405162461bcd60e51b815260040161043290613e81565b90505b92915050565b60008084848780600001516001600160a01b0316836001600160a01b0316148015611c42575080602001516001600160a01b0316826001600160a01b0316145b80611c79575080602001516001600160a01b0316836001600160a01b0316148015611c79575080516001600160a01b038381169116145b611c955760405162461bcd60e51b815260040161043290613f31565b611c9e896124d0565b8151919a5094506001600160a01b0389811691161415611d5d5788604001516001600160a01b03166352707d8c8a606001518b60800151611ce68d60c0015160000151612508565b8a6040518563ffffffff1660e01b8152600401611d069493929190613f8b565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d569190810190612f13565b9450611dfe565b88604001516001600160a01b03166352707d8c8a608001518b60600151611d8b8d60c0015160000151612508565b8a6040518563ffffffff1660e01b8152600401611dab9493929190613f8b565b60206040518083038186803b158015611dc357600080fd5b505afa158015611dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611dfb9190810190612f13565b94505b50505094509492505050565b8015611e6e57426002600088815260200190815260200160002060050181905550857f949f5db193cbfa01f2d443b1c656bfede15497de0d86838cea089bd60c43834286606001518760800151604051611e65929190613f70565b60405180910390a25b611e778561250c565b15611eff5784516001600160a01b0385811691161415611eca576060850151611ea6908463ffffffff61254316565b60608601526080850151611ec0908363ffffffff6123eb16565b6080860152611eff565b6060850151611edf908363ffffffff6123eb16565b60608601526080850151611ef9908463ffffffff61254316565b60808601525b505050606082015160009384526002602052604090932060038101939093555060800151600490910155565b6000611bf983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612568565b3390565b600081604001516001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015611fb057600080fd5b505afa158015611fc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fec9190810190612ea0565b604051602001611ffc9190613c42565b604051602081830303815290604052805190602001209050919050565b6004805482516040517f4f8e6e230000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692634f8e6e2392612062929101613c88565b60206040518083038186803b15801561207a57600080fd5b505afa15801561208e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506120b29190810190612d87565b6120ce5760405162461bcd60e51b815260040161043290613d91565b6004805460208301516040517f4f8e6e230000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692634f8e6e239261211a929101613c88565b60206040518083038186803b15801561213257600080fd5b505afa158015612146573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061216a9190810190612d87565b8061220c57506004805460208301516040517fcae182fe0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169263cae182fe926121bc929101613c88565b60206040518083038186803b1580156121d457600080fd5b505afa1580156121e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061220c9190810190612d87565b6122285760405162461bcd60e51b815260040161043290613e21565b60c08101515161223f9061223a6125a1565b6125c5565b61225b5760405162461bcd60e51b815260040161043290613e61565b60c0810151602001516001600160a01b0316611aad5760405162461bcd60e51b815260040161043290613ee1565b6000808260c001516080015191506000806122ab8560c00151602001516125cd565b90925090506122d0826122c4838763ffffffff611bbf16565b9063ffffffff611f2b16565b92505050915091565b60008084848780600001516001600160a01b0316836001600160a01b0316148015612319575080602001516001600160a01b0316826001600160a01b0316145b80612350575080602001516001600160a01b0316836001600160a01b0316148015612350575080516001600160a01b038381169116145b61236c5760405162461bcd60e51b815260040161043290613f31565b612375896124d0565b8151919a5094506001600160a01b03898116911614156123bd5788604001516001600160a01b031663571fd0128a606001518b60800151611ce68d60c0015160000151612508565b88604001516001600160a01b031663571fd0128a608001518b60600151611d8b8d60c0015160000151612508565b6000611bf983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061268c565b6001600160a01b0381166124535760405162461bcd60e51b815260040161043290613db1565b600080546040516001600160a01b038085169361010090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b6124d8612985565b60006124e3836126b8565b156124ff576124f183612289565b608085015260608401525060015b8291505b915091565b5190565b600060405160200161251d90613c72565b6040516020818303038152906040528051906020012061253c83611f71565b1492915050565b600082820183811015611bf95760405162461bcd60e51b815260040161043290613df1565b600081836125895760405162461bcd60e51b81526004016104329190613d70565b50600083858161259557fe5b049150505b9392505050565b6125a96129e2565b50604080516020810190915269d3c21bcecceda1000000815290565b519051111590565b6006546040517fef90e1b000000000000000000000000000000000000000000000000000000000815260009182916001600160a01b039091169063ef90e1b09061261b908690600401613c88565b604080518083038186803b15801561263257600080fd5b505afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061266a9190810190612f31565b9092509050806125035760405162461bcd60e51b815260040161043290613e41565b600081848411156126b05760405162461bcd60e51b81526004016104329190613d70565b505050900390565b6000806126c483612729565b90506126cf8361295c565b156126f157806126f15760405162461bcd60e51b815260040161043290613dc1565b60006127128460c00151604001518560a0015161254390919063ffffffff16565b42101590508080156127215750815b949350505050565b60065460c0820151602001516040517fffe736bf00000000000000000000000000000000000000000000000000000000815260009283926001600160a01b039091169163ffe736bf9161277e91600401613c88565b604080518083038186803b15801561279557600080fd5b505afa1580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127cd9190810190612da5565b5060c084015160608101516006546020909201516040517fbbc66a9400000000000000000000000000000000000000000000000000000000815293945060009391926001600160a01b03169163bbc66a949161282b91600401613c88565b60206040518083038186803b15801561284357600080fd5b505afa158015612857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061287b9190810190612f13565b10159050600061289c8560c0015160400151426123eb90919063ffffffff16565b60065460c0870151602001516040517f071b48fc0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163071b48fc916128ec91600401613c88565b60206040518083038186803b15801561290457600080fd5b505afa158015612918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061293c9190810190612f13565b1190508215801561294a5750815b80156129535750805b95945050505050565b600060405160200161251d90613c7d565b60408051808201909152600081526060602082015290565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016129dd6129f5565b905290565b6040518060200160405280600081525090565b6040518060a00160405280612a086129e2565b815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8035611bfc8161409f565b8051611bfc8161409f565b60008083601f840112612a5b57600080fd5b50813567ffffffffffffffff811115612a7357600080fd5b602083019150836020820283011115612a8b57600080fd5b9250929050565b8051611bfc816140b3565b8035611bfc816140bc565b8035611bfc816140c5565b600082601f830112612ac457600080fd5b8151612ad7612ad282613fe7565b613fc0565b91508082526020830160208301858383011115612af357600080fd5b612afe838284614069565b50505092915050565b600060208284031215612b1957600080fd5b612b236020613fc0565b90506000612b318484612a9d565b82525092915050565b600060a08284031215612b4c57600080fd5b612b5660a0613fc0565b90506000612b648484612b07565b8252506020612b7584848301612a33565b6020830152506040612b8984828501612a9d565b6040830152506060612b9d84828501612a9d565b6060830152506080612bb184828501612a9d565b60808301525092915050565b60006101608284031215612bd057600080fd5b50919050565b60006101608284031215612be957600080fd5b612bf360e0613fc0565b90506000612c018484612a33565b8252506020612c1284848301612a33565b6020830152506040612c2684828501612aa8565b6040830152506060612c3a84828501612a9d565b6060830152506080612c4e84828501612a9d565b60808301525060a0612c6284828501612a9d565b60a08301525060c0612c7684828501612b3a565b60c08301525092915050565b8051611bfc816140bc565b8051611bfc816140ce565b600060208284031215612caa57600080fd5b60006127218484612a33565b60008060008060808587031215612ccc57600080fd5b6000612cd88787612a33565b9450506020612ce987828801612aa8565b9350506040612cfa87828801612aa8565b9250506060612d0b87828801612aa8565b91505092959194509250565b60008060008060408587031215612d2d57600080fd5b843567ffffffffffffffff811115612d4457600080fd5b612d5087828801612a49565b9450945050602085013567ffffffffffffffff811115612d6f57600080fd5b612d7b87828801612a49565b95989497509550505050565b600060208284031215612d9957600080fd5b60006127218484612a92565b60008060408385031215612db857600080fd5b6000612dc48585612a92565b9250506020612dd585828601612a3e565b9150509250929050565b600060208284031215612df157600080fd5b60006127218484612a9d565b60008060008060808587031215612e1357600080fd5b6000612e1f8787612a9d565b9450506020612e3087828801612a33565b9350506040612e4187828801612a33565b9250506060612d0b87828801612a9d565b60008060408385031215612e6557600080fd5b6000612e718585612a9d565b9250506020612dd585828601612a9d565b600060208284031215612e9457600080fd5b60006127218484612aa8565b600060208284031215612eb257600080fd5b815167ffffffffffffffff811115612ec957600080fd5b61272184828501612ab3565b60006101608284031215612ee857600080fd5b60006127218484612bbd565b60006101608284031215612f0757600080fd5b60006127218484612bd6565b600060208284031215612f2557600080fd5b60006127218484612c82565b60008060408385031215612f4457600080fd5b6000612f508585612c82565b9250506020612dd585828601612c82565b600060208284031215612f7357600080fd5b60006127218484612c8d565b6000612f8b8383612fab565b505060200190565b6000612f8b8383613177565b6000611bf98383613b24565b612fb481614030565b82525050565b6000612fc68385614018565b9350612fd18261400f565b8060005b8581101561300757612fe78284614021565b612ff18882612f7f565b9750612ffc83614012565b925050600101612fd5565b509495945050505050565b600061301d82612508565b6130278185614018565b935061303283614012565b8060005b8381101561300757815161304a8882612f7f565b975061305583614012565b925050600101613036565b600061306c8385614018565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561309b57600080fd5b6020830292506130ac83858461405d565b50500190565b60006130bd82612508565b6130c78185614018565b93506130d283614012565b8060005b838110156130075781516130ea8882612f93565b97506130f583614012565b9250506001016130d6565b600061310b82612508565b6131158185614018565b93508360208202850161312785614012565b8060005b8581101561316157848403895281516131448582612f9f565b945061314f83614012565b60209a909a019992505060010161312b565b5091979650505050505050565b612fb48161403b565b612fb48161400f565b612fb481614040565b600061319482612508565b61319e8185614018565b93506131ae818560208601614069565b6131b781614095565b9093019392505050565b60006131cc82612508565b6131d6818561078e565b93506131e6818560208601614069565b9290920192915050565b60006131fd602c83614018565b7f54726164696e672069732073757370656e64656420666f72207468697320726581527f666572656e636520726174650000000000000000000000000000000000000000602082015260400192915050565b600061325c603383614018565b7f617373657430206d757374206265206120737461626c6520726567697374657281527f6564207769746820746865207265736572766500000000000000000000000000602082015260400192915050565b60006132bb601c83614018565b7f636f6e747261637420616c726561647920696e697469616c697a656400000000815260200192915050565b60006132f4602683614018565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181527f6464726573730000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613353600f83614018565b7f6e6f2076616c6964206d656469616e0000000000000000000000000000000000815260200192915050565b600061338c601283614018565b7f617373657430206d757374206265207365740000000000000000000000000000815260200192915050565b60006133c5601c83614018565b7f65786368616e67654964496e646578206e6f7420696e2072616e676500000000815260200192915050565b60006133fe601b83614018565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000613437600f8361078e565b7f436f6e7374616e7450726f6475637400000000000000000000000000000000008152600f0192915050565b6000613470603983614018565b7f416e2065786368616e676520776974682074686520737065636966696564206181527f737365747320616e642065786368616e67652065786973747300000000000000602082015260400192915050565b60006134cf601d83614018565b7f61737365743020646563696d616c73206d757374206265203c3d203138000000815260200192915050565b6000613508602583614018565b7f617373657431206d757374206265206120737461626c65206f7220636f6c6c6181527f746572616c000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613567601883614018565b7f43616c6c6572206973206e6f74207468652042726f6b65720000000000000000815260200192915050565b60006135a0603083614018565b7f65786368616e676520726174652064656e6f6d696e61746f72206d757374206281527f652067726561746572207468616e203000000000000000000000000000000000602082015260400192915050565b60006135ff601d83614018565b7f61737365743120646563696d616c73206d757374206265203c3d203138000000815260200192915050565b6000613638602683614018565b7f737072656164206d757374206265206c657373207468616e206f72206571756181527f6c20746f20310000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613697601983614018565b7f70726963696e674d6f64756c65206d7573742062652073657400000000000000815260200192915050565b60006136d0602183614018565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b600061372f601583614018565b7f696e76616c69642070726963696e674d6f64756c650000000000000000000000815260200192915050565b6000613768602083614018565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572815260200192915050565b60006137a1602283614018565b7f65786368616e6765206173736574732063616e2774206265206964656e74696381527f616c000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613800601283614018565b7f617373657431206d757374206265207365740000000000000000000000000000815260200192915050565b6000613839600b8361078e565b7f436f6e7374616e7453756d0000000000000000000000000000000000000000008152600b0192915050565b6000613872602183614018565b7f65786368616e6765496420617420696e64657820646f65736e2774206d61746381527f6800000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006138d1601f83614018565b7f7265666572656e636552617465466565644944206d7573742062652073657400815260200192915050565b600061390a603083614018565b7f416e2065786368616e676520776974682074686520737065636966696564206981527f6420646f6573206e6f7420657869737400000000000000000000000000000000602082015260400192915050565b6000613969602183614018565b7f536f727465644f7261636c65732061646472657373206d75737420626520736581527f7400000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006139c8601b83614018565b7f526573657276652061646472657373206d757374206265207365740000000000815260200192915050565b6000613a01601e83614018565b7f427265616b6572426f782061646472657373206d757374206265207365740000815260200192915050565b6000613a3a602883614018565b7f746f6b656e496e20616e6420746f6b656e4f7574206d757374206d617463682081527f65786368616e6765000000000000000000000000000000000000000000000000602082015260400192915050565b6000613a99601a83614018565b7f42726f6b65722061646472657373206d75737420626520736574000000000000815260200192915050565b6000613ad2602f83614018565b7f6964656e7469666965727320616e64206d6f64756c6573206d7573742062652081527f7468652073616d65206c656e6774680000000000000000000000000000000000602082015260400192915050565b80516000906040840190613b388582613177565b50602083015184820360208601526129538282613012565b80516020830190611bb98482613177565b805160a0830190613b728482613b50565b506020820151613b856020850182612fab565b506040820151613b986040850182613177565b506060820151613bab6060850182613177565b506080820151611bb96080850182613177565b8051610160830190613bd08482612fab565b506020820151613be36020850182612fab565b506040820151613bf66040850182613180565b506060820151613c096060850182613177565b506080820151613c1c6080850182613177565b5060a0820151613c2f60a0850182613177565b5060c0820151611bb960c0850182613b61565b600061259a82846131c1565b6000613c5a82866131c1565b9150613c6682856131c1565b915061295382846131c1565b6000611bfc8261342a565b6000611bfc8261382c565b60208101611bfc8284612fab565b6101608101613ca5828a612fab565b613cb26020830189612fab565b613cbf6040830188613180565b613ccc6060830187613177565b613cd96080830186613177565b613ce660a0830185613177565b610c5760c0830184613b61565b60408082528101613d05818688613060565b90508181036020830152613d1a818486612fba565b9695505050505050565b60208082528101611bf981846130b2565b60208082528101611bf98184613100565b60208101611bfc828461316e565b60208101611bfc8284613177565b60208101611bfc8284613180565b60208082528101611bf98184613189565b60208082528101611bfc816131f0565b60208082528101611bfc8161324f565b60208082528101611bfc816132ae565b60208082528101611bfc816132e7565b60208082528101611bfc81613346565b60208082528101611bfc8161337f565b60208082528101611bfc816133b8565b60208082528101611bfc816133f1565b60208082528101611bfc81613463565b60208082528101611bfc816134c2565b60208082528101611bfc816134fb565b60208082528101611bfc8161355a565b60208082528101611bfc81613593565b60208082528101611bfc816135f2565b60208082528101611bfc8161362b565b60208082528101611bfc8161368a565b60208082528101611bfc816136c3565b60208082528101611bfc81613722565b60208082528101611bfc8161375b565b60208082528101611bfc81613794565b60208082528101611bfc816137f3565b60208082528101611bfc81613865565b60208082528101611bfc816138c4565b60208082528101611bfc816138fd565b60208082528101611bfc8161395c565b60208082528101611bfc816139bb565b60208082528101611bfc816139f4565b60208082528101611bfc81613a2d565b60208082528101611bfc81613a8c565b60208082528101611bfc81613ac5565b6101608101611bfc8284613bbe565b60408101613f7e8285613177565b61259a6020830184613177565b60808101613f998287613177565b613fa66020830186613177565b613fb36040830185613177565b6129536060830184613177565b60405181810167ffffffffffffffff81118282101715613fdf57600080fd5b604052919050565b600067ffffffffffffffff821115613ffe57600080fd5b506020601f91909101601f19160190565b90565b60200190565b90815260200190565b6000611bf96020840184612a33565b6000611bfc8261404b565b151590565b6000611bfc82614030565b6001600160a01b031690565b60ff1690565b82818337506000910152565b60005b8381101561408457818101518382015260200161406c565b83811115611bb95750506000910152565b601f01601f191690565b6140a881614030565b8114611aad57600080fd5b6140a88161403b565b6140a88161400f565b6140a881614040565b6140a88161405756fea365627a7a72315820cdf63629dbfa428892096c567b160d266a74d256ec25fe8464e6f60fbc748f356c6578706572696d656e74616cf564736f6c634300051100400000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c8063abff011011610104578063d482dda6116100a2578063f2fde38b11610071578063f2fde38b146103cd578063f414c5e4146103e0578063f670dde1146103e8578063f8c8765e146103fb576101da565b8063d482dda61461036c578063dc162e3614610392578063e46eb5b6146103a7578063eaaba701146103ba576101da565b8063c0ad52d5116100de578063c0ad52d514610341578063cd3293de14610349578063cd8513ba14610351578063d3385d0514610359576101da565b8063abff011014610313578063b08986911461031b578063bf0d02131461032e576101da565b8063450154211161017c5780638da5cb5b1161014b5780638da5cb5b146102d05780638f32d59b146102e557806393c7e3bc146102ed5780639cecc80a14610300576101da565b8063450154211461028f57806345b2b467146102a25780634afb215e146102b5578063715018a6146102c8576101da565b80631e2e3a6b116101b85780631e2e3a6b14610227578063278488a41461023c57806338b1e9f71461025c57806342bfc99c1461027c576101da565b8063040bbd35146101df578063132e8aa7146101f4578063158ef93e14610212575b600080fd5b6101f26101ed366004612e82565b61040e565b005b6101fc6104cf565b6040516102099190613d62565b60405180910390f35b61021a6104de565b6040516102099190613d46565b61022f6104e7565b6040516102099190613d35565b61024f61024a366004612ddf565b6106b0565b6040516102099190613f61565b61026f61026a366004612ddf565b610793565b6040516102099190613d54565b61026f61028a366004612dfd565b6107b1565b6101f261029d366004612d17565b610939565b61026f6102b0366004612c98565b610a53565b6101f26102c3366004612e82565b610a65565b6101f2610b11565b6102d8610b9b565b6040516102099190613c88565b61021a610baf565b61026f6102fb366004612dfd565b610bd8565b6101f261030e366004612e82565b610c63565b6102d8610d0f565b61026f610329366004612ed5565b610d1e565b6101f261033c366004612c98565b6113b4565b61026f611460565b6101fc611488565b61026f611497565b61026f610367366004612dfd565b6114a6565b61037f61037a366004612ddf565b611621565b6040516102099796959493929190613c96565b61039a6116ad565b6040516102099190613d24565b61021a6103b5366004612e52565b611705565b6102d86103c8366004612ddf565b611a65565b6101f26103db366004612c98565b611a80565b6101fc611ab0565b61026f6103f6366004612dfd565b611abf565b6101f2610409366004612cb6565b611b3e565b610416610baf565b61043b5760405162461bcd60e51b815260040161043290613ea1565b60405180910390fd5b6001600160a01b0381166104615760405162461bcd60e51b815260040161043290613f21565b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383161790556040517f21921b3b46ef2c939e85d6a14410c6e3b9ce132b66e944357ff4f789f68e00e2906104c4908390613c88565b60405180910390a150565b6006546001600160a01b031681565b60005460ff1681565b6003546040805182815260208084028201019091526060919081801561052757816020015b61051461296d565b81526020019060019003908161050c5790505b50915060005b818110156106ab576003818154811061054257fe5b906000526020600020015483828151811061055957fe5b60209081029190910101515260408051600280825260608201909252908160200160208202803883390190505083828151811061059257fe5b60200260200101516020018190525060026000600383815481106105b257fe5b9060005260206000200154815260200190815260200160002060000160009054906101000a90046001600160a01b03168382815181106105ee57fe5b60200260200101516020015160008151811061060657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600260006003838154811061063757fe5b9060005260206000200154815260200190815260200160002060010160009054906101000a90046001600160a01b031683828151811061067357fe5b60200260200101516020015160018151811061068b57fe5b6001600160a01b039092166020928302919091019091015260010161052d565b505090565b6106b8612985565b50600081815260026020818152604092839020835160e08101855281546001600160a01b03908116825260018301548116828501529382015484168186015260038201546060808301919091526004830154608080840191909152600584015460a080850191909152875160c08181018a5260068701549282019283529181526007860154881696810196909652600885015497860197909752600984015491850191909152600a90920154918301919091529283015281511661078e5760405162461bcd60e51b815260040161043290613ef1565b919050565b600381815481106107a057fe5b600091825260209091200154905081565b6001546000906001600160a01b031633146107de5760405162461bcd60e51b815260040161043290613e31565b6107e6612985565b6107ef866106b0565b60055460c0820151602001516040517fc0b05da00000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039092169163c0b05da09161084591600401613c88565b60206040518083038186803b15801561085d57600080fd5b505afa158015610871573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108959190810190612f61565b60ff16146108b55760405162461bcd60e51b815260040161043290613d81565b6001600160a01b0385166000908152600760205260408120546108df90859063ffffffff611bbf16565b90506000806108f084898986611c02565b9150915061090289858a868686611e0a565b6001600160a01b03871660009081526007602052604090205461092c90839063ffffffff611f2b16565b9998505050505050505050565b610941610baf565b61095d5760405162461bcd60e51b815260040161043290613ea1565b82811461097c5760405162461bcd60e51b815260040161043290613f51565b60005b83811015610a0f5782828281811061099357fe5b90506020020160206109a89190810190612c98565b600860008787858181106109b857fe5b6020908102929092013583525081019190915260400160002080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039290921691909117905560010161097f565b507f84557d458d60fcb29d9a10a8f28861c76847f7ef6450a9266a228a6f3a590baa84848484604051610a459493929190613cf3565b60405180910390a150505050565b60076020526000908152604090205481565b610a6d610baf565b610a895760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b038116610aaf5760405162461bcd60e51b815260040161043290613f01565b600680547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b610b19610baf565b610b355760405162461bcd60e51b815260040161043290613ea1565b600080546040516101009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b60005461010090046001600160a01b031690565b6000805461010090046001600160a01b0316610bc9611f6d565b6001600160a01b031614905090565b6000610be2612985565b610beb866106b0565b6001600160a01b03861660009081526007602052604081205491925090610c1990859063ffffffff611bbf16565b90506000610c2983888885611c02565b506001600160a01b038716600090815260076020526040902054909150610c5790829063ffffffff611f2b16565b98975050505050505050565b610c6b610baf565b610c875760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b038116610cad5760405162461bcd60e51b815260040161043290613f11565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f0b248ab246a87e452fbedee8dc12dfc53e3f3bfdc6920999062c56dea4ab522a90600090a250565b6001546001600160a01b031681565b6000610d28610baf565b610d445760405162461bcd60e51b815260040161043290613ea1565b610d4c612985565b610d5b36849003840184612ef4565b60408101519091506001600160a01b0316610d885760405162461bcd60e51b815260040161043290613e71565b80516001600160a01b0316610daf5760405162461bcd60e51b815260040161043290613dd1565b60208101516001600160a01b0316610dd95760405162461bcd60e51b815260040161043290613ec1565b80602001516001600160a01b031681600001516001600160a01b03161415610e135760405162461bcd60e51b815260040161043290613eb1565b80604001516001600160a01b031660086000610e2e84611f71565b81526020810191909152604001600020546001600160a01b031614610e655760405162461bcd60e51b815260040161043290613e91565b80600001516001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610ea257600080fd5b505afa158015610eb6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ede9190810190612ea0565b81602001516001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610f1b57600080fd5b505afa158015610f2f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f579190810190612ea0565b82604001516001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015610f9457600080fd5b505afa158015610fa8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fd09190810190612ea0565b604051602001610fe293929190613c4e565b60408051601f198184030181529181528151602092830120600081815260029093529120549092506001600160a01b0316156110305760405162461bcd60e51b815260040161043290613e01565b61103981612019565b60008061104583612289565b915091508183606001818152505080836080018181525050600083600001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561109c57600080fd5b505afa1580156110b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110d49190810190612f61565b60ff169050600084602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561111857600080fd5b505afa15801561112c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111509190810190612f61565b60ff16905060128211156111765760405162461bcd60e51b815260040161043290613e11565b60128111156111975760405162461bcd60e51b815260040161043290613e51565b81601203600a0a6007600087600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555080601203600a0a6007600087602001516001600160a01b03166001600160a01b0316815260200190815260200160002081905550846002600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550606082015181600301556080820151816004015560a0820151816005015560c08201518160060160008201518160000160008201518160000155505060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816002015560608201518160030155608082015181600401555050905050600386908060018154018082558091505090600182039060005260206000200160009091929091909150555084602001516001600160a01b031685600001516001600160a01b0316877fb374789237d43aed0f75b4c50a45793fd70e354bb96eecd573f35f5d509d78a188604001516040516113a29190613c88565b60405180910390a45050505050919050565b6113bc610baf565b6113d85760405162461bcd60e51b815260040161043290613ea1565b6001600160a01b0381166113fe5760405162461bcd60e51b815260040161043290613f41565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f865dab7821134b6eb27cba259b40e33bbc1b898e970a535a18a83147f380a51f90600090a250565b60405160200161146f90613c7d565b6040516020818303038152906040528051906020012081565b6004546001600160a01b031681565b60405160200161146f90613c72565b6001546000906001600160a01b031633146114d35760405162461bcd60e51b815260040161043290613e31565b6114db612985565b6114e4866106b0565b60055460c0820151602001516040517fc0b05da00000000000000000000000000000000000000000000000000000000081529293506000926001600160a01b039092169163c0b05da09161153a91600401613c88565b60206040518083038186803b15801561155257600080fd5b505afa158015611566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061158a9190810190612f61565b60ff16146115aa5760405162461bcd60e51b815260040161043290613d81565b6001600160a01b0384166000908152600760205260408120546115d490859063ffffffff611bbf16565b90506000806115e5848989866122d9565b915091506115f789858a858786611e0a565b6001600160a01b03881660009081526007602052604090205461092c90839063ffffffff611f2b16565b6002602081815260009283526040928390208054600182015493820154600383015460048401546005850154885160c081018a52600687015460a08201908152815260078701546001600160a01b0390811698820198909852600887015499810199909952600986015460608a0152600a90950154608089015292851696958516959190941693929087565b606060038054806020026020016040519081016040528092919081815260200182805480156116fb57602002820191906000526020600020905b8154815260200190600101908083116116e7575b5050505050905090565b600061170f610baf565b61172b5760405162461bcd60e51b815260040161043290613ea1565b600354821061174c5760405162461bcd60e51b815260040161043290613de1565b826003838154811061175a57fe5b9060005260206000200154146117825760405162461bcd60e51b815260040161043290613ed1565b61178a612985565b600260008581526020019081526020016000206040518060e00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600382015481526020016004820154815260200160058201548152602001600682016040518060a00160405290816000820160405180602001604052908160008201548152505081526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001600282015481526020016003820154815260200160048201548152505081525050905060026000858152602001908152602001600020600080820160006101000a8154906001600160a01b0302191690556001820160006101000a8154906001600160a01b0302191690556002820160006101000a8154906001600160a01b03021916905560038201600090556004820160009055600582016000905560068201600080820160008082016000905550506001820160006101000a8154906001600160a01b0302191690556002820160009055600382016000905560048201600090555050505060036119b360016003805490506123eb90919063ffffffff16565b815481106119bd57fe5b9060005260206000200154600384815481106119d557fe5b60009182526020909120015560038054806119ec57fe5b600190038181906000526020600020016000905590556001915080602001516001600160a01b031681600001516001600160a01b0316857fadbbec6c203cb0248e89fe6d15ad651061a9d5203a1ab0273256e2b7decffa898460400151604051611a569190613c88565b60405180910390a45092915050565b6008602052600090815260409020546001600160a01b031681565b611a88610baf565b611aa45760405162461bcd60e51b815260040161043290613ea1565b611aad8161242d565b50565b6005546001600160a01b031681565b6000611ac9612985565b611ad2866106b0565b6001600160a01b03851660009081526007602052604081205491925090611b0090859063ffffffff611bbf16565b90506000611b10838888856122d9565b506001600160a01b038816600090815260076020526040902054909150610c5790829063ffffffff611f2b16565b60005460ff1615611b615760405162461bcd60e51b815260040161043290613da1565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611b953361242d565b611b9e846113b4565b611ba783610c63565b611bb082610a65565b611bb98161040e565b50505050565b600082611bce57506000611bfc565b82820282848281611bdb57fe5b0414611bf95760405162461bcd60e51b815260040161043290613e81565b90505b92915050565b60008084848780600001516001600160a01b0316836001600160a01b0316148015611c42575080602001516001600160a01b0316826001600160a01b0316145b80611c79575080602001516001600160a01b0316836001600160a01b0316148015611c79575080516001600160a01b038381169116145b611c955760405162461bcd60e51b815260040161043290613f31565b611c9e896124d0565b8151919a5094506001600160a01b0389811691161415611d5d5788604001516001600160a01b03166352707d8c8a606001518b60800151611ce68d60c0015160000151612508565b8a6040518563ffffffff1660e01b8152600401611d069493929190613f8b565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d569190810190612f13565b9450611dfe565b88604001516001600160a01b03166352707d8c8a608001518b60600151611d8b8d60c0015160000151612508565b8a6040518563ffffffff1660e01b8152600401611dab9493929190613f8b565b60206040518083038186803b158015611dc357600080fd5b505afa158015611dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611dfb9190810190612f13565b94505b50505094509492505050565b8015611e6e57426002600088815260200190815260200160002060050181905550857f949f5db193cbfa01f2d443b1c656bfede15497de0d86838cea089bd60c43834286606001518760800151604051611e65929190613f70565b60405180910390a25b611e778561250c565b15611eff5784516001600160a01b0385811691161415611eca576060850151611ea6908463ffffffff61254316565b60608601526080850151611ec0908363ffffffff6123eb16565b6080860152611eff565b6060850151611edf908363ffffffff6123eb16565b60608601526080850151611ef9908463ffffffff61254316565b60808601525b505050606082015160009384526002602052604090932060038101939093555060800151600490910155565b6000611bf983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612568565b3390565b600081604001516001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015611fb057600080fd5b505afa158015611fc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fec9190810190612ea0565b604051602001611ffc9190613c42565b604051602081830303815290604052805190602001209050919050565b6004805482516040517f4f8e6e230000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692634f8e6e2392612062929101613c88565b60206040518083038186803b15801561207a57600080fd5b505afa15801561208e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506120b29190810190612d87565b6120ce5760405162461bcd60e51b815260040161043290613d91565b6004805460208301516040517f4f8e6e230000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692634f8e6e239261211a929101613c88565b60206040518083038186803b15801561213257600080fd5b505afa158015612146573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061216a9190810190612d87565b8061220c57506004805460208301516040517fcae182fe0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169263cae182fe926121bc929101613c88565b60206040518083038186803b1580156121d457600080fd5b505afa1580156121e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061220c9190810190612d87565b6122285760405162461bcd60e51b815260040161043290613e21565b60c08101515161223f9061223a6125a1565b6125c5565b61225b5760405162461bcd60e51b815260040161043290613e61565b60c0810151602001516001600160a01b0316611aad5760405162461bcd60e51b815260040161043290613ee1565b6000808260c001516080015191506000806122ab8560c00151602001516125cd565b90925090506122d0826122c4838763ffffffff611bbf16565b9063ffffffff611f2b16565b92505050915091565b60008084848780600001516001600160a01b0316836001600160a01b0316148015612319575080602001516001600160a01b0316826001600160a01b0316145b80612350575080602001516001600160a01b0316836001600160a01b0316148015612350575080516001600160a01b038381169116145b61236c5760405162461bcd60e51b815260040161043290613f31565b612375896124d0565b8151919a5094506001600160a01b03898116911614156123bd5788604001516001600160a01b031663571fd0128a606001518b60800151611ce68d60c0015160000151612508565b88604001516001600160a01b031663571fd0128a608001518b60600151611d8b8d60c0015160000151612508565b6000611bf983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061268c565b6001600160a01b0381166124535760405162461bcd60e51b815260040161043290613db1565b600080546040516001600160a01b038085169361010090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b6124d8612985565b60006124e3836126b8565b156124ff576124f183612289565b608085015260608401525060015b8291505b915091565b5190565b600060405160200161251d90613c72565b6040516020818303038152906040528051906020012061253c83611f71565b1492915050565b600082820183811015611bf95760405162461bcd60e51b815260040161043290613df1565b600081836125895760405162461bcd60e51b81526004016104329190613d70565b50600083858161259557fe5b049150505b9392505050565b6125a96129e2565b50604080516020810190915269d3c21bcecceda1000000815290565b519051111590565b6006546040517fef90e1b000000000000000000000000000000000000000000000000000000000815260009182916001600160a01b039091169063ef90e1b09061261b908690600401613c88565b604080518083038186803b15801561263257600080fd5b505afa158015612646573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061266a9190810190612f31565b9092509050806125035760405162461bcd60e51b815260040161043290613e41565b600081848411156126b05760405162461bcd60e51b81526004016104329190613d70565b505050900390565b6000806126c483612729565b90506126cf8361295c565b156126f157806126f15760405162461bcd60e51b815260040161043290613dc1565b60006127128460c00151604001518560a0015161254390919063ffffffff16565b42101590508080156127215750815b949350505050565b60065460c0820151602001516040517fffe736bf00000000000000000000000000000000000000000000000000000000815260009283926001600160a01b039091169163ffe736bf9161277e91600401613c88565b604080518083038186803b15801561279557600080fd5b505afa1580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127cd9190810190612da5565b5060c084015160608101516006546020909201516040517fbbc66a9400000000000000000000000000000000000000000000000000000000815293945060009391926001600160a01b03169163bbc66a949161282b91600401613c88565b60206040518083038186803b15801561284357600080fd5b505afa158015612857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061287b9190810190612f13565b10159050600061289c8560c0015160400151426123eb90919063ffffffff16565b60065460c0870151602001516040517f071b48fc0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169163071b48fc916128ec91600401613c88565b60206040518083038186803b15801561290457600080fd5b505afa158015612918573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061293c9190810190612f13565b1190508215801561294a5750815b80156129535750805b95945050505050565b600060405160200161251d90613c7d565b60408051808201909152600081526060602082015290565b6040518060e0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016129dd6129f5565b905290565b6040518060200160405280600081525090565b6040518060a00160405280612a086129e2565b815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8035611bfc8161409f565b8051611bfc8161409f565b60008083601f840112612a5b57600080fd5b50813567ffffffffffffffff811115612a7357600080fd5b602083019150836020820283011115612a8b57600080fd5b9250929050565b8051611bfc816140b3565b8035611bfc816140bc565b8035611bfc816140c5565b600082601f830112612ac457600080fd5b8151612ad7612ad282613fe7565b613fc0565b91508082526020830160208301858383011115612af357600080fd5b612afe838284614069565b50505092915050565b600060208284031215612b1957600080fd5b612b236020613fc0565b90506000612b318484612a9d565b82525092915050565b600060a08284031215612b4c57600080fd5b612b5660a0613fc0565b90506000612b648484612b07565b8252506020612b7584848301612a33565b6020830152506040612b8984828501612a9d565b6040830152506060612b9d84828501612a9d565b6060830152506080612bb184828501612a9d565b60808301525092915050565b60006101608284031215612bd057600080fd5b50919050565b60006101608284031215612be957600080fd5b612bf360e0613fc0565b90506000612c018484612a33565b8252506020612c1284848301612a33565b6020830152506040612c2684828501612aa8565b6040830152506060612c3a84828501612a9d565b6060830152506080612c4e84828501612a9d565b60808301525060a0612c6284828501612a9d565b60a08301525060c0612c7684828501612b3a565b60c08301525092915050565b8051611bfc816140bc565b8051611bfc816140ce565b600060208284031215612caa57600080fd5b60006127218484612a33565b60008060008060808587031215612ccc57600080fd5b6000612cd88787612a33565b9450506020612ce987828801612aa8565b9350506040612cfa87828801612aa8565b9250506060612d0b87828801612aa8565b91505092959194509250565b60008060008060408587031215612d2d57600080fd5b843567ffffffffffffffff811115612d4457600080fd5b612d5087828801612a49565b9450945050602085013567ffffffffffffffff811115612d6f57600080fd5b612d7b87828801612a49565b95989497509550505050565b600060208284031215612d9957600080fd5b60006127218484612a92565b60008060408385031215612db857600080fd5b6000612dc48585612a92565b9250506020612dd585828601612a3e565b9150509250929050565b600060208284031215612df157600080fd5b60006127218484612a9d565b60008060008060808587031215612e1357600080fd5b6000612e1f8787612a9d565b9450506020612e3087828801612a33565b9350506040612e4187828801612a33565b9250506060612d0b87828801612a9d565b60008060408385031215612e6557600080fd5b6000612e718585612a9d565b9250506020612dd585828601612a9d565b600060208284031215612e9457600080fd5b60006127218484612aa8565b600060208284031215612eb257600080fd5b815167ffffffffffffffff811115612ec957600080fd5b61272184828501612ab3565b60006101608284031215612ee857600080fd5b60006127218484612bbd565b60006101608284031215612f0757600080fd5b60006127218484612bd6565b600060208284031215612f2557600080fd5b60006127218484612c82565b60008060408385031215612f4457600080fd5b6000612f508585612c82565b9250506020612dd585828601612c82565b600060208284031215612f7357600080fd5b60006127218484612c8d565b6000612f8b8383612fab565b505060200190565b6000612f8b8383613177565b6000611bf98383613b24565b612fb481614030565b82525050565b6000612fc68385614018565b9350612fd18261400f565b8060005b8581101561300757612fe78284614021565b612ff18882612f7f565b9750612ffc83614012565b925050600101612fd5565b509495945050505050565b600061301d82612508565b6130278185614018565b935061303283614012565b8060005b8381101561300757815161304a8882612f7f565b975061305583614012565b925050600101613036565b600061306c8385614018565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561309b57600080fd5b6020830292506130ac83858461405d565b50500190565b60006130bd82612508565b6130c78185614018565b93506130d283614012565b8060005b838110156130075781516130ea8882612f93565b97506130f583614012565b9250506001016130d6565b600061310b82612508565b6131158185614018565b93508360208202850161312785614012565b8060005b8581101561316157848403895281516131448582612f9f565b945061314f83614012565b60209a909a019992505060010161312b565b5091979650505050505050565b612fb48161403b565b612fb48161400f565b612fb481614040565b600061319482612508565b61319e8185614018565b93506131ae818560208601614069565b6131b781614095565b9093019392505050565b60006131cc82612508565b6131d6818561078e565b93506131e6818560208601614069565b9290920192915050565b60006131fd602c83614018565b7f54726164696e672069732073757370656e64656420666f72207468697320726581527f666572656e636520726174650000000000000000000000000000000000000000602082015260400192915050565b600061325c603383614018565b7f617373657430206d757374206265206120737461626c6520726567697374657281527f6564207769746820746865207265736572766500000000000000000000000000602082015260400192915050565b60006132bb601c83614018565b7f636f6e747261637420616c726561647920696e697469616c697a656400000000815260200192915050565b60006132f4602683614018565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181527f6464726573730000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613353600f83614018565b7f6e6f2076616c6964206d656469616e0000000000000000000000000000000000815260200192915050565b600061338c601283614018565b7f617373657430206d757374206265207365740000000000000000000000000000815260200192915050565b60006133c5601c83614018565b7f65786368616e67654964496e646578206e6f7420696e2072616e676500000000815260200192915050565b60006133fe601b83614018565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000613437600f8361078e565b7f436f6e7374616e7450726f6475637400000000000000000000000000000000008152600f0192915050565b6000613470603983614018565b7f416e2065786368616e676520776974682074686520737065636966696564206181527f737365747320616e642065786368616e67652065786973747300000000000000602082015260400192915050565b60006134cf601d83614018565b7f61737365743020646563696d616c73206d757374206265203c3d203138000000815260200192915050565b6000613508602583614018565b7f617373657431206d757374206265206120737461626c65206f7220636f6c6c6181527f746572616c000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613567601883614018565b7f43616c6c6572206973206e6f74207468652042726f6b65720000000000000000815260200192915050565b60006135a0603083614018565b7f65786368616e676520726174652064656e6f6d696e61746f72206d757374206281527f652067726561746572207468616e203000000000000000000000000000000000602082015260400192915050565b60006135ff601d83614018565b7f61737365743120646563696d616c73206d757374206265203c3d203138000000815260200192915050565b6000613638602683614018565b7f737072656164206d757374206265206c657373207468616e206f72206571756181527f6c20746f20310000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613697601983614018565b7f70726963696e674d6f64756c65206d7573742062652073657400000000000000815260200192915050565b60006136d0602183614018565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b600061372f601583614018565b7f696e76616c69642070726963696e674d6f64756c650000000000000000000000815260200192915050565b6000613768602083614018565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572815260200192915050565b60006137a1602283614018565b7f65786368616e6765206173736574732063616e2774206265206964656e74696381527f616c000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613800601283614018565b7f617373657431206d757374206265207365740000000000000000000000000000815260200192915050565b6000613839600b8361078e565b7f436f6e7374616e7453756d0000000000000000000000000000000000000000008152600b0192915050565b6000613872602183614018565b7f65786368616e6765496420617420696e64657820646f65736e2774206d61746381527f6800000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006138d1601f83614018565b7f7265666572656e636552617465466565644944206d7573742062652073657400815260200192915050565b600061390a603083614018565b7f416e2065786368616e676520776974682074686520737065636966696564206981527f6420646f6573206e6f7420657869737400000000000000000000000000000000602082015260400192915050565b6000613969602183614018565b7f536f727465644f7261636c65732061646472657373206d75737420626520736581527f7400000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006139c8601b83614018565b7f526573657276652061646472657373206d757374206265207365740000000000815260200192915050565b6000613a01601e83614018565b7f427265616b6572426f782061646472657373206d757374206265207365740000815260200192915050565b6000613a3a602883614018565b7f746f6b656e496e20616e6420746f6b656e4f7574206d757374206d617463682081527f65786368616e6765000000000000000000000000000000000000000000000000602082015260400192915050565b6000613a99601a83614018565b7f42726f6b65722061646472657373206d75737420626520736574000000000000815260200192915050565b6000613ad2602f83614018565b7f6964656e7469666965727320616e64206d6f64756c6573206d7573742062652081527f7468652073616d65206c656e6774680000000000000000000000000000000000602082015260400192915050565b80516000906040840190613b388582613177565b50602083015184820360208601526129538282613012565b80516020830190611bb98482613177565b805160a0830190613b728482613b50565b506020820151613b856020850182612fab565b506040820151613b986040850182613177565b506060820151613bab6060850182613177565b506080820151611bb96080850182613177565b8051610160830190613bd08482612fab565b506020820151613be36020850182612fab565b506040820151613bf66040850182613180565b506060820151613c096060850182613177565b506080820151613c1c6080850182613177565b5060a0820151613c2f60a0850182613177565b5060c0820151611bb960c0850182613b61565b600061259a82846131c1565b6000613c5a82866131c1565b9150613c6682856131c1565b915061295382846131c1565b6000611bfc8261342a565b6000611bfc8261382c565b60208101611bfc8284612fab565b6101608101613ca5828a612fab565b613cb26020830189612fab565b613cbf6040830188613180565b613ccc6060830187613177565b613cd96080830186613177565b613ce660a0830185613177565b610c5760c0830184613b61565b60408082528101613d05818688613060565b90508181036020830152613d1a818486612fba565b9695505050505050565b60208082528101611bf981846130b2565b60208082528101611bf98184613100565b60208101611bfc828461316e565b60208101611bfc8284613177565b60208101611bfc8284613180565b60208082528101611bf98184613189565b60208082528101611bfc816131f0565b60208082528101611bfc8161324f565b60208082528101611bfc816132ae565b60208082528101611bfc816132e7565b60208082528101611bfc81613346565b60208082528101611bfc8161337f565b60208082528101611bfc816133b8565b60208082528101611bfc816133f1565b60208082528101611bfc81613463565b60208082528101611bfc816134c2565b60208082528101611bfc816134fb565b60208082528101611bfc8161355a565b60208082528101611bfc81613593565b60208082528101611bfc816135f2565b60208082528101611bfc8161362b565b60208082528101611bfc8161368a565b60208082528101611bfc816136c3565b60208082528101611bfc81613722565b60208082528101611bfc8161375b565b60208082528101611bfc81613794565b60208082528101611bfc816137f3565b60208082528101611bfc81613865565b60208082528101611bfc816138c4565b60208082528101611bfc816138fd565b60208082528101611bfc8161395c565b60208082528101611bfc816139bb565b60208082528101611bfc816139f4565b60208082528101611bfc81613a2d565b60208082528101611bfc81613a8c565b60208082528101611bfc81613ac5565b6101608101611bfc8284613bbe565b60408101613f7e8285613177565b61259a6020830184613177565b60808101613f998287613177565b613fa66020830186613177565b613fb36040830185613177565b6129536060830184613177565b60405181810167ffffffffffffffff81118282101715613fdf57600080fd5b604052919050565b600067ffffffffffffffff821115613ffe57600080fd5b506020601f91909101601f19160190565b90565b60200190565b90815260200190565b6000611bf96020840184612a33565b6000611bfc8261404b565b151590565b6000611bfc82614030565b6001600160a01b031690565b60ff1690565b82818337506000910152565b60005b8381101561408457818101518382015260200161406c565b83811115611bb95750506000910152565b601f01601f191690565b6140a881614030565b8114611aad57600080fd5b6140a88161403b565b6140a88161400f565b6140a881614040565b6140a88161405756fea365627a7a72315820cdf63629dbfa428892096c567b160d266a74d256ec25fe8464e6f60fbc748f356c6578706572696d656e74616cf564736f6c63430005110040

External libraries

AddressLinkedList : 0x3e2cc57f83093ce1ee03482c1590e3b5f4225bd7  
AddressSortedLinkedListWithMedian : 0x99edce8143ff8aefa1fbb6c2103b349add2b9519