ETH Price: $3,071.80 (-6.87%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

3 Internal Transactions found.

Latest 3 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
188291212023-12-20 19:13:11403 days ago1703099591
0x1D610324...57a5CF155
 Contract Creation0 ETH
181156432023-09-11 20:57:35503 days ago1694465855
0x1D610324...57a5CF155
 Contract Creation0 ETH
178115092023-07-31 7:30:35546 days ago1690788635
0x1D610324...57a5CF155
 Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PluggableHatcher

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion
File 1 of 28 : PluggableHatcher.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity 0.8.17;

import "utils.sol/Hatcher.sol";
import "utils.sol/libs/LibSanitize.sol";

import "../src/interfaces/IPluggableHatcher.sol";

/// @title Pluggable Hatcher
/// @author mortimr @ Kiln
/// @notice The PluggableHatcher extends the Hatcher and allows the nexus to spawn cubs
contract PluggableHatcher is Hatcher, IPluggableHatcher {
    using LAddress for types.Address;

    using CAddress for address;

    /// @dev The nexus instance.
    /// @dev Slot: keccak256(bytes("pluggableHatcher.1.nexus")) - 1
    types.Address internal constant $nexus = types.Address.wrap(0xf9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d26559);

    /// @notice Prevents unauthorized calls
    modifier onlyNexus() {
        if (msg.sender != $nexus.get()) {
            revert LibErrors.Unauthorized(msg.sender, $nexus.get());
        }
        _;
    }

    /// @param _implementation Address of the common implementation
    /// @param _admin Address administrating this contract
    /// @param _nexus Address of the nexus allowed to use plug
    constructor(address _implementation, address _admin, address _nexus) {
        LibSanitize.notZeroAddress(_nexus);
        _setImplementation(_implementation);
        _setAdmin(_admin);
        $nexus.set(_nexus);
        emit SetNexus(_nexus);
    }

    /// @inheritdoc IPluggableHatcher
    function nexus() external view returns (address) {
        return $nexus.get();
    }

    /// @inheritdoc IPluggableHatcher
    function plug(bytes calldata cdata) external onlyNexus returns (address) {
        return _hatch(cdata);
    }
}

File 2 of 28 : Hatcher.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./interfaces/IHatcher.sol";

import "./Cub.sol";
import "./Administrable.sol";
import "./Freezable.sol";

import "./libs/LibUint256.sol";

import "./libs/LibSanitize.sol";
import "./types/address.sol";
import "./types/uint256.sol";
import "./types/mapping.sol";
import "./types/array.sol";
import "./types/bool.sol";

/// @title Administrable
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly.
/// @dev In general, regarding the fixes, try to always perform atomic actions to apply them.
/// @dev When using regular fixes, it's already the case.
/// @dev When using global fixes, try to wrap multiple actions in one tx/bundle to create the global fix and apply it on required instances.
/// @dev When removing a global fix, keep in mind that the action can be front runned and the fix that should be removed would be applied.
/// @dev The hatcher can be frozen by the admin. Once frozen, no more upgrade, pausing or fixing is allowed.
/// @dev If frozen and paused, a cub will be unpaused.
/// @dev If frozen and pending fixes are still there, they will be applied to cubs that haven't applied them.
/// @dev If frozen, pending fixes cannot be removed.
/// @dev Initial progress and cub progress can get updated by the admin. This means a fix can be applied twice if progress is decreased.
/// @notice This contract provides all the utilities to handle the administration and its transfer
abstract contract Hatcher is Administrable, Freezable, IHatcher {
    using LAddress for types.Address;
    using LUint256 for types.Uint256;
    using LMapping for types.Mapping;
    using LArray for types.Array;
    using LBool for types.Bool;

    using CAddress for address;
    using CUint256 for uint256;
    using CBool for bool;

    /// @dev Unstructured Storage Helper for hatcher.pauser.
    /// @dev Holds the pauser address.
    /// @dev Slot: keccak256(bytes("hatcher.pauser")) - 1
    types.Address internal constant $pauser =
        types.Address.wrap(0x67ad2ba345683ea58e6dcc49f12611548bc3a5b2c8c753edc1878aa0a76c3ce2);
    /// @dev Unstructured Storage Helper for hatcher.implementation.
    /// @dev Holds the common implementation used by all the cubs.
    /// @dev Slot: keccak256(bytes("hatcher.implementation")) - 1
    types.Address internal constant $implementation =
        types.Address.wrap(0x5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d);
    /// @dev Unstructured Storage Helper for hatcher.initialProgress.
    /// @dev Holds the initial progress value given to all new cubs.
    /// @dev Supersedes the progress of old cubs if the value is higher than their progress.
    /// @dev Slot: keccak256(bytes("hatcher.initialProgress")) - 1
    types.Uint256 internal constant $initialProgress =
        types.Uint256.wrap(0x4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d77);
    /// @dev Unstructured Storage Helper for hatcher.fixProgresses.
    /// @dev Holds the value of the fix progress of every cub.
    /// @dev Type: mapping (address => uint256)
    /// @dev Slot: keccak256(bytes("hatcher.fixProgresses")) - 1
    types.Mapping internal constant $fixProgresses =
        types.Mapping.wrap(0xa7208bf4db7440ac9388b234d45a5b207976f0fc12d31bf9eaa80e4e2fc0d57c);
    /// @dev Unstructured Storage Helper for hatcher.pauseStatus.
    /// @dev Holds the pause status of every cub.
    /// @dev Type: mapping (address => bool)
    /// @dev Slot: keccak256(bytes("hatcher.pauseStatus")) - 1
    types.Mapping internal constant $pauseStatus =
        types.Mapping.wrap(0xd0ad769ee84b03ff353d2cb4c134ab25db1f330b56357f28eadc5b28c2f88991);
    /// @dev Unstructured Storage Helper for hatcher.globalPauseStatus.
    /// @dev Holds the global pause status.
    /// @dev Slot: keccak256(bytes("hatcher.globalPauseStatus")) - 1
    types.Bool internal constant $globalPauseStatus =
        types.Bool.wrap(0x798f8d9ad9ed68e65653cd13b4f27162f01222155b56622ae81337e4888e20c0);
    /// @dev Unstructured Storage Helper for hatcher.fixes.
    /// @dev Holds the array of global fixes.
    /// @dev Slot: keccak256(bytes("hatcher.fixes")) - 1
    types.Array internal constant $fixes =
        types.Array.wrap(0xa8612761e880b1989e2ad0bb2c51004fad089f897b1cd8dc3dbfeae33493df55);
    /// @dev Unstructured Storage Helper for hatcher.initialProgress.
    /// @dev Holds the create2 salt.
    /// @dev Slot: keccak256(bytes("hatcher.creationSalt")) - 1
    types.Uint256 internal constant $creationSalt =
        types.Uint256.wrap(0x7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d);

    /// @dev Only allows admin or pauser to perform the call.
    modifier onlyAdminOrPauser() {
        if (msg.sender != _getAdmin() && msg.sender != $pauser.get()) {
            revert LibErrors.Unauthorized(msg.sender, address(0));
        }
        _;
    }

    /// @inheritdoc IHatcher
    function implementation() external view returns (address) {
        return $implementation.get();
    }

    /// @inheritdoc IHatcher
    // slither-disable-next-line timestamp
    function status(address cub) external view returns (address, bool, bool) {
        return (
            $implementation.get(),
            $fixProgresses.get()[cub.k()] < $fixes.toAddressA().length,
            ($globalPauseStatus.get() || $pauseStatus.get()[cub.k()].toBool()) && !_isFrozen()
        );
    }

    /// @inheritdoc IHatcher
    function initialProgress() external view returns (uint256) {
        return $initialProgress.get();
    }

    /// @inheritdoc IHatcher
    function progress(address cub) external view returns (uint256) {
        return $fixProgresses.get()[cub.k()];
    }

    /// @inheritdoc IHatcher
    function globalPaused() external view returns (bool) {
        return $globalPauseStatus.get();
    }

    /// @inheritdoc IHatcher
    function paused(address cub) external view returns (bool) {
        return $pauseStatus.get()[cub.k()].toBool();
    }

    /// @inheritdoc IHatcher
    function pauser() external view returns (address) {
        return $pauser.get();
    }

    /// @inheritdoc IHatcher
    function fixes(address cub) external view returns (address[] memory) {
        uint256 currentProgress = $fixProgresses.get()[cub.k()];
        uint256 rawFixCount = $fixes.toAddressA().length;
        uint256 fixCount = rawFixCount - LibUint256.min(currentProgress, rawFixCount);
        address[] memory forwardedFixes = new address[](fixCount);

        for (uint256 idx = 0; idx < fixCount;) {
            forwardedFixes[idx] = $fixes.toAddressA()[idx + currentProgress];
            unchecked {
                ++idx;
            }
        }

        return forwardedFixes;
    }

    /// @inheritdoc IHatcher
    /// @dev This method is not view because it reads the fixes from storage.
    function globalFixes() external pure returns (address[] memory) {
        return $fixes.toAddressA();
    }

    /// @inheritdoc IHatcher
    function nextHatch() external view returns (address) {
        return _nextHatch();
    }

    /// @inheritdoc IHatcher
    function frozen() external view returns (bool) {
        return _isFrozen();
    }

    /// @inheritdoc IHatcher
    function freezeTime() external view returns (uint256) {
        return _freezeTime();
    }

    /// @inheritdoc IHatcher
    function hatch(bytes calldata cdata) external virtual onlyAdmin returns (address) {
        return _hatch(cdata);
    }

    /// @inheritdoc IHatcher
    function hatch() external virtual onlyAdmin returns (address) {
        return _hatch("");
    }

    /// @inheritdoc IHatcher
    function commitFixes() external {
        address cub = msg.sender;
        uint256 newProgress = $fixes.toAddressA().length;
        $fixProgresses.get()[cub.k()] = newProgress;
        emit CommittedFixes(cub, newProgress);
    }

    /// @inheritdoc IHatcher
    function setPauser(address newPauser) external onlyAdmin {
        _setPauser(newPauser);
    }

    /// @inheritdoc IHatcher
    // slither-disable-next-line reentrancy-events,calls-loop
    function applyFixToCubs(address fixer, address[] calldata cubs) external notFrozen onlyAdmin {
        LibSanitize.notZeroAddress(fixer);
        uint256 cubCount = cubs.length;
        for (uint256 idx = 0; idx < cubCount;) {
            LibSanitize.notZeroAddress(cubs[idx]);
            Cub(payable(cubs[idx])).applyFix(fixer);
            emit AppliedFix(cubs[idx], fixer);
            unchecked {
                ++idx;
            }
        }
    }

    /// @inheritdoc IHatcher
    // slither-disable-next-line reentrancy-events,calls-loop
    function applyFixesToCub(address cub, address[] calldata fixers) external notFrozen onlyAdmin {
        LibSanitize.notZeroAddress(cub);
        uint256 fixCount = fixers.length;
        for (uint256 idx = 0; idx < fixCount;) {
            LibSanitize.notZeroAddress(fixers[idx]);
            Cub(payable(cub)).applyFix(fixers[idx]);
            emit AppliedFix(cub, fixers[idx]);
            unchecked {
                ++idx;
            }
        }
    }

    /// @inheritdoc IHatcher
    function registerGlobalFix(address fixer) external notFrozen onlyAdmin {
        LibSanitize.notZeroAddress(fixer);
        $fixes.toAddressA().push(fixer);
        emit RegisteredGlobalFix(fixer, $fixes.toAddressA().length - 1);
    }

    /// @inheritdoc IHatcher
    function deleteGlobalFix(uint256 index) external notFrozen onlyAdmin {
        $fixes.toAddressA()[index] = address(0);
        emit DeletedGlobalFix(index);
    }

    /// @inheritdoc IHatcher
    function upgradeTo(address newImplementation) external notFrozen onlyAdmin {
        _setImplementation(newImplementation);
    }

    /// @inheritdoc IHatcher
    function upgradeToAndChangeInitialProgress(address newImplementation, uint256 initialProgress_)
        external
        notFrozen
        onlyAdmin
    {
        _setInitialProgress(initialProgress_);
        _setImplementation(newImplementation);
    }

    /// @inheritdoc IHatcher
    function setInitialProgress(uint256 initialProgress_) external notFrozen onlyAdmin {
        _setInitialProgress(initialProgress_);
    }

    /// @inheritdoc IHatcher
    function setCubProgress(address cub, uint256 newProgress) external notFrozen onlyAdmin {
        $fixProgresses.get()[cub.k()] = newProgress;
        emit CommittedFixes(cub, newProgress);
    }

    /// @inheritdoc IHatcher
    function pauseCubs(address[] calldata cubs) external notFrozen onlyAdminOrPauser {
        for (uint256 idx = 0; idx < cubs.length;) {
            LibSanitize.notZeroAddress(cubs[idx]);
            _pause(cubs[idx]);
            unchecked {
                ++idx;
            }
        }
    }

    /// @inheritdoc IHatcher
    function unpauseCubs(address[] calldata cubs) external notFrozen onlyAdmin {
        for (uint256 idx = 0; idx < cubs.length;) {
            LibSanitize.notZeroAddress(cubs[idx]);
            _unpause(cubs[idx]);
            unchecked {
                ++idx;
            }
        }
    }

    /// @inheritdoc IHatcher
    function globalPause() external notFrozen onlyAdminOrPauser {
        $globalPauseStatus.set(true);
        emit GlobalPause();
    }

    /// @inheritdoc IHatcher
    function globalUnpause() external notFrozen onlyAdmin {
        $globalPauseStatus.set(false);
        emit GlobalUnpause();
    }

    /// @inheritdoc IHatcher
    function freeze(uint256 freezeTimeout) external {
        _freeze(freezeTimeout);
    }

    /// @inheritdoc IHatcher
    function cancelFreeze() external {
        _cancelFreeze();
    }

    /// @dev Internal utility to set the pauser address.
    /// @param newPauser Address of the new pauser
    function _setPauser(address newPauser) internal {
        $pauser.set(newPauser);
        emit SetPauser(newPauser);
    }

    /// @dev Internal utility to change the common implementation.
    /// @dev Reverts if the new implementation is not a contract.
    /// @param newImplementation Address of the new implementation
    function _setImplementation(address newImplementation) internal {
        LibSanitize.notZeroAddress(newImplementation);
        if (newImplementation.code.length == 0) {
            revert ImplementationNotAContract(newImplementation);
        }
        $implementation.set(newImplementation);
        emit Upgraded(newImplementation);
    }

    /// @dev Internal utility to retrieve the address of the next deployed Cub.
    /// @return Address of the next cub
    // slither-disable-next-line too-many-digits
    function _nextHatch() internal view returns (address) {
        return address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex"ff", address(this), bytes32($creationSalt.get()), keccak256(type(Cub).creationCode)
                        )
                    )
                )
            )
        );
    }

    /// @dev Internal utility to create a new Cub.
    /// @dev The provided cdata is used to perform an atomic call upon contract creation.
    /// @param cdata The calldata to use for the atomic creation call
    // slither-disable-next-line reentrancy-events
    function _hatch(bytes memory cdata) internal returns (address cub) {
        uint256 salt = $creationSalt.get();
        $creationSalt.set(salt + 1);
        cub = address((new Cub){salt: bytes32(salt)}());

        uint256 currentInitialProgress = $initialProgress.get();
        if (currentInitialProgress > 0) {
            $fixProgresses.get()[cub.k()] = currentInitialProgress;
        }

        Cub(payable(cub)).___initializeCub(address(this), cdata);
        emit Hatched(cub, cdata);
    }

    /// @dev Internal utility to pause a cub.
    /// @param cub The cub to pause
    function _pause(address cub) internal {
        $pauseStatus.get()[cub.k()] = true.v();
        emit Pause(cub);
    }

    /// @dev Internal utility to unpause a cub.
    /// @param cub The cub to unpause
    function _unpause(address cub) internal {
        $pauseStatus.get()[cub.k()] = false.v();
        emit Unpause(cub);
    }

    /// @dev Internal utility to set the initial cub progress.
    /// @dev This value defines where the new cubs should start applying fixes from the global fix array.
    /// @dev This value supersedes existing cub progresses if the progress is lower than this value.
    /// @param initialProgress_ New initial progress
    function _setInitialProgress(uint256 initialProgress_) internal {
        $initialProgress.set(initialProgress_);
        emit SetInitialProgress(initialProgress_);
    }

    /// @dev Internal utility to retrieve the address of the freezer.
    /// @return Address of the freezer
    function _getFreezer() internal view override returns (address) {
        return _getAdmin();
    }
}

File 3 of 28 : LibSanitize.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./LibErrors.sol";
import "./LibConstant.sol";

/// @title Lib Sanitize
/// @dev This library helps sanitizing inputs.
library LibSanitize {
    /// @dev Internal utility to sanitize an address and ensure its value is not 0.
    /// @param addressValue The address to verify
    // slither-disable-next-line dead-code
    function notZeroAddress(address addressValue) internal pure {
        if (addressValue == address(0)) {
            revert LibErrors.InvalidZeroAddress();
        }
    }

    /// @dev Internal utility to sanitize an uint256 value and ensure its value is not 0.
    /// @param value The value to verify
    // slither-disable-next-line dead-code
    function notNullValue(uint256 value) internal pure {
        if (value == 0) {
            revert LibErrors.InvalidNullValue();
        }
    }

    /// @dev Internal utility to sanitize a bps value and ensure it's <= 100%.
    /// @param value The bps value to verify
    // slither-disable-next-line dead-code
    function notInvalidBps(uint256 value) internal pure {
        if (value > LibConstant.BASIS_POINTS_MAX) {
            revert LibErrors.InvalidBPSValue();
        }
    }

    /// @dev Internal utility to sanitize a string value and ensure it's not empty.
    /// @param stringValue The string value to verify
    // slither-disable-next-line dead-code
    function notEmptyString(string memory stringValue) internal pure {
        if (bytes(stringValue).length == 0) {
            revert LibErrors.InvalidEmptyString();
        }
    }
}

File 4 of 28 : IPluggableHatcher.sol
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity 0.8.17;

/// @title Pluggable Hatcher Interface
/// @author mortimr @ Kiln
/// @notice The PluggableHatcher extends the Hatcher and allows the nexus to spawn cubs
interface IPluggableHatcher {
    /// @notice Emitted when the stored Nexus address is changed
    /// @param nexus The new nexus address
    event SetNexus(address nexus);

    /// @notice Method allowing the Nexus to hatch a new cub
    /// @param cdata The calldata to provide to the hatch method
    /// @return The address of the new cub
    function plug(bytes calldata cdata) external returns (address);

    /// @notice Retrieve the configured nexus address
    /// @return The nexus address
    function nexus() external view returns (address);
}

File 5 of 28 : IHatcher.sol
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "openzeppelin-contracts/proxy/beacon/IBeacon.sol";

/// @title Hatcher Interface
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice The Hatcher can deploy, upgrade, fix and pause a set of instances called cubs.
///         All cubs point to the same coomon implementation.
interface IHatcher is IBeacon {
    /// @notice Emitted when the system is globally paused.
    event GlobalPause();

    /// @notice Emitted when the system is globally unpaused.
    event GlobalUnpause();

    /// @notice Emitted when a specific cub is paused.
    /// @param cub Address of the cub being paused
    event Pause(address cub);

    /// @notice Emitted when a specific cub is unpaused.
    /// @param cub Address of the cub being unpaused
    event Unpause(address cub);

    /// @notice Emitted when a global fix is removed.
    /// @param index Index of the global fix being removed
    event DeletedGlobalFix(uint256 index);

    /// @notice Emitted when a cub has properly applied a fix.
    /// @param cub Address of the cub that applied the fix
    /// @param fix Address of the fix was applied
    event AppliedFix(address cub, address fix);

    /// @notice Emitted the common implementation is updated.
    /// @param implementation New common implementation address
    event Upgraded(address indexed implementation);

    /// @notice Emitted a new cub is hatched.
    /// @param cub Address of the new instance
    /// @param cdata Calldata used to perform the atomic first call
    event Hatched(address indexed cub, bytes cdata);

    /// @notice Emitted a the initial progress has been changed.
    /// @param initialProgress New initial progress value
    event SetInitialProgress(uint256 initialProgress);

    /// @notice Emitted a new pauser is set.
    /// @param pauser Address of the new pauser
    event SetPauser(address pauser);

    /// @notice Emitted a cub committed some global fixes.
    /// @param cub Address of the cub that applied the global fixes
    /// @param progress New cub progress
    event CommittedFixes(address cub, uint256 progress);

    /// @notice Emitted a global fix is registered.
    /// @param fix Address of the new global fix
    /// @param index Index of the new global fix in the global fix array
    event RegisteredGlobalFix(address fix, uint256 index);

    /// @notice The provided implementation is not a smart contract.
    /// @param implementation The provided implementation
    error ImplementationNotAContract(address implementation);

    /// @notice Retrieve the common implementation.
    /// @return implementationAddress Address of the common implementation
    function implementation() external view returns (address implementationAddress);

    /// @notice Retrieve cub status details.
    /// @param cub The address of the cub to fetch the status of
    /// @return implementationAddress The current implementation address to use
    /// @return hasFixes True if there are fixes to apply
    /// @return isPaused True if the system is paused globally or the calling cub is paused
    function status(address cub) external view returns (address implementationAddress, bool hasFixes, bool isPaused);

    /// @notice Retrieve the initial progress.
    /// @dev This value is the starting progress value for all new cubs
    /// @return currentInitialProgress The initial progress
    function initialProgress() external view returns (uint256 currentInitialProgress);

    /// @notice Retrieve the current progress of a specific cub.
    /// @param cub Address of the cub
    /// @return currentProgress The current progress of the cub
    function progress(address cub) external view returns (uint256 currentProgress);

    /// @notice Retrieve the global pause status.
    /// @return isGlobalPaused True if globally paused
    function globalPaused() external view returns (bool isGlobalPaused);

    /// @notice Retrieve a cub pause status.
    /// @param cub Address of the cub
    /// @return isPaused True if paused
    function paused(address cub) external view returns (bool isPaused);

    /// @notice Retrieve the address of the pauser.
    function pauser() external view returns (address);

    /// @notice Retrieve a cub's global fixes that need to be applied, taking its progress into account.
    /// @param cub Address of the cub
    /// @return fixesAddresses An array of addresses that implement fixes
    function fixes(address cub) external view returns (address[] memory fixesAddresses);

    /// @notice Retrieve the raw list of global fixes.
    /// @return globalFixesAddresses An array of addresses that implement the global fixes
    function globalFixes() external view returns (address[] memory globalFixesAddresses);

    /// @notice Retrieve the address of the next hatched cub.
    /// @return nextHatchedCub The address of the next cub
    function nextHatch() external view returns (address nextHatchedCub);

    /// @notice Retrieve the freeze status.
    /// @return True if frozen
    function frozen() external view returns (bool);

    /// @notice Retrieve the timestamp when the freeze happens.
    /// @return The freeze timestamp
    function freezeTime() external view returns (uint256);

    /// @notice Creates a new cub.
    /// @param cdata The calldata to use for the initial atomic call
    /// @return cubAddress The address of the new cub
    function hatch(bytes calldata cdata) external returns (address cubAddress);

    /// @notice Creates a new cub, without calldata.
    /// @return cubAddress The address of the new cub
    function hatch() external returns (address cubAddress);

    /// @notice Sets the progress of the caller to the current global fixes array length.
    function commitFixes() external;

    /// @notice Sets the address of the pauser.
    /// @param newPauser Address of the new pauser
    function setPauser(address newPauser) external;

    /// @notice Apply a fix to several cubs.
    /// @param fixer Fixer contract implementing the fix
    /// @param cubs List of cubs to apply the fix on
    function applyFixToCubs(address fixer, address[] calldata cubs) external;

    /// @notice Apply several fixes to one cub.
    /// @param cub The cub to apply the fixes on
    /// @param fixers List of fixer contracts implementing the fixes
    function applyFixesToCub(address cub, address[] calldata fixers) external;

    /// @notice Register a new global fix for cubs to call asynchronously.
    /// @param fixer Address of the fixer implementing the fix
    function registerGlobalFix(address fixer) external;

    /// @notice Deletes a global fix from the array.
    /// @param index Index of the global fix to remove
    function deleteGlobalFix(uint256 index) external;

    /// @notice Upgrades the common implementation address.
    /// @param newImplementation Address of the new common implementation
    function upgradeTo(address newImplementation) external;

    /// @notice Upgrades the common implementation address and the initial progress value.
    /// @param newImplementation Address of the new common implementation
    /// @param initialProgress_ The new initial progress value
    function upgradeToAndChangeInitialProgress(address newImplementation, uint256 initialProgress_) external;

    /// @notice Sets the initial progress value.
    /// @param initialProgress_ The new initial progress value
    function setInitialProgress(uint256 initialProgress_) external;

    /// @notice Sets the progress of a cub.
    /// @param cub Address of the cub
    /// @param newProgress New progress value
    function setCubProgress(address cub, uint256 newProgress) external;

    /// @notice Pauses a set of cubs.
    /// @param cubs List of cubs to pause
    function pauseCubs(address[] calldata cubs) external;

    /// @notice Unpauses a set of cubs.
    /// @param cubs List of cubs to unpause
    function unpauseCubs(address[] calldata cubs) external;

    /// @notice Pauses all the cubs of the system.
    function globalPause() external;

    /// @notice Unpauses all the cubs of the system.
    /// @dev If a cub was specifically paused, this method won't unpause it
    function globalUnpause() external;

    /// @notice Sets the freeze timestamp.
    /// @param freezeTimeout The timeout to add to current timestamp before freeze happens
    function freeze(uint256 freezeTimeout) external;

    /// @notice Cancels the freezing procedure.
    function cancelFreeze() external;
}

File 6 of 28 : Cub.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "openzeppelin-contracts/proxy/beacon/BeaconProxy.sol";
import "./interfaces/IFixer.sol";
import "./interfaces/IHatcher.sol";
import "./interfaces/ICub.sol";

/// @title Cub
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice The cub is controlled by a Hatcher in charge of providing its status details and implementation address.
contract Cub is Proxy, ERC1967Upgrade, ICub {
    /// @notice Initializer to not rely on the constructor.
    /// @param beacon The address of the beacon to pull its info from
    /// @param data The calldata to add to the initial call, if any
    // slither-disable-next-line naming-convention
    function ___initializeCub(address beacon, bytes memory data) external {
        if (_getBeacon() != address(0)) {
            revert CubAlreadyInitialized();
        }
        _upgradeBeaconToAndCall(beacon, data, false);
    }

    /// @dev Internal utility to retrieve the implementation from the beacon.
    /// @return The implementation address
    // slither-disable-next-line dead-code
    function _implementation() internal view virtual override returns (address) {
        return IBeacon(_getBeacon()).implementation();
    }

    /// @dev Prevents unauthorized calls.
    /// @dev This will make the method transparent, forcing unauthorized callers into the fallback.
    modifier onlyBeacon() {
        if (msg.sender != _getBeacon()) {
            _fallback();
        } else {
            _;
        }
    }

    /// @dev Prevents unauthorized calls.
    /// @dev This will make the method transparent, forcing unauthorized callers into the fallback.
    modifier onlyMe() {
        if (msg.sender != address(this)) {
            _fallback();
        } else {
            _;
        }
    }

    /// @inheritdoc ICub
    // slither-disable-next-line reentrancy-events
    function appliedFixes(address[] memory fixers) public onlyMe {
        emit AppliedFixes(fixers);
    }

    /// @inheritdoc ICub
    function applyFix(address fixer) external onlyBeacon {
        _applyFix(fixer);
    }

    /// @dev Retrieve the list of fixes for this cub from the hatcher.
    /// @param beacon Address of the hatcher acting as a beacon
    /// @return List of fixes to apply
    function _fixes(address beacon) internal view returns (address[] memory) {
        return IHatcher(beacon).fixes(address(this));
    }

    /// @dev Retrieve the status for this cub from the hatcher.
    /// @param beacon Address of the hatcher acting as a beacon
    /// @return First value is true if fixes are pending, second value is true if cub is paused
    function _status(address beacon) internal view returns (address, bool, bool) {
        return IHatcher(beacon).status(address(this));
    }

    /// @dev Commits fixes to the hatcher.
    /// @param beacon Address of the hatcher acting as a beacon
    function _commit(address beacon) internal {
        IHatcher(beacon).commitFixes();
    }

    /// @dev Fetches the current cub status and acts accordingly.
    /// @param beacon Address of the hatcher acting as a beacon
    function _fix(address beacon) internal returns (address) {
        (address implementation, bool hasFixes, bool isPaused) = _status(beacon);
        if (isPaused && msg.sender != address(0)) {
            revert CalledWhenPaused(msg.sender);
        }
        if (hasFixes) {
            bool isStaticCall = false;
            address[] memory fixes = _fixes(beacon);
            // This is a trick to check if the current execution context
            // allows state modifications
            try this.appliedFixes(fixes) {}
            catch {
                isStaticCall = true;
            }
            // if we properly emitted AppliedFixes, we are not in a view or pure call
            // we can then apply fixes
            if (!isStaticCall) {
                for (uint256 idx = 0; idx < fixes.length;) {
                    if (fixes[idx] != address(0)) {
                        _applyFix(fixes[idx]);
                    }

                    unchecked {
                        ++idx;
                    }
                }
                _commit(beacon);
            }
        }
        return implementation;
    }

    /// @dev Applies the given fix, and reverts in case of error.
    /// @param fixer Address that implements the fix
    // slither-disable-next-line controlled-delegatecall,delegatecall-loop,low-level-calls
    function _applyFix(address fixer) internal {
        (bool success, bytes memory rdata) = fixer.delegatecall(abi.encodeCall(IFixer.fix, ()));
        if (!success) {
            revert FixDelegateCallError(fixer, rdata);
        }
        (success) = abi.decode(rdata, (bool));
        if (!success) {
            revert FixCallError(fixer);
        }
    }

    /// @dev Fallback method that ends up forwarding calls as delegatecalls to the implementation.
    function _fallback() internal override(Proxy) {
        _beforeFallback();
        address beacon = _getBeacon();
        address implementation = _fix(beacon);
        _delegate(implementation);
    }
}

File 7 of 28 : Administrable.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./libs/LibSanitize.sol";
import "./types/address.sol";
import "./interfaces/IAdministrable.sol";

/// @title Administrable
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice This contract provides all the utilities to handle the administration and its transfer.
abstract contract Administrable is IAdministrable {
    using LAddress for types.Address;

    /// @dev The admin address in storage.
    /// @dev Slot: keccak256(bytes("administrable.admin")) - 1
    types.Address internal constant $admin =
        types.Address.wrap(0x927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af09);
    /// @dev The pending admin address in storage.
    /// @dev Slot: keccak256(bytes("administrable.pendingAdmin")) - 1
    types.Address internal constant $pendingAdmin =
        types.Address.wrap(0x3c1eebcc225c6cc7f5f8765767af6eff617b4139dc3624923a2db67dbca7b68e);

    /// @dev This modifier ensures that only the admin is able to call the method.
    modifier onlyAdmin() {
        if (msg.sender != _getAdmin()) {
            revert LibErrors.Unauthorized(msg.sender, _getAdmin());
        }
        _;
    }

    /// @dev This modifier ensures that only the pending admin is able to call the method.
    modifier onlyPendingAdmin() {
        if (msg.sender != _getPendingAdmin()) {
            revert LibErrors.Unauthorized(msg.sender, _getPendingAdmin());
        }
        _;
    }

    /// @inheritdoc IAdministrable
    function admin() external view returns (address) {
        return _getAdmin();
    }

    /// @inheritdoc IAdministrable
    function pendingAdmin() external view returns (address) {
        return _getPendingAdmin();
    }

    /// @notice Propose a new admin.
    /// @dev Only callable by the admin.
    /// @param newAdmin The new admin to propose
    function transferAdmin(address newAdmin) external onlyAdmin {
        _setPendingAdmin(newAdmin);
    }

    /// @notice Accept an admin transfer.
    /// @dev Only callable by the pending admin.
    function acceptAdmin() external onlyPendingAdmin {
        _setAdmin(msg.sender);
        _setPendingAdmin(address(0));
    }

    /// @dev Retrieve the admin address.
    /// @return The admin address
    function _getAdmin() internal view returns (address) {
        return $admin.get();
    }

    /// @dev Change the admin address.
    /// @param newAdmin The new admin address
    function _setAdmin(address newAdmin) internal {
        LibSanitize.notZeroAddress(newAdmin);
        emit SetAdmin(newAdmin);
        $admin.set(newAdmin);
    }

    /// @dev Retrieve the pending admin address.
    /// @return The pending admin address
    function _getPendingAdmin() internal view returns (address) {
        return $pendingAdmin.get();
    }

    /// @dev Change the pending admin address.
    /// @param newPendingAdmin The new pending admin address
    function _setPendingAdmin(address newPendingAdmin) internal {
        emit SetPendingAdmin(newPendingAdmin);
        $pendingAdmin.set(newPendingAdmin);
    }
}

File 8 of 28 : Freezable.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

// For some unexplainable and mysterious reason, adding this line would make slither crash
// This is the reason why we are not using our own unstructured storage libs in this contract
// (while the libs work properly in a lot of contracts without slither having any issue with it)
// import "./types/uint256.sol";

import "./libs/LibErrors.sol";
import "./libs/LibConstant.sol";
import "openzeppelin-contracts/utils/StorageSlot.sol";

/// @title Freezable
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice The Freezable contract is used to add a freezing capability to admin related actions.
///         The goal would be to ossify an implementation after a certain amount of time.
// slither-disable-next-line unimplemented-functions
abstract contract Freezable {
    /// @notice Thrown when a call happened while it was forbidden when frozen.
    error Frozen();

    /// @notice Thrown when the provided timeout value is lower than 100 days.
    /// @param providedValue The user provided value
    /// @param minimumValue The minimum allowed value
    error FreezeTimeoutTooLow(uint256 providedValue, uint256 minimumValue);

    /// @notice Emitted when the freeze timeout is changed.
    /// @param freezeTime The timestamp after which the contract will be frozen
    event SetFreezeTime(uint256 freezeTime);

    /// @dev This is the keccak-256 hash of "freezable.freeze_timestamp" subtracted by 1.
    bytes32 private constant _FREEZE_TIMESTAMP_SLOT = 0x04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a;

    /// @dev Only callable by the freezer account.
    modifier onlyFreezer() {
        _onlyFreezer();
        _;
    }

    /// @dev Only callable when not frozen.
    modifier notFrozen() {
        _notFrozen();
        _;
    }

    /// @dev Override and set it to return the address to consider as the freezer.
    /// @return The freezer address
    // slither-disable-next-line dead-code
    function _getFreezer() internal view virtual returns (address);

    /// @dev Retrieve the freeze status.
    /// @return True if contract is frozen
    // slither-disable-next-line dead-code,timestamp
    function _isFrozen() internal view returns (bool) {
        uint256 freezeTime_ = _freezeTime();
        return (freezeTime_ > 0 && block.timestamp >= freezeTime_);
    }

    /// @dev Retrieve the freeze timestamp.
    /// @return The freeze timestamp
    // slither-disable-next-line dead-code
    function _freezeTime() internal view returns (uint256) {
        return StorageSlot.getUint256Slot(_FREEZE_TIMESTAMP_SLOT).value;
    }

    /// @dev Internal utility to set the freeze timestamp.
    /// @param freezeTime The new freeze timestamp
    // slither-disable-next-line dead-code
    function _setFreezeTime(uint256 freezeTime) internal {
        StorageSlot.getUint256Slot(_FREEZE_TIMESTAMP_SLOT).value = freezeTime;
        emit SetFreezeTime(freezeTime);
    }

    /// @dev Internal utility to revert if caller is not freezer.
    // slither-disable-next-line dead-code
    function _onlyFreezer() internal view {
        if (msg.sender != _getFreezer()) {
            revert LibErrors.Unauthorized(msg.sender, _getFreezer());
        }
    }

    /// @dev Internal utility to revert if contract is frozen.
    // slither-disable-next-line dead-code
    function _notFrozen() internal view {
        if (_isFrozen()) {
            revert Frozen();
        }
    }

    /// @dev Internal utility to start the freezing procedure.
    /// @param freezeTimeout Timeout to add to current timestamp to define freeze timestamp
    // slither-disable-next-line dead-code
    function _freeze(uint256 freezeTimeout) internal {
        _notFrozen();
        _onlyFreezer();
        if (freezeTimeout < LibConstant.MINIMUM_FREEZE_TIMEOUT) {
            revert FreezeTimeoutTooLow(freezeTimeout, LibConstant.MINIMUM_FREEZE_TIMEOUT);
        }

        // overflow would revert
        uint256 now_ = block.timestamp;
        uint256 freezeTime_ = now_ + freezeTimeout;

        _setFreezeTime(freezeTime_);
    }

    /// @dev Internal utility to cancel the freezing procedure.
    // slither-disable-next-line dead-code
    function _cancelFreeze() internal {
        _notFrozen();
        _onlyFreezer();
        _setFreezeTime(0);
    }
}

File 9 of 28 : LibUint256.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "prb-math/PRBMath.sol";

library LibUint256 {
    // slither-disable-next-line dead-code
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        // slither-disable-next-line assembly
        assembly {
            z := xor(x, mul(xor(x, y), lt(y, x)))
        }
    }

    /// @custom:author Vectorized/solady#58681e79de23082fd3881a76022e0842f5c08db8
    // slither-disable-next-line dead-code
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        // slither-disable-next-line assembly
        assembly {
            z := xor(x, mul(xor(x, y), gt(y, x)))
        }
    }

    // slither-disable-next-line dead-code
    function mulDiv(uint256 a, uint256 b, uint256 c) internal pure returns (uint256) {
        return PRBMath.mulDiv(a, b, c);
    }

    // slither-disable-next-line dead-code
    function ceil(uint256 num, uint256 den) internal pure returns (uint256) {
        return (num / den) + (num % den > 0 ? 1 : 0);
    }
}

File 10 of 28 : address.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./types.sol";

/// @notice Library Address - Address slot utilities.
library LAddress {
    // slither-disable-next-line dead-code, assembly
    function get(types.Address position) internal view returns (address data) {
        // slither-disable-next-line assembly
        assembly {
            data := sload(position)
        }
    }

    // slither-disable-next-line dead-code
    function set(types.Address position, address data) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, data)
        }
    }

    // slither-disable-next-line dead-code
    function del(types.Address position) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, 0)
        }
    }
}

library CAddress {
    // slither-disable-next-line dead-code
    function toUint256(address val) internal pure returns (uint256) {
        return uint256(uint160(val));
    }

    // slither-disable-next-line dead-code
    function toBytes32(address val) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(val)));
    }

    // slither-disable-next-line dead-code
    function toBool(address val) internal pure returns (bool converted) {
        // slither-disable-next-line assembly
        assembly {
            converted := gt(val, 0)
        }
    }

    /// @notice This method should be used to convert an address to a uint256 when used as a key in a mapping.
    // slither-disable-next-line dead-code
    function k(address val) internal pure returns (uint256) {
        return toUint256(val);
    }

    /// @notice This method should be used to convert an address to a uint256 when used as a value in a mapping.
    // slither-disable-next-line dead-code
    function v(address val) internal pure returns (uint256) {
        return toUint256(val);
    }
}

File 11 of 28 : uint256.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./types.sol";

library LUint256 {
    // slither-disable-next-line dead-code
    function get(types.Uint256 position) internal view returns (uint256 data) {
        // slither-disable-next-line assembly
        assembly {
            data := sload(position)
        }
    }

    // slither-disable-next-line dead-code
    function set(types.Uint256 position, uint256 data) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, data)
        }
    }

    // slither-disable-next-line dead-code
    function del(types.Uint256 position) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, 0)
        }
    }
}

library CUint256 {
    // slither-disable-next-line dead-code
    function toBytes32(uint256 val) internal pure returns (bytes32) {
        return bytes32(val);
    }

    // slither-disable-next-line dead-code
    function toAddress(uint256 val) internal pure returns (address) {
        return address(uint160(val));
    }

    // slither-disable-next-line dead-code
    function toBool(uint256 val) internal pure returns (bool) {
        return (val & 1) == 1;
    }
}

File 12 of 28 : mapping.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./types.sol";

library LMapping {
    // slither-disable-next-line dead-code
    function get(types.Mapping position) internal pure returns (mapping(uint256 => uint256) storage data) {
        // slither-disable-next-line assembly
        assembly {
            data.slot := position
        }
    }
}

File 13 of 28 : array.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./types.sol";

library LArray {
    // slither-disable-next-line dead-code
    function toUintA(types.Array position) internal pure returns (uint256[] storage data) {
        // slither-disable-next-line assembly
        assembly {
            data.slot := position
        }
    }

    // slither-disable-next-line dead-code
    function toAddressA(types.Array position) internal pure returns (address[] storage data) {
        // slither-disable-next-line assembly
        assembly {
            data.slot := position
        }
    }

    // slither-disable-next-line dead-code
    function toBoolA(types.Array position) internal pure returns (bool[] storage data) {
        // slither-disable-next-line assembly
        assembly {
            data.slot := position
        }
    }

    // slither-disable-next-line dead-code
    function toBytes32A(types.Array position) internal pure returns (bytes32[] storage data) {
        // slither-disable-next-line assembly
        assembly {
            data.slot := position
        }
    }

    // slither-disable-next-line dead-code
    function del(types.Array position) internal {
        // slither-disable-next-line assembly
        assembly {
            let len := sload(position)

            if len {
                // clear the length slot
                sstore(position, 0)

                // calculate the starting slot of the array elements in storage
                mstore(0, position)
                let startPtr := keccak256(0, 0x20)

                for {} len {} {
                    len := sub(len, 1)
                    sstore(add(startPtr, len), 0)
                }
            }
        }
    }

    /// @dev This delete can be used if and only if we only want to clear the length of the array.
    ///         Doing so will create an array that behaves like an empty array in solidity.
    ///         It can have advantages if we often rewrite to the same slots of the array.
    ///         Prefer using `del` if you don't know what you're doing.
    // slither-disable-next-line dead-code
    function dangerousDirtyDel(types.Array position) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, 0)
        }
    }
}

File 14 of 28 : bool.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

import "./types.sol";

library LBool {
    // slither-disable-next-line dead-code
    function get(types.Bool position) internal view returns (bool data) {
        // slither-disable-next-line assembly
        assembly {
            data := sload(position)
        }
    }

    // slither-disable-next-line dead-code
    function set(types.Bool position, bool data) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, data)
        }
    }

    // slither-disable-next-line dead-code
    function del(types.Bool position) internal {
        // slither-disable-next-line assembly
        assembly {
            sstore(position, 0)
        }
    }
}

library CBool {
    // slither-disable-next-line dead-code
    function toBytes32(bool val) internal pure returns (bytes32) {
        return bytes32(toUint256(val));
    }

    // slither-disable-next-line dead-code
    function toAddress(bool val) internal pure returns (address) {
        return address(uint160(toUint256(val)));
    }

    // slither-disable-next-line dead-code
    function toUint256(bool val) internal pure returns (uint256 converted) {
        // slither-disable-next-line assembly
        assembly {
            converted := iszero(iszero(val))
        }
    }

    /// @dev This method should be used to convert a bool to a uint256 when used as a key in a mapping.
    // slither-disable-next-line dead-code
    function k(bool val) internal pure returns (uint256) {
        return toUint256(val);
    }

    /// @dev This method should be used to convert a bool to a uint256 when used as a value in a mapping.
    // slither-disable-next-line dead-code
    function v(bool val) internal pure returns (uint256) {
        return toUint256(val);
    }
}

File 15 of 28 : LibErrors.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

library LibErrors {
    error Unauthorized(address account, address expected);
    error InvalidZeroAddress();
    error InvalidNullValue();
    error InvalidBPSValue();
    error InvalidEmptyString();
}

File 16 of 28 : LibConstant.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

library LibConstant {
    /// @dev The basis points value representing 100%.
    uint256 internal constant BASIS_POINTS_MAX = 10_000;
    /// @dev The size of a deposit to activate a validator.
    uint256 internal constant DEPOSIT_SIZE = 32 ether;
    /// @dev The minimum freeze timeout before freeze is active.
    uint256 internal constant MINIMUM_FREEZE_TIMEOUT = 100 days;
    /// @dev Address used to represent ETH when an address is required to identify an asset.
    address internal constant ETHER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}

File 17 of 28 : IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 18 of 28 : BeaconProxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)

pragma solidity ^0.8.0;

import "./IBeacon.sol";
import "../Proxy.sol";
import "../ERC1967/ERC1967Upgrade.sol";

/**
 * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.
 *
 * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
 * conflict with the storage layout of the implementation behind the proxy.
 *
 * _Available since v3.4._
 */
contract BeaconProxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the proxy with `beacon`.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
     * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity
     * constructor.
     *
     * Requirements:
     *
     * - `beacon` must be a contract with the interface {IBeacon}.
     */
    constructor(address beacon, bytes memory data) payable {
        _upgradeBeaconToAndCall(beacon, data, false);
    }

    /**
     * @dev Returns the current beacon address.
     */
    function _beacon() internal view virtual returns (address) {
        return _getBeacon();
    }

    /**
     * @dev Returns the current implementation address of the associated beacon.
     */
    function _implementation() internal view virtual override returns (address) {
        return IBeacon(_getBeacon()).implementation();
    }

    /**
     * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
     *
     * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
     *
     * Requirements:
     *
     * - `beacon` must be a contract.
     * - The implementation returned by `beacon` must be a contract.
     */
    function _setBeacon(address beacon, bytes memory data) internal virtual {
        _upgradeBeaconToAndCall(beacon, data, false);
    }
}

File 19 of 28 : IFixer.sol
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

/// @title Fixer
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice The Hatcher can deploy, upgrade, fix and pause a set of instances called cubs.
///         All cubs point to the same common implementation.
interface IFixer {
    /// @notice Interface to implement on a Fixer contract.
    /// @return isFixed True if fix was properly applied
    function fix() external returns (bool isFixed);
}

File 20 of 28 : ICub.sol
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

/// @title Cub
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice The cub is controlled by a Hatcher in charge of providing its status details and implementation address.
interface ICub {
    /// @notice An error occured when performing the delegatecall to the fix.
    /// @param fixer Address implementing the fix
    /// @param err The return data from the call error
    error FixDelegateCallError(address fixer, bytes err);

    /// @notice The fix method failed by returning false.
    /// @param fixer Added implementing the fix
    error FixCallError(address fixer);

    /// @notice A call was made while the cub was paused.
    /// @param caller The address that performed the call
    error CalledWhenPaused(address caller);

    error CubAlreadyInitialized();

    /// @notice Emitted when several fixes have been applied.
    /// @param fixes List of fixes to apply
    event AppliedFixes(address[] fixes);

    /// @notice Public method that emits the AppliedFixes event.
    /// @dev Transparent to all callers except the cub itself
    /// @dev Only callable by the cub itself as a regular call
    /// @dev This method is used to detect the execution context (view/non-view)
    /// @param _fixers List of applied fixes
    function appliedFixes(address[] memory _fixers) external;

    /// @notice Applies the provided fix.
    /// @dev Transparent to all callers except the hatcher
    /// @param _fixer The address of the contract implementing the fix to apply
    function applyFix(address _fixer) external;
}

File 21 of 28 : IAdministrable.sol
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

/// @title Administrable Interface
/// @author mortimr @ Kiln
/// @dev Unstructured Storage Friendly
/// @notice This contract provides all the utilities to handle the administration and its transfer.
interface IAdministrable {
    /// @notice The admin address has been changed.
    /// @param admin The new admin address
    event SetAdmin(address admin);

    /// @notice The pending admin address has been changed.
    /// @param pendingAdmin The pending admin has been changed
    event SetPendingAdmin(address pendingAdmin);

    /// @notice Retrieve the admin address.
    /// @return adminAddress The admin address
    function admin() external view returns (address adminAddress);

    /// @notice Retrieve the pending admin address.
    /// @return pendingAdminAddress The pending admin address
    function pendingAdmin() external view returns (address pendingAdminAddress);

    /// @notice Propose a new admin.
    /// @dev Only callable by the admin
    /// @param _newAdmin The new admin to propose
    function transferAdmin(address _newAdmin) external;

    /// @notice Accept an admin transfer.
    /// @dev Only callable by the pending admin
    function acceptAdmin() external;
}

File 22 of 28 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}

File 23 of 28 : PRBMath.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);

/// @notice Emitted when one of the inputs is type(int256).min.
error PRBMath__MulDivSignedInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows int256.
error PRBMath__MulDivSignedOverflow(uint256 rAbs);

/// @notice Emitted when the input is MIN_SD59x18.
error PRBMathSD59x18__AbsInputTooSmall();

/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMathSD59x18__CeilOverflow(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__DivInputTooSmall();

/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
error PRBMathSD59x18__DivOverflow(uint256 rAbs);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathSD59x18__ExpInputTooBig(int256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathSD59x18__Exp2InputTooBig(int256 x);

/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMathSD59x18__FloorUnderflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMathSD59x18__FromIntOverflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMathSD59x18__FromIntUnderflow(int256 x);

/// @notice Emitted when the product of the inputs is negative.
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);

/// @notice Emitted when multiplying the inputs overflows SD59x18.
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);

/// @notice Emitted when the input is less than or equal to zero.
error PRBMathSD59x18__LogInputTooSmall(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__MulInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__MulOverflow(uint256 rAbs);

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);

/// @notice Emitted when the input is negative.
error PRBMathSD59x18__SqrtNegativeInput(int256 x);

/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMathSD59x18__SqrtOverflow(int256 x);

/// @notice Emitted when addition overflows UD60x18.
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);

/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMathUD60x18__CeilOverflow(uint256 x);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathUD60x18__ExpInputTooBig(uint256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
error PRBMathUD60x18__FromUintOverflow(uint256 x);

/// @notice Emitted when multiplying the inputs overflows UD60x18.
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);

/// @notice Emitted when the input is less than 1.
error PRBMathUD60x18__LogInputTooSmall(uint256 x);

/// @notice Emitted when the calculating the square root overflows UD60x18.
error PRBMathUD60x18__SqrtOverflow(uint256 x);

/// @notice Emitted when subtraction underflows UD60x18.
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);

/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
library PRBMath {
    /// STRUCTS ///

    struct SD59x18 {
        int256 value;
    }

    struct UD60x18 {
        uint256 value;
    }

    /// STORAGE ///

    /// @dev How many trailing decimals can be represented.
    uint256 internal constant SCALE = 1e18;

    /// @dev Largest power of two divisor of SCALE.
    uint256 internal constant SCALE_LPOTD = 262144;

    /// @dev SCALE inverted mod 2^256.
    uint256 internal constant SCALE_INVERSE =
        78156646155174841979727994598816262306175212592076161876661_508869554232690281;

    /// FUNCTIONS ///

    /// @notice Calculates the binary exponent of x using the binary fraction method.
    /// @dev Has to use 192.64-bit fixed-point numbers.
    /// See https://ethereum.stackexchange.com/a/96594/24693.
    /// @param x The exponent as an unsigned 192.64-bit fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function exp2(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            // Start from 0.5 in the 192.64-bit fixed-point format.
            result = 0x800000000000000000000000000000000000000000000000;

            // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
            // because the initial result is 2^191 and all magic factors are less than 2^65.
            if (x & 0x8000000000000000 > 0) {
                result = (result * 0x16A09E667F3BCC909) >> 64;
            }
            if (x & 0x4000000000000000 > 0) {
                result = (result * 0x1306FE0A31B7152DF) >> 64;
            }
            if (x & 0x2000000000000000 > 0) {
                result = (result * 0x1172B83C7D517ADCE) >> 64;
            }
            if (x & 0x1000000000000000 > 0) {
                result = (result * 0x10B5586CF9890F62A) >> 64;
            }
            if (x & 0x800000000000000 > 0) {
                result = (result * 0x1059B0D31585743AE) >> 64;
            }
            if (x & 0x400000000000000 > 0) {
                result = (result * 0x102C9A3E778060EE7) >> 64;
            }
            if (x & 0x200000000000000 > 0) {
                result = (result * 0x10163DA9FB33356D8) >> 64;
            }
            if (x & 0x100000000000000 > 0) {
                result = (result * 0x100B1AFA5ABCBED61) >> 64;
            }
            if (x & 0x80000000000000 > 0) {
                result = (result * 0x10058C86DA1C09EA2) >> 64;
            }
            if (x & 0x40000000000000 > 0) {
                result = (result * 0x1002C605E2E8CEC50) >> 64;
            }
            if (x & 0x20000000000000 > 0) {
                result = (result * 0x100162F3904051FA1) >> 64;
            }
            if (x & 0x10000000000000 > 0) {
                result = (result * 0x1000B175EFFDC76BA) >> 64;
            }
            if (x & 0x8000000000000 > 0) {
                result = (result * 0x100058BA01FB9F96D) >> 64;
            }
            if (x & 0x4000000000000 > 0) {
                result = (result * 0x10002C5CC37DA9492) >> 64;
            }
            if (x & 0x2000000000000 > 0) {
                result = (result * 0x1000162E525EE0547) >> 64;
            }
            if (x & 0x1000000000000 > 0) {
                result = (result * 0x10000B17255775C04) >> 64;
            }
            if (x & 0x800000000000 > 0) {
                result = (result * 0x1000058B91B5BC9AE) >> 64;
            }
            if (x & 0x400000000000 > 0) {
                result = (result * 0x100002C5C89D5EC6D) >> 64;
            }
            if (x & 0x200000000000 > 0) {
                result = (result * 0x10000162E43F4F831) >> 64;
            }
            if (x & 0x100000000000 > 0) {
                result = (result * 0x100000B1721BCFC9A) >> 64;
            }
            if (x & 0x80000000000 > 0) {
                result = (result * 0x10000058B90CF1E6E) >> 64;
            }
            if (x & 0x40000000000 > 0) {
                result = (result * 0x1000002C5C863B73F) >> 64;
            }
            if (x & 0x20000000000 > 0) {
                result = (result * 0x100000162E430E5A2) >> 64;
            }
            if (x & 0x10000000000 > 0) {
                result = (result * 0x1000000B172183551) >> 64;
            }
            if (x & 0x8000000000 > 0) {
                result = (result * 0x100000058B90C0B49) >> 64;
            }
            if (x & 0x4000000000 > 0) {
                result = (result * 0x10000002C5C8601CC) >> 64;
            }
            if (x & 0x2000000000 > 0) {
                result = (result * 0x1000000162E42FFF0) >> 64;
            }
            if (x & 0x1000000000 > 0) {
                result = (result * 0x10000000B17217FBB) >> 64;
            }
            if (x & 0x800000000 > 0) {
                result = (result * 0x1000000058B90BFCE) >> 64;
            }
            if (x & 0x400000000 > 0) {
                result = (result * 0x100000002C5C85FE3) >> 64;
            }
            if (x & 0x200000000 > 0) {
                result = (result * 0x10000000162E42FF1) >> 64;
            }
            if (x & 0x100000000 > 0) {
                result = (result * 0x100000000B17217F8) >> 64;
            }
            if (x & 0x80000000 > 0) {
                result = (result * 0x10000000058B90BFC) >> 64;
            }
            if (x & 0x40000000 > 0) {
                result = (result * 0x1000000002C5C85FE) >> 64;
            }
            if (x & 0x20000000 > 0) {
                result = (result * 0x100000000162E42FF) >> 64;
            }
            if (x & 0x10000000 > 0) {
                result = (result * 0x1000000000B17217F) >> 64;
            }
            if (x & 0x8000000 > 0) {
                result = (result * 0x100000000058B90C0) >> 64;
            }
            if (x & 0x4000000 > 0) {
                result = (result * 0x10000000002C5C860) >> 64;
            }
            if (x & 0x2000000 > 0) {
                result = (result * 0x1000000000162E430) >> 64;
            }
            if (x & 0x1000000 > 0) {
                result = (result * 0x10000000000B17218) >> 64;
            }
            if (x & 0x800000 > 0) {
                result = (result * 0x1000000000058B90C) >> 64;
            }
            if (x & 0x400000 > 0) {
                result = (result * 0x100000000002C5C86) >> 64;
            }
            if (x & 0x200000 > 0) {
                result = (result * 0x10000000000162E43) >> 64;
            }
            if (x & 0x100000 > 0) {
                result = (result * 0x100000000000B1721) >> 64;
            }
            if (x & 0x80000 > 0) {
                result = (result * 0x10000000000058B91) >> 64;
            }
            if (x & 0x40000 > 0) {
                result = (result * 0x1000000000002C5C8) >> 64;
            }
            if (x & 0x20000 > 0) {
                result = (result * 0x100000000000162E4) >> 64;
            }
            if (x & 0x10000 > 0) {
                result = (result * 0x1000000000000B172) >> 64;
            }
            if (x & 0x8000 > 0) {
                result = (result * 0x100000000000058B9) >> 64;
            }
            if (x & 0x4000 > 0) {
                result = (result * 0x10000000000002C5D) >> 64;
            }
            if (x & 0x2000 > 0) {
                result = (result * 0x1000000000000162E) >> 64;
            }
            if (x & 0x1000 > 0) {
                result = (result * 0x10000000000000B17) >> 64;
            }
            if (x & 0x800 > 0) {
                result = (result * 0x1000000000000058C) >> 64;
            }
            if (x & 0x400 > 0) {
                result = (result * 0x100000000000002C6) >> 64;
            }
            if (x & 0x200 > 0) {
                result = (result * 0x10000000000000163) >> 64;
            }
            if (x & 0x100 > 0) {
                result = (result * 0x100000000000000B1) >> 64;
            }
            if (x & 0x80 > 0) {
                result = (result * 0x10000000000000059) >> 64;
            }
            if (x & 0x40 > 0) {
                result = (result * 0x1000000000000002C) >> 64;
            }
            if (x & 0x20 > 0) {
                result = (result * 0x10000000000000016) >> 64;
            }
            if (x & 0x10 > 0) {
                result = (result * 0x1000000000000000B) >> 64;
            }
            if (x & 0x8 > 0) {
                result = (result * 0x10000000000000006) >> 64;
            }
            if (x & 0x4 > 0) {
                result = (result * 0x10000000000000003) >> 64;
            }
            if (x & 0x2 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }
            if (x & 0x1 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }

            // We're doing two things at the same time:
            //
            //   1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
            //      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
            //      rather than 192.
            //   2. Convert the result to the unsigned 60.18-decimal fixed-point format.
            //
            // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
            result *= SCALE;
            result >>= (191 - (x >> 64));
        }
    }

    /// @notice Finds the zero-based index of the first one in the binary representation of x.
    /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
    /// @param x The uint256 number for which to find the index of the most significant bit.
    /// @return msb The index of the most significant bit as an uint256.
    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
        if (x >= 2**128) {
            x >>= 128;
            msb += 128;
        }
        if (x >= 2**64) {
            x >>= 64;
            msb += 64;
        }
        if (x >= 2**32) {
            x >>= 32;
            msb += 32;
        }
        if (x >= 2**16) {
            x >>= 16;
            msb += 16;
        }
        if (x >= 2**8) {
            x >>= 8;
            msb += 8;
        }
        if (x >= 2**4) {
            x >>= 4;
            msb += 4;
        }
        if (x >= 2**2) {
            x >>= 2;
            msb += 2;
        }
        if (x >= 2**1) {
            // No need to shift x any more.
            msb += 1;
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
    ///
    /// Requirements:
    /// - The denominator cannot be zero.
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The multiplicand as an uint256.
    /// @param y The multiplier as an uint256.
    /// @param denominator The divisor as an uint256.
    /// @return result The result as an uint256.
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
        // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2^256 + prod0.
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(x, y, not(0))
            prod0 := mul(x, y)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        // Handle non-overflow cases, 256 by 256 division.
        if (prod1 == 0) {
            unchecked {
                result = prod0 / denominator;
            }
            return result;
        }

        // Make sure the result is less than 2^256. Also prevents denominator == 0.
        if (prod1 >= denominator) {
            revert PRBMath__MulDivOverflow(prod1, denominator);
        }

        ///////////////////////////////////////////////
        // 512 by 256 division.
        ///////////////////////////////////////////////

        // Make division exact by subtracting the remainder from [prod1 prod0].
        uint256 remainder;
        assembly {
            // Compute remainder using mulmod.
            remainder := mulmod(x, y, denominator)

            // Subtract 256 bit number from 512 bit number.
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }

        // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
        // See https://cs.stackexchange.com/q/138556/92363.
        unchecked {
            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 lpotdod = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by lpotdod.
                denominator := div(denominator, lpotdod)

                // Divide [prod1 prod0] by lpotdod.
                prod0 := div(prod0, lpotdod)

                // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
                lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * lpotdod;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /// @notice Calculates floor(x*y÷1e18) with full precision.
    ///
    /// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
    /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
    /// being rounded to 1e-18.  See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
    ///
    /// Requirements:
    /// - The result must fit within uint256.
    ///
    /// Caveats:
    /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
    /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
    ///     1. x * y = type(uint256).max * SCALE
    ///     2. (x * y) % SCALE >= SCALE / 2
    ///
    /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
    /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
    /// @return result The result as an unsigned 60.18-decimal fixed-point number.
    function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
        uint256 prod0;
        uint256 prod1;
        assembly {
            let mm := mulmod(x, y, not(0))
            prod0 := mul(x, y)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }

        if (prod1 >= SCALE) {
            revert PRBMath__MulDivFixedPointOverflow(prod1);
        }

        uint256 remainder;
        uint256 roundUpUnit;
        assembly {
            remainder := mulmod(x, y, SCALE)
            roundUpUnit := gt(remainder, 499999999999999999)
        }

        if (prod1 == 0) {
            unchecked {
                result = (prod0 / SCALE) + roundUpUnit;
                return result;
            }
        }

        assembly {
            result := add(
                mul(
                    or(
                        div(sub(prod0, remainder), SCALE_LPOTD),
                        mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
                    ),
                    SCALE_INVERSE
                ),
                roundUpUnit
            )
        }
    }

    /// @notice Calculates floor(x*y÷denominator) with full precision.
    ///
    /// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
    ///
    /// Requirements:
    /// - None of the inputs can be type(int256).min.
    /// - The result must fit within int256.
    ///
    /// @param x The multiplicand as an int256.
    /// @param y The multiplier as an int256.
    /// @param denominator The divisor as an int256.
    /// @return result The result as an int256.
    function mulDivSigned(
        int256 x,
        int256 y,
        int256 denominator
    ) internal pure returns (int256 result) {
        if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
            revert PRBMath__MulDivSignedInputTooSmall();
        }

        // Get hold of the absolute values of x, y and the denominator.
        uint256 ax;
        uint256 ay;
        uint256 ad;
        unchecked {
            ax = x < 0 ? uint256(-x) : uint256(x);
            ay = y < 0 ? uint256(-y) : uint256(y);
            ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
        }

        // Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
        uint256 rAbs = mulDiv(ax, ay, ad);
        if (rAbs > uint256(type(int256).max)) {
            revert PRBMath__MulDivSignedOverflow(rAbs);
        }

        // Get the signs of x, y and the denominator.
        uint256 sx;
        uint256 sy;
        uint256 sd;
        assembly {
            sx := sgt(x, sub(0, 1))
            sy := sgt(y, sub(0, 1))
            sd := sgt(denominator, sub(0, 1))
        }

        // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
        // If yes, the result should be negative.
        result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
    }

    /// @notice Calculates the square root of x, rounding down.
    /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
    ///
    /// Caveats:
    /// - This function does not work with fixed-point numbers.
    ///
    /// @param x The uint256 number for which to calculate the square root.
    /// @return result The result as an uint256.
    function sqrt(uint256 x) internal pure returns (uint256 result) {
        if (x == 0) {
            return 0;
        }

        // Set the initial guess to the least power of two that is greater than or equal to sqrt(x).
        uint256 xAux = uint256(x);
        result = 1;
        if (xAux >= 0x100000000000000000000000000000000) {
            xAux >>= 128;
            result <<= 64;
        }
        if (xAux >= 0x10000000000000000) {
            xAux >>= 64;
            result <<= 32;
        }
        if (xAux >= 0x100000000) {
            xAux >>= 32;
            result <<= 16;
        }
        if (xAux >= 0x10000) {
            xAux >>= 16;
            result <<= 8;
        }
        if (xAux >= 0x100) {
            xAux >>= 8;
            result <<= 4;
        }
        if (xAux >= 0x10) {
            xAux >>= 4;
            result <<= 2;
        }
        if (xAux >= 0x8) {
            result <<= 1;
        }

        // The operations can never overflow because the result is max 2^127 when it enters this block.
        unchecked {
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1;
            result = (result + x / result) >> 1; // Seven iterations should be enough
            uint256 roundedDownResult = x / result;
            return result >= roundedDownResult ? roundedDownResult : result;
        }
    }
}

File 24 of 28 : types.sol
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: 2023 Kiln <[email protected]>
//
// ██╗  ██╗██╗██╗     ███╗   ██╗
// ██║ ██╔╝██║██║     ████╗  ██║
// █████╔╝ ██║██║     ██╔██╗ ██║
// ██╔═██╗ ██║██║     ██║╚██╗██║
// ██║  ██╗██║███████╗██║ ╚████║
// ╚═╝  ╚═╝╚═╝╚══════╝╚═╝  ╚═══╝
//
pragma solidity >=0.8.17;

/// @dev Library holding bytes32 custom types
// slither-disable-next-line naming-convention
library types {
    type Uint256 is bytes32;
    type Address is bytes32;
    type Bytes32 is bytes32;
    type Bool is bytes32;
    type String is bytes32;
    type Mapping is bytes32;
    type Array is bytes32;
}

File 25 of 28 : Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

File 26 of 28 : ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeacon.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967Upgrade {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}

File 27 of 28 : draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

Settings
{
  "remappings": [
    "deploy.sol/=lib/deploy.sol/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-gas-snapshot/=lib/forge-gas-snapshot/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "prb-math/=lib/utils.sol/lib/prb-math/contracts/",
    "solmate/=lib/deploy.sol/lib/solmate/src/",
    "utils.sol.test/=lib/utils.sol/test/",
    "utils.sol/=lib/utils.sol/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "vulcan/=lib/vulcan/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_implementation","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_nexus","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"providedValue","type":"uint256"},{"internalType":"uint256","name":"minimumValue","type":"uint256"}],"name":"FreezeTimeoutTooLow","type":"error"},{"inputs":[],"name":"Frozen","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ImplementationNotAContract","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"cub","type":"address"},{"indexed":false,"internalType":"address","name":"fix","type":"address"}],"name":"AppliedFix","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"cub","type":"address"},{"indexed":false,"internalType":"uint256","name":"progress","type":"uint256"}],"name":"CommittedFixes","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"DeletedGlobalFix","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalPause","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalUnpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cub","type":"address"},{"indexed":false,"internalType":"bytes","name":"cdata","type":"bytes"}],"name":"Hatched","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"cub","type":"address"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fix","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"RegisteredGlobalFix","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"SetAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"freezeTime","type":"uint256"}],"name":"SetFreezeTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initialProgress","type":"uint256"}],"name":"SetInitialProgress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nexus","type":"address"}],"name":"SetNexus","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pauser","type":"address"}],"name":"SetPauser","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pendingAdmin","type":"address"}],"name":"SetPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"cub","type":"address"}],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fixer","type":"address"},{"internalType":"address[]","name":"cubs","type":"address[]"}],"name":"applyFixToCubs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"},{"internalType":"address[]","name":"fixers","type":"address[]"}],"name":"applyFixesToCub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelFreeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commitFixes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"deleteGlobalFix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"}],"name":"fixes","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"freezeTimeout","type":"uint256"}],"name":"freeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freezeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalFixes","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"globalPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"globalPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalUnpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"cdata","type":"bytes"}],"name":"hatch","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hatch","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialProgress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextHatch","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nexus","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"cubs","type":"address[]"}],"name":"pauseCubs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"}],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"cdata","type":"bytes"}],"name":"plug","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"}],"name":"progress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fixer","type":"address"}],"name":"registerGlobalFix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"},{"internalType":"uint256","name":"newProgress","type":"uint256"}],"name":"setCubProgress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialProgress_","type":"uint256"}],"name":"setInitialProgress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPauser","type":"address"}],"name":"setPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cub","type":"address"}],"name":"status","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"cubs","type":"address[]"}],"name":"unpauseCubs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"uint256","name":"initialProgress_","type":"uint256"}],"name":"upgradeToAndChangeInitialProgress","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162002e7e38038062002e7e833981016040819052620000349162000282565b6200004a81620000e260201b620012fe1760201c565b62000055836200010d565b6200006082620001d2565b6200009d817ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d2655960001b6200026160201b620013251790919060201c565b6040516001600160a01b03821681527ff32604fed544dfbdef9fe3da7f51a9c2cb416b8a2cf0e47818420dee34ba20ea9060200160405180910390a1505050620002cc565b6001600160a01b0381166200010a5760405163f6b2911f60e01b815260040160405180910390fd5b50565b6200012381620000e260201b620012fe1760201c565b806001600160a01b03163b6000036200015e57604051637a905aed60e01b81526001600160a01b038216600482015260240160405180910390fd5b6200019b817f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d60001b6200026160201b620013251790919060201c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b620001e881620000e260201b620012fe1760201c565b6040516001600160a01b03821681527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a16200010a817f927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af0960001b6200026160201b620013251790919060201c565b9055565b80516001600160a01b03811681146200027d57600080fd5b919050565b6000806000606084860312156200029857600080fd5b620002a38462000265565b9250620002b36020850162000265565b9150620002c36040850162000265565b90509250925092565b612ba280620002dc6000396000f3fe608060405234801561001057600080fd5b506004361061021b5760003560e01c80636906d58211610125578063ce190578116100ad578063df199c331161007c578063df199c3314610448578063f0772f311461045b578063f12d54d81461046e578063f851a44014610476578063fd7e1bee1461047e57600080fd5b8063ce19057814610412578063d0db50831461041a578063d7a78db814610422578063da8589a21461043557600080fd5b80639fd0506d116100f45780639fd0506d146103d4578063a3f5c1d2146103dc578063a70070bf146103e4578063abec754b146103f7578063bad490dc1461040a57600080fd5b80636906d5821461039e57806375829def146103a6578063764cb8c9146103b9578063797f1165146103c157600080fd5b80633638f367116101a857806359740f901161017757806359740f90146103395780635c60da1b1461034c57806361a552dc14610354578063645b8b1b1461035c57806365413a4d1461039657600080fd5b80633638f367146102ed5780633659cfe61461030057806338267bda146103135780633d9c33241461032657600080fd5b8063229659e2116101ef578063229659e21461027e57806326782247146102a95780632d88af4a146102b15780632e48152c146102c45780633173250d146102d757600080fd5b806275ee0a1461022057806302c5220614610235578063054f7d9c1461025e5780630e18b68114610276575b600080fd5b61023361022e366004611acb565b610486565b005b610248610243366004611b1e565b610629565b6040516102559190611b39565b60405180910390f35b610266610769565b6040519015158152602001610255565b610233610778565b61029161028c366004611b86565b6107b6565b6040516001600160a01b039091168152602001610255565b610291610869565b6102336102bf366004611b1e565b610873565b6102666102d2366004611b1e565b6108a8565b6102df6108e8565b604051908152602001610255565b6102336102fb366004611b1e565b610912565b61023361030e366004611b1e565b6109ec565b610291610321366004611b86565b610a26565b610233610334366004611bf8565b610a51565b610233610347366004611c22565b610b01565b610291610b8e565b610266610bb8565b61036f61036a366004611b1e565b610bd0565b604080516001600160a01b0390941684529115156020840152151590820152606001610255565b610233610ca2565b610248610cc9565b6102336103b4366004611b1e565b610d38565b610291610d6a565b6102336103cf366004611bf8565b610d74565b610291610dbb565b610291610dd3565b6102336103f2366004611c22565b610dfd565b610233610405366004611acb565b610ecd565b61023361102b565b610233611033565b6102916110a1565b610233610430366004611c64565b6110e4565b6102df610443366004611b1e565b6110ed565b610233610456366004611c64565b611128565b610233610469366004611c64565b6111da565b610233611214565b6102916112ca565b6102df6112d4565b61048e611329565b61049661134f565b6001600160a01b0316336001600160a01b0316146104e857336104b761134f565b60405163295a81c160e01b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b6104f1836112fe565b8060005b818110156106225761052c84848381811061051257610512611c7d565b90506020020160208101906105279190611b1e565b6112fe565b83838281811061053e5761053e611c7d565b90506020020160208101906105539190611b1e565b604051630fc5bd3b60e01b81526001600160a01b0387811660048301529190911690630fc5bd3b90602401600060405180830381600087803b15801561059857600080fd5b505af11580156105ac573d6000803e3d6000fd5b505050507fa1b2d2f59fced963b3e7cb859bc1fb60c12512c583987498d4b818e9b7ca24df8484838181106105e3576105e3611c7d565b90506020020160208101906105f89190611b1e565b604080516001600160a01b03928316815291881660208301520160405180910390a16001016104f5565b5050505050565b60606000600080516020612acd8339815191526000610650856001600160a01b0316611379565b8152602001908152602001600020549050600061067b600080516020612aed83398151915260001b90565b549050600061069283831883851102841883611ca9565b905060008167ffffffffffffffff8111156106af576106af611cbc565b6040519080825280602002602001820160405280156106d8578160200160208202803683370190505b50905060005b8281101561075f57600080516020612aed8339815191526106ff8683611cd2565b8154811061070f5761070f611c7d565b9060005260206000200160009054906101000a90046001600160a01b031682828151811061073f5761073f611c7d565b6001600160a01b03909216602092830291909101909101526001016106de565b5095945050505050565b600061077361138a565b905090565b6107806113cd565b6001600160a01b0316336001600160a01b0316146107a157336104b76113cd565b6107aa336113f7565b6107b46000611465565b565b60006107e07ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b6001600160a01b0316336001600160a01b03161461082157336104b77ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b61086083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114ca92505050565b90505b92915050565b60006107736113cd565b61087b61134f565b6001600160a01b0316336001600160a01b03161461089c57336104b761134f565b6108a58161166a565b50565b6000610863600080516020612b2d83398151915260006108d0856001600160a01b0316611379565b81526020019081526020016000205460019081161490565b60006107737f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d775490565b61091a611329565b61092261134f565b6001600160a01b0316336001600160a01b03161461094357336104b761134f565b61094c816112fe565b600080516020612aed833981519152805460018082018355600092835260209092200180546001600160a01b0319166001600160a01b0384161790557fbafcedce88399447ff8d2ae013b9ee0f8cabab75b253dd514ece06253b7b0b97908290600080516020612aed833981519152546109c69190611ca9565b604080516001600160a01b0390931683526020830191909152015b60405180910390a150565b6109f4611329565b6109fc61134f565b6001600160a01b0316336001600160a01b031614610a1d57336104b761134f565b6108a5816116ba565b6000610a3061134f565b6001600160a01b0316336001600160a01b03161461082157336104b761134f565b610a59611329565b610a6161134f565b6001600160a01b0316336001600160a01b031614610a8257336104b761134f565b80600080516020612acd8339815191525b6000610aa7856001600160a01b0316611379565b815260208082019290925260409081016000209290925581516001600160a01b03851681529081018390527f7e32675c5ba8a706b96979a4e952dc30ddac837d9d0e79220c766936da9be782910160405180910390a15050565b610b09611329565b610b1161134f565b6001600160a01b0316336001600160a01b031614610b3257336104b761134f565b60005b81811015610b8957610b5283838381811061051257610512611c7d565b610b81838383818110610b6757610b67611c7d565b9050602002016020810190610b7c9190611b1e565b611759565b600101610b35565b505050565b60006107737f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d5490565b6000610773600080516020612b4d8339815191525490565b60008080610bfc7f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d5490565b600080516020612aed83398151915254600080516020612acd8339815191526000610c2f886001600160a01b0316611379565b81526020019081526020016000205410610c58600080516020612b4d83398151915260001b5490565b80610c845750610c84600080516020612b2d83398151915260006108d0896001600160a01b0316611379565b8015610c955750610c9361138a565b155b9250925092509193909250565b600080516020612aed83398151915254339080600080516020612acd833981519152610a93565b6060600080516020612aed833981519152805480602002602001604051908101604052809291908181526020018280548015610d2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d10575b5050505050905090565b610d4061134f565b6001600160a01b0316336001600160a01b031614610d6157336104b761134f565b6108a581611465565b60006107736117d3565b610d7c611329565b610d8461134f565b6001600160a01b0316336001600160a01b031614610da557336104b761134f565b610dae8161188b565b610db7826116ba565b5050565b6000610773600080516020612b0d8339815191525490565b60006107737ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b610e05611329565b610e0d61134f565b6001600160a01b0316336001600160a01b031614158015610e4f5750600080516020612b0d833981519152546001600160a01b0316336001600160a01b031614155b15610e765760405163295a81c160e01b8152336004820152600060248201526044016104df565b60005b81811015610b8957610e9683838381811061051257610512611c7d565b610ec5838383818110610eab57610eab611c7d565b9050602002016020810190610ec09190611b1e565b6118e4565b600101610e79565b610ed5611329565b610edd61134f565b6001600160a01b0316336001600160a01b031614610efe57336104b761134f565b610f07836112fe565b8060005b8181101561062257610f2884848381811061051257610512611c7d565b846001600160a01b0316630fc5bd3b858584818110610f4957610f49611c7d565b9050602002016020810190610f5e9190611b1e565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610f9f57600080fd5b505af1158015610fb3573d6000803e3d6000fd5b505050507fa1b2d2f59fced963b3e7cb859bc1fb60c12512c583987498d4b818e9b7ca24df85858584818110610feb57610feb611c7d565b90506020020160208101906110009190611b1e565b604080516001600160a01b0393841681529290911660208301520160405180910390a1600101610f0b565b6107b461195e565b61103b611329565b61104361134f565b6001600160a01b0316336001600160a01b03161461106457336104b761134f565b6000600080516020612b4d833981519152556040517f09b17ad4b525602f3a736c430612735b5047e4dcc19b82ae55ae7789fb6b0b2790600090a1565b60006110ab61134f565b6001600160a01b0316336001600160a01b0316146110cc57336104b761134f565b610773604051806020016040528060008152506114ca565b6108a581611978565b6000600080516020612acd8339815191526000611112846001600160a01b0316611379565b8152602001908152602001600020549050919050565b611130611329565b61113861134f565b6001600160a01b0316336001600160a01b03161461115957336104b761134f565b6000600080516020612aed833981519152828154811061117b5761117b611c7d565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f207a0d968f9718fdcdaf3f397c62a6c9a182e67f91d6f10b9749602ddb8dd339816040516109e191815260200190565b6111e2611329565b6111ea61134f565b6001600160a01b0316336001600160a01b03161461120b57336104b761134f565b6108a58161188b565b61121c611329565b61122461134f565b6001600160a01b0316336001600160a01b0316141580156112665750600080516020612b0d833981519152546001600160a01b0316336001600160a01b031614155b1561128d5760405163295a81c160e01b8152336004820152600060248201526044016104df565b6001600080516020612b4d833981519152556040517f9d6b436c52ac5881c7f5f3a199d740774e3d801babdf1542c7cc3d6e962c1b1390600090a1565b600061077361134f565b60006107737f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a5490565b6001600160a01b0381166108a55760405163f6b2911f60e01b815260040160405180910390fd5b9055565b61133161138a565b156107b45760405163a8cab3d160e01b815260040160405180910390fd5b60006107737f927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af095490565b60006001600160a01b038216610863565b6000806113b57f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a5490565b90506000811180156113c75750804210155b91505090565b60006107737f3c1eebcc225c6cc7f5f8765767af6eff617b4139dc3624923a2db67dbca7b68e5490565b611400816112fe565b6040516001600160a01b03821681527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a16108a57f927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af09829055565b6040516001600160a01b03821681527f2a0f8515de3fa34ef68b99300347b8793c01683350743e96fe440594528298f49060200160405180910390a16108a57f3c1eebcc225c6cc7f5f8765767af6eff617b4139dc3624923a2db67dbca7b68e829055565b6000806114f57f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d5490565b9050611529611505826001611cd2565b7f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d55565b604051819061153790611a56565b8190604051809103906000f5905080158015611557573d6000803e3d6000fd5b50915060006115847f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d775490565b905080156115c25780600080516020612acd83398151915260006115b0866001600160a01b0316611379565b81526020810191909152604001600020555b604051633d4652f360e21b81526001600160a01b0384169063f5194bcc906115f09030908890600401611d2b565b600060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b50505050826001600160a01b03167f0f63c3f1c25e087b216d02e32f83e7b44955437e8df7779a8e2141adb082d8018560405161165b9190611d57565b60405180910390a25050919050565b611681600080516020612b0d833981519152829055565b6040516001600160a01b03821681527fe02efb9e8f0fc21546730ab32d594f62d586e1bbb15bb5045edd0b1878a77b35906020016109e1565b6116c3816112fe565b806001600160a01b03163b6000036116f957604051637a905aed60e01b81526001600160a01b03821660048201526024016104df565b6117227f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d829055565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b61176360006119d0565b600080516020612b2d8339815191526000611786846001600160a01b0316611379565b815260208082019290925260409081016000209290925590516001600160a01b03831681527faeb196d352664784d1900b0e7414a8face7d29f4dae8c4b0cf68ed477423bbf491016109e1565b6000306117fe7f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d5490565b60405161180d60208201611a56565b6020820181038252601f19601f820116604052508051906020012060405160200161186d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b6040516020818303038152906040528051906020012060001c905090565b6118b47f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d77829055565b6040518181527f3dae0839612e45cc8359369987b54ef8896c2ae5dc36d732c2fb6b7e2298e4c7906020016109e1565b6118ee60016119d0565b600080516020612b2d8339815191526000611911846001600160a01b0316611379565b815260208082019290925260409081016000209290925590516001600160a01b03831681527f5ee71a369c8672edded508e624ffc9257fa1ae6886ef32905c18e60196bca39991016109e1565b611966611329565b61196e6119da565b6107b46000611a03565b611980611329565b6119886119da565b6283d6008110156119b857604051636cb1216560e11b8152600481018290526283d60060248201526044016104df565b4260006119c58383611cd2565b9050610b8981611a03565b6000811515610863565b6119e26112ca565b6001600160a01b0316336001600160a01b0316146107b457336104b76112ca565b807f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a556040518181527f7413b2ccac0d914f9764525af0b89a12aaf913cb0de2b18adb85e22b80c86ca0906020016109e1565b610d6280611d6b83390190565b80356001600160a01b0381168114611a7a57600080fd5b919050565b60008083601f840112611a9157600080fd5b50813567ffffffffffffffff811115611aa957600080fd5b6020830191508360208260051b8501011115611ac457600080fd5b9250929050565b600080600060408486031215611ae057600080fd5b611ae984611a63565b9250602084013567ffffffffffffffff811115611b0557600080fd5b611b1186828701611a7f565b9497909650939450505050565b600060208284031215611b3057600080fd5b61086082611a63565b6020808252825182820181905260009190848201906040850190845b81811015611b7a5783516001600160a01b031683529284019291840191600101611b55565b50909695505050505050565b60008060208385031215611b9957600080fd5b823567ffffffffffffffff80821115611bb157600080fd5b818501915085601f830112611bc557600080fd5b813581811115611bd457600080fd5b866020828501011115611be657600080fd5b60209290920196919550909350505050565b60008060408385031215611c0b57600080fd5b611c1483611a63565b946020939093013593505050565b60008060208385031215611c3557600080fd5b823567ffffffffffffffff811115611c4c57600080fd5b611c5885828601611a7f565b90969095509350505050565b600060208284031215611c7657600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561086357610863611c93565b634e487b7160e01b600052604160045260246000fd5b8082018082111561086357610863611c93565b6000815180845260005b81811015611d0b57602081850181015186830182015201611cef565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611d4f90830184611ce5565b949350505050565b6020815260006108606020830184611ce556fe608060405234801561001057600080fd5b50610d42806100206000396000f3fe6080604052600436106100385760003560e01c80630fc5bd3b1461004f5780638f3006241461006f578063f5194bcc1461008f57610047565b36610047576100456100af565b005b6100456100af565b34801561005b57600080fd5b5061004561006a3660046108ef565b6100d5565b34801561007b57600080fd5b5061004561008a366004610977565b610109565b34801561009b57600080fd5b506100456100aa366004610a16565b610152565b60006100b961018f565b905060006100c6826101bd565b90506100d1816102f3565b5050565b6100dd61018f565b6001600160a01b0316336001600160a01b031614610100576100fd6100af565b50565b6100fd8161031c565b333014610118576100fd6100af565b7f068f5763814dd924221a093a33c8516e9b05b882bb7e5fa1534d9e454db87402816040516101479190610abe565b60405180910390a150565b600061015c61018f565b6001600160a01b03161461018357604051633bfe06fb60e01b815260040160405180910390fd5b6100d182826000610405565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6000806000806101cc856104c5565b9250925092508080156101de57503315155b156102035760405163beab20b960e01b81523360048201526024015b60405180910390fd5b81156102ea5760008061021587610541565b6040516323cc018960e21b81529091503090638f3006249061023b908490600401610abe565b600060405180830381600087803b15801561025557600080fd5b505af1925050508015610266575060015b61026f57600191505b816102e75760005b81518110156102dd5760006001600160a01b031682828151811061029d5761029d610b0b565b60200260200101516001600160a01b0316146102d5576102d58282815181106102c8576102c8610b0b565b602002602001015161031c565b600101610277565b506102e7876105b6565b50505b50909392505050565b3660008037600080366000845af43d6000803e808015610312573d6000f35b3d6000fd5b505050565b60408051600481526024810182526020810180516001600160e01b03166352a8c3c760e11b179052905160009182916001600160a01b0385169161035f91610b45565b600060405180830381855af49150503d806000811461039a576040519150601f19603f3d011682016040523d82523d6000602084013e61039f565b606091505b5091509150816103c6578281604051636b45476360e01b81526004016101fa929190610b8d565b808060200190518101906103da9190610bc6565b9150816103175760405163f930393360e01b81526001600160a01b03841660048201526024016101fa565b61040e8361060c565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061044f5750805b15610317576104bf836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610495573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b99190610be1565b8361078b565b50505050565b60405163645b8b1b60e01b8152306004820152600090819081906001600160a01b0385169063645b8b1b90602401606060405180830381865afa158015610510573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105349190610bfe565b9250925092509193909250565b604051630162910360e11b81523060048201526060906001600160a01b038316906302c5220690602401600060405180830381865afa158015610588573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b09190810190610c43565b92915050565b806001600160a01b03166365413a4d6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105f157600080fd5b505af1158015610605573d6000803e3d6000fd5b5050505050565b6001600160a01b0381163b6106715760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084016101fa565b6106e5816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190610be1565b6001600160a01b03163b151590565b61074a5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b60648201526084016101fa565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392909216919091179055565b60606107b08383604051806060016040528060278152602001610ce6602791396107b7565b9392505050565b6060600080856001600160a01b0316856040516107d49190610b45565b600060405180830381855af49150503d806000811461080f576040519150601f19603f3d011682016040523d82523d6000602084013e610814565b606091505b50915091506108258683838761082f565b9695505050505050565b6060831561089e578251600003610897576001600160a01b0385163b6108975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101fa565b50816108a8565b6108a883836108b0565b949350505050565b8151156108c05781518083602001fd5b8060405162461bcd60e51b81526004016101fa9190610cd2565b6001600160a01b03811681146100fd57600080fd5b60006020828403121561090157600080fd5b81356107b0816108da565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561094b5761094b61090c565b604052919050565b600067ffffffffffffffff82111561096d5761096d61090c565b5060051b60200190565b6000602080838503121561098a57600080fd5b823567ffffffffffffffff8111156109a157600080fd5b8301601f810185136109b257600080fd5b80356109c56109c082610953565b610922565b81815260059190911b820183019083810190878311156109e457600080fd5b928401925b82841015610a0b5783356109fc816108da565b825292840192908401906109e9565b979650505050505050565b60008060408385031215610a2957600080fd5b8235610a34816108da565b915060208381013567ffffffffffffffff80821115610a5257600080fd5b818601915086601f830112610a6657600080fd5b813581811115610a7857610a7861090c565b610a8a601f8201601f19168501610922565b91508082528784828501011115610aa057600080fd5b80848401858401376000848284010152508093505050509250929050565b6020808252825182820181905260009190848201906040850190845b81811015610aff5783516001600160a01b031683529284019291840191600101610ada565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610b3c578181015183820152602001610b24565b50506000910152565b60008251610b57818460208701610b21565b9190910192915050565b60008151808452610b79816020860160208601610b21565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906108a890830184610b61565b80518015158114610bc157600080fd5b919050565b600060208284031215610bd857600080fd5b6107b082610bb1565b600060208284031215610bf357600080fd5b81516107b0816108da565b600080600060608486031215610c1357600080fd5b8351610c1e816108da565b9250610c2c60208501610bb1565b9150610c3a60408501610bb1565b90509250925092565b60006020808385031215610c5657600080fd5b825167ffffffffffffffff811115610c6d57600080fd5b8301601f81018513610c7e57600080fd5b8051610c8c6109c082610953565b81815260059190911b82018301908381019087831115610cab57600080fd5b928401925b82841015610a0b578351610cc3816108da565b82529284019290840190610cb0565b6020815260006107b06020830184610b6156fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202dfd1c538b20e58fb6e36306c60db90fc84bfe0acde5b4a2f0ad93bca1b0e36564736f6c63430008110033a7208bf4db7440ac9388b234d45a5b207976f0fc12d31bf9eaa80e4e2fc0d57ca8612761e880b1989e2ad0bb2c51004fad089f897b1cd8dc3dbfeae33493df5567ad2ba345683ea58e6dcc49f12611548bc3a5b2c8c753edc1878aa0a76c3ce2d0ad769ee84b03ff353d2cb4c134ab25db1f330b56357f28eadc5b28c2f88991798f8d9ad9ed68e65653cd13b4f27162f01222155b56622ae81337e4888e20c0a26469706673582212202f5c25c8daef37b0fdea75039a19c7db7719742b0dd0dcc24836468a4daccd2d64736f6c63430008110033000000000000000000000000a2714e6e7758c1767eae818df992498d6078f2f1000000000000000000000000418c1f1f83cf34c0ea8bcfce951c5d75317897540000000000000000000000008a113da63f02811e63c1e38ef615df94df5d9e70

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061021b5760003560e01c80636906d58211610125578063ce190578116100ad578063df199c331161007c578063df199c3314610448578063f0772f311461045b578063f12d54d81461046e578063f851a44014610476578063fd7e1bee1461047e57600080fd5b8063ce19057814610412578063d0db50831461041a578063d7a78db814610422578063da8589a21461043557600080fd5b80639fd0506d116100f45780639fd0506d146103d4578063a3f5c1d2146103dc578063a70070bf146103e4578063abec754b146103f7578063bad490dc1461040a57600080fd5b80636906d5821461039e57806375829def146103a6578063764cb8c9146103b9578063797f1165146103c157600080fd5b80633638f367116101a857806359740f901161017757806359740f90146103395780635c60da1b1461034c57806361a552dc14610354578063645b8b1b1461035c57806365413a4d1461039657600080fd5b80633638f367146102ed5780633659cfe61461030057806338267bda146103135780633d9c33241461032657600080fd5b8063229659e2116101ef578063229659e21461027e57806326782247146102a95780632d88af4a146102b15780632e48152c146102c45780633173250d146102d757600080fd5b806275ee0a1461022057806302c5220614610235578063054f7d9c1461025e5780630e18b68114610276575b600080fd5b61023361022e366004611acb565b610486565b005b610248610243366004611b1e565b610629565b6040516102559190611b39565b60405180910390f35b610266610769565b6040519015158152602001610255565b610233610778565b61029161028c366004611b86565b6107b6565b6040516001600160a01b039091168152602001610255565b610291610869565b6102336102bf366004611b1e565b610873565b6102666102d2366004611b1e565b6108a8565b6102df6108e8565b604051908152602001610255565b6102336102fb366004611b1e565b610912565b61023361030e366004611b1e565b6109ec565b610291610321366004611b86565b610a26565b610233610334366004611bf8565b610a51565b610233610347366004611c22565b610b01565b610291610b8e565b610266610bb8565b61036f61036a366004611b1e565b610bd0565b604080516001600160a01b0390941684529115156020840152151590820152606001610255565b610233610ca2565b610248610cc9565b6102336103b4366004611b1e565b610d38565b610291610d6a565b6102336103cf366004611bf8565b610d74565b610291610dbb565b610291610dd3565b6102336103f2366004611c22565b610dfd565b610233610405366004611acb565b610ecd565b61023361102b565b610233611033565b6102916110a1565b610233610430366004611c64565b6110e4565b6102df610443366004611b1e565b6110ed565b610233610456366004611c64565b611128565b610233610469366004611c64565b6111da565b610233611214565b6102916112ca565b6102df6112d4565b61048e611329565b61049661134f565b6001600160a01b0316336001600160a01b0316146104e857336104b761134f565b60405163295a81c160e01b81526001600160a01b039283166004820152911660248201526044015b60405180910390fd5b6104f1836112fe565b8060005b818110156106225761052c84848381811061051257610512611c7d565b90506020020160208101906105279190611b1e565b6112fe565b83838281811061053e5761053e611c7d565b90506020020160208101906105539190611b1e565b604051630fc5bd3b60e01b81526001600160a01b0387811660048301529190911690630fc5bd3b90602401600060405180830381600087803b15801561059857600080fd5b505af11580156105ac573d6000803e3d6000fd5b505050507fa1b2d2f59fced963b3e7cb859bc1fb60c12512c583987498d4b818e9b7ca24df8484838181106105e3576105e3611c7d565b90506020020160208101906105f89190611b1e565b604080516001600160a01b03928316815291881660208301520160405180910390a16001016104f5565b5050505050565b60606000600080516020612acd8339815191526000610650856001600160a01b0316611379565b8152602001908152602001600020549050600061067b600080516020612aed83398151915260001b90565b549050600061069283831883851102841883611ca9565b905060008167ffffffffffffffff8111156106af576106af611cbc565b6040519080825280602002602001820160405280156106d8578160200160208202803683370190505b50905060005b8281101561075f57600080516020612aed8339815191526106ff8683611cd2565b8154811061070f5761070f611c7d565b9060005260206000200160009054906101000a90046001600160a01b031682828151811061073f5761073f611c7d565b6001600160a01b03909216602092830291909101909101526001016106de565b5095945050505050565b600061077361138a565b905090565b6107806113cd565b6001600160a01b0316336001600160a01b0316146107a157336104b76113cd565b6107aa336113f7565b6107b46000611465565b565b60006107e07ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b6001600160a01b0316336001600160a01b03161461082157336104b77ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b61086083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114ca92505050565b90505b92915050565b60006107736113cd565b61087b61134f565b6001600160a01b0316336001600160a01b03161461089c57336104b761134f565b6108a58161166a565b50565b6000610863600080516020612b2d83398151915260006108d0856001600160a01b0316611379565b81526020019081526020016000205460019081161490565b60006107737f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d775490565b61091a611329565b61092261134f565b6001600160a01b0316336001600160a01b03161461094357336104b761134f565b61094c816112fe565b600080516020612aed833981519152805460018082018355600092835260209092200180546001600160a01b0319166001600160a01b0384161790557fbafcedce88399447ff8d2ae013b9ee0f8cabab75b253dd514ece06253b7b0b97908290600080516020612aed833981519152546109c69190611ca9565b604080516001600160a01b0390931683526020830191909152015b60405180910390a150565b6109f4611329565b6109fc61134f565b6001600160a01b0316336001600160a01b031614610a1d57336104b761134f565b6108a5816116ba565b6000610a3061134f565b6001600160a01b0316336001600160a01b03161461082157336104b761134f565b610a59611329565b610a6161134f565b6001600160a01b0316336001600160a01b031614610a8257336104b761134f565b80600080516020612acd8339815191525b6000610aa7856001600160a01b0316611379565b815260208082019290925260409081016000209290925581516001600160a01b03851681529081018390527f7e32675c5ba8a706b96979a4e952dc30ddac837d9d0e79220c766936da9be782910160405180910390a15050565b610b09611329565b610b1161134f565b6001600160a01b0316336001600160a01b031614610b3257336104b761134f565b60005b81811015610b8957610b5283838381811061051257610512611c7d565b610b81838383818110610b6757610b67611c7d565b9050602002016020810190610b7c9190611b1e565b611759565b600101610b35565b505050565b60006107737f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d5490565b6000610773600080516020612b4d8339815191525490565b60008080610bfc7f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d5490565b600080516020612aed83398151915254600080516020612acd8339815191526000610c2f886001600160a01b0316611379565b81526020019081526020016000205410610c58600080516020612b4d83398151915260001b5490565b80610c845750610c84600080516020612b2d83398151915260006108d0896001600160a01b0316611379565b8015610c955750610c9361138a565b155b9250925092509193909250565b600080516020612aed83398151915254339080600080516020612acd833981519152610a93565b6060600080516020612aed833981519152805480602002602001604051908101604052809291908181526020018280548015610d2e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d10575b5050505050905090565b610d4061134f565b6001600160a01b0316336001600160a01b031614610d6157336104b761134f565b6108a581611465565b60006107736117d3565b610d7c611329565b610d8461134f565b6001600160a01b0316336001600160a01b031614610da557336104b761134f565b610dae8161188b565b610db7826116ba565b5050565b6000610773600080516020612b0d8339815191525490565b60006107737ff9a2bbc6604b460dea2b9e85ead19324d4c2b79c6ba1c0a5443b33d1c7d265595490565b610e05611329565b610e0d61134f565b6001600160a01b0316336001600160a01b031614158015610e4f5750600080516020612b0d833981519152546001600160a01b0316336001600160a01b031614155b15610e765760405163295a81c160e01b8152336004820152600060248201526044016104df565b60005b81811015610b8957610e9683838381811061051257610512611c7d565b610ec5838383818110610eab57610eab611c7d565b9050602002016020810190610ec09190611b1e565b6118e4565b600101610e79565b610ed5611329565b610edd61134f565b6001600160a01b0316336001600160a01b031614610efe57336104b761134f565b610f07836112fe565b8060005b8181101561062257610f2884848381811061051257610512611c7d565b846001600160a01b0316630fc5bd3b858584818110610f4957610f49611c7d565b9050602002016020810190610f5e9190611b1e565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015610f9f57600080fd5b505af1158015610fb3573d6000803e3d6000fd5b505050507fa1b2d2f59fced963b3e7cb859bc1fb60c12512c583987498d4b818e9b7ca24df85858584818110610feb57610feb611c7d565b90506020020160208101906110009190611b1e565b604080516001600160a01b0393841681529290911660208301520160405180910390a1600101610f0b565b6107b461195e565b61103b611329565b61104361134f565b6001600160a01b0316336001600160a01b03161461106457336104b761134f565b6000600080516020612b4d833981519152556040517f09b17ad4b525602f3a736c430612735b5047e4dcc19b82ae55ae7789fb6b0b2790600090a1565b60006110ab61134f565b6001600160a01b0316336001600160a01b0316146110cc57336104b761134f565b610773604051806020016040528060008152506114ca565b6108a581611978565b6000600080516020612acd8339815191526000611112846001600160a01b0316611379565b8152602001908152602001600020549050919050565b611130611329565b61113861134f565b6001600160a01b0316336001600160a01b03161461115957336104b761134f565b6000600080516020612aed833981519152828154811061117b5761117b611c7d565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f207a0d968f9718fdcdaf3f397c62a6c9a182e67f91d6f10b9749602ddb8dd339816040516109e191815260200190565b6111e2611329565b6111ea61134f565b6001600160a01b0316336001600160a01b03161461120b57336104b761134f565b6108a58161188b565b61121c611329565b61122461134f565b6001600160a01b0316336001600160a01b0316141580156112665750600080516020612b0d833981519152546001600160a01b0316336001600160a01b031614155b1561128d5760405163295a81c160e01b8152336004820152600060248201526044016104df565b6001600080516020612b4d833981519152556040517f9d6b436c52ac5881c7f5f3a199d740774e3d801babdf1542c7cc3d6e962c1b1390600090a1565b600061077361134f565b60006107737f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a5490565b6001600160a01b0381166108a55760405163f6b2911f60e01b815260040160405180910390fd5b9055565b61133161138a565b156107b45760405163a8cab3d160e01b815260040160405180910390fd5b60006107737f927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af095490565b60006001600160a01b038216610863565b6000806113b57f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a5490565b90506000811180156113c75750804210155b91505090565b60006107737f3c1eebcc225c6cc7f5f8765767af6eff617b4139dc3624923a2db67dbca7b68e5490565b611400816112fe565b6040516001600160a01b03821681527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a16108a57f927a17e5ea75d9461748062a2652f4d3698a628896c9832f8488fa0d2846af09829055565b6040516001600160a01b03821681527f2a0f8515de3fa34ef68b99300347b8793c01683350743e96fe440594528298f49060200160405180910390a16108a57f3c1eebcc225c6cc7f5f8765767af6eff617b4139dc3624923a2db67dbca7b68e829055565b6000806114f57f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d5490565b9050611529611505826001611cd2565b7f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d55565b604051819061153790611a56565b8190604051809103906000f5905080158015611557573d6000803e3d6000fd5b50915060006115847f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d775490565b905080156115c25780600080516020612acd83398151915260006115b0866001600160a01b0316611379565b81526020810191909152604001600020555b604051633d4652f360e21b81526001600160a01b0384169063f5194bcc906115f09030908890600401611d2b565b600060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b50505050826001600160a01b03167f0f63c3f1c25e087b216d02e32f83e7b44955437e8df7779a8e2141adb082d8018560405161165b9190611d57565b60405180910390a25050919050565b611681600080516020612b0d833981519152829055565b6040516001600160a01b03821681527fe02efb9e8f0fc21546730ab32d594f62d586e1bbb15bb5045edd0b1878a77b35906020016109e1565b6116c3816112fe565b806001600160a01b03163b6000036116f957604051637a905aed60e01b81526001600160a01b03821660048201526024016104df565b6117227f5822215992e9fc50486d8256024d96ad28d5ca5cb787840aef51159121dccd9d829055565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b61176360006119d0565b600080516020612b2d8339815191526000611786846001600160a01b0316611379565b815260208082019290925260409081016000209290925590516001600160a01b03831681527faeb196d352664784d1900b0e7414a8face7d29f4dae8c4b0cf68ed477423bbf491016109e1565b6000306117fe7f7b4670a3a88a40c4de314967df154b504cc215cbd280a064c677342c49c2759d5490565b60405161180d60208201611a56565b6020820181038252601f19601f820116604052508051906020012060405160200161186d939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b6040516020818303038152906040528051906020012060001c905090565b6118b47f4a267ea82c1f4624b3dc08ad19614228bbdeee20d07eb9966d67c16d39550d77829055565b6040518181527f3dae0839612e45cc8359369987b54ef8896c2ae5dc36d732c2fb6b7e2298e4c7906020016109e1565b6118ee60016119d0565b600080516020612b2d8339815191526000611911846001600160a01b0316611379565b815260208082019290925260409081016000209290925590516001600160a01b03831681527f5ee71a369c8672edded508e624ffc9257fa1ae6886ef32905c18e60196bca39991016109e1565b611966611329565b61196e6119da565b6107b46000611a03565b611980611329565b6119886119da565b6283d6008110156119b857604051636cb1216560e11b8152600481018290526283d60060248201526044016104df565b4260006119c58383611cd2565b9050610b8981611a03565b6000811515610863565b6119e26112ca565b6001600160a01b0316336001600160a01b0316146107b457336104b76112ca565b807f04b06dd5becaad633b58f99e01f1e05103eff5a573d10d18c9baf1bc4e6bfd3a556040518181527f7413b2ccac0d914f9764525af0b89a12aaf913cb0de2b18adb85e22b80c86ca0906020016109e1565b610d6280611d6b83390190565b80356001600160a01b0381168114611a7a57600080fd5b919050565b60008083601f840112611a9157600080fd5b50813567ffffffffffffffff811115611aa957600080fd5b6020830191508360208260051b8501011115611ac457600080fd5b9250929050565b600080600060408486031215611ae057600080fd5b611ae984611a63565b9250602084013567ffffffffffffffff811115611b0557600080fd5b611b1186828701611a7f565b9497909650939450505050565b600060208284031215611b3057600080fd5b61086082611a63565b6020808252825182820181905260009190848201906040850190845b81811015611b7a5783516001600160a01b031683529284019291840191600101611b55565b50909695505050505050565b60008060208385031215611b9957600080fd5b823567ffffffffffffffff80821115611bb157600080fd5b818501915085601f830112611bc557600080fd5b813581811115611bd457600080fd5b866020828501011115611be657600080fd5b60209290920196919550909350505050565b60008060408385031215611c0b57600080fd5b611c1483611a63565b946020939093013593505050565b60008060208385031215611c3557600080fd5b823567ffffffffffffffff811115611c4c57600080fd5b611c5885828601611a7f565b90969095509350505050565b600060208284031215611c7657600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561086357610863611c93565b634e487b7160e01b600052604160045260246000fd5b8082018082111561086357610863611c93565b6000815180845260005b81811015611d0b57602081850181015186830182015201611cef565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611d4f90830184611ce5565b949350505050565b6020815260006108606020830184611ce556fe608060405234801561001057600080fd5b50610d42806100206000396000f3fe6080604052600436106100385760003560e01c80630fc5bd3b1461004f5780638f3006241461006f578063f5194bcc1461008f57610047565b36610047576100456100af565b005b6100456100af565b34801561005b57600080fd5b5061004561006a3660046108ef565b6100d5565b34801561007b57600080fd5b5061004561008a366004610977565b610109565b34801561009b57600080fd5b506100456100aa366004610a16565b610152565b60006100b961018f565b905060006100c6826101bd565b90506100d1816102f3565b5050565b6100dd61018f565b6001600160a01b0316336001600160a01b031614610100576100fd6100af565b50565b6100fd8161031c565b333014610118576100fd6100af565b7f068f5763814dd924221a093a33c8516e9b05b882bb7e5fa1534d9e454db87402816040516101479190610abe565b60405180910390a150565b600061015c61018f565b6001600160a01b03161461018357604051633bfe06fb60e01b815260040160405180910390fd5b6100d182826000610405565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6000806000806101cc856104c5565b9250925092508080156101de57503315155b156102035760405163beab20b960e01b81523360048201526024015b60405180910390fd5b81156102ea5760008061021587610541565b6040516323cc018960e21b81529091503090638f3006249061023b908490600401610abe565b600060405180830381600087803b15801561025557600080fd5b505af1925050508015610266575060015b61026f57600191505b816102e75760005b81518110156102dd5760006001600160a01b031682828151811061029d5761029d610b0b565b60200260200101516001600160a01b0316146102d5576102d58282815181106102c8576102c8610b0b565b602002602001015161031c565b600101610277565b506102e7876105b6565b50505b50909392505050565b3660008037600080366000845af43d6000803e808015610312573d6000f35b3d6000fd5b505050565b60408051600481526024810182526020810180516001600160e01b03166352a8c3c760e11b179052905160009182916001600160a01b0385169161035f91610b45565b600060405180830381855af49150503d806000811461039a576040519150601f19603f3d011682016040523d82523d6000602084013e61039f565b606091505b5091509150816103c6578281604051636b45476360e01b81526004016101fa929190610b8d565b808060200190518101906103da9190610bc6565b9150816103175760405163f930393360e01b81526001600160a01b03841660048201526024016101fa565b61040e8361060c565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061044f5750805b15610317576104bf836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610495573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b99190610be1565b8361078b565b50505050565b60405163645b8b1b60e01b8152306004820152600090819081906001600160a01b0385169063645b8b1b90602401606060405180830381865afa158015610510573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105349190610bfe565b9250925092509193909250565b604051630162910360e11b81523060048201526060906001600160a01b038316906302c5220690602401600060405180830381865afa158015610588573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b09190810190610c43565b92915050565b806001600160a01b03166365413a4d6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105f157600080fd5b505af1158015610605573d6000803e3d6000fd5b5050505050565b6001600160a01b0381163b6106715760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084016101fa565b6106e5816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d69190610be1565b6001600160a01b03163b151590565b61074a5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b60648201526084016101fa565b7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b0392909216919091179055565b60606107b08383604051806060016040528060278152602001610ce6602791396107b7565b9392505050565b6060600080856001600160a01b0316856040516107d49190610b45565b600060405180830381855af49150503d806000811461080f576040519150601f19603f3d011682016040523d82523d6000602084013e610814565b606091505b50915091506108258683838761082f565b9695505050505050565b6060831561089e578251600003610897576001600160a01b0385163b6108975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101fa565b50816108a8565b6108a883836108b0565b949350505050565b8151156108c05781518083602001fd5b8060405162461bcd60e51b81526004016101fa9190610cd2565b6001600160a01b03811681146100fd57600080fd5b60006020828403121561090157600080fd5b81356107b0816108da565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561094b5761094b61090c565b604052919050565b600067ffffffffffffffff82111561096d5761096d61090c565b5060051b60200190565b6000602080838503121561098a57600080fd5b823567ffffffffffffffff8111156109a157600080fd5b8301601f810185136109b257600080fd5b80356109c56109c082610953565b610922565b81815260059190911b820183019083810190878311156109e457600080fd5b928401925b82841015610a0b5783356109fc816108da565b825292840192908401906109e9565b979650505050505050565b60008060408385031215610a2957600080fd5b8235610a34816108da565b915060208381013567ffffffffffffffff80821115610a5257600080fd5b818601915086601f830112610a6657600080fd5b813581811115610a7857610a7861090c565b610a8a601f8201601f19168501610922565b91508082528784828501011115610aa057600080fd5b80848401858401376000848284010152508093505050509250929050565b6020808252825182820181905260009190848201906040850190845b81811015610aff5783516001600160a01b031683529284019291840191600101610ada565b50909695505050505050565b634e487b7160e01b600052603260045260246000fd5b60005b83811015610b3c578181015183820152602001610b24565b50506000910152565b60008251610b57818460208701610b21565b9190910192915050565b60008151808452610b79816020860160208601610b21565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906108a890830184610b61565b80518015158114610bc157600080fd5b919050565b600060208284031215610bd857600080fd5b6107b082610bb1565b600060208284031215610bf357600080fd5b81516107b0816108da565b600080600060608486031215610c1357600080fd5b8351610c1e816108da565b9250610c2c60208501610bb1565b9150610c3a60408501610bb1565b90509250925092565b60006020808385031215610c5657600080fd5b825167ffffffffffffffff811115610c6d57600080fd5b8301601f81018513610c7e57600080fd5b8051610c8c6109c082610953565b81815260059190911b82018301908381019087831115610cab57600080fd5b928401925b82841015610a0b578351610cc3816108da565b82529284019290840190610cb0565b6020815260006107b06020830184610b6156fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202dfd1c538b20e58fb6e36306c60db90fc84bfe0acde5b4a2f0ad93bca1b0e36564736f6c63430008110033a7208bf4db7440ac9388b234d45a5b207976f0fc12d31bf9eaa80e4e2fc0d57ca8612761e880b1989e2ad0bb2c51004fad089f897b1cd8dc3dbfeae33493df5567ad2ba345683ea58e6dcc49f12611548bc3a5b2c8c753edc1878aa0a76c3ce2d0ad769ee84b03ff353d2cb4c134ab25db1f330b56357f28eadc5b28c2f88991798f8d9ad9ed68e65653cd13b4f27162f01222155b56622ae81337e4888e20c0a26469706673582212202f5c25c8daef37b0fdea75039a19c7db7719742b0dd0dcc24836468a4daccd2d64736f6c63430008110033

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

000000000000000000000000a2714e6e7758c1767eae818df992498d6078f2f1000000000000000000000000418c1f1f83cf34c0ea8bcfce951c5d75317897540000000000000000000000008a113da63f02811e63c1e38ef615df94df5d9e70

-----Decoded View---------------
Arg [0] : _implementation (address): 0xA2714e6E7758c1767eAe818dF992498D6078F2F1
Arg [1] : _admin (address): 0x418c1F1F83Cf34C0eA8bCfCe951c5D7531789754
Arg [2] : _nexus (address): 0x8a113dA63F02811E63C1e38Ef615DF94df5D9e70

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a2714e6e7758c1767eae818df992498d6078f2f1
Arg [1] : 000000000000000000000000418c1f1f83cf34c0ea8bcfce951c5d7531789754
Arg [2] : 0000000000000000000000008a113da63f02811e63c1e38ef615df94df5d9e70


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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