FRAX Price: $0.82 (-18.88%)

Contract

0xe7C6385Cf5d4Ea61774A56E3aeaf60a09fC8E1d5

Overview

FRAX Balance | FXTL Balance

0 FRAX | 899,522 FXTL

FRAX Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Add Round Data S...160740112025-02-07 20:05:33352 days ago1738958733IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000009810.00099999
Add Round Data S...160739672025-02-07 20:04:05352 days ago1738958645IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000009070.00099999
Add Round Data S...160739192025-02-07 20:02:29352 days ago1738958549IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000008220.00099999
Add Round Data S...160738882025-02-07 20:01:27352 days ago1738958487IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000007130.00099999
Add Round Data S...160738672025-02-07 20:00:45352 days ago1738958445IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000006650.00099999
Add Round Data S...160738552025-02-07 20:00:21352 days ago1738958421IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000006880.00099999
Add Round Data S...160738492025-02-07 20:00:09352 days ago1738958409IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000006790.00099999
Add Round Data S...160049992025-02-06 5:45:09353 days ago1738820709IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000006870.00099999
Add Round Data S...159948002025-02-06 0:05:11353 days ago1738800311IN
0xe7C6385C...09fC8E1d5
0 FRAX0.00001140.00099999
Add Round Data S...159511492025-02-04 23:50:09354 days ago1738713009IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000007960.00099999
Add Round Data S...158914492025-02-03 14:40:09356 days ago1738593609IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000154550.00099999
Add Round Data S...157700992025-01-31 19:15:09359 days ago1738350909IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000036130.00099999
Add Round Data S...156923992025-01-30 0:05:09360 days ago1738195509IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000017610.00099999
Add Round Data S...156847492025-01-29 19:50:09361 days ago1738180209IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000066350.00099999
Add Round Data S...156106492025-01-28 2:40:09362 days ago1738032009IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000023250.00099999
Add Round Data S...155476492025-01-26 15:40:09364 days ago1737906009IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000049380.00099999
Add Round Data S...154738492025-01-24 22:40:09365 days ago1737758409IN
0xe7C6385C...09fC8E1d5
0 FRAX0.00004290.00099999
Add Round Data S...153900062025-01-23 0:05:23367 days ago1737590723IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000034660.00099999
Add Round Data S...153685562025-01-22 12:10:23368 days ago1737547823IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000043480.00099999
Add Round Data S...153048052025-01-21 0:45:21369 days ago1737420321IN
0xe7C6385C...09fC8E1d5
0 FRAX0.00006520.00099999
Add Round Data S...152256072025-01-19 4:45:25371 days ago1737261925IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000063570.00099999
Add Round Data S...151662032025-01-17 19:45:17373 days ago1737143117IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000052790.00099999
Add Round Data S...150876042025-01-16 0:05:19374 days ago1736985919IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000032230.00099999
Add Round Data S...150240042025-01-14 12:45:19376 days ago1736858719IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000035920.00099999
Add Round Data S...149514032025-01-12 20:25:17378 days ago1736713517IN
0xe7C6385C...09fC8E1d5
0 FRAX0.000011650.00099999
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
160740112025-02-07 20:05:33352 days ago1738958733
0xe7C6385C...09fC8E1d5
0 FRAX
160740112025-02-07 20:05:33352 days ago1738958733
0xe7C6385C...09fC8E1d5
0 FRAX
160739672025-02-07 20:04:05352 days ago1738958645
0xe7C6385C...09fC8E1d5
0 FRAX
160739672025-02-07 20:04:05352 days ago1738958645
0xe7C6385C...09fC8E1d5
0 FRAX
160739192025-02-07 20:02:29352 days ago1738958549
0xe7C6385C...09fC8E1d5
0 FRAX
160739192025-02-07 20:02:29352 days ago1738958549
0xe7C6385C...09fC8E1d5
0 FRAX
160738882025-02-07 20:01:27352 days ago1738958487
0xe7C6385C...09fC8E1d5
0 FRAX
160738882025-02-07 20:01:27352 days ago1738958487
0xe7C6385C...09fC8E1d5
0 FRAX
160738672025-02-07 20:00:45352 days ago1738958445
0xe7C6385C...09fC8E1d5
0 FRAX
160738672025-02-07 20:00:45352 days ago1738958445
0xe7C6385C...09fC8E1d5
0 FRAX
160738552025-02-07 20:00:21352 days ago1738958421
0xe7C6385C...09fC8E1d5
0 FRAX
160738552025-02-07 20:00:21352 days ago1738958421
0xe7C6385C...09fC8E1d5
0 FRAX
160738492025-02-07 20:00:09352 days ago1738958409
0xe7C6385C...09fC8E1d5
0 FRAX
160738492025-02-07 20:00:09352 days ago1738958409
0xe7C6385C...09fC8E1d5
0 FRAX
160049992025-02-06 5:45:09353 days ago1738820709
0xe7C6385C...09fC8E1d5
0 FRAX
160049992025-02-06 5:45:09353 days ago1738820709
0xe7C6385C...09fC8E1d5
0 FRAX
159948002025-02-06 0:05:11353 days ago1738800311
0xe7C6385C...09fC8E1d5
0 FRAX
159948002025-02-06 0:05:11353 days ago1738800311
0xe7C6385C...09fC8E1d5
0 FRAX
159511492025-02-04 23:50:09354 days ago1738713009
0xe7C6385C...09fC8E1d5
0 FRAX
159511492025-02-04 23:50:09354 days ago1738713009
0xe7C6385C...09fC8E1d5
0 FRAX
158914492025-02-03 14:40:09356 days ago1738593609
0xe7C6385C...09fC8E1d5
0 FRAX
158914492025-02-03 14:40:09356 days ago1738593609
0xe7C6385C...09fC8E1d5
0 FRAX
157700992025-01-31 19:15:09359 days ago1738350909
0xe7C6385C...09fC8E1d5
0 FRAX
157700992025-01-31 19:15:09359 days ago1738350909
0xe7C6385C...09fC8E1d5
0 FRAX
156923992025-01-30 0:05:09360 days ago1738195509
0xe7C6385C...09fC8E1d5
0 FRAX
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MerkleProofPriceSourceSfrax

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: ISC
pragma solidity ^0.8.19;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ====================== MerkleProofSfrax ============================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// ====================================================================
import { ERC165Storage } from "src/contracts/utils/ERC165Storage.sol";
import { Timelock2Step } from "frax-std/access-control/v1/Timelock2Step.sol";
import { ITimelock2Step } from "frax-std/access-control/v1/interfaces/ITimelock2Step.sol";
import { MerkleTreeProver } from "./lib/MerkleTreeProver.sol";
import { StateProofVerifier as Verifier } from "./lib/StateProofVerifier.sol";
import { IERC4626Receiver } from "src/contracts/interfaces/IERC4626Receiver.sol";
import { IStateRootOracle } from "./interfaces/IStateRootOracle.sol";
import { FixedPointMathLib } from "@solmate/utils/FixedPointMathLib.sol";

import "node_modules/forge-std/src/console.sol";

/// @title MerkleProofPriceSource
/// @author Jon Walch (Frax Finance) https://github.com/jonwalch
/// @notice Proves price round data from an L1 Frax Oracle and pushes the price data to an L2 Frax Oracle
contract MerkleProofPriceSourceSfrax is ERC165Storage, Timelock2Step {
    /// @notice The address of the StateRootOracle on Layer 2
    IStateRootOracle public immutable STATE_ROOT_ORACLE;

    using FixedPointMathLib for uint256;

    struct OracleConfig {
        address layer1Oracle;
        uint96 lastBlockProofed;
    }

    struct PoofPackedsFrax {
        bytes[] _accountProofSfrax;
        bytes[] _storageProofTotalSupply;
        bytes[] _storageProofTotalAssets;
        bytes[] _storageProofLastDist;
        bytes[] _storageProofRewardsPacked;
        bytes[] _storageProofRewardsCycleAmount;
    }

    /// @notice Information about the current rewards cycle
    struct RewardsCycleData {
        uint40 cycleEnd; // Timestamp of the end of the current rewards cycle
        uint40 lastSync; // Timestamp of the last time the rewards cycle was synced
        uint216 rewardCycleAmount; // Amount of rewards to be distributed in the current cycle
    }

    /// @notice Configuration linking Frax Oracles for the same asset on L1 / L2
    mapping(address layer2FraxOracle => OracleConfig layer1Config) public oracleLookup;

    /// @notice The ```constructor``` function
    /// @param _stateRootOracle Address of the L2 StateRootOracle
    /// @param _timelockAddress Address of Timelock contract on L2
    constructor(address _stateRootOracle, address _timelockAddress) Timelock2Step() {
        _setTimelock({ _newTimelock: _timelockAddress });
        _registerInterface({ interfaceId: type(ITimelock2Step).interfaceId });

        STATE_ROOT_ORACLE = IStateRootOracle(_stateRootOracle);
    }

    // ====================================================================
    // Events
    // ====================================================================

    /// @notice The ```OraclePairAdded``` event is emitted when a new Frax Oracle pair is added
    /// @param fraxOracleLayer1 The address of the layer 1 Frax Oracle
    /// @param fraxOracleLayer2 The address of the layer 2 Frax Oracle
    event OraclePairAdded(address indexed fraxOracleLayer1, address indexed fraxOracleLayer2);

    // ====================================================================
    // Configuration Setters
    // ====================================================================

    /// @dev A pair of addresses that are the Frax Oracles for the same asset on layer 1 and layer 2
    struct OraclePair {
        address layer1FraxOracle;
        address layer2FraxOracle;
    }

    /// @notice The ```addOraclePairs``` function sets an L1/L2 pair if they haven't been set already
    /// @param _oraclePairs List of OraclePairs representing the same oracle on L1 and L2
    function addOraclePairs(OraclePair[] calldata _oraclePairs) external {
        _requireTimelock();

        for (uint256 i = 0; i < _oraclePairs.length; ++i) {
            OraclePair memory _oraclePair = _oraclePairs[i];
            if (oracleLookup[_oraclePair.layer2FraxOracle].layer1Oracle != address(0)) {
                revert OraclePairAlreadySet({
                    fraxOracleLayer1: oracleLookup[_oraclePair.layer2FraxOracle].layer1Oracle,
                    fraxOracleLayer2: _oraclePair.layer2FraxOracle
                });
            }
            oracleLookup[_oraclePair.layer2FraxOracle].layer1Oracle = _oraclePair.layer1FraxOracle;
            emit OraclePairAdded({
                fraxOracleLayer1: _oraclePair.layer1FraxOracle,
                fraxOracleLayer2: _oraclePair.layer2FraxOracle
            });
        }
    }

    // ====================================================================
    // Proof / Add Price Function
    // ====================================================================
    function _fetchAndProofMaxRewards(
        address _sFraxAddress,
        uint96 _blockNumber,
        bytes[] memory _accountProofSfrax,
        bytes[] memory _storageProofMaxDistPerSecond
    ) public view returns (uint256 maxDistributionPerSecond) {
        IStateRootOracle.BlockInfo memory _blockInfo = STATE_ROOT_ORACLE.getBlockInfo(_blockNumber);
        Verifier.Account memory accountProofSfrax = MerkleTreeProver.proveStorageRoot({
            stateRootHash: _blockInfo.stateRootHash,
            proofAddress: _sFraxAddress,
            accountProof: _accountProofSfrax
        });
        maxDistributionPerSecond = uint256(
            MerkleTreeProver
                .proveStorageSlotValue({
                    storageRootHash: accountProofSfrax.storageRoot,
                    slot: bytes32(uint256(12)),
                    storageProof: _storageProofMaxDistPerSecond
                })
                .value
        );
        if (maxDistributionPerSecond == 0) revert MustBeGtZero();
    }

    function _fetchAndProofSfrax(
        address _sfraxEthAddress,
        uint96 _blockNumber,
        PoofPackedsFrax memory proofPacked
    )
        internal
        view
        returns (
            uint256 totalSupply,
            uint256 totalAssets,
            uint256 lastRewardsDistribution,
            IERC4626Receiver.RewardsCycleData memory data
        )
    {
        data = IERC4626Receiver.RewardsCycleData(0, 0, 0);
        IStateRootOracle.BlockInfo memory _blockInfo = STATE_ROOT_ORACLE.getBlockInfo(_blockNumber);
        Verifier.Account memory _accountProofSfrax = MerkleTreeProver.proveStorageRoot({
            stateRootHash: _blockInfo.stateRootHash,
            proofAddress: _sfraxEthAddress,
            accountProof: proofPacked._accountProofSfrax
        });
        totalSupply = uint256(
            MerkleTreeProver
                .proveStorageSlotValue({
                    storageRootHash: _accountProofSfrax.storageRoot,
                    slot: bytes32(uint256(2)),
                    storageProof: proofPacked._storageProofTotalSupply
                })
                .value
        );
        totalAssets = uint256(
            MerkleTreeProver
                .proveStorageSlotValue({
                    storageRootHash: _accountProofSfrax.storageRoot,
                    slot: bytes32(uint256(9)),
                    storageProof: proofPacked._storageProofTotalAssets
                })
                .value
        );
        lastRewardsDistribution = uint256(
            MerkleTreeProver
                .proveStorageSlotValue({
                    storageRootHash: _accountProofSfrax.storageRoot,
                    slot: bytes32(uint256(8)),
                    storageProof: proofPacked._storageProofLastDist
                })
                .value
        );
        {
            uint256 rewardsPacked = uint256(
                MerkleTreeProver
                    .proveStorageSlotValue({
                        storageRootHash: _accountProofSfrax.storageRoot,
                        slot: bytes32(uint256(6)),
                        storageProof: proofPacked._storageProofRewardsPacked
                    })
                    .value
            );
            uint256 rewardCycleAmount = uint256(
                MerkleTreeProver
                    .proveStorageSlotValue({
                        storageRootHash: _accountProofSfrax.storageRoot,
                        slot: bytes32(uint256(7)),
                        storageProof: proofPacked._storageProofRewardsCycleAmount
                    })
                    .value
            );
            data.lastSync = uint40(bytes5(bytes32(rewardsPacked) << 176));
            data.cycleEnd = uint40(bytes5(bytes32(rewardsPacked) << 216));
            data.rewardCycleAmount = uint216(bytes27(bytes32(rewardCycleAmount) << 40));
        }
        if (totalSupply == 0) revert MustBeGtZero();
        if (data.lastSync == 0) revert MustBeGtZero();
        if (totalAssets == 0) revert MustBeGtZero();
    }

    function addMaxDistributionPerSecond(
        IERC4626Receiver _sFraxOracle,
        uint96 _blockNumber,
        bytes[] memory _accountProofSfrax,
        bytes[] memory _storageProofMaxDistPerSecond
    ) external {
        uint96 lastBlockProofed = oracleLookup[address(_sFraxOracle)].lastBlockProofed;
        if (lastBlockProofed != 0) {
            if (_blockNumber < lastBlockProofed) revert StalePush();
        }
        // Address of the L1 oracle
        address _proofAddress = oracleLookup[address(_sFraxOracle)].layer1Oracle;
        if (_proofAddress == address(0)) revert WrongOracleAddress();
        uint256 maxPerSecond = _fetchAndProofMaxRewards(
            _proofAddress,
            _blockNumber,
            _accountProofSfrax,
            _storageProofMaxDistPerSecond
        );
        _sFraxOracle.updateMaxDistributionPerSecond(_blockNumber, maxPerSecond);
    }

    function addRoundDataSfrax(
        IERC4626Receiver _sFraxOracle,
        uint96 _blockNumber,
        PoofPackedsFrax memory proof
    ) external {
        uint96 lastBlockProofed = oracleLookup[address(_sFraxOracle)].lastBlockProofed;
        address _proofAddress;
        {
            if (lastBlockProofed != 0) {
                if (_blockNumber < lastBlockProofed) revert StalePush();
            }
            // Address of the L1 oracle
            _proofAddress = oracleLookup[address(_sFraxOracle)].layer1Oracle;
            if (_proofAddress == address(0)) revert WrongOracleAddress();
        }
        (
            uint256 totalSupply,
            uint256 totalStoredAssets,
            uint256 lastRewardsDistribution,
            IERC4626Receiver.RewardsCycleData memory data
        ) = _fetchAndProofSfrax(_proofAddress, _blockNumber, proof);
        _sFraxOracle.updatesFRAXData(_blockNumber, totalSupply, totalStoredAssets, lastRewardsDistribution, data);
        oracleLookup[address(_sFraxOracle)].lastBlockProofed = _blockNumber;
    }

    // ====================================================================
    // Errors
    // ====================================================================

    error OraclePairAlreadySet(address fraxOracleLayer1, address fraxOracleLayer2);
    error WrongOracleAddress();
    error StalePush();
    error MustBeGtZero();
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol)
pragma solidity ^0.8.0;

import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * @dev Storage based implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165Storage is ERC165 {
    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// SPDX-License-Identifier: ISC
pragma solidity >=0.8.0;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================== Timelock2Step ===========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Primary Author
// Drake Evans: https://github.com/DrakeEvans

// Reviewers
// Dennis: https://github.com/denett

// ====================================================================

/// @title Timelock2Step
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @dev Inspired by the OpenZeppelin's Ownable2Step contract
/// @notice  An abstract contract which contains 2-step transfer and renounce logic for a timelock address
abstract contract Timelock2Step {
    /// @notice The pending timelock address
    address public pendingTimelockAddress;

    /// @notice The current timelock address
    address public timelockAddress;

    constructor() {
        timelockAddress = msg.sender;
    }

    /// @notice Emitted when timelock is transferred
    error OnlyTimelock();

    /// @notice Emitted when pending timelock is transferred
    error OnlyPendingTimelock();

    /// @notice The ```TimelockTransferStarted``` event is emitted when the timelock transfer is initiated
    /// @param previousTimelock The address of the previous timelock
    /// @param newTimelock The address of the new timelock
    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);

    /// @notice The ```TimelockTransferred``` event is emitted when the timelock transfer is completed
    /// @param previousTimelock The address of the previous timelock
    /// @param newTimelock The address of the new timelock
    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);

    /// @notice The ```_isSenderTimelock``` function checks if msg.sender is current timelock address
    /// @return Whether or not msg.sender is current timelock address
    function _isSenderTimelock() internal view returns (bool) {
        return msg.sender == timelockAddress;
    }

    /// @notice The ```_requireTimelock``` function reverts if msg.sender is not current timelock address
    function _requireTimelock() internal view {
        if (msg.sender != timelockAddress) revert OnlyTimelock();
    }

    /// @notice The ```_isSenderPendingTimelock``` function checks if msg.sender is pending timelock address
    /// @return Whether or not msg.sender is pending timelock address
    function _isSenderPendingTimelock() internal view returns (bool) {
        return msg.sender == pendingTimelockAddress;
    }

    /// @notice The ```_requirePendingTimelock``` function reverts if msg.sender is not pending timelock address
    function _requirePendingTimelock() internal view {
        if (msg.sender != pendingTimelockAddress) revert OnlyPendingTimelock();
    }

    /// @notice The ```_transferTimelock``` function initiates the timelock transfer
    /// @dev This function is to be implemented by a public function
    /// @param _newTimelock The address of the nominated (pending) timelock
    function _transferTimelock(address _newTimelock) internal {
        pendingTimelockAddress = _newTimelock;
        emit TimelockTransferStarted(timelockAddress, _newTimelock);
    }

    /// @notice The ```_acceptTransferTimelock``` function completes the timelock transfer
    /// @dev This function is to be implemented by a public function
    function _acceptTransferTimelock() internal {
        pendingTimelockAddress = address(0);
        _setTimelock(msg.sender);
    }

    /// @notice The ```_setTimelock``` function sets the timelock address
    /// @dev This function is to be implemented by a public function
    /// @param _newTimelock The address of the new timelock
    function _setTimelock(address _newTimelock) internal {
        emit TimelockTransferred(timelockAddress, _newTimelock);
        timelockAddress = _newTimelock;
    }

    /// @notice The ```transferTimelock``` function initiates the timelock transfer
    /// @dev Must be called by the current timelock
    /// @param _newTimelock The address of the nominated (pending) timelock
    function transferTimelock(address _newTimelock) external virtual {
        _requireTimelock();
        _transferTimelock(_newTimelock);
    }

    /// @notice The ```acceptTransferTimelock``` function completes the timelock transfer
    /// @dev Must be called by the pending timelock
    function acceptTransferTimelock() external virtual {
        _requirePendingTimelock();
        _acceptTransferTimelock();
    }

    /// @notice The ```renounceTimelock``` function renounces the timelock after setting pending timelock to current timelock
    /// @dev Pending timelock must be set to current timelock before renouncing, creating a 2-step renounce process
    function renounceTimelock() external virtual {
        _requireTimelock();
        _requirePendingTimelock();
        _transferTimelock(address(0));
        _setTimelock(address(0));
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;

interface ITimelock2Step {
    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);
    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);

    function acceptTransferTimelock() external;

    function pendingTimelockAddress() external view returns (address);

    function renounceTimelock() external;

    function timelockAddress() external view returns (address);

    function transferTimelock(address _newTimelock) external;
}

//SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================= MerkleTreeProver =========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Authors
// Jon Walch: https://github.com/jonwalch
// Dennis: https://github.com/denett

// Reviewers
// Drake Evans: https://github.com/DrakeEvans

// ====================================================================
import { RLPReader } from "rlp/RLPReader.sol";
import { StateProofVerifier as Verifier } from "./StateProofVerifier.sol";

/// @title MerkleTreeProver
/// @author Jon Walch (Frax Finance) https://github.com/jonwalch
/// @notice Helper function library for interacting with StateProofVerifier and RLPReader
library MerkleTreeProver {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    /// @notice The ```proveStorageRoot``` function is a helper function for StateProofVerifier.extractAccountFromProof()
    /// @param stateRootHash The hash of the state root
    /// @param proofAddress The address of the contract we're proving
    /// @param accountProof The accountProof retrieved from eth_getProof
    function proveStorageRoot(
        bytes32 stateRootHash,
        address proofAddress,
        bytes[] memory accountProof
    ) internal view returns (Verifier.Account memory accountPool) {
        RLPReader.RLPItem[] memory accountProofRlp = new RLPReader.RLPItem[](accountProof.length);
        for (uint256 i = 0; i < accountProof.length; ++i) {
            accountProofRlp[i] = accountProof[i].toRlpItem();
        }
        accountPool = Verifier.extractAccountFromProof({
            _addressHash: keccak256(abi.encodePacked(proofAddress)),
            _stateRootHash: stateRootHash,
            _proof: accountProofRlp
        });
    }

    /// @notice The ```proveStorageSlotValue``` function is a helper function for StateProofVerifier.extractSlotValueFromProof()
    /// @param storageRootHash The hash of the storage root
    /// @param slot The slot we want to prove for the contract
    /// @param storageProof The storageProof.proof retrieved from eth_getProof
    function proveStorageSlotValue(
        bytes32 storageRootHash,
        bytes32 slot,
        bytes[] memory storageProof
    ) internal view returns (Verifier.SlotValue memory slotValue) {
        RLPReader.RLPItem[] memory storageProofRlp = new RLPReader.RLPItem[](storageProof.length);
        for (uint256 i = 0; i < storageProof.length; ++i) {
            storageProofRlp[i] = storageProof[i].toRlpItem();
        }
        slotValue = Verifier.extractSlotValueFromProof({
            _slotHash: keccak256(abi.encodePacked(slot)),
            _storageRootHash: storageRootHash,
            _proof: storageProofRlp
        });
    }
}

// SPDX-License-Identifier: MIT
// Copied from https://github.com/lidofinance/curve-merkle-oracle/blob/1033b3e84142317ffd8f366b52e489d5eb49c73f/contracts/StateProofVerifier.sol
pragma solidity ^0.8.20;

import { RLPReader } from "rlp/RLPReader.sol";
import { MerklePatriciaProofVerifier } from "./MerklePatriciaProofVerifier.sol";

/**
 * @title A helper library for verification of Merkle Patricia account and state proofs.
 */
library StateProofVerifier {
    using RLPReader for RLPReader.RLPItem;
    using RLPReader for bytes;

    uint256 constant HEADER_STATE_ROOT_INDEX = 3;
    uint256 constant HEADER_NUMBER_INDEX = 8;
    uint256 constant HEADER_TIMESTAMP_INDEX = 11;

    struct BlockHeader {
        bytes32 hash;
        bytes32 stateRootHash;
        uint256 number;
        uint256 timestamp;
    }

    struct Account {
        bool exists;
        uint256 nonce;
        uint256 balance;
        bytes32 storageRoot;
        bytes32 codeHash;
    }

    struct SlotValue {
        bool exists;
        uint256 value;
    }

    /**
     * @notice Parses block header and verifies its presence onchain within the latest 256 blocks.
     * @param _headerRlpBytes RLP-encoded block header.
     */
    function verifyBlockHeader(bytes memory _headerRlpBytes) internal view returns (BlockHeader memory) {
        BlockHeader memory header = parseBlockHeader(_headerRlpBytes);
        // ensure that the block is actually in the blockchain
        require(header.hash == blockhash(header.number), "blockhash mismatch");
        return header;
    }

    /**
     * @notice Parses RLP-encoded block header.
     * @param _headerRlpBytes RLP-encoded block header.
     */
    function parseBlockHeader(bytes memory _headerRlpBytes) internal pure returns (BlockHeader memory) {
        BlockHeader memory result;
        RLPReader.RLPItem[] memory headerFields = _headerRlpBytes.toRlpItem().toList();

        require(headerFields.length > HEADER_TIMESTAMP_INDEX);

        result.stateRootHash = bytes32(headerFields[HEADER_STATE_ROOT_INDEX].toUint());
        result.number = headerFields[HEADER_NUMBER_INDEX].toUint();
        result.timestamp = headerFields[HEADER_TIMESTAMP_INDEX].toUint();
        result.hash = keccak256(_headerRlpBytes);

        return result;
    }

    /**
     * @notice Verifies Merkle Patricia proof of an account and extracts the account fields.
     *
     * @param _addressHash Keccak256 hash of the address corresponding to the account.
     * @param _stateRootHash MPT root hash of the Ethereum state trie.
     */
    function extractAccountFromProof(
        bytes32 _addressHash, // keccak256(abi.encodePacked(address))
        bytes32 _stateRootHash,
        RLPReader.RLPItem[] memory _proof
    ) internal pure returns (Account memory) {
        bytes memory acctRlpBytes = MerklePatriciaProofVerifier.extractProofValue(
            _stateRootHash,
            abi.encodePacked(_addressHash),
            _proof
        );

        Account memory account;

        if (acctRlpBytes.length == 0) {
            return account;
        }

        RLPReader.RLPItem[] memory acctFields = acctRlpBytes.toRlpItem().toList();
        require(acctFields.length == 4);

        account.exists = true;
        account.nonce = acctFields[0].toUint();
        account.balance = acctFields[1].toUint();
        account.storageRoot = bytes32(acctFields[2].toUint());
        account.codeHash = bytes32(acctFields[3].toUint());

        return account;
    }

    /**
     * @notice Verifies Merkle Patricia proof of a slot and extracts the slot's value.
     *
     * @param _slotHash Keccak256 hash of the slot position.
     * @param _storageRootHash MPT root hash of the account's storage trie.
     */
    function extractSlotValueFromProof(
        bytes32 _slotHash,
        bytes32 _storageRootHash,
        RLPReader.RLPItem[] memory _proof
    ) internal pure returns (SlotValue memory) {
        bytes memory valueRlpBytes = MerklePatriciaProofVerifier.extractProofValue(
            _storageRootHash,
            abi.encodePacked(_slotHash),
            _proof
        );

        SlotValue memory value;

        if (valueRlpBytes.length != 0) {
            value.exists = true;
            value.value = valueRlpBytes.toRlpItem().toUint();
        }

        return value;
    }
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.19;

interface IERC4626Receiver {
    function updateErc4262VaultData(
        uint96 _l1BlockNumber,
        uint256 _totalSupply,
        uint256 _totalAssets,
        uint192 _lastRewardsAmount,
        uint32 _lastSync,
        uint32 _rewardsCycleEnd
    ) external;

    /// @notice Information about the current rewards cycle
    struct RewardsCycleData {
        uint40 cycleEnd; // Timestamp of the end of the current rewards cycle
        uint40 lastSync; // Timestamp of the last time the rewards cycle was synced
        uint216 rewardCycleAmount; // Amount of rewards to be distributed in the current cycle
    }

    function updatesFRAXData(
        uint96 _l1BlockNumber,
        uint256 _totalSupply,
        uint256 _totalAssets,
        uint256 _lastDistributionAmount,
        RewardsCycleData memory data
    ) external;

    function updateMaxDistributionPerSecond(uint96 _l1BlockNumber, uint256 maxPerSecond) external;
    function updateDaiVaultData(uint96 _l1BlockNumber, uint256 _dsr, uint256 _rho, uint256 _chi) external;

    function getPrices() external view returns (bool, uint256, uint256);

    function dsr() external view returns (uint256);
    function chi() external view returns (uint256);
    function rho() external view returns (uint256);
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

interface IStateRootOracle {
    struct BlockInfo {
        bytes32 stateRootHash;
        uint40 timestamp;
    }

    function getBlockInfo(uint256 blockNumber) external view returns (BlockInfo memory _blockInfo);
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // Divide z by the denominator.
            z := div(z, denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // First, divide z - 1 by the denominator and add 1.
            // We allow z - 1 to underflow if z is 0, because we multiply the
            // end result by 0 if z is zero, ensuring we return 0 if z is zero.
            z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            // Start off with z at 1.
            z := 1

            // Used below to help find a nearby power of 2.
            let y := x

            // Find the lowest power of 2 that is at least sqrt(x).
            if iszero(lt(y, 0x100000000000000000000000000000000)) {
                y := shr(128, y) // Like dividing by 2 ** 128.
                z := shl(64, z) // Like multiplying by 2 ** 64.
            }
            if iszero(lt(y, 0x10000000000000000)) {
                y := shr(64, y) // Like dividing by 2 ** 64.
                z := shl(32, z) // Like multiplying by 2 ** 32.
            }
            if iszero(lt(y, 0x100000000)) {
                y := shr(32, y) // Like dividing by 2 ** 32.
                z := shl(16, z) // Like multiplying by 2 ** 16.
            }
            if iszero(lt(y, 0x10000)) {
                y := shr(16, y) // Like dividing by 2 ** 16.
                z := shl(8, z) // Like multiplying by 2 ** 8.
            }
            if iszero(lt(y, 0x100)) {
                y := shr(8, y) // Like dividing by 2 ** 8.
                z := shl(4, z) // Like multiplying by 2 ** 4.
            }
            if iszero(lt(y, 0x10)) {
                y := shr(4, y) // Like dividing by 2 ** 4.
                z := shl(2, z) // Like multiplying by 2 ** 2.
            }
            if iszero(lt(y, 0x8)) {
                // Equivalent to 2 ** z.
                z := shl(1, z)
            }

            // Shifting right by 1 is like dividing by 2.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // Compute a rounded down version of z.
            let zRoundDown := div(x, z)

            // If zRoundDown is smaller, use it.
            if lt(zRoundDown, z) {
                z := zRoundDown
            }
        }
    }
}

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

}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * @author Hamdi Allam [email protected]
 * Please reach out with any questions or concerns
 */
pragma solidity >=0.5.10 <0.9.0;

library RLPReader {
    uint8 constant STRING_SHORT_START = 0x80;
    uint8 constant STRING_LONG_START = 0xb8;
    uint8 constant LIST_SHORT_START = 0xc0;
    uint8 constant LIST_LONG_START = 0xf8;
    uint8 constant WORD_SIZE = 32;

    struct RLPItem {
        uint256 len;
        uint256 memPtr;
    }

    struct Iterator {
        RLPItem item; // Item that's being iterated over.
        uint256 nextPtr; // Position of the next item in the list.
    }

    /*
     * @dev Returns the next element in the iteration. Reverts if it has not next element.
     * @param self The iterator.
     * @return The next element in the iteration.
     */
    function next(Iterator memory self) internal pure returns (RLPItem memory) {
        require(hasNext(self));

        uint256 ptr = self.nextPtr;
        uint256 itemLength = _itemLength(ptr);
        self.nextPtr = ptr + itemLength;

        return RLPItem(itemLength, ptr);
    }

    /*
     * @dev Returns true if the iteration has more elements.
     * @param self The iterator.
     * @return true if the iteration has more elements.
     */
    function hasNext(Iterator memory self) internal pure returns (bool) {
        RLPItem memory item = self.item;
        return self.nextPtr < item.memPtr + item.len;
    }

    /*
     * @param item RLP encoded bytes
     */
    function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
        uint256 memPtr;
        assembly {
            memPtr := add(item, 0x20)
        }

        return RLPItem(item.length, memPtr);
    }

    /*
     * @dev Create an iterator. Reverts if item is not a list.
     * @param self The RLP item.
     * @return An 'Iterator' over the item.
     */
    function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
        require(isList(self));

        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
        return Iterator(self, ptr);
    }

    /*
     * @param the RLP item.
     */
    function rlpLen(RLPItem memory item) internal pure returns (uint256) {
        return item.len;
    }

    /*
     * @param the RLP item.
     * @return (memPtr, len) pair: location of the item's payload in memory.
     */
    function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) {
        uint256 offset = _payloadOffset(item.memPtr);
        uint256 memPtr = item.memPtr + offset;
        uint256 len = item.len - offset; // data length
        return (memPtr, len);
    }

    /*
     * @param the RLP item.
     */
    function payloadLen(RLPItem memory item) internal pure returns (uint256) {
        (, uint256 len) = payloadLocation(item);
        return len;
    }

    /*
     * @param the RLP item containing the encoded list.
     */
    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
        require(isList(item));

        uint256 items = numItems(item);
        RLPItem[] memory result = new RLPItem[](items);

        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 dataLen;
        for (uint256 i = 0; i < items; i++) {
            dataLen = _itemLength(memPtr);
            result[i] = RLPItem(dataLen, memPtr);
            memPtr = memPtr + dataLen;
        }

        return result;
    }

    // @return indicator whether encoded payload is a list. negate this function call for isData.
    function isList(RLPItem memory item) internal pure returns (bool) {
        if (item.len == 0) return false;

        uint8 byte0;
        uint256 memPtr = item.memPtr;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < LIST_SHORT_START) return false;
        return true;
    }

    /*
     * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.
     * @return keccak256 hash of RLP encoded bytes.
     */
    function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) {
        uint256 ptr = item.memPtr;
        uint256 len = item.len;
        bytes32 result;
        assembly {
            result := keccak256(ptr, len)
        }
        return result;
    }

    /*
     * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.
     * @return keccak256 hash of the item payload.
     */
    function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) {
        (uint256 memPtr, uint256 len) = payloadLocation(item);
        bytes32 result;
        assembly {
            result := keccak256(memPtr, len)
        }
        return result;
    }

    /** RLPItem conversions into data types **/

    // @returns raw rlp encoding in bytes
    function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
        bytes memory result = new bytes(item.len);
        if (result.length == 0) return result;

        uint256 ptr;
        assembly {
            ptr := add(0x20, result)
        }

        copy(item.memPtr, ptr, item.len);
        return result;
    }

    // any non-zero byte except "0x80" is considered true
    function toBoolean(RLPItem memory item) internal pure returns (bool) {
        require(item.len == 1);
        uint256 result;
        uint256 memPtr = item.memPtr;
        assembly {
            result := byte(0, mload(memPtr))
        }

        // SEE Github Issue #5.
        // Summary: Most commonly used RLP libraries (i.e Geth) will encode
        // "0" as "0x80" instead of as "0". We handle this edge case explicitly
        // here.
        if (result == 0 || result == STRING_SHORT_START) {
            return false;
        } else {
            return true;
        }
    }

    function toAddress(RLPItem memory item) internal pure returns (address) {
        // 1 byte for the length prefix
        require(item.len == 21);

        return address(uint160(toUint(item)));
    }

    function toUint(RLPItem memory item) internal pure returns (uint256) {
        require(item.len > 0 && item.len <= 33);

        (uint256 memPtr, uint256 len) = payloadLocation(item);

        uint256 result;
        assembly {
            result := mload(memPtr)

            // shift to the correct location if neccesary
            if lt(len, 32) {
                result := div(result, exp(256, sub(32, len)))
            }
        }

        return result;
    }

    // enforces 32 byte length
    function toUintStrict(RLPItem memory item) internal pure returns (uint256) {
        // one byte prefix
        require(item.len == 33);

        uint256 result;
        uint256 memPtr = item.memPtr + 1;
        assembly {
            result := mload(memPtr)
        }

        return result;
    }

    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
        require(item.len > 0);

        (uint256 memPtr, uint256 len) = payloadLocation(item);
        bytes memory result = new bytes(len);

        uint256 destPtr;
        assembly {
            destPtr := add(0x20, result)
        }

        copy(memPtr, destPtr, len);
        return result;
    }

    /*
     * Private Helpers
     */

    // @return number of payload items inside an encoded list.
    function numItems(RLPItem memory item) private pure returns (uint256) {
        if (item.len == 0) return 0;

        uint256 count = 0;
        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 endPtr = item.memPtr + item.len;
        while (currPtr < endPtr) {
            currPtr = currPtr + _itemLength(currPtr); // skip over an item
            count++;
        }

        return count;
    }

    // @return entire rlp item byte length
    function _itemLength(uint256 memPtr) private pure returns (uint256) {
        uint256 itemLen;
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) {
            itemLen = 1;
        } else if (byte0 < STRING_LONG_START) {
            itemLen = byte0 - STRING_SHORT_START + 1;
        } else if (byte0 < LIST_SHORT_START) {
            assembly {
                let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
                memPtr := add(memPtr, 1) // skip over the first byte

                /* 32 byte word size */
                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
                itemLen := add(dataLen, add(byteLen, 1))
            }
        } else if (byte0 < LIST_LONG_START) {
            itemLen = byte0 - LIST_SHORT_START + 1;
        } else {
            assembly {
                let byteLen := sub(byte0, 0xf7)
                memPtr := add(memPtr, 1)

                let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
                itemLen := add(dataLen, add(byteLen, 1))
            }
        }

        return itemLen;
    }

    // @return number of bytes until the data
    function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
        uint256 byte0;
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) {
            return 0;
        } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) {
            return 1;
        } else if (byte0 < LIST_SHORT_START) {
            // being explicit
            return byte0 - (STRING_LONG_START - 1) + 1;
        } else {
            return byte0 - (LIST_LONG_START - 1) + 1;
        }
    }

    /*
     * @param src Pointer to source
     * @param dest Pointer to destination
     * @param len Amount of memory to copy from the source
     */
    function copy(uint256 src, uint256 dest, uint256 len) private pure {
        if (len == 0) return;

        // copy as many word sizes as possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }

            src += WORD_SIZE;
            dest += WORD_SIZE;
        }

        if (len > 0) {
            // left over bytes. Mask is used to remove unwanted bytes from the word
            uint256 mask = 256**(WORD_SIZE - len) - 1;
            assembly {
                let srcpart := and(mload(src), not(mask)) // zero out src
                let destpart := and(mload(dest), mask) // retrieve the bytes
                mstore(dest, or(destpart, srcpart))
            }
        }
    }
}

// SPDX-License-Identifier: MIT
// Copied from https://github.com/lidofinance/curve-merkle-oracle/blob/1033b3e84142317ffd8f366b52e489d5eb49c73f/contracts/MerklePatriciaProofVerifier.sol
/**
 * Copied from https://github.com/lorenzb/proveth/blob/c74b20e/onchain/ProvethVerifier.sol
 * with minor performance and code style-related modifications.
 */
pragma solidity ^0.8.20;

import { RLPReader } from "rlp/RLPReader.sol";

library MerklePatriciaProofVerifier {
    using RLPReader for RLPReader.RLPItem;
    using RLPReader for bytes;

    /// @dev Validates a Merkle-Patricia-Trie proof.
    ///      If the proof proves the inclusion of some key-value pair in the
    ///      trie, the value is returned. Otherwise, i.e. if the proof proves
    ///      the exclusion of a key from the trie, an empty byte array is
    ///      returned.
    /// @param rootHash is the Keccak-256 hash of the root node of the MPT.
    /// @param path is the key of the node whose inclusion/exclusion we are
    ///        proving.
    /// @param stack is the stack of MPT nodes (starting with the root) that
    ///        need to be traversed during verification.
    /// @return value whose inclusion is proved or an empty byte array for
    ///         a proof of exclusion
    function extractProofValue(
        bytes32 rootHash,
        bytes memory path,
        RLPReader.RLPItem[] memory stack
    ) internal pure returns (bytes memory value) {
        bytes memory mptKey = _decodeNibbles(path, 0);
        uint256 mptKeyOffset = 0;

        bytes32 nodeHashHash;
        RLPReader.RLPItem[] memory node;

        RLPReader.RLPItem memory rlpValue;

        if (stack.length == 0) {
            // Root hash of empty Merkle-Patricia-Trie
            require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421);
            return new bytes(0);
        }

        // Traverse stack of nodes starting at root.
        for (uint256 i = 0; i < stack.length; i++) {
            // We use the fact that an rlp encoded list consists of some
            // encoding of its length plus the concatenation of its
            // *rlp-encoded* items.

            // The root node is hashed with Keccak-256 ...
            if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) {
                revert();
            }
            // ... whereas all other nodes are hashed with the MPT
            // hash function.
            if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) {
                revert();
            }
            // We verified that stack[i] has the correct hash, so we
            // may safely decode it.
            node = stack[i].toList();

            if (node.length == 2) {
                // Extension or Leaf node

                bool isLeaf;
                bytes memory nodeKey;
                (isLeaf, nodeKey) = _merklePatriciaCompactDecode(node[0].toBytes());

                uint256 prefixLength = _sharedPrefixLength(mptKeyOffset, mptKey, nodeKey);
                mptKeyOffset += prefixLength;

                if (prefixLength < nodeKey.length) {
                    // Proof claims divergent extension or leaf. (Only
                    // relevant for proofs of exclusion.)
                    // An Extension/Leaf node is divergent iff it "skips" over
                    // the point at which a Branch node should have been had the
                    // excluded key been included in the trie.
                    // Example: Imagine a proof of exclusion for path [1, 4],
                    // where the current node is a Leaf node with
                    // path [1, 3, 3, 7]. For [1, 4] to be included, there
                    // should have been a Branch node at [1] with a child
                    // at 3 and a child at 4.

                    // Sanity check
                    if (i < stack.length - 1) {
                        // divergent node must come last in proof
                        revert();
                    }

                    return new bytes(0);
                }

                if (isLeaf) {
                    // Sanity check
                    if (i < stack.length - 1) {
                        // leaf node must come last in proof
                        revert();
                    }

                    if (mptKeyOffset < mptKey.length) {
                        return new bytes(0);
                    }

                    rlpValue = node[1];
                    return rlpValue.toBytes();
                } else {
                    // extension
                    // Sanity check
                    if (i == stack.length - 1) {
                        // shouldn't be at last level
                        revert();
                    }

                    if (!node[1].isList()) {
                        // rlp(child) was at least 32 bytes. node[1] contains
                        // Keccak256(rlp(child)).
                        nodeHashHash = node[1].payloadKeccak256();
                    } else {
                        // rlp(child) was less than 32 bytes. node[1] contains
                        // rlp(child).
                        nodeHashHash = node[1].rlpBytesKeccak256();
                    }
                }
            } else if (node.length == 17) {
                // Branch node

                if (mptKeyOffset != mptKey.length) {
                    // we haven't consumed the entire path, so we need to look at a child
                    uint8 nibble = uint8(mptKey[mptKeyOffset]);
                    mptKeyOffset += 1;
                    if (nibble >= 16) {
                        // each element of the path has to be a nibble
                        revert();
                    }

                    if (_isEmptyBytesequence(node[nibble])) {
                        // Sanity
                        if (i != stack.length - 1) {
                            // leaf node should be at last level
                            revert();
                        }

                        return new bytes(0);
                    } else if (!node[nibble].isList()) {
                        nodeHashHash = node[nibble].payloadKeccak256();
                    } else {
                        nodeHashHash = node[nibble].rlpBytesKeccak256();
                    }
                } else {
                    // we have consumed the entire mptKey, so we need to look at what's contained in this node.

                    // Sanity
                    if (i != stack.length - 1) {
                        // should be at last level
                        revert();
                    }

                    return node[16].toBytes();
                }
            }
        }
    }

    /// @dev Computes the hash of the Merkle-Patricia-Trie hash of the RLP item.
    ///      Merkle-Patricia-Tries use a weird "hash function" that outputs
    ///      *variable-length* hashes: If the item is shorter than 32 bytes,
    ///      the MPT hash is the item. Otherwise, the MPT hash is the
    ///      Keccak-256 hash of the item.
    ///      The easiest way to compare variable-length byte sequences is
    ///      to compare their Keccak-256 hashes.
    /// @param item The RLP item to be hashed.
    /// @return Keccak-256(MPT-hash(item))
    function _mptHashHash(RLPReader.RLPItem memory item) private pure returns (bytes32) {
        if (item.len < 32) {
            return item.rlpBytesKeccak256();
        } else {
            return keccak256(abi.encodePacked(item.rlpBytesKeccak256()));
        }
    }

    function _isEmptyBytesequence(RLPReader.RLPItem memory item) private pure returns (bool) {
        if (item.len != 1) {
            return false;
        }
        uint8 b;
        uint256 memPtr = item.memPtr;
        assembly {
            b := byte(0, mload(memPtr))
        }
        return b == 0x80; /* empty byte string */
    }

    function _merklePatriciaCompactDecode(
        bytes memory compact
    ) private pure returns (bool isLeaf, bytes memory nibbles) {
        require(compact.length > 0);
        uint256 first_nibble = (uint8(compact[0]) >> 4) & 0xF;
        uint256 skipNibbles;
        if (first_nibble == 0) {
            skipNibbles = 2;
            isLeaf = false;
        } else if (first_nibble == 1) {
            skipNibbles = 1;
            isLeaf = false;
        } else if (first_nibble == 2) {
            skipNibbles = 2;
            isLeaf = true;
        } else if (first_nibble == 3) {
            skipNibbles = 1;
            isLeaf = true;
        } else {
            // Not supposed to happen!
            revert();
        }
        return (isLeaf, _decodeNibbles(compact, skipNibbles));
    }

    function _decodeNibbles(bytes memory compact, uint256 skipNibbles) private pure returns (bytes memory nibbles) {
        require(compact.length > 0);

        uint256 length = compact.length * 2;
        require(skipNibbles <= length);
        length -= skipNibbles;

        nibbles = new bytes(length);
        uint256 nibblesLength = 0;

        for (uint256 i = skipNibbles; i < skipNibbles + length; i += 1) {
            if (i % 2 == 0) {
                nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 4) & 0xF);
            } else {
                nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 0) & 0xF);
            }
            nibblesLength += 1;
        }

        assert(nibblesLength == nibbles.length);
    }

    function _sharedPrefixLength(uint256 xsOffset, bytes memory xs, bytes memory ys) private pure returns (uint256) {
        uint256 i;
        for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) {
            if (xs[i + xsOffset] != ys[i]) {
                return i;
            }
        }
        return i;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "ds-test/=node_modules/ds-test/src/",
    "forge-std/=node_modules/forge-std/src/",
    "frax-std/=node_modules/frax-standard-solidity/src/",
    "script/=src/script/",
    "src/=src/",
    "test/=src/test/",
    "interfaces/=src/contracts/interfaces/",
    "arbitrum/=node_modules/@arbitrum/",
    "rlp/=node_modules/solidity-rlp/contracts/",
    "@solmate/=node_modules/@rari-capital/solmate/src/",
    "@arbitrum/=node_modules/@arbitrum/",
    "@chainlink/=node_modules/@chainlink/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "@mean-finance/=node_modules/@mean-finance/",
    "@offchainlabs/=node_modules/@offchainlabs/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@rari-capital/=node_modules/@rari-capital/",
    "@uniswap/=node_modules/@uniswap/",
    "base64-sol/=node_modules/base64-sol/",
    "frax-standard-solidity/=node_modules/frax-standard-solidity/",
    "hardhat/=node_modules/hardhat/",
    "prb-math/=node_modules/prb-math/",
    "solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
    "solidity-rlp/=node_modules/solidity-rlp/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_stateRootOracle","type":"address"},{"internalType":"address","name":"_timelockAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"MustBeGtZero","type":"error"},{"inputs":[],"name":"OnlyPendingTimelock","type":"error"},{"inputs":[],"name":"OnlyTimelock","type":"error"},{"inputs":[{"internalType":"address","name":"fraxOracleLayer1","type":"address"},{"internalType":"address","name":"fraxOracleLayer2","type":"address"}],"name":"OraclePairAlreadySet","type":"error"},{"inputs":[],"name":"StalePush","type":"error"},{"inputs":[],"name":"WrongOracleAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fraxOracleLayer1","type":"address"},{"indexed":true,"internalType":"address","name":"fraxOracleLayer2","type":"address"}],"name":"OraclePairAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferred","type":"event"},{"inputs":[],"name":"STATE_ROOT_ORACLE","outputs":[{"internalType":"contract IStateRootOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sFraxAddress","type":"address"},{"internalType":"uint96","name":"_blockNumber","type":"uint96"},{"internalType":"bytes[]","name":"_accountProofSfrax","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofMaxDistPerSecond","type":"bytes[]"}],"name":"_fetchAndProofMaxRewards","outputs":[{"internalType":"uint256","name":"maxDistributionPerSecond","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTransferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC4626Receiver","name":"_sFraxOracle","type":"address"},{"internalType":"uint96","name":"_blockNumber","type":"uint96"},{"internalType":"bytes[]","name":"_accountProofSfrax","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofMaxDistPerSecond","type":"bytes[]"}],"name":"addMaxDistributionPerSecond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"layer1FraxOracle","type":"address"},{"internalType":"address","name":"layer2FraxOracle","type":"address"}],"internalType":"struct MerkleProofPriceSourceSfrax.OraclePair[]","name":"_oraclePairs","type":"tuple[]"}],"name":"addOraclePairs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC4626Receiver","name":"_sFraxOracle","type":"address"},{"internalType":"uint96","name":"_blockNumber","type":"uint96"},{"components":[{"internalType":"bytes[]","name":"_accountProofSfrax","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofTotalSupply","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofTotalAssets","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofLastDist","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofRewardsPacked","type":"bytes[]"},{"internalType":"bytes[]","name":"_storageProofRewardsCycleAmount","type":"bytes[]"}],"internalType":"struct MerkleProofPriceSourceSfrax.PoofPackedsFrax","name":"proof","type":"tuple"}],"name":"addRoundDataSfrax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"layer2FraxOracle","type":"address"}],"name":"oracleLookup","outputs":[{"internalType":"address","name":"layer1Oracle","type":"address"},{"internalType":"uint96","name":"lastBlockProofed","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingTimelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newTimelock","type":"address"}],"name":"transferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801562000010575f80fd5b506040516200289d3803806200289d83398101604081905262000033916200016f565b600280546001600160a01b03191633179055620000508162000075565b62000062632fa3fc3160e21b620000d0565b506001600160a01b0316608052620001a5565b6002546040516001600160a01b038084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160e01b031980821690036200012f5760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015260640160405180910390fd5b6001600160e01b0319165f908152602081905260409020805460ff19166001179055565b80516001600160a01b03811681146200016a575f80fd5b919050565b5f806040838503121562000181575f80fd5b6200018c8362000153565b91506200019c6020840162000153565b90509250929050565b6080516126d1620001cc5f395f81816101b60152818161038c0152610ea901526126d15ff3fe608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80638c16b3ba1161007d578063bd6eb23111610058578063bd6eb231146101eb578063edb219c0146101fe578063f6ccaad414610294575f80fd5b80638c16b3ba1461019e5780639378ca56146101b1578063a6d7fdf2146101d8575f80fd5b80634bc66f32116100ad5780634bc66f32146101555780634dd4ee5f146101755780634f8b4ae714610196575f80fd5b806301ffc9a7146100d3578063090f3f50146100fb5780634501409514610140575b5f80fd5b6100e66100e1366004611f2c565b61029c565b60405190151581526020015b60405180910390f35b60015461011b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f2565b61015361014e366004611f8c565b610323565b005b60025461011b9073ffffffffffffffffffffffffffffffffffffffff1681565b610188610183366004612196565b610337565b6040519081526020016100f2565b610153610462565b6101536101ac366004612196565b610486565b61011b7f000000000000000000000000000000000000000000000000000000000000000081565b6101536101e6366004612218565b610633565b6101536101f9366004612287565b6107b8565b61025b61020c366004611f8c565b60036020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff8116907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff9091166020830152016100f2565b610153610a19565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061031d57507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526020819052604090205460ff165b92915050565b61032b610a29565b61033481610a7a565b50565b6040517fbb141cf40000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff841660048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063bb141cf4906024016040805180830381865afa1580156103d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f491906123c2565b90505f610405825f01518887610af0565b90506104198160600151600c5f1b86610c5b565b602001519250825f03610458576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050949350505050565b61046a610a29565b610472610d52565b61047b5f610a7a565b6104845f610da3565b565b73ffffffffffffffffffffffffffffffffffffffff84165f908152600360205260409020547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff16801561052d57806bffffffffffffffffffffffff16846bffffffffffffffffffffffff16101561052d576040517f011d308100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8086165f90815260036020526040902054168061058b576040517f17e740e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61059882878787610337565b6040517f330a73550000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff881660048201526024810182905290915073ffffffffffffffffffffffffffffffffffffffff88169063330a7355906044015f604051808303815f87803b158015610614575f80fd5b505af1158015610626573d5f803e3d5ffd5b5050505050505050505050565b61063b610a29565b5f5b818110156107b3575f83838381811061065857610658612401565b90506040020180360381019061066e919061242e565b60208082015173ffffffffffffffffffffffffffffffffffffffff9081165f90815260039092526040909120549192501615610714576020818101805173ffffffffffffffffffffffffffffffffffffffff9081165f908152600390935260409283902054915183517f729d6d9c000000000000000000000000000000000000000000000000000000008152928216600484015216602482015290519081900360440190fd5b80516020808301805173ffffffffffffffffffffffffffffffffffffffff9081165f9081526003909352604080842080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169583169590951790945590518451935190821693909116917fc662d74d8469d456352095edb1ed6a69f64c66ace9fa3598de77edfccfad12a291a3506107ac8161248e565b905061063d565b505050565b73ffffffffffffffffffffffffffffffffffffffff83165f908152600360205260408120547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1690811561086057816bffffffffffffffffffffffff16846bffffffffffffffffffffffff161015610860576040517f011d308100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff8085165f9081526003602052604090205416806108bf576040517f17e740e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f806108ce858989610e30565b604080517fc473071e0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff8e166004820152602481018690526044810185905260648101849052825164ffffffffff908116608483015260208401511660a4820152908201517affffffffffffffffffffffffffffffffffffffffffffffffffffff1660c48201529397509195509350915073ffffffffffffffffffffffffffffffffffffffff8a169063c473071e9060e4015f604051808303815f87803b1580156109a1575f80fd5b505af11580156109b3573d5f803e3d5ffd5b50505073ffffffffffffffffffffffffffffffffffffffff998a165f90815260036020526040902080546bffffffffffffffffffffffff909a16740100000000000000000000000000000000000000000299909a16989098179098555050505050505050565b610a21610d52565b6104846110c7565b60025473ffffffffffffffffffffffffffffffffffffffff163314610484576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a905f90a350565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f825167ffffffffffffffff811115610b3557610b35611fc2565b604051908082528060200260200182016040528015610b7957816020015b604080518082019091525f8082526020820152815260200190600190039081610b535790505b5090505f5b8351811015610bfe57610bd0848281518110610b9c57610b9c612401565b60200260200101516040805180820182525f8082526020918201528151808301909252825182529182019181019190915290565b828281518110610be257610be2612401565b602002602001018190525080610bf79061248e565b9050610b7e565b506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b166020820152610c52906034016040516020818303038152906040528051906020012086836110f8565b95945050505050565b604080518082019091525f80825260208201525f825167ffffffffffffffff811115610c8957610c89611fc2565b604051908082528060200260200182016040528015610ccd57816020015b604080518082019091525f8082526020820152815260200190600190039081610ca75790505b5090505f5b8351811015610d1e57610cf0848281518110610b9c57610b9c612401565b828281518110610d0257610d02612401565b602002602001018190525080610d179061248e565b9050610cd2565b50610c5284604051602001610d3591815260200190565b604051602081830303815290604052805190602001208683611267565b60015473ffffffffffffffffffffffffffffffffffffffff163314610484576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b604080516060810182525f808252602082018190529181018290528190819050604080516060810182525f8082526020820181905281830181905291517fbb141cf40000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff881660048201529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063bb141cf4906024016040805180830381865afa158015610f02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2691906123c2565b90505f610f3a825f01518a895f0151610af0565b9050610f52816060015160025f1b8960200151610c5b565b602001519550610f6e816060015160095f1b8960400151610c5b565b602001519450610f8a816060015160085f1b8960600151610c5b565b6020015193505f610fa7826060015160065f1b8a60800151610c5b565b6020015190505f610fc4836060015160075f1b8b60a00151610c5b565b60209081015164ffffffffff602885901c81169288019290925292168552507affffffffffffffffffffffffffffffffffffffffffffffffffffff1660408401525f86900361103f576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015164ffffffffff165f03611083576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f036110bc576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505093509350935093565b600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561048433610da3565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f61114f848660405160200161113a91815260200190565b604051602081830303815290604052856112f0565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915290915081515f0361118d5791506112609050565b5f6111c66111c1846040805180820182525f8082526020918201528151808301909252825182529182019181019190915290565b611714565b905080516004146111d5575f80fd5b6001825280516111fc9082905f906111ef576111ef612401565b6020026020010151611824565b6020830152805161121a90829060019081106111ef576111ef612401565b6040830152805161123890829060029081106111ef576111ef612401565b6060830152805161125690829060039081106111ef576111ef612401565b6080830152509150505b9392505050565b604080518082019091525f80825260208201525f611292848660405160200161113a91815260200190565b604080518082019091525f8082526020820152909150815115610c5257600181526040805180820182525f808252602091820152815180830190925283518252808401908201526112e290611824565b602082015295945050505050565b60605f6112fd845f61186f565b90505f80606061131e60405180604001604052805f81526020015f81525090565b86515f0361136c577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218914611351575f80fd5b5050604080515f815260208101909152935061126092505050565b5f5b875181101561170757801580156113ad57506113a988828151811061139557611395612401565b602002602001015160208101519051902090565b8a14155b156113b6575f80fd5b80158015906113e657506113e28882815181106113d5576113d5612401565b6020026020010151611a3c565b8414155b156113ef575f80fd5b61141188828151811061140457611404612401565b6020026020010151611714565b925082516002036115b5575f6060611449611444865f8151811061143757611437612401565b6020026020010151611a94565b611b0f565b90925090505f61145a888a84611ba2565b905061146681896124c5565b975081518110156114c75760018b5161147f91906124d8565b84101561148a575f80fd5b5f5b6040519080825280601f01601f1916602001820160405280156114b6576020820181803683370190505b509950505050505050505050611260565b821561152b5760018b516114db91906124d8565b8410156114e6575f80fd5b88518810156114f5575f61148c565b8560018151811061150857611508612401565b6020026020010151945061151b85611a94565b9950505050505050505050611260565b60018b5161153991906124d8565b8403611543575f80fd5b6115668660018151811061155957611559612401565b6020026020010151611c5c565b6115945761158d8660018151811061158057611580612401565b6020026020010151611c93565b96506115ad565b6115aa8660018151811061139557611395612401565b96505b5050506116f5565b82516011036116f557855185146116ba575f8686815181106115d9576115d9612401565b016020015160f81c90506115ee6001876124c5565b955060108160ff16106115ff575f80fd5b611624848260ff168151811061161757611617612401565b6020026020010151611ca9565b1561165e576001895161163791906124d8565b8214611641575f80fd5b5050604080515f8152602081019091529550611260945050505050565b611676848260ff168151811061155957611559612401565b61169957611692848260ff168151811061158057611580612401565b94506116b4565b6116b1848260ff168151811061139557611395612401565b94505b506116f5565b600188516116c891906124d8565b81146116d2575f80fd5b6116e88360108151811061143757611437612401565b9650505050505050611260565b806116ff8161248e565b91505061136e565b5050505050509392505050565b606061171f82611c5c565b611727575f80fd5b5f61173183611cc9565b90505f8167ffffffffffffffff81111561174d5761174d611fc2565b60405190808252806020026020018201604052801561179157816020015b604080518082019091525f808252602082015281526020019060019003908161176b5790505b5090505f6117a28560200151611d49565b85602001516117b191906124c5565b90505f805b84811015611819576117c783611dc2565b91506040518060400160405280838152602001848152508482815181106117f0576117f0612401565b602090810291909101015261180582846124c5565b9250806118118161248e565b9150506117b6565b509195945050505050565b80515f901580159061183857508151602110155b611840575f80fd5b5f8061184b84611e6a565b8151919350915060208210156118675760208290036101000a90045b949350505050565b60605f83511161187d575f80fd5b5f8351600261188c91906124eb565b90508083111561189a575f80fd5b6118a483826124d8565b90508067ffffffffffffffff8111156118bf576118bf611fc2565b6040519080825280601f01601f1916602001820160405280156118e9576020820181803683370190505b5091505f835b6118f983866124c5565b811015611a235761190b60028261252f565b5f0361198d5760048661191f600284612542565b8151811061192f5761192f612401565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061195a5761195a612401565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350611a04565b5f8661199a600284612542565b815181106119aa576119aa612401565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b8483815181106119d5576119d5612401565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505b611a0f6001836124c5565b9150611a1c6001826124c5565b90506118ef565b5082518114611a3457611a34612555565b505092915050565b5f6020825f01511015611a575760208201518251902061031d565b602082015182519020604051602001611a7291815260200190565b604051602081830303815290604052805190602001209050919050565b919050565b8051606090611aa1575f80fd5b5f80611aac84611e6a565b915091505f8167ffffffffffffffff811115611aca57611aca611fc2565b6040519080825280601f01601f191660200182016040528015611af4576020820181803683370190505b50905060208101611b06848285611eac565b50949350505050565b5f60605f835111611b1e575f80fd5b5f6004845f81518110611b3357611b33612401565b60209101015160f81c901c600f1690505f818103611b5657505f92506002611b8c565b81600103611b6957505f92506001611b8c565b81600203611b7d5750600192506002611b8c565b816003036100cf575060019250825b83611b97868361186f565b935093505050915091565b5f805b8351611bb186836124c5565b108015611bbe5750825181105b1561186757828181518110611bd557611bd5612401565b01602001517fff000000000000000000000000000000000000000000000000000000000000001684611c0787846124c5565b81518110611c1757611c17612401565b01602001517fff000000000000000000000000000000000000000000000000000000000000001614611c4a579050611260565b80611c548161248e565b915050611ba5565b80515f908103611c6d57505f919050565b602082015180515f1a9060c0821015611c8957505f9392505050565b5060019392505050565b5f805f611c9f84611e6a565b9020949350505050565b80515f90600114611cbb57505f919050565b5060200151515f1a60801490565b80515f908103611cda57505f919050565b5f80611ce98460200151611d49565b8460200151611cf891906124c5565b90505f845f01518560200151611d0e91906124c5565b90505b80821015611d4057611d2282611dc2565b611d2c90836124c5565b915082611d388161248e565b935050611d11565b50909392505050565b80515f90811a6080811015611d6057505f92915050565b60b8811080611d7b575060c08110801590611d7b575060f881105b15611d895750600192915050565b60c0811015611db657611d9e600160b8612582565b611dab9060ff16826124d8565b6112609060016124c5565b611d9e600160f8612582565b80515f908190811a6080811015611ddc5760019150611e63565b60b8811015611e0257611df06080826124d8565b611dfb9060016124c5565b9150611e63565b60c0811015611e2f5760b78103600185019450806020036101000a85510460018201810193505050611e63565b60f8811015611e4357611df060c0826124d8565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b5f805f611e7a8460200151611d49565b90505f818560200151611e8d91906124c5565b90505f82865f0151611e9f91906124d8565b9196919550909350505050565b805f03611eb857505050565b60208110611ef05782518252611ecf6020846124c5565b9250611edc6020836124c5565b9150611ee96020826124d8565b9050611eb8565b80156107b3575f6001611f048360206124d8565b611f10906101006126b9565b611f1a91906124d8565b84518451821691191617835250505050565b5f60208284031215611f3c575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611260575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610334575f80fd5b5f60208284031215611f9c575f80fd5b813561126081611f6b565b80356bffffffffffffffffffffffff81168114611a8f575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561201257612012611fc2565b60405290565b6040805190810167ffffffffffffffff8111828210171561201257612012611fc2565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561208257612082611fc2565b604052919050565b5f601f838184011261209a575f80fd5b8235602067ffffffffffffffff808311156120b7576120b7611fc2565b8260051b6120c683820161203b565b93845286810183019383810190898611156120df575f80fd5b84890192505b85831015612189578235848111156120fc575f8081fd5b8901603f81018b1361210d575f8081fd5b8581013560408682111561212357612123611fc2565b612152887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08c8501160161203b565b8281528d82848601011115612166575f8081fd5b828285018a8301375f9281018901929092525083525091840191908401906120e5565b9998505050505050505050565b5f805f80608085870312156121a9575f80fd5b84356121b481611f6b565b93506121c260208601611fa7565b9250604085013567ffffffffffffffff808211156121de575f80fd5b6121ea8883890161208a565b935060608701359150808211156121ff575f80fd5b5061220c8782880161208a565b91505092959194509250565b5f8060208385031215612229575f80fd5b823567ffffffffffffffff80821115612240575f80fd5b818501915085601f830112612253575f80fd5b813581811115612261575f80fd5b8660208260061b8501011115612275575f80fd5b60209290920196919550909350505050565b5f805f60608486031215612299575f80fd5b83356122a481611f6b565b92506122b260208501611fa7565b9150604084013567ffffffffffffffff808211156122ce575f80fd5b9085019060c082880312156122e1575f80fd5b6122e9611fef565b8235828111156122f7575f80fd5b6123038982860161208a565b825250602083013582811115612317575f80fd5b6123238982860161208a565b60208301525060408301358281111561233a575f80fd5b6123468982860161208a565b60408301525060608301358281111561235d575f80fd5b6123698982860161208a565b606083015250608083013582811115612380575f80fd5b61238c8982860161208a565b60808301525060a0830135828111156123a3575f80fd5b6123af8982860161208a565b60a0830152508093505050509250925092565b5f604082840312156123d2575f80fd5b6123da612018565b82518152602083015164ffffffffff811681146123f5575f80fd5b60208201529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6040828403121561243e575f80fd5b612446612018565b823561245181611f6b565b815260208301356123f581611f6b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036124be576124be612461565b5060010190565b8082018082111561031d5761031d612461565b8181038181111561031d5761031d612461565b808202811582820484141761031d5761031d612461565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261253d5761253d612502565b500690565b5f8261255057612550612502565b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b60ff828116828216039081111561031d5761031d612461565b600181815b808511156125f457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156125da576125da612461565b808516156125e757918102915b93841c93908002906125a0565b509250929050565b5f8261260a5750600161031d565b8161261657505f61031d565b816001811461262c576002811461263657612652565b600191505061031d565b60ff84111561264757612647612461565b50506001821b61031d565b5060208310610133831016604e8410600b8410161715612675575081810a61031d565b61267f838361259b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156126b1576126b1612461565b029392505050565b5f61126083836125fc56fea164736f6c6343000814000a000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf951200000000000000000000000031562ae726afebe25417df01bedc72ef489f45b3

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80638c16b3ba1161007d578063bd6eb23111610058578063bd6eb231146101eb578063edb219c0146101fe578063f6ccaad414610294575f80fd5b80638c16b3ba1461019e5780639378ca56146101b1578063a6d7fdf2146101d8575f80fd5b80634bc66f32116100ad5780634bc66f32146101555780634dd4ee5f146101755780634f8b4ae714610196575f80fd5b806301ffc9a7146100d3578063090f3f50146100fb5780634501409514610140575b5f80fd5b6100e66100e1366004611f2c565b61029c565b60405190151581526020015b60405180910390f35b60015461011b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f2565b61015361014e366004611f8c565b610323565b005b60025461011b9073ffffffffffffffffffffffffffffffffffffffff1681565b610188610183366004612196565b610337565b6040519081526020016100f2565b610153610462565b6101536101ac366004612196565b610486565b61011b7f000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf951281565b6101536101e6366004612218565b610633565b6101536101f9366004612287565b6107b8565b61025b61020c366004611f8c565b60036020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff8116907401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff9091166020830152016100f2565b610153610a19565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061031d57507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526020819052604090205460ff165b92915050565b61032b610a29565b61033481610a7a565b50565b6040517fbb141cf40000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff841660048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf9512169063bb141cf4906024016040805180830381865afa1580156103d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f491906123c2565b90505f610405825f01518887610af0565b90506104198160600151600c5f1b86610c5b565b602001519250825f03610458576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050949350505050565b61046a610a29565b610472610d52565b61047b5f610a7a565b6104845f610da3565b565b73ffffffffffffffffffffffffffffffffffffffff84165f908152600360205260409020547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff16801561052d57806bffffffffffffffffffffffff16846bffffffffffffffffffffffff16101561052d576040517f011d308100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8086165f90815260036020526040902054168061058b576040517f17e740e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61059882878787610337565b6040517f330a73550000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff881660048201526024810182905290915073ffffffffffffffffffffffffffffffffffffffff88169063330a7355906044015f604051808303815f87803b158015610614575f80fd5b505af1158015610626573d5f803e3d5ffd5b5050505050505050505050565b61063b610a29565b5f5b818110156107b3575f83838381811061065857610658612401565b90506040020180360381019061066e919061242e565b60208082015173ffffffffffffffffffffffffffffffffffffffff9081165f90815260039092526040909120549192501615610714576020818101805173ffffffffffffffffffffffffffffffffffffffff9081165f908152600390935260409283902054915183517f729d6d9c000000000000000000000000000000000000000000000000000000008152928216600484015216602482015290519081900360440190fd5b80516020808301805173ffffffffffffffffffffffffffffffffffffffff9081165f9081526003909352604080842080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169583169590951790945590518451935190821693909116917fc662d74d8469d456352095edb1ed6a69f64c66ace9fa3598de77edfccfad12a291a3506107ac8161248e565b905061063d565b505050565b73ffffffffffffffffffffffffffffffffffffffff83165f908152600360205260408120547401000000000000000000000000000000000000000090046bffffffffffffffffffffffff1690811561086057816bffffffffffffffffffffffff16846bffffffffffffffffffffffff161015610860576040517f011d308100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff8085165f9081526003602052604090205416806108bf576040517f17e740e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f806108ce858989610e30565b604080517fc473071e0000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff8e166004820152602481018690526044810185905260648101849052825164ffffffffff908116608483015260208401511660a4820152908201517affffffffffffffffffffffffffffffffffffffffffffffffffffff1660c48201529397509195509350915073ffffffffffffffffffffffffffffffffffffffff8a169063c473071e9060e4015f604051808303815f87803b1580156109a1575f80fd5b505af11580156109b3573d5f803e3d5ffd5b50505073ffffffffffffffffffffffffffffffffffffffff998a165f90815260036020526040902080546bffffffffffffffffffffffff909a16740100000000000000000000000000000000000000000299909a16989098179098555050505050505050565b610a21610d52565b6104846110c7565b60025473ffffffffffffffffffffffffffffffffffffffff163314610484576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a905f90a350565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f825167ffffffffffffffff811115610b3557610b35611fc2565b604051908082528060200260200182016040528015610b7957816020015b604080518082019091525f8082526020820152815260200190600190039081610b535790505b5090505f5b8351811015610bfe57610bd0848281518110610b9c57610b9c612401565b60200260200101516040805180820182525f8082526020918201528151808301909252825182529182019181019190915290565b828281518110610be257610be2612401565b602002602001018190525080610bf79061248e565b9050610b7e565b506040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b166020820152610c52906034016040516020818303038152906040528051906020012086836110f8565b95945050505050565b604080518082019091525f80825260208201525f825167ffffffffffffffff811115610c8957610c89611fc2565b604051908082528060200260200182016040528015610ccd57816020015b604080518082019091525f8082526020820152815260200190600190039081610ca75790505b5090505f5b8351811015610d1e57610cf0848281518110610b9c57610b9c612401565b828281518110610d0257610d02612401565b602002602001018190525080610d179061248e565b9050610cd2565b50610c5284604051602001610d3591815260200190565b604051602081830303815290604052805190602001208683611267565b60015473ffffffffffffffffffffffffffffffffffffffff163314610484576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b604080516060810182525f808252602082018190529181018290528190819050604080516060810182525f8082526020820181905281830181905291517fbb141cf40000000000000000000000000000000000000000000000000000000081526bffffffffffffffffffffffff881660048201529091907f000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf951273ffffffffffffffffffffffffffffffffffffffff169063bb141cf4906024016040805180830381865afa158015610f02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2691906123c2565b90505f610f3a825f01518a895f0151610af0565b9050610f52816060015160025f1b8960200151610c5b565b602001519550610f6e816060015160095f1b8960400151610c5b565b602001519450610f8a816060015160085f1b8960600151610c5b565b6020015193505f610fa7826060015160065f1b8a60800151610c5b565b6020015190505f610fc4836060015160075f1b8b60a00151610c5b565b60209081015164ffffffffff602885901c81169288019290925292168552507affffffffffffffffffffffffffffffffffffffffffffffffffffff1660408401525f86900361103f576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015164ffffffffff165f03611083576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f036110bc576040517fac34915700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505093509350935093565b600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561048433610da3565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f61114f848660405160200161113a91815260200190565b604051602081830303815290604052856112f0565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915290915081515f0361118d5791506112609050565b5f6111c66111c1846040805180820182525f8082526020918201528151808301909252825182529182019181019190915290565b611714565b905080516004146111d5575f80fd5b6001825280516111fc9082905f906111ef576111ef612401565b6020026020010151611824565b6020830152805161121a90829060019081106111ef576111ef612401565b6040830152805161123890829060029081106111ef576111ef612401565b6060830152805161125690829060039081106111ef576111ef612401565b6080830152509150505b9392505050565b604080518082019091525f80825260208201525f611292848660405160200161113a91815260200190565b604080518082019091525f8082526020820152909150815115610c5257600181526040805180820182525f808252602091820152815180830190925283518252808401908201526112e290611824565b602082015295945050505050565b60605f6112fd845f61186f565b90505f80606061131e60405180604001604052805f81526020015f81525090565b86515f0361136c577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218914611351575f80fd5b5050604080515f815260208101909152935061126092505050565b5f5b875181101561170757801580156113ad57506113a988828151811061139557611395612401565b602002602001015160208101519051902090565b8a14155b156113b6575f80fd5b80158015906113e657506113e28882815181106113d5576113d5612401565b6020026020010151611a3c565b8414155b156113ef575f80fd5b61141188828151811061140457611404612401565b6020026020010151611714565b925082516002036115b5575f6060611449611444865f8151811061143757611437612401565b6020026020010151611a94565b611b0f565b90925090505f61145a888a84611ba2565b905061146681896124c5565b975081518110156114c75760018b5161147f91906124d8565b84101561148a575f80fd5b5f5b6040519080825280601f01601f1916602001820160405280156114b6576020820181803683370190505b509950505050505050505050611260565b821561152b5760018b516114db91906124d8565b8410156114e6575f80fd5b88518810156114f5575f61148c565b8560018151811061150857611508612401565b6020026020010151945061151b85611a94565b9950505050505050505050611260565b60018b5161153991906124d8565b8403611543575f80fd5b6115668660018151811061155957611559612401565b6020026020010151611c5c565b6115945761158d8660018151811061158057611580612401565b6020026020010151611c93565b96506115ad565b6115aa8660018151811061139557611395612401565b96505b5050506116f5565b82516011036116f557855185146116ba575f8686815181106115d9576115d9612401565b016020015160f81c90506115ee6001876124c5565b955060108160ff16106115ff575f80fd5b611624848260ff168151811061161757611617612401565b6020026020010151611ca9565b1561165e576001895161163791906124d8565b8214611641575f80fd5b5050604080515f8152602081019091529550611260945050505050565b611676848260ff168151811061155957611559612401565b61169957611692848260ff168151811061158057611580612401565b94506116b4565b6116b1848260ff168151811061139557611395612401565b94505b506116f5565b600188516116c891906124d8565b81146116d2575f80fd5b6116e88360108151811061143757611437612401565b9650505050505050611260565b806116ff8161248e565b91505061136e565b5050505050509392505050565b606061171f82611c5c565b611727575f80fd5b5f61173183611cc9565b90505f8167ffffffffffffffff81111561174d5761174d611fc2565b60405190808252806020026020018201604052801561179157816020015b604080518082019091525f808252602082015281526020019060019003908161176b5790505b5090505f6117a28560200151611d49565b85602001516117b191906124c5565b90505f805b84811015611819576117c783611dc2565b91506040518060400160405280838152602001848152508482815181106117f0576117f0612401565b602090810291909101015261180582846124c5565b9250806118118161248e565b9150506117b6565b509195945050505050565b80515f901580159061183857508151602110155b611840575f80fd5b5f8061184b84611e6a565b8151919350915060208210156118675760208290036101000a90045b949350505050565b60605f83511161187d575f80fd5b5f8351600261188c91906124eb565b90508083111561189a575f80fd5b6118a483826124d8565b90508067ffffffffffffffff8111156118bf576118bf611fc2565b6040519080825280601f01601f1916602001820160405280156118e9576020820181803683370190505b5091505f835b6118f983866124c5565b811015611a235761190b60028261252f565b5f0361198d5760048661191f600284612542565b8151811061192f5761192f612401565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061195a5761195a612401565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350611a04565b5f8661199a600284612542565b815181106119aa576119aa612401565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b8483815181106119d5576119d5612401565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505b611a0f6001836124c5565b9150611a1c6001826124c5565b90506118ef565b5082518114611a3457611a34612555565b505092915050565b5f6020825f01511015611a575760208201518251902061031d565b602082015182519020604051602001611a7291815260200190565b604051602081830303815290604052805190602001209050919050565b919050565b8051606090611aa1575f80fd5b5f80611aac84611e6a565b915091505f8167ffffffffffffffff811115611aca57611aca611fc2565b6040519080825280601f01601f191660200182016040528015611af4576020820181803683370190505b50905060208101611b06848285611eac565b50949350505050565b5f60605f835111611b1e575f80fd5b5f6004845f81518110611b3357611b33612401565b60209101015160f81c901c600f1690505f818103611b5657505f92506002611b8c565b81600103611b6957505f92506001611b8c565b81600203611b7d5750600192506002611b8c565b816003036100cf575060019250825b83611b97868361186f565b935093505050915091565b5f805b8351611bb186836124c5565b108015611bbe5750825181105b1561186757828181518110611bd557611bd5612401565b01602001517fff000000000000000000000000000000000000000000000000000000000000001684611c0787846124c5565b81518110611c1757611c17612401565b01602001517fff000000000000000000000000000000000000000000000000000000000000001614611c4a579050611260565b80611c548161248e565b915050611ba5565b80515f908103611c6d57505f919050565b602082015180515f1a9060c0821015611c8957505f9392505050565b5060019392505050565b5f805f611c9f84611e6a565b9020949350505050565b80515f90600114611cbb57505f919050565b5060200151515f1a60801490565b80515f908103611cda57505f919050565b5f80611ce98460200151611d49565b8460200151611cf891906124c5565b90505f845f01518560200151611d0e91906124c5565b90505b80821015611d4057611d2282611dc2565b611d2c90836124c5565b915082611d388161248e565b935050611d11565b50909392505050565b80515f90811a6080811015611d6057505f92915050565b60b8811080611d7b575060c08110801590611d7b575060f881105b15611d895750600192915050565b60c0811015611db657611d9e600160b8612582565b611dab9060ff16826124d8565b6112609060016124c5565b611d9e600160f8612582565b80515f908190811a6080811015611ddc5760019150611e63565b60b8811015611e0257611df06080826124d8565b611dfb9060016124c5565b9150611e63565b60c0811015611e2f5760b78103600185019450806020036101000a85510460018201810193505050611e63565b60f8811015611e4357611df060c0826124d8565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b5f805f611e7a8460200151611d49565b90505f818560200151611e8d91906124c5565b90505f82865f0151611e9f91906124d8565b9196919550909350505050565b805f03611eb857505050565b60208110611ef05782518252611ecf6020846124c5565b9250611edc6020836124c5565b9150611ee96020826124d8565b9050611eb8565b80156107b3575f6001611f048360206124d8565b611f10906101006126b9565b611f1a91906124d8565b84518451821691191617835250505050565b5f60208284031215611f3c575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611260575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610334575f80fd5b5f60208284031215611f9c575f80fd5b813561126081611f6b565b80356bffffffffffffffffffffffff81168114611a8f575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160c0810167ffffffffffffffff8111828210171561201257612012611fc2565b60405290565b6040805190810167ffffffffffffffff8111828210171561201257612012611fc2565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561208257612082611fc2565b604052919050565b5f601f838184011261209a575f80fd5b8235602067ffffffffffffffff808311156120b7576120b7611fc2565b8260051b6120c683820161203b565b93845286810183019383810190898611156120df575f80fd5b84890192505b85831015612189578235848111156120fc575f8081fd5b8901603f81018b1361210d575f8081fd5b8581013560408682111561212357612123611fc2565b612152887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08c8501160161203b565b8281528d82848601011115612166575f8081fd5b828285018a8301375f9281018901929092525083525091840191908401906120e5565b9998505050505050505050565b5f805f80608085870312156121a9575f80fd5b84356121b481611f6b565b93506121c260208601611fa7565b9250604085013567ffffffffffffffff808211156121de575f80fd5b6121ea8883890161208a565b935060608701359150808211156121ff575f80fd5b5061220c8782880161208a565b91505092959194509250565b5f8060208385031215612229575f80fd5b823567ffffffffffffffff80821115612240575f80fd5b818501915085601f830112612253575f80fd5b813581811115612261575f80fd5b8660208260061b8501011115612275575f80fd5b60209290920196919550909350505050565b5f805f60608486031215612299575f80fd5b83356122a481611f6b565b92506122b260208501611fa7565b9150604084013567ffffffffffffffff808211156122ce575f80fd5b9085019060c082880312156122e1575f80fd5b6122e9611fef565b8235828111156122f7575f80fd5b6123038982860161208a565b825250602083013582811115612317575f80fd5b6123238982860161208a565b60208301525060408301358281111561233a575f80fd5b6123468982860161208a565b60408301525060608301358281111561235d575f80fd5b6123698982860161208a565b606083015250608083013582811115612380575f80fd5b61238c8982860161208a565b60808301525060a0830135828111156123a3575f80fd5b6123af8982860161208a565b60a0830152508093505050509250925092565b5f604082840312156123d2575f80fd5b6123da612018565b82518152602083015164ffffffffff811681146123f5575f80fd5b60208201529392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6040828403121561243e575f80fd5b612446612018565b823561245181611f6b565b815260208301356123f581611f6b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036124be576124be612461565b5060010190565b8082018082111561031d5761031d612461565b8181038181111561031d5761031d612461565b808202811582820484141761031d5761031d612461565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261253d5761253d612502565b500690565b5f8261255057612550612502565b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b60ff828116828216039081111561031d5761031d612461565b600181815b808511156125f457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156125da576125da612461565b808516156125e757918102915b93841c93908002906125a0565b509250929050565b5f8261260a5750600161031d565b8161261657505f61031d565b816001811461262c576002811461263657612652565b600191505061031d565b60ff84111561264757612647612461565b50506001821b61031d565b5060208310610133831016604e8410600b8410161715612675575081810a61031d565b61267f838361259b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156126b1576126b1612461565b029392505050565b5f61126083836125fc56fea164736f6c6343000814000a

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

000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf951200000000000000000000000031562ae726afebe25417df01bedc72ef489f45b3

-----Decoded View---------------
Arg [0] : _stateRootOracle (address): 0xeD403d48e2bC946438B5686AA1AD65056Ccf9512
Arg [1] : _timelockAddress (address): 0x31562ae726AFEBe25417df01bEdC72EF489F45b3

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ed403d48e2bc946438b5686aa1ad65056ccf9512
Arg [1] : 00000000000000000000000031562ae726afebe25417df01bedc72ef489f45b3


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.