Unichain Sepolia Testnet

Contract

0x3f94989763A27CAeAF1f7aEF4Df2752CD5B58a5A

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Enable Adapters40436762024-11-06 12:28:24138 days ago1730896104IN
0x3f949897...CD5B58a5A
0 ETH0.000000160.00100026
Enable Adapters40436662024-11-06 12:28:14138 days ago1730896094IN
0x3f949897...CD5B58a5A
0 ETH0.000000160.00100026
Enable Adapters40436562024-11-06 12:28:04138 days ago1730896084IN
0x3f949897...CD5B58a5A
0 ETH0.000000160.00100026
Enable Adapters40436392024-11-06 12:27:47138 days ago1730896067IN
0x3f949897...CD5B58a5A
0 ETH0.000000160.00100026

Parent Transaction Hash Block From To
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ShoyuBashi

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 10000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : ShoyuBashi.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.20;

import { ShuSo } from "./ShuSo.sol";
import { IAdapter } from "../interfaces/IAdapter.sol";
import { IShoyuBashi } from "../interfaces/IShoyuBashi.sol";
import { IHashi } from "../interfaces/IHashi.sol";

contract ShoyuBashi is IShoyuBashi, ShuSo {
    constructor(address _owner, address _hashi) ShuSo(_owner, _hashi) {} // solhint-disable no-empty-blocks

    /// @inheritdoc IShoyuBashi
    function setThreshold(uint256 domain, uint256 threshold) external {
        _setThreshold(domain, threshold);
    }

    /// @inheritdoc IShoyuBashi
    function enableAdapters(uint256 domain, IAdapter[] memory adapters, uint256 threshold) external {
        _enableAdapters(domain, adapters, threshold);
    }

    /// @inheritdoc IShoyuBashi
    function disableAdapters(uint256 domain, IAdapter[] memory adapters) external {
        _disableAdapters(domain, adapters);
    }

    /// @inheritdoc IShoyuBashi
    function getUnanimousHash(uint256 domain, uint256 id) external view returns (bytes32) {
        return _getUnanimousHash(domain, id);
    }

    /// @inheritdoc IShoyuBashi
    function getThresholdHash(uint256 domain, uint256 id) external view returns (bytes32) {
        return _getThresholdHash(domain, id);
    }

    /// @inheritdoc IShoyuBashi
    function getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) external view returns (bytes32) {
        return _getHash(domain, id, adapters);
    }

    /// @inheritdoc IShoyuBashi
    function setHashi(IHashi _hashi) external {
        _setHashi(_hashi);
    }
}

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

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal onlyInitializing {
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal onlyInitializing {
        _transferOwnership(_msgSender());
    }

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

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

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

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

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

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 3 of 10 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized < type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

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

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 6 of 10 : IAdapter.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.0;

/**
 * @title IAdapter
 */
interface IAdapter {
    error ConflictingBlockHeader(uint256 blockNumber, bytes32 blockHash, bytes32 storedBlockHash);
    error InvalidBlockHeaderRLP();

    /**
     * @dev Emitted when a hash is stored.
     * @param id - The ID of the stored hash.
     * @param hash - The stored hash as bytes32 values.
     */
    event HashStored(uint256 indexed id, bytes32 indexed hash);

    /**
     * @dev Returns the hash for a given ID.
     * @param domain - Identifier for the domain to query.
     * @param id - Identifier for the ID to query.
     * @return hash Bytes32 hash for the given ID on the given domain.
     * @notice MUST return bytes32(0) if the hash is not present.
     */
    function getHash(uint256 domain, uint256 id) external view returns (bytes32 hash);
}

File 7 of 10 : IHashi.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.0;

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

/**
 * @title IHashi
 */
interface IHashi {
    error AdaptersDisagree(IAdapter adapterOne, IAdapter adapterTwo);
    error HashNotAvailableInAdapter(IAdapter adapter);
    error InvalidThreshold(uint256 threshold, uint256 maxThreshold);
    error NoAdaptersGiven();

    /**
     * @dev Checks whether the threshold is reached for a message given a set of adapters.
     * @param domain - ID of the domain to query.
     * @param id - ID for which to return hash.
     * @param threshold - Threshold to use.
     * @param adapters - Array of addresses for the adapters to query.
     * @notice If the threshold is 1, it will always return true.
     * @return result A boolean indicating if a threshold for a given message has been reached.
     */
    function checkHashWithThresholdFromAdapters(
        uint256 domain,
        uint256 id,
        uint256 threshold,
        IAdapter[] calldata adapters
    ) external view returns (bool);

    /**
     * @dev Returns the hash stored by a given adapter for a given ID.
     * @param domain - ID of the domain to query.
     * @param id - ID for which to return a hash.
     * @param adapter - Address of the adapter to query.
     * @return hash stored by the given adapter for the given ID.
     */
    function getHashFromAdapter(uint256 domain, uint256 id, IAdapter adapter) external view returns (bytes32);

    /**
     * @dev Returns the hashes for a given ID stored by a given set of adapters.
     * @param domain - The ID of the domain to query.
     * @param id - The ID for which to return hashes.
     * @param adapters - An array of addresses for the adapters to query.
     * @return hashes An array of hashes stored by the given adapters for the specified ID.
     */
    function getHashesFromAdapters(
        uint256 domain,
        uint256 id,
        IAdapter[] calldata adapters
    ) external view returns (bytes32[] memory);

    /**
     * @dev Returns the hash unanimously agreed upon by a given set of adapters.
     * @param domain - The ID of the domain to query.
     * @param id - The ID for which to return a hash.
     * @param adapters - An array of addresses for the adapters to query.
     * @return hash agreed on by the given set of adapters.
     * @notice MUST revert if adapters disagree on the hash or if an adapter does not report.
     */
    function getHash(uint256 domain, uint256 id, IAdapter[] calldata adapters) external view returns (bytes32);
}

File 8 of 10 : IShoyuBashi.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.0;

import { IHashi } from "./IHashi.sol";
import { IAdapter } from "./IAdapter.sol";
import { IShuSho } from "./IShuSho.sol";

/**
 * @title IShoyuBashi
 */
interface IShoyuBashi is IShuSho {
    /**
     * @dev Disables the given adapters for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set adapters.
     * @param adapters - Array of adapter addresses.
     * @notice Only callable by the owner of this contract.
     * @notice Reverts if adapters are out of order or contain duplicates.
     */
    function disableAdapters(uint256 domain, IAdapter[] memory adapters) external;

    /**
     * @dev Enables the given adapters for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set adapters.
     * @param adapters - Array of adapter addresses.
     * @param threshold - Uint256 threshold to set for the given domain.
     * @notice Only callable by the owner of this contract.
     * @notice Reverts if adapters are out of order, contain duplicates or if the threshold is not higher than half the count of the adapters
     */
    function enableAdapters(uint256 domain, IAdapter[] memory adapters, uint256 threshold) external;

    /**
     * @dev Returns the hash unanimously agreed upon by ALL of the enabled adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param id - Uint256 identifier to query.
     * @return Bytes32 hash agreed upon by the adapters for the given domain.
     * @notice Revert if the adapters do not yet have the hash for the given ID.
     * @notice Reverts if adapters disagree.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function getUnanimousHash(uint256 domain, uint256 id) external view returns (bytes32);

    /**
     * @dev Returns the hash agreed upon by a threshold of the enabled adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param id - Uint256 identifier to query.
     * @return Bytes32 hash agreed upon by a threshold of the adapters for the given domain.
     * @notice Reverts if the threshold is not reached.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function getThresholdHash(uint256 domain, uint256 id) external view returns (bytes32);

    /**
     * @dev Returns the hash unanimously agreed upon by all of the given adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param adapters - Array of adapter addresses to query.
     * @param id - Uint256 identifier to query.
     * @return Bytes32 hash agreed upon by the adapters for the given domain.
     * @notice adapters must be in numerical order from smallest to largest and contain no duplicates.
     * @notice Reverts if adapters are out of order or contain duplicates.
     * @notice Reverts if adapters disagree.
     * @notice Revert if the adapters do not yet have the hash for the given ID.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) external view returns (bytes32);

    /**
     * @dev Sets the threshold of adapters required for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set the threshold.
     * @param threshold - Uint256 threshold to set for the given domain.
     * @notice Only callable by the owner of this contract.
     * @notice Reverts if the threshold is already set to the given value.
     */
    function setThreshold(uint256 domain, uint256 threshold) external;

    /**
     * @dev Sets the address of the IHashi contract.
     * @param hashi - Address of the hashi contract.
     * @notice Only callable by the owner of this contract.
     */
    function setHashi(IHashi hashi) external;
}

File 9 of 10 : IShuSho.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.0;

import { IHashi } from "./IHashi.sol";
import { IAdapter } from "./IAdapter.sol";

/**
 * @title IShuSho
 */
interface IShuSho {
    struct Domain {
        uint256 threshold;
        uint256 count;
    }

    struct Link {
        IAdapter previous;
        IAdapter next;
    }

    error AdapterNotEnabled(IAdapter adapter);
    error AdapterAlreadyEnabled(IAdapter adapter);
    error CountCannotBeZero();
    error DuplicateHashiAddress(IHashi hashi);
    error DuplicateOrOutOfOrderAdapters(IAdapter adapterOne, IAdapter adapterTwo);
    error DuplicateThreshold(uint256 threshold);
    error InvalidAdapter(IAdapter adapter);
    error InvalidThreshold(uint256 threshold);
    error NoAdaptersEnabled(uint256 domain);
    error NoAdaptersGiven();
    error ThresholdNotMet();

    /**
     * @dev Emitted when adapters are disabled for a specific domain.
     * @param domain - The domain associated with the disabled adapters.
     * @param adapters - An array of disabled adapter addresses associated with this event.
     */
    event AdaptersDisabled(uint256 indexed domain, IAdapter[] adapters);

    /**
     * @dev Emitted when adapters are enabled for a specific domain.
     * @param domain - The domain associated with the enabled adapters.
     * @param adapters - An array of enabled adapter addresses associated with this event.
     */
    event AdaptersEnabled(uint256 indexed domain, IAdapter[] adapters);

    /**
     * @dev Emitted when the address of the IHashi contract is set.
     * @param hashi - The address of the IHashi contract associated with this event.
     */
    event HashiSet(IHashi indexed hashi);

    /**
     * @dev Emitted when initialization occurs with the owner's address and the IHashi contract address.
     * @param owner - The address of the owner associated with this event.
     * @param hashi - The address of the IHashi contract associated with this event.
     */
    event Init(address indexed owner, IHashi indexed hashi);

    /**
     * @dev Emitted when the threshold is set for a specific domain.
     * @param domain - The domain associated with the set threshold.
     * @param threshold - The new threshold value associated with this event.
     */
    event ThresholdSet(uint256 domain, uint256 threshold);

    /**
     * @dev Checks the order and validity of adapters for a given domain.
     * @param domain - The Uint256 identifier for the domain.
     * @param _adapters - An array of adapter instances.
     */
    function checkAdapterOrderAndValidity(uint256 domain, IAdapter[] memory _adapters) external view;

    /**
     * @dev Get the previous and the next adapter given a domain and an adapter.
     * @param domain - Uint256 identifier for the domain.
     * @param adapter - IAdapter value for the adapter.
     * @return link - The Link struct containing the previous and the next adapter.
     */
    function getAdapterLink(uint256 domain, IAdapter adapter) external view returns (Link memory);

    /**
     * @dev Returns an array of enabled adapters for a given domain.
     * @param domain - Uint256 identifier for the domain for which to list adapters.
     * @return adapters - The adapters for a given domain.
     */
    function getAdapters(uint256 domain) external view returns (IAdapter[] memory);

    /**
     * @dev Get the current configuration for a given domain.
     * @param domain - Uint256 identifier for the domain.
     * @return domain - The Domain struct containing the current configuration for a given domain.
     */
    function getDomain(uint256 domain) external view returns (Domain memory);

    /**
     * @dev Returns the threshold and count for a given domain.
     * @param domain - Uint256 identifier for the domain.
     * @return threshold - Uint256 adapters threshold for the given domain.
     * @return count - Uint256 adapters count for the given domain.
     * @notice If the threshold for a domain has not been set, or is explicitly set to 0, this function will return a threshold equal to the adapters count for the given domain.
     */
    function getThresholdAndCount(uint256 domain) external view returns (uint256, uint256);

    /**
     * @dev Returns the address of the specified Hashi.
     * @return hashi - The Hashi address.
     */
    function hashi() external view returns (IHashi);
}

File 10 of 10 : ShuSo.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.20;

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { IAdapter } from "../interfaces/IAdapter.sol";
import { IHashi } from "../interfaces/IHashi.sol";
import { IShuSho } from "../interfaces/IShuSho.sol";

abstract contract ShuSo is IShuSho, OwnableUpgradeable {
    IAdapter internal constant LIST_END = IAdapter(address(0x1));

    IHashi public hashi;
    mapping(uint256 => mapping(IAdapter => Link)) private _adapters;
    mapping(uint256 => Domain) private _domains;

    constructor(address _owner, address _hashi) {
        bytes memory initParams = abi.encode(_owner, _hashi);
        init(initParams);
    }

    function init(bytes memory initParams) public initializer {
        (address _owner, IHashi _hashi) = abi.decode(initParams, (address, IHashi));
        __Ownable_init();
        _setHashi(_hashi);
        transferOwnership(_owner);
        emit Init(_owner, _hashi);
    }

    /// @inheritdoc IShuSho
    function checkAdapterOrderAndValidity(uint256 domain, IAdapter[] memory adapters) public view {
        for (uint256 i = 0; i < adapters.length; i++) {
            IAdapter adapter = adapters[i];
            if (i > 0 && adapter <= adapters[i - 1]) revert DuplicateOrOutOfOrderAdapters(adapter, adapters[i - 1]);
            if (_adapters[domain][adapter].next == IAdapter(address(0))) revert InvalidAdapter(adapter);
        }
    }

    /// @inheritdoc IShuSho
    function getAdapterLink(uint256 domain, IAdapter adapter) external view returns (Link memory) {
        return _adapters[domain][adapter];
    }

    /// @inheritdoc IShuSho
    function getAdapters(uint256 domain) public view returns (IAdapter[] memory) {
        IAdapter[] memory adapters = new IAdapter[](_domains[domain].count);
        IAdapter currentAdapter = _adapters[domain][LIST_END].next;
        for (uint256 i = 0; i < adapters.length; i++) {
            adapters[i] = currentAdapter;
            currentAdapter = _adapters[domain][currentAdapter].next;
        }
        return adapters;
    }

    /// @inheritdoc IShuSho
    function getDomain(uint256 domain) external view returns (Domain memory) {
        return _domains[domain];
    }

    /// @inheritdoc IShuSho
    function getThresholdAndCount(uint256 domain_) public view returns (uint256, uint256) {
        Domain storage domain = _domains[domain_];
        uint256 threshold = domain.threshold;
        uint256 count = domain.count;
        if (threshold == 0) threshold = count;
        return (threshold, count);
    }

    /**
     * @dev Disables the given adapters for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set adapters.
     * @param adapters - Array of adapter addresses.
     * @notice Reverts if adapters are out of order or contain duplicates.
     * @notice Only callable by the owner of this contract.
     */
    function _disableAdapters(uint256 domain, IAdapter[] memory adapters) internal onlyOwner {
        if (_domains[domain].count == 0) revert NoAdaptersEnabled(domain);
        if (adapters.length == 0) revert NoAdaptersGiven();
        for (uint256 i = 0; i < adapters.length; i++) {
            IAdapter adapter = adapters[i];
            if (adapter == IAdapter(address(0)) || adapter == LIST_END) revert InvalidAdapter(adapter);
            Link memory current = _adapters[domain][adapter];
            if (current.next == IAdapter(address(0))) revert AdapterNotEnabled(adapter);
            IAdapter next = current.next;
            IAdapter previous = current.previous;
            _adapters[domain][next].previous = previous;
            _adapters[domain][previous].next = next;
            delete _adapters[domain][adapter].next;
            delete _adapters[domain][adapter].previous;
            _domains[domain].count--;
        }
        emit AdaptersDisabled(domain, adapters);
    }

    /**
     * @dev Enables the given adapters for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set adapters.
     * @param adapters - Array of adapter addresses.
     * @param threshold - Uint256 threshold to set for the given domain.
     * @notice Reverts if adapters are out of order, contain duplicates or if the threshold is not higher than half the count of the adapters
     * @notice Only callable by the owner of this contract.
     */
    function _enableAdapters(uint256 domain, IAdapter[] memory adapters, uint256 threshold) internal onlyOwner {
        if (_adapters[domain][LIST_END].next == IAdapter(address(0))) {
            _adapters[domain][LIST_END].next = LIST_END;
            _adapters[domain][LIST_END].previous = LIST_END;
        }
        if (adapters.length == 0) revert NoAdaptersGiven();
        for (uint256 i = 0; i < adapters.length; i++) {
            IAdapter adapter = adapters[i];
            if (adapter == IAdapter(address(0)) || adapter == LIST_END) revert InvalidAdapter(adapter);
            if (_adapters[domain][adapter].next != IAdapter(address(0))) revert AdapterAlreadyEnabled(adapter);
            IAdapter previous = _adapters[domain][LIST_END].previous;
            _adapters[domain][previous].next = adapter;
            _adapters[domain][adapter].previous = previous;
            _adapters[domain][LIST_END].previous = adapter;
            _adapters[domain][adapter].next = LIST_END;
            _domains[domain].count++;
        }
        if (threshold < (_domains[domain].count / 2) + 1) revert InvalidThreshold(threshold);
        _domains[domain].threshold = threshold;
        emit ThresholdSet(domain, threshold);
        emit AdaptersEnabled(domain, adapters);
    }

    /**
     * @dev Returns the hash unanimously agreed upon by all of the given adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param id - Uint256 identifier to query.
     * @param adapters - Array of adapter addresses to query.
     * @return hash - Bytes32 hash agreed upon by the adapters for the given domain.
     * @notice adapters must be in numerical order from smallest to largest and contain no duplicates.
     * @notice Reverts if adapters are out of order or contain duplicates.
     * @notice Reverts if adapters disagree.
     * @notice Revert if the adapters do not yet have the hash for the given ID.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function _getHash(uint256 domain, uint256 id, IAdapter[] memory adapters) internal view returns (bytes32) {
        (uint256 threshold, uint256 count) = getThresholdAndCount(domain);
        if (adapters.length == 0) revert NoAdaptersGiven();
        if (count == 0) revert NoAdaptersEnabled(domain);
        if (adapters.length < threshold) revert ThresholdNotMet();
        checkAdapterOrderAndValidity(domain, adapters);
        return hashi.getHash(domain, id, adapters);
    }

    /**
     * @dev Returns the hash agreed upon by a threshold of the enabled adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param id - Uint256 identifier to query.
     * @return hash - Bytes32 hash agreed upon by a threshold of the adapters for the given domain.
     * @notice If the threshold is set to 1, the function will return the hash of the first adapter in the list.
     * @notice Reverts if no threshold is not reached.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function _getThresholdHash(uint256 domain, uint256 id) internal view returns (bytes32 hash) {
        IAdapter[] memory adapters = getAdapters(domain);
        (uint256 threshold, uint256 count) = getThresholdAndCount(domain);
        if (count == 0) revert NoAdaptersEnabled(domain);
        if (adapters.length < threshold) revert ThresholdNotMet();

        bytes32[] memory hashes = new bytes32[](adapters.length);
        for (uint256 i = 0; i < adapters.length; i++) {
            hashes[i] = adapters[i].getHash(domain, id);
        }

        for (uint256 i = 0; i < hashes.length; i++) {
            if (i > hashes.length - threshold) break;

            bytes32 baseHash = hashes[i];
            if (baseHash == bytes32(0)) continue;

            uint256 num = 0;
            for (uint256 j = i; j < hashes.length; j++) {
                if (baseHash == hashes[j]) {
                    num++;
                    if (num == threshold) return hashes[i];
                }
            }
        }
        revert ThresholdNotMet();
    }

    /**
     * @dev Returns the hash unanimously agreed upon by ALL of the enabled adapters.
     * @param domain - Uint256 identifier for the domain to query.
     * @param id - Uint256 identifier to query.
     * @return hash - Bytes32 hash agreed upon by the adapters for the given domain.
     * @notice Reverts if adapters disagree.
     * @notice Revert if the adapters do not yet have the hash for the given ID.
     * @notice Reverts if no adapters are set for the given domain.
     */
    function _getUnanimousHash(uint256 domain, uint256 id) internal view returns (bytes32 hash) {
        IAdapter[] memory adapters = getAdapters(domain);
        (uint256 threshold, uint256 count) = getThresholdAndCount(domain);
        if (count == 0) revert NoAdaptersEnabled(domain);
        if (adapters.length < threshold) revert ThresholdNotMet();
        return hashi.getHash(domain, id, adapters);
    }

    /**
     * @dev Sets the address of the IHashi contract.
     * @param _hashi - Address of the hashi contract.
     * @notice Only callable by the owner of this contract.
     */
    function _setHashi(IHashi _hashi) internal onlyOwner {
        if (hashi == _hashi) revert DuplicateHashiAddress(_hashi);
        hashi = _hashi;
        emit HashiSet(hashi);
    }

    /**
     * @dev Sets the threshold of adapters required for a given domain.
     * @param domain - Uint256 identifier for the domain for which to set the threshold.
     * @param threshold - Uint256 threshold to set for the given domain.
     * @notice Only callable by the owner of this contract.
     * @notice Reverts if threshold is already set to the given value.
     */
    function _setThreshold(uint256 domain, uint256 threshold) internal onlyOwner {
        uint256 count = _domains[domain].count;
        if (count == 0) revert CountCannotBeZero();
        if (threshold < (count / 2) + 1) revert InvalidThreshold(threshold);
        if (_domains[domain].threshold == threshold) revert DuplicateThreshold(threshold);
        _domains[domain].threshold = threshold;
        emit ThresholdSet(domain, threshold);
    }
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_hashi","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"contract IAdapter","name":"adapter","type":"address"}],"name":"AdapterAlreadyEnabled","type":"error"},{"inputs":[{"internalType":"contract IAdapter","name":"adapter","type":"address"}],"name":"AdapterNotEnabled","type":"error"},{"inputs":[],"name":"CountCannotBeZero","type":"error"},{"inputs":[{"internalType":"contract IHashi","name":"hashi","type":"address"}],"name":"DuplicateHashiAddress","type":"error"},{"inputs":[{"internalType":"contract IAdapter","name":"adapterOne","type":"address"},{"internalType":"contract IAdapter","name":"adapterTwo","type":"address"}],"name":"DuplicateOrOutOfOrderAdapters","type":"error"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"DuplicateThreshold","type":"error"},{"inputs":[{"internalType":"contract IAdapter","name":"adapter","type":"address"}],"name":"InvalidAdapter","type":"error"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"InvalidThreshold","type":"error"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"}],"name":"NoAdaptersEnabled","type":"error"},{"inputs":[],"name":"NoAdaptersGiven","type":"error"},{"inputs":[],"name":"ThresholdNotMet","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"domain","type":"uint256"},{"indexed":false,"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"}],"name":"AdaptersDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"domain","type":"uint256"},{"indexed":false,"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"}],"name":"AdaptersEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IHashi","name":"hashi","type":"address"}],"name":"HashiSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"contract IHashi","name":"hashi","type":"address"}],"name":"Init","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"domain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"ThresholdSet","type":"event"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"}],"name":"checkAdapterOrderAndValidity","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"}],"name":"disableAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"enableAdapters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"contract IAdapter","name":"adapter","type":"address"}],"name":"getAdapterLink","outputs":[{"components":[{"internalType":"contract IAdapter","name":"previous","type":"address"},{"internalType":"contract IAdapter","name":"next","type":"address"}],"internalType":"struct IShuSho.Link","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"}],"name":"getAdapters","outputs":[{"internalType":"contract IAdapter[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"}],"name":"getDomain","outputs":[{"components":[{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"internalType":"struct IShuSho.Domain","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"contract IAdapter[]","name":"adapters","type":"address[]"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain_","type":"uint256"}],"name":"getThresholdAndCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getThresholdHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUnanimousHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hashi","outputs":[{"internalType":"contract IHashi","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initParams","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IHashi","name":"_hashi","type":"address"}],"name":"setHashi","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"domain","type":"uint256"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080346102e957611f7a906001600160401b0390601f38849003908101601f1916820190838211838310176102d357808391604096879485528339810103126102e9576100576020610050836102ee565b92016102ee565b918351916020830160018060a01b03809216815281868501951685528584526060840192848410908411176102d357828652600093845460ff8160081c1615948580966102c6575b80156102af575b15610257575060ff198116600117865587919085610246575b50805181010312610242575193818516809503610242575190808216809203610242576100fb60ff855460081c166100f681610302565b610302565b610104336103ba565b61010c610362565b816065549182161461022a576001600160a01b0319168117606555807f1e44815867bf36700178046dec2874b58492fa049a6775df578903717bb05b358480a2610154610362565b83156101d757610163846103ba565b8451937f45acd56f401dc3db1d520e5e214f090b4ab3e3fbf42fd24596cb511edaad876a8480a361019d575b8251611b7690816104048239f35b805461ff0019169055600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1388061018f565b845162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b8551634636033760e01b815260048101839052602490fd5b8380fd5b61ffff1916610101178655386100bf565b6084906d191e481a5b9a5d1a585b1a5e995960921b60c48562461bcd60e51b845260206064820152602e858201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160a48201520152fd5b50303b1580156100a65750600160ff8316146100a6565b50600160ff83161061009f565b634e487b7160e01b600052604160045260246000fd5b600080fd5b51906001600160a01b03821682036102e957565b1561030957565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b6033546001600160a01b0316330361037657565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a356fe6040608081526004908136101561001557600080fd5b600091823560e01c806314223645146111da57806314d33830146111b05780631a7a98e2146111565780634ddf47d414610d6157806367e2120e14610c98578063715018a614610c185780638c634d0b14610be05780638da5cb5b14610bab578063958f9ee814610903578063b3105439146108e0578063b89bff5f146108c8578063b9c3620914610782578063c3cc4d031461040c578063d3a5458b1461037c578063ead22754146101ec578063ec2cf2d5146101b35763f2fde38b146100dc57600080fd5b346101af5760206003193601126101af5780359173ffffffffffffffffffffffffffffffffffffffff83168084036101ab576101166117e2565b15610128578361012584611861565b80f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8480fd5b8280fd5b5050346101e857816003193601126101e85760209073ffffffffffffffffffffffffffffffffffffffff606554169051908152f35b5080fd5b50346101af5760606003193601126101af57803560443567ffffffffffffffff81116101ab5761021f90369084016113c0565b9161022982611470565b8451156103545715610325578351106102fe5791816102a0949361024f836020956115bf565b73ffffffffffffffffffffffffffffffffffffffff60655416918551968794859384937fead2275400000000000000000000000000000000000000000000000000000000855260243591850161173b565b03915afa9182156102f45783926102bc575b6020838351908152f35b9091506020813d6020116102ec575b816102d86020938361131d565b810103126101af57602092505190386102b2565b3d91506102cb565b81513d85823e3d90fd5b83517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b506024918451917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b8286517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b50823461040957826003193601126104095760243573ffffffffffffffffffffffffffffffffffffffff928382168092036101af579082918593602085516103c3816112d2565b82815201523582526066602052828220908252602052209082516103e6816112d2565b602082600181865416958685520154169101908152835192835251166020820152f35b80fd5b508290346101e85760606003193601126101e8578035906024803567ffffffffffffffff81116101ab5761044390369084016113c0565b91604435906104506117e2565b84865260669260209380855288882091600192838a52865273ffffffffffffffffffffffffffffffffffffffff9081848c8c2001541615610727575b8751156106ff5789845b61058f575b5050505085875260678452808888200154811c9081018091116105635782106105355750857fa9b994c5f360eb267c36dec4b76776cae1c2f79cf0b3863baf389a499a6d689a869761052f93877fded0d38026c6e9ca7e2ee1647ae6f70e2306bcc9dcabbb9888888683513e16099899526067865280828b205581519089825286820152a15192828493845283019061135e565b0390a280f35b6024918751917f651a749b000000000000000000000000000000000000000000000000000000008352820152fd5b6024876011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88518110156106fa57826105a3828b611495565b5116801580156106f1575b6106c35783868e8e8e8152888d528181208582528d5220015416610695578594939291858e8e8e8d84968284528a82528484208685528252898585205416918385528b815285852083865281528686862001927fffffffffffffffffffffffff00000000000000000000000000000000000000009383858254161790558486528c8252868620838752825286862090848254161790558385528b8152858520878652815285852082848254161790558385528b81528585209185525284808585200191825416179055815260678d52200161068981546118ce565b90550190919293610496565b8691508c51917fb7b944b2000000000000000000000000000000000000000000000000000000008352820152fd5b8691508c51917fca0f21b4000000000000000000000000000000000000000000000000000000008352820152fd5b508581146105ae565b61049b565b848b517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b888a528287528a8a20848b528752838b8b20017fffffffffffffffffffffffff0000000000000000000000000000000000000000908582825416179055898b528388528b8b20858c528852848c8c209182541617905561048c565b509190346101e857610793366112b7565b9361079c6117e2565b81845260676020526001838520015480156108a05760011c6001810180911161087457851061084557818452606760205284838520541461081657508293817fa9b994c5f360eb267c36dec4b76776cae1c2f79cf0b3863baf389a499a6d689a94526067602052808386205582519182526020820152a180f35b602490858451917f5335ca84000000000000000000000000000000000000000000000000000000008352820152fd5b602490858451917f651a749b000000000000000000000000000000000000000000000000000000008352820152fd5b6024856011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082517f1741ad92000000000000000000000000000000000000000000000000000000008152fd5b8334610409576101256108da3661143d565b906115bf565b5050346101e8576020906108fc6108f6366112b7565b906118fb565b9051908152f35b508290346101e8576109143661143d565b909161091e6117e2565b8284526067946020916067835260019081838820015415610b7c57845115610b555786825b610981575b5050509061052f7f445aa3dd0c2baa28306a020b0ad28802dac8ce56b94bf9ae2521afa90f855bfb93925192828493845283019061135e565b8551811015610b505773ffffffffffffffffffffffffffffffffffffffff806109aa8389611495565b511680158015610b47575b610b1857888a526066808852868b20828c528852868b209280878951956109db876112d2565b8281541687520154168985019080825215610ae95781905116935116928a8c52818952878c20818d528952878c20937fffffffffffffffffffffffff00000000000000000000000000000000000000009481868254161790558b8d52828a52888d20908d52895286888d20019084825416179055898b52808852868b20828c52885285878c2001838154169055898b528752858a20908a528652848920908154169055868852888552828489200180548015610abd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055820182610943565b60248a6011867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b602487858b51917f950764a3000000000000000000000000000000000000000000000000000000008352820152fd5b836024918751917fca0f21b4000000000000000000000000000000000000000000000000000000008352820152fd5b508481146109b5565b610948565b82517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b602490868451917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b5050346101e857816003193601126101e85760209073ffffffffffffffffffffffffffffffffffffffff603354169051908152f35b5091346104095760206003193601126104095750610c01610c1492356114d8565b905191829160208352602083019061135e565b0390f35b8334610409578060031936011261040957610c316117e2565b8073ffffffffffffffffffffffffffffffffffffffff6033547fffffffffffffffffffffffff00000000000000000000000000000000000000008116603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5090346101af5760206003193601126101af5781359173ffffffffffffffffffffffffffffffffffffffff918284168094036101ab57610cd66117e2565b8360655493841614610d325750507fffffffffffffffffffffffff00000000000000000000000000000000000000001681176065557f1e44815867bf36700178046dec2874b58492fa049a6775df578903717bb05b358280a280f35b908360249251917f46360337000000000000000000000000000000000000000000000000000000008352820152fd5b50346101af576020908160031936011261115257803567ffffffffffffffff9384821161114e573660238301121561114e57818301359260249584116111235786825193610dd6877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f890116018661131d565b85855286850195368982840101116101af57808989930188378501015286549360ff8560081c161594858096611116575b80156110ff575b1561107e578560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008316178a55611050575b50828480518101031261104c57519573ffffffffffffffffffffffffffffffffffffffff93848816809803611048578301519380851680950361104857610e9760ff8a5460081c16610e9281611757565b611757565b610ea033611861565b610ea86117e2565b846065549182161461101a577fffffffffffffffffffffffff0000000000000000000000000000000000000000168417606555837f1e44815867bf36700178046dec2874b58492fa049a6775df578903717bb05b358980a2610f086117e2565b8615610f9a575050610f1985611861565b51937f45acd56f401dc3db1d520e5e214f090b4ab3e3fbf42fd24596cb511edaad876a8680a3610f47578280f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff845416845560018152a138808280f35b6026908660849451937f08c379a00000000000000000000000000000000000000000000000000000000085528401528201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b5092909151917f46360337000000000000000000000000000000000000000000000000000000008352820152fd5b8880fd5b8780fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661010117885538610e41565b608483602e8a8a8851937f08c379a00000000000000000000000000000000000000000000000000000000085528401528201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b158015610e0e5750600160ff821614610e0e565b50600160ff821610610e07565b86604187927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8580fd5b8380fd5b50346101af5760206003193601126101af579181928160208451611179816112d2565b82815201523581526067602052208151611192816112d2565b60206001835493848452015491019081528251918252516020820152f35b50823461040957602060031936011261040957506111ce9035611470565b82519182526020820152f35b5090346101af576111ea366112b7565b90926111f5846114d8565b936111ff81611470565b156112885785511061126057906020929173ffffffffffffffffffffffffffffffffffffffff60655416916102a08651978895869485947fead22754000000000000000000000000000000000000000000000000000000008652850161173b565b5082517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b602483838751917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b60031960409101126112cd576004359060243590565b600080fd5b6040810190811067ffffffffffffffff8211176112ee57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176112ee57604052565b90815180825260208080930193019160005b82811061137e575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611370565b67ffffffffffffffff81116112ee5760051b60200190565b9080601f830112156112cd5760209082356113da816113a8565b936113e8604051958661131d565b81855260208086019260051b8201019283116112cd57602001905b828210611411575050505090565b813573ffffffffffffffffffffffffffffffffffffffff811681036112cd578152908301908301611403565b9060406003198301126112cd57600435916024359067ffffffffffffffff82116112cd5761146d916004016113c0565b90565b600052606760205260406000209060018254920154918015611490579190565b508190565b80518210156114a95760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600090808252602090606782526001916040838186200154947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061153361151e886113a8565b9761152b8551998a61131d565b8089526113a8565b0136848801378381528460669360668152838320828452815273ffffffffffffffffffffffffffffffffffffffff9485838686200154169684935b61157f575b50505050505050505090565b89518410156115ba57889787611595868d611495565b911680915281865282845286862090865283528787818888200154169401939761156e565b611573565b60005b82518110156117365773ffffffffffffffffffffffffffffffffffffffff806115eb8386611495565b511690821515806116f6575b61165b578360005260209060668252604091826000209084600052526001826000200154161561162b5750506001016115c2565b6024925051907fca0f21b40000000000000000000000000000000000000000000000000000000082526004820152fd5b847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116116c75760449361169291611495565b5116604051917fe3d4931700000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116116c75761172c829187611495565b51168211156115f7565b505050565b61146d939260609282526020820152816040820152019061135e565b1561175e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff60335416330361180357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6033549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146116c75760010190565b919091611907816114d8565b9061191181611470565b93909315611b0f5783835110611adb5782519461192d866113a8565b93611949604097611941604051978861131d565b8087526113a8565b927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020940136602088013760005b8251811015611a3a5760448573ffffffffffffffffffffffffffffffffffffffff6119a38487611495565b51168b51928380927f1b8550440000000000000000000000000000000000000000000000000000000082528b60048301528960248301525afa908115611a2f57600091611a01575b50906001916119fa828a611495565b5201611978565b908682813d8311611a28575b611a17818361131d565b8101031261040957505160016119eb565b503d611a0d565b8a513d6000823e3d90fd5b509650505050506000905b805180831015611b05578381039081116116c7578211611ad657611a698282611495565b51928315611acb576000835b8351811015611abb57611a888185611495565b518614611a98575b600101611a75565b90611aa2906118ce565b90828203611a9057505050611ab79250611495565b5190565b50509250906001905b0190611a45565b925090600190611ac4565b505050505b60046040517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b5050505050611adb565b602482604051907fcf9349b10000000000000000000000000000000000000000000000000000000082526004820152fdfea2646970667358221220fc5c9b4d76adb2450bb0ce52d34eaeac938639542a6ebea92f8d371ba16c5fe764736f6c6343000819003300000000000000000000000067e5855aa4d5786c086b7fc6b4203a5ea50e93f8000000000000000000000000a86bc62ac53dc86687ab6c15fdebc71ad51fb615

Deployed Bytecode

0x6040608081526004908136101561001557600080fd5b600091823560e01c806314223645146111da57806314d33830146111b05780631a7a98e2146111565780634ddf47d414610d6157806367e2120e14610c98578063715018a614610c185780638c634d0b14610be05780638da5cb5b14610bab578063958f9ee814610903578063b3105439146108e0578063b89bff5f146108c8578063b9c3620914610782578063c3cc4d031461040c578063d3a5458b1461037c578063ead22754146101ec578063ec2cf2d5146101b35763f2fde38b146100dc57600080fd5b346101af5760206003193601126101af5780359173ffffffffffffffffffffffffffffffffffffffff83168084036101ab576101166117e2565b15610128578361012584611861565b80f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8480fd5b8280fd5b5050346101e857816003193601126101e85760209073ffffffffffffffffffffffffffffffffffffffff606554169051908152f35b5080fd5b50346101af5760606003193601126101af57803560443567ffffffffffffffff81116101ab5761021f90369084016113c0565b9161022982611470565b8451156103545715610325578351106102fe5791816102a0949361024f836020956115bf565b73ffffffffffffffffffffffffffffffffffffffff60655416918551968794859384937fead2275400000000000000000000000000000000000000000000000000000000855260243591850161173b565b03915afa9182156102f45783926102bc575b6020838351908152f35b9091506020813d6020116102ec575b816102d86020938361131d565b810103126101af57602092505190386102b2565b3d91506102cb565b81513d85823e3d90fd5b83517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b506024918451917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b8286517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b50823461040957826003193601126104095760243573ffffffffffffffffffffffffffffffffffffffff928382168092036101af579082918593602085516103c3816112d2565b82815201523582526066602052828220908252602052209082516103e6816112d2565b602082600181865416958685520154169101908152835192835251166020820152f35b80fd5b508290346101e85760606003193601126101e8578035906024803567ffffffffffffffff81116101ab5761044390369084016113c0565b91604435906104506117e2565b84865260669260209380855288882091600192838a52865273ffffffffffffffffffffffffffffffffffffffff9081848c8c2001541615610727575b8751156106ff5789845b61058f575b5050505085875260678452808888200154811c9081018091116105635782106105355750857fa9b994c5f360eb267c36dec4b76776cae1c2f79cf0b3863baf389a499a6d689a869761052f93877fded0d38026c6e9ca7e2ee1647ae6f70e2306bcc9dcabbb9888888683513e16099899526067865280828b205581519089825286820152a15192828493845283019061135e565b0390a280f35b6024918751917f651a749b000000000000000000000000000000000000000000000000000000008352820152fd5b6024876011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b88518110156106fa57826105a3828b611495565b5116801580156106f1575b6106c35783868e8e8e8152888d528181208582528d5220015416610695578594939291858e8e8e8d84968284528a82528484208685528252898585205416918385528b815285852083865281528686862001927fffffffffffffffffffffffff00000000000000000000000000000000000000009383858254161790558486528c8252868620838752825286862090848254161790558385528b8152858520878652815285852082848254161790558385528b81528585209185525284808585200191825416179055815260678d52200161068981546118ce565b90550190919293610496565b8691508c51917fb7b944b2000000000000000000000000000000000000000000000000000000008352820152fd5b8691508c51917fca0f21b4000000000000000000000000000000000000000000000000000000008352820152fd5b508581146105ae565b61049b565b848b517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b888a528287528a8a20848b528752838b8b20017fffffffffffffffffffffffff0000000000000000000000000000000000000000908582825416179055898b528388528b8b20858c528852848c8c209182541617905561048c565b509190346101e857610793366112b7565b9361079c6117e2565b81845260676020526001838520015480156108a05760011c6001810180911161087457851061084557818452606760205284838520541461081657508293817fa9b994c5f360eb267c36dec4b76776cae1c2f79cf0b3863baf389a499a6d689a94526067602052808386205582519182526020820152a180f35b602490858451917f5335ca84000000000000000000000000000000000000000000000000000000008352820152fd5b602490858451917f651a749b000000000000000000000000000000000000000000000000000000008352820152fd5b6024856011847f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082517f1741ad92000000000000000000000000000000000000000000000000000000008152fd5b8334610409576101256108da3661143d565b906115bf565b5050346101e8576020906108fc6108f6366112b7565b906118fb565b9051908152f35b508290346101e8576109143661143d565b909161091e6117e2565b8284526067946020916067835260019081838820015415610b7c57845115610b555786825b610981575b5050509061052f7f445aa3dd0c2baa28306a020b0ad28802dac8ce56b94bf9ae2521afa90f855bfb93925192828493845283019061135e565b8551811015610b505773ffffffffffffffffffffffffffffffffffffffff806109aa8389611495565b511680158015610b47575b610b1857888a526066808852868b20828c528852868b209280878951956109db876112d2565b8281541687520154168985019080825215610ae95781905116935116928a8c52818952878c20818d528952878c20937fffffffffffffffffffffffff00000000000000000000000000000000000000009481868254161790558b8d52828a52888d20908d52895286888d20019084825416179055898b52808852868b20828c52885285878c2001838154169055898b528752858a20908a528652848920908154169055868852888552828489200180548015610abd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055820182610943565b60248a6011867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b602487858b51917f950764a3000000000000000000000000000000000000000000000000000000008352820152fd5b836024918751917fca0f21b4000000000000000000000000000000000000000000000000000000008352820152fd5b508481146109b5565b610948565b82517fc77f9c81000000000000000000000000000000000000000000000000000000008152fd5b602490868451917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b5050346101e857816003193601126101e85760209073ffffffffffffffffffffffffffffffffffffffff603354169051908152f35b5091346104095760206003193601126104095750610c01610c1492356114d8565b905191829160208352602083019061135e565b0390f35b8334610409578060031936011261040957610c316117e2565b8073ffffffffffffffffffffffffffffffffffffffff6033547fffffffffffffffffffffffff00000000000000000000000000000000000000008116603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5090346101af5760206003193601126101af5781359173ffffffffffffffffffffffffffffffffffffffff918284168094036101ab57610cd66117e2565b8360655493841614610d325750507fffffffffffffffffffffffff00000000000000000000000000000000000000001681176065557f1e44815867bf36700178046dec2874b58492fa049a6775df578903717bb05b358280a280f35b908360249251917f46360337000000000000000000000000000000000000000000000000000000008352820152fd5b50346101af576020908160031936011261115257803567ffffffffffffffff9384821161114e573660238301121561114e57818301359260249584116111235786825193610dd6877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f890116018661131d565b85855286850195368982840101116101af57808989930188378501015286549360ff8560081c161594858096611116575b80156110ff575b1561107e578560017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008316178a55611050575b50828480518101031261104c57519573ffffffffffffffffffffffffffffffffffffffff93848816809803611048578301519380851680950361104857610e9760ff8a5460081c16610e9281611757565b611757565b610ea033611861565b610ea86117e2565b846065549182161461101a577fffffffffffffffffffffffff0000000000000000000000000000000000000000168417606555837f1e44815867bf36700178046dec2874b58492fa049a6775df578903717bb05b358980a2610f086117e2565b8615610f9a575050610f1985611861565b51937f45acd56f401dc3db1d520e5e214f090b4ab3e3fbf42fd24596cb511edaad876a8680a3610f47578280f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff845416845560018152a138808280f35b6026908660849451937f08c379a00000000000000000000000000000000000000000000000000000000085528401528201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b5092909151917f46360337000000000000000000000000000000000000000000000000000000008352820152fd5b8880fd5b8780fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661010117885538610e41565b608483602e8a8a8851937f08c379a00000000000000000000000000000000000000000000000000000000085528401528201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152fd5b50303b158015610e0e5750600160ff821614610e0e565b50600160ff821610610e07565b86604187927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8580fd5b8380fd5b50346101af5760206003193601126101af579181928160208451611179816112d2565b82815201523581526067602052208151611192816112d2565b60206001835493848452015491019081528251918252516020820152f35b50823461040957602060031936011261040957506111ce9035611470565b82519182526020820152f35b5090346101af576111ea366112b7565b90926111f5846114d8565b936111ff81611470565b156112885785511061126057906020929173ffffffffffffffffffffffffffffffffffffffff60655416916102a08651978895869485947fead22754000000000000000000000000000000000000000000000000000000008652850161173b565b5082517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b602483838751917fcf9349b1000000000000000000000000000000000000000000000000000000008352820152fd5b60031960409101126112cd576004359060243590565b600080fd5b6040810190811067ffffffffffffffff8211176112ee57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176112ee57604052565b90815180825260208080930193019160005b82811061137e575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611370565b67ffffffffffffffff81116112ee5760051b60200190565b9080601f830112156112cd5760209082356113da816113a8565b936113e8604051958661131d565b81855260208086019260051b8201019283116112cd57602001905b828210611411575050505090565b813573ffffffffffffffffffffffffffffffffffffffff811681036112cd578152908301908301611403565b9060406003198301126112cd57600435916024359067ffffffffffffffff82116112cd5761146d916004016113c0565b90565b600052606760205260406000209060018254920154918015611490579190565b508190565b80518210156114a95760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600090808252602090606782526001916040838186200154947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061153361151e886113a8565b9761152b8551998a61131d565b8089526113a8565b0136848801378381528460669360668152838320828452815273ffffffffffffffffffffffffffffffffffffffff9485838686200154169684935b61157f575b50505050505050505090565b89518410156115ba57889787611595868d611495565b911680915281865282845286862090865283528787818888200154169401939761156e565b611573565b60005b82518110156117365773ffffffffffffffffffffffffffffffffffffffff806115eb8386611495565b511690821515806116f6575b61165b578360005260209060668252604091826000209084600052526001826000200154161561162b5750506001016115c2565b6024925051907fca0f21b40000000000000000000000000000000000000000000000000000000082526004820152fd5b847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116116c75760449361169291611495565b5116604051917fe3d4931700000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018381116116c75761172c829187611495565b51168211156115f7565b505050565b61146d939260609282526020820152816040820152019061135e565b1561175e57565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152fd5b73ffffffffffffffffffffffffffffffffffffffff60335416330361180357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6033549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146116c75760010190565b919091611907816114d8565b9061191181611470565b93909315611b0f5783835110611adb5782519461192d866113a8565b93611949604097611941604051978861131d565b8087526113a8565b927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020940136602088013760005b8251811015611a3a5760448573ffffffffffffffffffffffffffffffffffffffff6119a38487611495565b51168b51928380927f1b8550440000000000000000000000000000000000000000000000000000000082528b60048301528960248301525afa908115611a2f57600091611a01575b50906001916119fa828a611495565b5201611978565b908682813d8311611a28575b611a17818361131d565b8101031261040957505160016119eb565b503d611a0d565b8a513d6000823e3d90fd5b509650505050506000905b805180831015611b05578381039081116116c7578211611ad657611a698282611495565b51928315611acb576000835b8351811015611abb57611a888185611495565b518614611a98575b600101611a75565b90611aa2906118ce565b90828203611a9057505050611ab79250611495565b5190565b50509250906001905b0190611a45565b925090600190611ac4565b505050505b60046040517f59fa4a93000000000000000000000000000000000000000000000000000000008152fd5b5050505050611adb565b602482604051907fcf9349b10000000000000000000000000000000000000000000000000000000082526004820152fdfea2646970667358221220fc5c9b4d76adb2450bb0ce52d34eaeac938639542a6ebea92f8d371ba16c5fe764736f6c63430008190033

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

00000000000000000000000067e5855aa4d5786c086b7fc6b4203a5ea50e93f8000000000000000000000000a86bc62ac53dc86687ab6c15fdebc71ad51fb615

-----Decoded View---------------
Arg [0] : _owner (address): 0x67E5855Aa4D5786c086b7FC6B4203a5Ea50E93F8
Arg [1] : _hashi (address): 0xA86bc62Ac53Dc86687AB6C15fdebC71ad51fB615

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000067e5855aa4d5786c086b7fc6b4203a5ea50e93f8
Arg [1] : 000000000000000000000000a86bc62ac53dc86687ab6c15fdebc71ad51fb615


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
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.