ETH Price: $3,067.11 (+3.94%)
Gas: 12 Gwei

Contract

0xA612FCA4652EF94Ae3D0E0AeFeDb1932C5F1B61D
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Activate Node196360012024-04-12 0:38:356 days ago1712882315IN
0xA612FCA4...2C5F1B61D
0 ETH0.0003188211.58563474
Register Node196313502024-04-11 9:00:357 days ago1712826035IN
0xA612FCA4...2C5F1B61D
0 ETH0.0008018117.47931472
Create Subscript...196249092024-04-10 11:23:598 days ago1712748239IN
0xA612FCA4...2C5F1B61D
0 ETH0.0021034117.34660769
Register Node196235212024-04-10 6:43:598 days ago1712731439IN
0xA612FCA4...2C5F1B61D
0 ETH0.0007023715.31156296
Activate Node196211622024-04-09 22:48:478 days ago1712702927IN
0xA612FCA4...2C5F1B61D
0 ETH0.0004706317.10219253
Register Node196203582024-04-09 20:06:478 days ago1712693207IN
0xA612FCA4...2C5F1B61D
0 ETH0.0012277226.76413967
Register Node195825312024-04-04 12:54:4714 days ago1712235287IN
0xA612FCA4...2C5F1B61D
0 ETH0.0010492822.87409292
Register Node194458922024-03-16 7:10:4733 days ago1710573047IN
0xA612FCA4...2C5F1B61D
0 ETH0.0012651327.5797567
Register Node194019782024-03-10 3:21:2339 days ago1710040883IN
0xA612FCA4...2C5F1B61D
0 ETH0.0019230841.92276733
Activate Node193990942024-03-09 17:40:3539 days ago1710006035IN
0xA612FCA4...2C5F1B61D
0 ETH0.001918169.70125653
Register Node193979072024-03-09 13:42:2340 days ago1709991743IN
0xA612FCA4...2C5F1B61D
0 ETH0.003150768.68481162
Activate Node193572792024-03-03 21:19:4745 days ago1709500787IN
0xA612FCA4...2C5F1B61D
0 ETH0.0013278648.25266965
Activate Node193551262024-03-03 14:05:1146 days ago1709474711IN
0xA612FCA4...2C5F1B61D
0 ETH0.0013301948.3374693
Register Node193548642024-03-03 13:12:3546 days ago1709471555IN
0xA612FCA4...2C5F1B61D
0 ETH0.0021338846.51833875
Register Node193547662024-03-03 12:52:4746 days ago1709470367IN
0xA612FCA4...2C5F1B61D
0 ETH0.002186947.67404062
Activate Node193539052024-03-03 9:59:4746 days ago1709459987IN
0xA612FCA4...2C5F1B61D
0 ETH0.001135941.27718463
Activate Node193538032024-03-03 9:39:2346 days ago1709458763IN
0xA612FCA4...2C5F1B61D
0 ETH0.0011867643.12523762
Activate Node193537322024-03-03 9:25:1146 days ago1709457911IN
0xA612FCA4...2C5F1B61D
0 ETH0.0009974336.24525243
Activate Node193537212024-03-03 9:22:5946 days ago1709457779IN
0xA612FCA4...2C5F1B61D
0 ETH0.0009974336.24525243
Activate Node193536342024-03-03 9:05:3546 days ago1709456735IN
0xA612FCA4...2C5F1B61D
0 ETH0.0011629342.25925606
Activate Node193536022024-03-03 8:59:1146 days ago1709456351IN
0xA612FCA4...2C5F1B61D
0 ETH0.0011091540.30502283
Register Node193535372024-03-03 8:46:1146 days ago1709455571IN
0xA612FCA4...2C5F1B61D
0 ETH0.0021603847.0959668
Activate Node193534922024-03-03 8:36:5946 days ago1709455019IN
0xA612FCA4...2C5F1B61D
0 ETH0.0010672138.78092388
Register Node193534712024-03-03 8:32:3546 days ago1709454755IN
0xA612FCA4...2C5F1B61D
0 ETH0.002016643.96166761
Register Node193534072024-03-03 8:19:3546 days ago1709453975IN
0xA612FCA4...2C5F1B61D
0 ETH0.0022113248.2064357
View all transactions

Advanced mode:
Parent Transaction Hash Block From To Value
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
EIP712Coordinator

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion, GNU GPLv3 license
File 1 of 7 : EIP712Coordinator.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.4;

import {ECDSA} from "solady/utils/ECDSA.sol";
import {Coordinator} from "./Coordinator.sol";
import {EIP712} from "solady/utils/EIP712.sol";
import {Delegator} from "./pattern/Delegator.sol";

/// @title EIP712Coordinator
/// @notice Coordinator enhanced with ability to created subscriptions via off-chain EIP-712 signature
/// @dev Allows creating a subscription on behalf of a contract via delegatee EOA signature
/// @dev Allows nodes to atomically create subscriptions and deliver compute responses
contract EIP712Coordinator is EIP712, Coordinator {
    /*//////////////////////////////////////////////////////////////
                               CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @notice EIP-712 signing domain major version
    string public constant EIP712_VERSION = "1";

    /// @notice EIP-712 signing domain name
    string public constant EIP712_NAME = "InfernetCoordinator";

    /// @notice Gas overhead in wei to retrieve cached subscriptionId for existing delegatee-created subscription
    /// @dev A uint16 is sufficient but increases control plane costs. While we can pack this and the subsequent uint24
    ///      in contract storage to save data plane costs, we prioritize control plane and instead simply use a uint256
    uint256 public constant DELEGATEE_OVERHEAD_CACHED_WEI = 600 wei;

    /// @notice Gas overhead in wei to create a new subscription via delegatee signature
    /// @dev Make note that this does not account for gas costs of dynamic inputs (containerId, inputs), just base overhead
    /// @dev Can fit within uint24, see comment for `DELEGATEE_OVERHEAD_CACHED_WEI` for details
    uint256 public constant DELEGATEE_OVERHEAD_CREATE_WEI = 91_200 wei;

    /// @notice EIP-712 struct(Subscription) typeHash
    bytes32 private constant EIP712_SUBSCRIPTION_TYPEHASH = keccak256(
        "Subscription(address owner,uint32 activeAt,uint32 period,uint32 frequency,uint16 redundancy,uint48 maxGasPrice,uint32 maxGasLimit,string containerId,bytes inputs)"
    );

    /// @notice EIP-712 struct(DelegateSubscription) typeHash
    /// @dev struct(DelegateSubscription) == { uint32 nonce, uint32 expiry, Subscription sub }
    /// @dev The `nonce` represents the nonce of the subscribing contract (sub-owner); prevents signature replay
    /// @dev The `expiry` is when the delegated subscription signature expires and can no longer be used
    bytes32 private constant EIP712_DELEGATE_SUBSCRIPTION_TYPEHASH = keccak256(
        "DelegateSubscription(uint32 nonce,uint32 expiry,Subscription sub)Subscription(address owner,uint32 activeAt,uint32 period,uint32 frequency,uint16 redundancy,uint48 maxGasPrice,uint32 maxGasLimit,string containerId,bytes inputs)"
    );

    /*//////////////////////////////////////////////////////////////
                                MUTABLE
    //////////////////////////////////////////////////////////////*/

    /// @notice Subscribing contract => maximum seen nonce
    /// @dev The nonce is a uint32 size(4.2B) which would take > 100 years of incrementing nonce per second to overflow
    mapping(address => uint32) public maxSubscriberNonce;

    /// @notice hash(subscribing contract, nonce) => subscriptionId
    /// @notice Allows lookup between a delegated subscription creation (unique(subscriber, nonce)) and subscriptionId
    mapping(bytes32 => uint32) public delegateCreatedIds;

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @notice Thrown by `createSubscriptionDelegatee()` if subscription signature does not match contract delegatee
    /// @dev 4-byte signature: `0x10c74b03`
    error SignerMismatch();

    /// @notice Thrown by `createSubscriptionDelegatee()` if signature for delegated subscription has expired
    /// @dev 4-byte signature: `0x0819bdcd`
    error SignatureExpired();

    /*//////////////////////////////////////////////////////////////
                           OVERRIDE FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Overrides Solady.EIP712._domainNameAndVersion to return EIP712-compatible domain name, version
    function _domainNameAndVersion() internal pure override returns (string memory, string memory) {
        return (EIP712_NAME, EIP712_VERSION);
    }

    /// @notice Overrides Solady.EIP712._domainNameAndVersionMayChange to always return false since the domain params are not updateable
    function _domainNameAndVersionMayChange() internal pure override returns (bool) {
        return false;
    }

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Allows a delegatee to create a subscription on behalf of a subscribing contract (sub.owner)
    /// @dev Unlike `Coordinator.createSubscription()`, offers maximum flexibility to set subscription parameters
    /// @param nonce subscribing contract nonce (included in signature)
    /// @param expiry delegated subscription signature expiry (included in signature)
    /// @param sub subscription to create
    /// @param v ECDSA recovery id
    /// @param r ECDSA signature output (r)
    /// @param s ECDSA signature output (s)
    /// @return 0: subscriptionId (if subscription exists, returns existing ID, else returns new ID),
    ///         1: exists (true if returning existing subscription, else false)
    function createSubscriptionDelegatee(
        uint32 nonce,
        uint32 expiry,
        Subscription calldata sub,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public returns (uint32, bool) {
        // Check if subscription already exists via delegate-created lookup table
        bytes32 key = keccak256(abi.encode(sub.owner, nonce));
        uint32 subscriptionId = delegateCreatedIds[key];

        // If subscription exists, return existing subscriptionId
        // This implicitly prevents nonce replay because if the nonce was already used, a subscription would exist
        if (subscriptionId != 0) {
            return (subscriptionId, true);
        }

        // Else, if subscription does not exist
        // First, verify that signature has not expired
        if (uint32(block.timestamp) >= expiry) {
            revert SignatureExpired();
        }

        // Generate EIP-712 data
        bytes32 digest = _hashTypedData(
            keccak256(
                // Encode(DelegateSubscription, nonce, expiry, sub)
                abi.encode(
                    EIP712_DELEGATE_SUBSCRIPTION_TYPEHASH,
                    nonce,
                    expiry,
                    // Encode(Subscription, sub)
                    keccak256(
                        abi.encode(
                            EIP712_SUBSCRIPTION_TYPEHASH,
                            sub.owner,
                            sub.activeAt,
                            sub.period,
                            sub.frequency,
                            sub.redundancy,
                            sub.maxGasPrice,
                            sub.maxGasLimit,
                            // Hash dynamic values
                            keccak256(bytes(sub.containerId)),
                            keccak256(sub.inputs)
                        )
                    )
                )
            )
        );

        // Get recovered signer from data
        // Throws `InvalidSignature()` (4-byte signature: `0x8baa579f`) if can't recover signer
        address recoveredSigner = ECDSA.recover(digest, v, r, s);

        // Collect delegated signer from subscribing contract
        address delegatedSigner = Delegator(sub.owner).signer();

        // Verify signatures (recoveredSigner should equal delegatedSigner)
        if (recoveredSigner != delegatedSigner) {
            revert SignerMismatch();
        }

        // By this point, the signer is verified and a net-new subscription can be created
        // Assign new subscription id
        // Unlikely this will ever overflow so we can toss in unchecked
        unchecked {
            subscriptionId = id++;
        }

        // Store provided subscription as-is
        subscriptions[subscriptionId] = sub;

        // Update delegate-created ID lookup table
        delegateCreatedIds[key] = subscriptionId;

        // Emit new subscription
        emit SubscriptionCreated(subscriptionId);

        // Update max known subscriber nonce (useful for off-chain signing utilities to prevent nonce-collision)
        if (nonce > maxSubscriberNonce[sub.owner]) {
            maxSubscriberNonce[sub.owner] = nonce;
        }

        // Explicitly return subscriptionId
        return (subscriptionId, false);
    }

    /// @notice Allows active nodes to (1) atomically create or collect subscription via signed EIP-712 message,
    ///         (2) deliver container compute responses for created or collected subscription
    /// @param nonce subscribing contract nonce (included in signature)
    /// @param expiry delegated subscription signature expiry (included in signature)
    /// @param sub subscription to create
    /// @param v ECDSA recovery id
    /// @param r ECDSA signature output (r)
    /// @param s ECDSA signature output (s)
    /// @param deliveryInterval subscription `interval`
    /// @param input optional off-chain input recorded by Infernet node (empty, hashed input, processed input, or both)
    /// @param output optional off-chain container output (empty, hashed output, processed output, both, or fallback: all encodeable data)
    /// @param proof optional container execution proof (or arbitrary metadata)
    function deliverComputeDelegatee(
        uint32 nonce,
        uint32 expiry,
        Subscription calldata sub,
        uint8 v,
        bytes32 r,
        bytes32 s,
        uint32 deliveryInterval,
        bytes calldata input,
        bytes calldata output,
        bytes calldata proof
    ) external onlyActiveNode {
        // Create subscriptionId via delegatee creation + or collect if subscription already exists
        (uint32 subscriptionId, bool cached) = createSubscriptionDelegatee(nonce, expiry, sub, v, r, s);

        // Calculate additional gas overhead imposed from delivering container compute response via delegatee function
        uint256 overhead;
        if (cached) {
            // Subscription exists, cost to retrieve subscriptionId
            overhead = DELEGATEE_OVERHEAD_CACHED_WEI;
        } else {
            // Subscription does not exist, cost to create subscription w/ delegatee signature
            overhead = DELEGATEE_OVERHEAD_CREATE_WEI;
        }

        // Deliver subscription response
        _deliverComputeWithOverhead(subscriptionId, deliveryInterval, input, output, proof, overhead);
    }
}

File 3 of 7 : ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
///   This is for more safety by default.
///   Use the `tryRecover` variants if you need to get the zero address back
///   upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 4 of 7 : Coordinator.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.4;

import {Manager} from "./Manager.sol";
import {BaseConsumer} from "./consumer/Base.sol";

/// @title Coordinator
/// @notice Coordination layer between consuming smart contracts and off-chain Infernet nodes
/// @dev Allows creating and deleting `Subscription`(s)
/// @dev Allows nodes with `Manager.NodeStatus.Active` to deliver subscription outputs via off-chain container compute
contract Coordinator is Manager {
    /*//////////////////////////////////////////////////////////////
                                STRUCTS
    //////////////////////////////////////////////////////////////*/

    /// @notice A subscription is the fundamental unit of Infernet
    /// @dev A subscription represents some request configuration for off-chain compute via containers on Infernet nodes
    /// @dev A subscription with `frequency == 1` is a one-time subscription (a callback)
    /// @dev A subscription with `frequency > 1` is a recurring subscription (many callbacks)
    /// @dev Tightly-packed struct:
    ///      - [owner, activeAt, period, frequency]: [32, 160, 32, 32] = 256
    ///      - [redundancy, maxGasPrice, maxGasLimit]: [16, 48, 32] = 96
    struct Subscription {
        /// @notice Subscription owner + recipient
        /// @dev This is the address called to fulfill a subscription request and must inherit `BaseConsumer`
        /// @dev Default initializes to `address(0)`
        address owner;
        /// @notice Timestamp when subscription is first active and an off-chain Infernet node can respond
        /// @dev When `period == 0`, the subscription is immediately active
        /// @dev When `period > 0`, subscription is active at `createdAt + period`
        uint32 activeAt;
        /// @notice Time, in seconds, between each subscription interval
        /// @dev At worst, assuming subscription occurs once/year << uint32
        uint32 period;
        /// @notice Number of times a subscription is processed
        /// @dev At worst, assuming 30 req/min * 60 min * 24 hours * 365 days * 10 years << uint32
        uint32 frequency;
        /// @notice Number of unique nodes that can fulfill a subscription at each `interval`
        /// @dev uint16 allows for >255 nodes (uint8) but <65,535
        uint16 redundancy;
        /// @notice Max gas price in wei paid by an Infernet node when fulfilling callback
        /// @dev uint40 caps out at ~1099 gwei, uint48 allows up to ~281K gwei
        uint48 maxGasPrice;
        /// @notice Max gas limit in wei used by an Infernet node when fulfilling callback
        /// @dev Must be at least equal to the gas limit of your receiving function execution + DELIVERY_OVERHEAD_WEI
        /// @dev uint24 is too small at ~16.7M (<30M mainnet gas limit), but uint32 is more than enough (~4.2B wei)
        uint32 maxGasLimit;
        /// @notice Container identifier used by off-chain Infernet nodes to determine which container is used to fulfill a subscription
        /// @dev Can be used to specify a linear DAG of containers by seperating container names with a "," delimiter ("A,B,C")
        /// @dev Better represented by a string[] type but constrained to string to keep struct and functions simple
        string containerId;
        /// @notice Optional container input parameters
        /// @dev If left empty, off-chain Infernet nodes call public view fn: `BaseConsumer(owner).getContainerInputs()`
        bytes inputs;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Gas overhead in wei to deliver container compute responses
    /// @dev This is the additional cost of any validation checks performed within the `Coordinator`
    ///      before delivering responses to consumer contracts
    /// @dev A uint16 is sufficient but we are not packing variables so control plane cost is higher because of type
    ///      casting during operations. Thus, we can just stick to uint256
    uint256 public constant DELIVERY_OVERHEAD_WEI = 56_600 wei;

    /*//////////////////////////////////////////////////////////////
                                MUTABLE
    //////////////////////////////////////////////////////////////*/

    /// @notice Current highest subscription ID
    /// @dev 1-indexed to allow using id as a mapping value (prevent 0-indexed default from being misused)
    /// @dev uint32 size(4.2B) should be sufficiently large
    uint32 public id = 1;

    /// @notice hash(subscriptionId, interval, caller) => has caller responded for (sub, interval)?
    mapping(bytes32 => bool) public nodeResponded;

    /// @notice hash(subscriptionId, interval) => Number of responses for (sub, interval)?
    /// @dev Limited to type(Subscription.redundancy) == uint16
    /// @dev Technically, this is not required and we can save an SLOAD if we simply add a uint48 to the subscription
    ///      struct that represents 32 bits of the interval -> 16 bits of redundancy count, reset each interval change
    ///      But, this is a little over the optimization:redability line and would make Subscriptions harder to grok
    mapping(bytes32 => uint16) public redundancyCount;

    /// @notice subscriptionID => Subscription
    /// @dev 1-indexed, 0th-subscription is empty
    mapping(uint32 => Subscription) public subscriptions;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a new subscription is created
    /// @param id subscription ID
    event SubscriptionCreated(uint32 indexed id);

    /// @notice Emitted when a subscription is cancelled
    /// @param id subscription ID
    event SubscriptionCancelled(uint32 indexed id);

    /// @notice Emitted when a subscription is fulfilled
    /// @param id subscription ID
    /// @param node address of fulfilling node
    event SubscriptionFulfilled(uint32 indexed id, address indexed node);

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @notice Thrown by `deliverComputeWithOverhead()` if delivering tx with gasPrice > subscription maxGasPrice
    /// @dev E.g. submitting tx with gas price `10 gwei` when network basefee is `11 gwei`
    /// @dev 4-byte signature: `0x682bad5a`
    error GasPriceExceeded();

    /// @notice Thrown by `deliverComputeWithOverhead()` if delivering tx with consumed gas > subscription maxGasLimit
    /// @dev E.g. submitting tx with gas consumed `200_000 wei` when max allowed by subscription is `175_000 wei`
    /// @dev 4-byte signature: `0xbe9179a6`
    error GasLimitExceeded();

    /// @notice Thrown by `deliverComputeWithOverhead()` if attempting to deliver container compute response for non-current interval
    /// @dev E.g submitting tx for `interval` < current (period elapsed) or `interval` > current (too early to submit)
    /// @dev 4-byte signature: `0x4db310c3`
    error IntervalMismatch();

    /// @notice Thrown by `deliverComputeWithOverhead()` if `redundancy` has been met for current `interval`
    /// @dev E.g submitting 4th output tx for a subscription with `redundancy == 3`
    /// @dev 4-byte signature: `0x2f4ca85b`
    error IntervalCompleted();

    /// @notice Thrown by `deliverComputeWithOverhead()` if `node` has already responded this `interval`
    /// @dev 4-byte signature: `0x88a21e4f`
    error NodeRespondedAlready();

    /// @notice Thrown by `deliverComputeWithOverhead()` if attempting to access a subscription that does not exist
    /// @dev 4-byte signature: `0x1a00354f`
    error SubscriptionNotFound();

    /// @notice Thrown by `cancelSubscription()` if attempting to modify a subscription not owned by caller
    /// @dev 4-byte signature: `0xa7fba711`
    error NotSubscriptionOwner();

    /// @notice Thrown by `deliverComputeWithOverhead()` if attempting to deliver a completed subscription
    /// @dev 4-byte signature: `0xae6704a7`
    error SubscriptionCompleted();

    /// @notice Thrown by `deliverComputeWithOverhead()` if attempting to deliver a subscription before `activeAt`
    /// @dev 4-byte signature: `0xefb74efe`
    error SubscriptionNotActive();

    /*//////////////////////////////////////////////////////////////
                           INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Internal counterpart to `deliverCompute()` w/ ability to set custom gas overhead allowance
    /// @dev When called by `deliverCompute()`, `callingOverheadWei == 0` because no additional overhead imposed
    /// @dev When called by `deliverComputeDelegatee()`, `DELEGATEE_OVERHEAD_*_WEI` is imposed
    /// @param subscriptionId subscription ID to deliver
    /// @param deliveryInterval subscription `interval` to deliver
    /// @param input optional off-chain input recorded by Infernet node (empty, hashed input, processed input, or both)
    /// @param output optional off-chain container output (empty, hashed output, processed output, both, or fallback: all encodeable data)
    /// @param proof optional container execution proof (or arbitrary metadata)
    /// @param callingOverheadWei additional overhead gas used for delivery
    function _deliverComputeWithOverhead(
        uint32 subscriptionId,
        uint32 deliveryInterval,
        bytes calldata input,
        bytes calldata output,
        bytes calldata proof,
        uint256 callingOverheadWei
    ) internal {
        // Naively, one would think that loading a subscription into memory via
        // `Subscription memory subscription = subscriptions[subscriptionId]`
        // would be cost-effective and most readable.

        // Unfortunately, this is not the case. This function makes no use of
        // `subscription.containerId` or `subscription.inputs`. Because these
        // are dynamic types, we are forced to pay to load into memory the length
        // + content of these parameters. In some cases (say, container input being
        // 100 uint256's), we are forced to pay 2 SLOAD (length slot containerId, inputs)
        // + N SLOAD (containerId + inputs byte length / word size) (for example, 100
        // SLOAD's in the case of 100 uint256's) + N MSTORE (copying into memory)
        // + memory expansion costs.

        // To avoid this, we can first access memory parameters selectively, copying
        // just the fixed size params (uint16, etc.) into memory by accessing state via
        // `subscriptions[subscriptionId].activeAt` syntax.

        // But, with this syntax, while we avoid the significant overhead of copying
        // from storage, into memory, the unnecessary dynamic parameters, we are now
        // forced to pay 100 gas for each non-first storage slot read (hot SLOAD).

        // For example, even if accessing two tightly-packed variables in slot 0, we must
        // pay COLD SLOAD + HOT SLOAD, rather than just COLD SLOAD + MLOAD.

        // To avoid this, we can drop down to assembly and:
        //      1. Manually SLOAD tightly-packed struct slots
        //      2. Unpack and MSTORE variables to avoid the hot SLOAD penalty since we
        //         only copy from storage into memory once (rather than for each variable)

        // Setup parameters in first slot
        // Note, we could load these variables right before they are used but the MSTORE is cheap and this is cleaner
        address subOwner;
        uint32 subActiveAt;
        uint32 subPeriod;
        uint32 subFrequency;

        // Store slot identifier for subscriptions[subscriptionId][slot 0]
        bytes32 storageSlot;
        assembly ("memory-safe") {
            // Load address of free-memory pointer
            let m := mload(0x40)

            // Store subscription ID to first free slot
            // uint32 automatically consumes full word
            mstore(m, subscriptionId)
            // Store subscriptions mapping storage slot (4) to 32 byte (1 word) offset
            mstore(add(m, 0x20), 4)

            // At this point, memory layout [0 -> 0x20 == subscriptionId, 0x20 -> 0x40 == 4]
            // Calculate mapping storage slot — hash(key, mapping slot)
            // Hash data from 0 -> 0x40 (2 words)
            storageSlot := keccak256(m, 0x40)

            // SLOAD struct data
            let data := sload(storageSlot)

            // Solidity packs structs right to left (least-significant bits a la little-endian)
            // MSTORE'ing tightly-packed variables from storage slot data
            // Erase first 96 bits via AND, grab last 160
            subOwner := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
            // Grab first 32 bits preceeding owner
            subActiveAt := and(shr(160, data), 0xFFFFFFFF)
            // Grab first 32 bits preceeding activeAt
            subPeriod := and(shr(192, data), 0xFFFFFFFF)
            // Grab first 32 bits from left
            subFrequency := shr(224, data)
        }

        // Revert if subscription does not exist
        if (subOwner == address(0)) {
            revert SubscriptionNotFound();
        }

        // Revert if subscription is not yet active
        if (block.timestamp < subActiveAt) {
            revert SubscriptionNotActive();
        }

        // Calculate subscription interval
        uint32 interval = getSubscriptionInterval(subActiveAt, subPeriod);

        // Revert if not processing curent interval
        if (interval != deliveryInterval) {
            revert IntervalMismatch();
        }

        // Revert if interval > frequency
        if (interval > subFrequency) {
            revert SubscriptionCompleted();
        }

        // Setup parameters in second slot
        uint16 subRedundancy;
        uint48 subMaxGasPrice;
        uint32 subMaxGasLimit;

        assembly ("memory-safe") {
            // SLOAD struct data
            // Second slot is simply offset from first by 1
            let data := sload(add(storageSlot, 1))

            // MSTORE'ing tightly-packed variables from storage slot data
            // Grab last 16 bits
            subRedundancy := and(data, 0xFFFF)
            // Grab first 48 bits preceeding redundancy
            subMaxGasPrice := and(shr(16, data), 0xFFFFFFFFFFFF)
            // Grab first 32 bits from left
            subMaxGasLimit := and(shr(64, data), 0xFFFFFFFF)
        }

        // Revert if tx gas price > max subscription allowed
        if (tx.gasprice > subMaxGasPrice) {
            revert GasPriceExceeded();
        }

        // Revert if redundancy requirements for this interval have been met
        bytes32 key = keccak256(abi.encode(subscriptionId, interval));
        uint16 numRedundantDeliveries = redundancyCount[key];
        if (numRedundantDeliveries == subRedundancy) {
            revert IntervalCompleted();
        }
        // Highly unlikely to overflow given incrementing by 1/node
        unchecked {
            redundancyCount[key] = numRedundantDeliveries + 1;
        }

        // Revert if node has already responded this interval
        key = keccak256(abi.encode(subscriptionId, interval, msg.sender));
        if (nodeResponded[key]) {
            revert NodeRespondedAlready();
        }
        nodeResponded[key] = true;

        // Deliver container compute output to contract (measuring execution cost)
        uint256 startingGas = gasleft();
        BaseConsumer(subOwner).rawReceiveCompute(
            subscriptionId, interval, numRedundantDeliveries + 1, msg.sender, input, output, proof
        );
        uint256 endingGas = gasleft();

        // Revert if gas used > allowed, we can make unchecked:
        // Gas limit in most networks is usually much below uint256 max, and by this point a decent amount is spent
        // `callingOverheadWei`, `DELIVERY_OVERHEAD_WEI` both fit in under uint24's
        // Thus, this operation is unlikely to ever overflow ((uint256 - uint256) + (uint16 + uint24))
        // Unless the bounds are along the lines of: {startingGas: UINT256_MAX, endingGas: << (callingOverheadWei + DELIVERY_OVERHEAD_WEI)}
        uint256 executionCost;
        unchecked {
            executionCost = startingGas - endingGas + callingOverheadWei + DELIVERY_OVERHEAD_WEI;
        }
        if (executionCost > subMaxGasLimit) {
            revert GasLimitExceeded();
        }

        // Emit successful delivery
        emit SubscriptionFulfilled(subscriptionId, msg.sender);
    }

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Creates new subscription
    /// @param containerId compute container identifier used by off-chain Infernet node
    /// @param inputs optional container inputs
    /// @param maxGasPrice max gas price in wei paid by an Infernet node when fulfilling callback
    /// @param maxGasLimit max gas limit in wei paid by an Infernet node in callback tx
    /// @param frequency max number of times to process subscription (i.e, `frequency == 1` is a one-time request)
    /// @param period period, in seconds, at which to progress each responding `interval`
    /// @param redundancy number of unique responding Infernet nodes
    /// @return subscription ID
    function createSubscription(
        string memory containerId,
        bytes calldata inputs,
        uint48 maxGasPrice,
        uint32 maxGasLimit,
        uint32 frequency,
        uint32 period,
        uint16 redundancy
    ) external returns (uint32) {
        // Get subscription id and increment
        // Unlikely this will ever overflow so we can toss in unchecked
        uint32 subscriptionId;
        unchecked {
            subscriptionId = id++;
        }

        // Store new subscription
        subscriptions[subscriptionId] = Subscription({
            // If period is = 0 (one-time), active immediately
            // Else, next active at first period mark
            // Probably reasonable to keep the overflow protection here given adding 2 uint32's into a uint32
            activeAt: uint32(block.timestamp) + period,
            owner: msg.sender,
            maxGasPrice: maxGasPrice,
            redundancy: redundancy,
            maxGasLimit: maxGasLimit,
            frequency: frequency,
            period: period,
            containerId: containerId,
            inputs: inputs
        });

        // Emit new subscription
        emit SubscriptionCreated(subscriptionId);

        // Explicitly return subscriptionId
        return subscriptionId;
    }

    /// @notice Cancel a subscription
    /// @dev Must be called by `subscriptions[subscriptionId].owner`
    /// @param subscriptionId subscription ID to cancel
    function cancelSubscription(uint32 subscriptionId) external {
        // Throw if owner of subscription is not caller
        if (subscriptions[subscriptionId].owner != msg.sender) {
            revert NotSubscriptionOwner();
        }

        // Nullify subscription
        delete subscriptions[subscriptionId];

        // Emit cancellation
        emit SubscriptionCancelled(subscriptionId);
    }

    /// @notice Calculates subscription `interval` based on `activeAt` and `period`
    /// @param activeAt when does a subscription start accepting callback responses
    /// @param period time, in seconds, between each subscription response `interval`
    /// @return current subscription interval
    function getSubscriptionInterval(uint32 activeAt, uint32 period) public view returns (uint32) {
        // If period is 0, we're always at interval 1
        if (period == 0) {
            return 1;
        }

        // Else, interval = ((block.timestamp - activeAt) / period) + 1
        // This is only called after validating block.timestamp >= activeAt so timestamp can't underflow
        // We also short-circuit above if period is zero so no need for division by zero checks
        unchecked {
            return ((uint32(block.timestamp) - activeAt) / period) + 1;
        }
    }

    /// @notice Allows nodes with `Manager.NodeStatus.Active` to deliver container compute responses for a subscription
    /// @dev Re-entering does not work because only active nodes (max 1 response) can call `deliverCompute`
    /// @dev Re-entering and delivering via a seperate node `msg.sender` works but is ignored in favor of explicit `maxGasLimit`
    /// @dev For containers without succinctly-verifiable proofs, the `proof` field can be repurposed for arbitrary metadata
    /// @dev Enforces an overhead delivery cost of `DELIVERY_OVERHEAD_WEI` and `0` additional overhead
    /// @param subscriptionId subscription ID to deliver
    /// @param deliveryInterval subscription `interval` to deliver
    /// @param input optional off-chain container input recorded by Infernet node (empty, hashed input, processed input, or both)
    /// @param output optional off-chain container output (empty, hashed output, processed output, both, or fallback: all encodeable data)
    /// @param proof optional off-chain container execution proof (or arbitrary metadata)
    function deliverCompute(
        uint32 subscriptionId,
        uint32 deliveryInterval,
        bytes calldata input,
        bytes calldata output,
        bytes calldata proof
    ) external onlyActiveNode {
        _deliverComputeWithOverhead(subscriptionId, deliveryInterval, input, output, proof, 0);
    }
}

File 5 of 7 : EIP712.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    uint256 private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = uint256(uint160(address(this)));
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        // We will use `digest` to store the domain separator to save a bit of gas.
        if (_domainNameAndVersionMayChange()) {
            digest = _buildDomainSeparator();
        } else {
            digest = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, digest) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        // We will use `separator` to store the name hash to save a bit of gas.
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            separator = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            separator = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), separator) // Name hash.
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        uint256 cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

File 6 of 7 : Delegator.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.4;

/// @title Delegator
/// @notice Exposes a `signer` address that allows an authorized EOA to sign off on actions on behalf of a contract
/// @dev Allows developers to create Coordinator subscriptions off-chain, on behalf of a contract, by signing a
///      `DelegateSubscription` from `signer` and submitting to `EIP712Coordinator.createSubscriptionDelegatee()`
abstract contract Delegator {
    /*//////////////////////////////////////////////////////////////
                                MUTABLE
    //////////////////////////////////////////////////////////////*/

    /// @notice Authorized address with signing privileges
    /// @dev Recommended to use an EOA so that it can sign EIP-712 messages
    /// @dev Visibility is `public` to automatically generate and expose a getter
    address public signer;

    /*//////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /// @notice Initialize new Delegator
    /// @param signer_ authorized address
    constructor(address signer_) {
        signer = signer_;
    }

    /*//////////////////////////////////////////////////////////////
                           INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Update delegated signer
    /// @dev No event is emitted given contract is meant to be inherited
    /// @param newSigner new delegated signer address
    function _updateSigner(address newSigner) internal {
        signer = newSigner;
    }
}

File 7 of 7 : Manager.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.4;

/// @title Manager
/// @notice Manages node lifecycle (registration, activation, deactivation)
/// @dev Allows anyone to register to become an active node
/// @dev Allows registered nodes to become active after a `cooldown` seconds waiting period
/// @dev Allows any node to deactivate itself and return to an inactive state
/// @dev Exposes an `onlyActiveNode()` modifier used to restrict functions to being called by only active nodes
/// @dev Restricts addresses to 1 of 3 states: `Inactive`, `Registered`, `Active`
abstract contract Manager {
    /*//////////////////////////////////////////////////////////////
                                STRUCTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Packed information about a node (status, cooldown start)
    /// @dev Cheaper to use a struct to store `status` + `cooldownStart` rather than SSTORE 2 independent mappings
    /// @dev Technically, could bitshift pack uint40 of data into single uint256 but readability penalty not worth it
    /// @dev Tightly-packed (well under 32-byte slot): [uint8, uint32] = 40 bits = 5 bytes
    struct NodeInfo {
        /// @notice Node status
        NodeStatus status;
        /// @notice Cooldown start timestamp in seconds
        /// @dev Default initializes to `0`; no cooldown active to start
        /// @dev Equal to `0` if `status != NodeStatus.Registered`, else equal to cooldown start time
        /// @dev Is modified by `registerNode()` to initiate `cooldown` holding period
        /// @dev uint32 allows for a timestamp up to year ~2106, likely far beyond lifecycle of this contract
        uint32 cooldownStart;
    }

    /*//////////////////////////////////////////////////////////////
                                 ENUMS
    //////////////////////////////////////////////////////////////*/

    /// @notice Possible node statuses
    /// @dev Enums in Solidity are unsigned integers capped at 256 members, so Inactive is the 0-initialized default
    /// @dev Inactive (0): Default status is inactive; no status
    /// @dev Registered (1): Node has registered to become active, initiating a period of `cooldown`
    /// @dev Active (2): Node is active, able to fulfill subscriptions, and is part of `modifier(onlyActiveNode)`
    enum NodeStatus {
        Inactive,
        Registered,
        Active
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Cooldown period, in seconds, before a node with `NodeStatus.Registered` can call `activateNode()`
    /// @dev type(uint32) is sufficient but we are not packing variables so control plane costs are higher because we
    ///      need to cast the 32-bit type into the 256-bit type anyways. Thus, we use type(uint256).
    uint256 public constant cooldown = 1 hours;

    /*//////////////////////////////////////////////////////////////
                                MUTABLE
    //////////////////////////////////////////////////////////////*/

    /// @dev Node address => node information
    mapping(address => NodeInfo) public nodeInfo;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a node moves from `NodeStatus.Inactive` to `NodeStatus.Registered`
    /// @dev It's actually slightly more expensive (~6 gas) to emit the uint32 given the explicit conversion needed
    ///      but this is necessary to have better readability and uniformity across the type (not casting in event)
    /// @param node newly-registered node address
    /// @param registerer optional proxy address registering on behalf of node (is equal to node when self-registering)
    /// @param cooldownStart start timestamp of registration cooldown
    event NodeRegistered(address indexed node, address indexed registerer, uint32 cooldownStart);

    /// @notice Emitted when a node moves from `NodeStatus.Registered` to `NodeStatus.Active`
    /// @param node newly-activated node address
    event NodeActivated(address indexed node);

    /// @notice Emitted when a node moves from any status to `NodeStatus.Inactive`
    /// @param node newly-deactivated node address
    event NodeDeactivated(address indexed node);

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @notice Thrown if attempting to call function that requires a node to have status `NodeStatus.Active`
    /// @dev Only used by `modifier(onlyActiveNode)`
    /// @dev 4-byte signature: `0x8741cbb8`
    error NodeNotActive();

    /// @notice Thrown by `registerNode()` if attempting to register node with status that is not `NodeStatus.Inactive`
    /// @dev 4-byte signature: `0x5acfd518`
    /// @param node address of node attempting to register
    /// @param status current status of node failing registration
    error NodeNotRegisterable(address node, NodeStatus status);

    /// @notice Thrown by `activateNode()` if `cooldown` has not elapsed since node was registered
    /// @dev Like `NodeRegistered`, slightly more expensive to use uint32 over uint256 (~6 gas) but better readability
    /// @dev 4-byte signature: `0xc84b5bdd`
    /// @param cooldownStart start timestamp of node cooldown
    error CooldownActive(uint32 cooldownStart);

    /// @notice Thrown by `activateNode()` if attempting to active node with status that is not `NodeStatus.Registered`
    /// @dev 4-byte signature: `0x33daa7f9`
    /// @param status current status of node failing activation
    error NodeNotActivateable(NodeStatus status);

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

    /// @notice Allow only callers that are active nodes
    modifier onlyActiveNode() {
        if (nodeInfo[msg.sender].status != NodeStatus.Active) {
            revert NodeNotActive();
        }
        _;
    }

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Allows registering a node for activation
    /// @dev First-step of two-step process (followed by `activateNode()`)
    /// @dev Can call on behalf of other nodes as a proxy registerer
    /// @dev Node must have `NodeStatus.Inactive` to begin registration
    /// @param node node address to register
    function registerNode(address node) external {
        // SLOAD node info
        NodeInfo storage info = nodeInfo[node];

        // Ensure node is registerable
        // Current status must be `NodeStatus.Inactive`
        if (info.status != NodeStatus.Inactive) {
            revert NodeNotRegisterable(node, info.status);
        }

        // Update node status to Registered
        info.status = NodeStatus.Registered;
        // Update cooldown start timestamp to now
        info.cooldownStart = uint32(block.timestamp);

        // Emit new registration event
        emit NodeRegistered(node, msg.sender, uint32(block.timestamp));
    }

    /// @notice Allows activating a registered node after `cooldown` has elapsed
    /// @dev Second-step of two-step process (preceeded by `registerNode()`)
    /// @dev Must be called by node accepting a pending registration (`msg.sender == node`)
    /// @dev Must be called at least `cooldown` seconds after `registerNode()`
    function activateNode() external {
        // SLOAD node info
        NodeInfo storage info = nodeInfo[msg.sender];

        // Ensure node is already registered
        // Technically this check is not needed since the next check would fail anyways, but it provides a useful error
        if (info.status != NodeStatus.Registered) {
            revert NodeNotActivateable(info.status);
        }

        // Ensure node has elapsed required cooldown
        // Adding a uint32 to a uint32-bounded uint256 and upcasting to a uint256, so can't overflow
        uint256 cooldownEnd;
        unchecked {
            cooldownEnd = info.cooldownStart + cooldown;
        }
        if (block.timestamp < cooldownEnd) {
            revert CooldownActive(info.cooldownStart);
        }

        // Toggle node status to Active
        info.status = NodeStatus.Active;
        // Reset cooldown start timestamp
        info.cooldownStart = 0;

        // Emit activation event
        emit NodeActivated(msg.sender);
    }

    /// @notice Allows deactivating a node
    /// @dev Can be called to set the status of any node back to `NodeStatus.Inactive` with no cooldown
    /// @dev Must be called by the node deactivating itself (`msg.sender == node`)
    function deactivateNode() external {
        delete nodeInfo[msg.sender];

        // Emit deactivation event
        emit NodeDeactivated(msg.sender);
    }
}

File 8 of 7 : Base.sol
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.4;

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

/// @title BaseConsumer
/// @notice Handles receiving container compute responses from Infernet coordinator
/// @dev Contains a single public entrypoint `rawReceiveCompute` callable by only the Infernet coordinator. Once
///      call origin is verified, parameters are proxied to internal function `_receiveCompute`
abstract contract BaseConsumer {
    /*//////////////////////////////////////////////////////////////
                               IMMUTABLE
    //////////////////////////////////////////////////////////////*/

    /// @notice Infernet Coordinator
    /// @dev Internal visibility since COORDINATOR is consumed by inheriting contracts
    Coordinator internal immutable COORDINATOR;

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @notice Thrown if attempting to call `rawReceiveCompute` from a `msg.sender != address(COORDINATOR)`
    /// @dev 4-byte signature: `0x9ec853e6`
    error NotCoordinator();

    /*//////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /// @notice Initialize new BaseConsumer
    /// @param coordinator coordinator address
    constructor(address coordinator) {
        // Setup Coordinator
        COORDINATOR = Coordinator(coordinator);
    }

    /*//////////////////////////////////////////////////////////////
                           VIRTUAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Callback entrypoint to receive container compute responses from validated Coordinator source
    /// @dev Called by `rawReceiveCompute` once validated that `msg.sender == address(COORDINATOR)`
    /// @dev Same function parameters as `rawReceiveCompute`
    /// @param subscriptionId id of subscription being responded to
    /// @param interval subscription interval
    /// @param redundancy after this call succeeds, how many nodes will have delivered a response for this interval
    /// @param node address of responding Infernet node
    /// @param input optional off-chain container input recorded by Infernet node (empty, hashed input, processed input, or both)
    /// @param output optional off-chain container output (empty, hashed output, processed output, both, or fallback: all encodeable data)
    /// @param proof optional off-chain container execution proof (or arbitrary metadata)
    function _receiveCompute(
        uint32 subscriptionId,
        uint32 interval,
        uint16 redundancy,
        address node,
        bytes calldata input,
        bytes calldata output,
        bytes calldata proof
    ) internal virtual {}

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Callback entrypoint called by Infernet Coordinator to return container compute responses
    /// @dev Callable only by `address(COORDINATOR)`, else throws `NotCoordinator()` error
    /// @param subscriptionId id of subscription being responded to
    /// @param interval subscription interval
    /// @param redundancy after this call succeeds, how many nodes will have delivered a response for this interval
    /// @param node address of responding Infernet node
    /// @param input optional off-chain container input recorded by Infernet node (empty, hashed input, processed input, or both)
    /// @param output optional off-chain container output (empty, hashed output, processed output, both, or fallback: all encodeable data)
    /// @param proof optional off-chain container execution proof (or arbitrary metadata)
    function rawReceiveCompute(
        uint32 subscriptionId,
        uint32 interval,
        uint16 redundancy,
        address node,
        bytes calldata input,
        bytes calldata output,
        bytes calldata proof
    ) external {
        // Ensure caller is coordinator
        if (msg.sender != address(COORDINATOR)) {
            revert NotCoordinator();
        }

        // Call internal receive function, since caller is validated
        _receiveCompute(subscriptionId, interval, redundancy, node, input, output, proof);
    }
}

Settings
{
  "remappings": [
    "solady/=lib/solady/src/",
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint32","name":"cooldownStart","type":"uint32"}],"name":"CooldownActive","type":"error"},{"inputs":[],"name":"GasLimitExceeded","type":"error"},{"inputs":[],"name":"GasPriceExceeded","type":"error"},{"inputs":[],"name":"IntervalCompleted","type":"error"},{"inputs":[],"name":"IntervalMismatch","type":"error"},{"inputs":[{"internalType":"enum Manager.NodeStatus","name":"status","type":"uint8"}],"name":"NodeNotActivateable","type":"error"},{"inputs":[],"name":"NodeNotActive","type":"error"},{"inputs":[{"internalType":"address","name":"node","type":"address"},{"internalType":"enum Manager.NodeStatus","name":"status","type":"uint8"}],"name":"NodeNotRegisterable","type":"error"},{"inputs":[],"name":"NodeRespondedAlready","type":"error"},{"inputs":[],"name":"NotSubscriptionOwner","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignerMismatch","type":"error"},{"inputs":[],"name":"SubscriptionCompleted","type":"error"},{"inputs":[],"name":"SubscriptionNotActive","type":"error"},{"inputs":[],"name":"SubscriptionNotFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"}],"name":"NodeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"}],"name":"NodeDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":true,"internalType":"address","name":"registerer","type":"address"},{"indexed":false,"internalType":"uint32","name":"cooldownStart","type":"uint32"}],"name":"NodeRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"id","type":"uint32"}],"name":"SubscriptionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"id","type":"uint32"}],"name":"SubscriptionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"id","type":"uint32"},{"indexed":true,"internalType":"address","name":"node","type":"address"}],"name":"SubscriptionFulfilled","type":"event"},{"inputs":[],"name":"DELEGATEE_OVERHEAD_CACHED_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATEE_OVERHEAD_CREATE_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELIVERY_OVERHEAD_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"subscriptionId","type":"uint32"}],"name":"cancelSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"containerId","type":"string"},{"internalType":"bytes","name":"inputs","type":"bytes"},{"internalType":"uint48","name":"maxGasPrice","type":"uint48"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"uint32","name":"frequency","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"uint16","name":"redundancy","type":"uint16"}],"name":"createSubscription","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"activeAt","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"uint32","name":"frequency","type":"uint32"},{"internalType":"uint16","name":"redundancy","type":"uint16"},{"internalType":"uint48","name":"maxGasPrice","type":"uint48"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"string","name":"containerId","type":"string"},{"internalType":"bytes","name":"inputs","type":"bytes"}],"internalType":"struct Coordinator.Subscription","name":"sub","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"createSubscriptionDelegatee","outputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deactivateNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"delegateCreatedIds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"subscriptionId","type":"uint32"},{"internalType":"uint32","name":"deliveryInterval","type":"uint32"},{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"bytes","name":"output","type":"bytes"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"deliverCompute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"activeAt","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"uint32","name":"frequency","type":"uint32"},{"internalType":"uint16","name":"redundancy","type":"uint16"},{"internalType":"uint48","name":"maxGasPrice","type":"uint48"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"string","name":"containerId","type":"string"},{"internalType":"bytes","name":"inputs","type":"bytes"}],"internalType":"struct Coordinator.Subscription","name":"sub","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint32","name":"deliveryInterval","type":"uint32"},{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"bytes","name":"output","type":"bytes"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"deliverComputeDelegatee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"activeAt","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"}],"name":"getSubscriptionInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"id","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxSubscriberNonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nodeInfo","outputs":[{"internalType":"enum Manager.NodeStatus","name":"status","type":"uint8"},{"internalType":"uint32","name":"cooldownStart","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nodeResponded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"redundancyCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"node","type":"address"}],"name":"registerNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"subscriptions","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"activeAt","type":"uint32"},{"internalType":"uint32","name":"period","type":"uint32"},{"internalType":"uint32","name":"frequency","type":"uint32"},{"internalType":"uint16","name":"redundancy","type":"uint16"},{"internalType":"uint48","name":"maxGasPrice","type":"uint48"},{"internalType":"uint32","name":"maxGasLimit","type":"uint32"},{"internalType":"string","name":"containerId","type":"string"},{"internalType":"bytes","name":"inputs","type":"bytes"}],"stateMutability":"view","type":"function"}]

6101203461012b57306080524660a0526040906001600160401b03908083018281118282101761011557835260138152602081017f496e6665726e6574436f6f7264696e61746f72000000000000000000000000008152835190848201938285109085111761011557602060019260a09587528381520192603160f81b845251902091208160c0528060e0528351917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83526020830152838201524660608201523060808201522090610100918252600163ffffffff198154161760015551612baf918261013183396080518261233a015260a0518261235d015260c05182612adf015260e05182612b06015251816123180152f35b634e487b7160e01b600052604160045260246000fd5b600080fdfe608080604052600436101561001357600080fd5b60003560e01c908163105ddd1d14611ae65750806323c2e2bc14611a67578063298f7bdc14611a1857806331e451a91461189e5780633b2fb7a81461186457806341770e9a146117cf57806341cf2b7f146117945780634d9bf22f1461112957806360ed0f61146110d9578063642012c714610c8d578063672d7a0d14610b715780636e021332146105d057806373fb5c3a146104c4578063787a08a6146104895780637fb61b271461041b578063836a6cc9146103c357806384b0196e146102e157806390b04c15146102a657806396ef592e1461023f578063af640d0f146101fd578063bc85694f146101af578063e7cab346146101735763eccec5a81461011c57600080fd5b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761016a610156611f22565b604051918291602083526020830190611d19565b0390f35b600080fd5b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576020604051620164408152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526003602052602061ffff60406000205416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602063ffffffff60015416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5733600052600060205260006040812055337fd9957750e6343405c319eb99a4ec67fa11cfd66969318cbc71aa2d45fa53a349600080a2005b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602060405161dd188152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761037161031b611ce0565b610323611f22565b906040519283927f0f00000000000000000000000000000000000000000000000000000000000000845261036360209360e08587015260e0860190611d19565b908482036040860152611d19565b90466060840152306080840152600060a084015282820360c08401528060605192838152019160809160005b8281106103ac57505050500390f35b83518552869550938101939281019260010161039d565b3461016e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602061040d6103ff611c11565b610407611c24565b90611fb9565b63ffffffff60405191168152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e576000526005602052602063ffffffff60406000205416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576020604051610e108152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5763ffffffff80610501611c11565b166000526004602052604060002061016a60036105c183549360018101549561054f6040519261053f846105388160028501611e6d565b0385611c9f565b6105386040518097819301611e6d565b604051968673ffffffffffffffffffffffffffffffffffffffff8998168852828160a01c166020890152828160c01c16604089015260e01c606088015261ffff8116608088015265ffffffffffff8160101c1660a088015260401c1660c08601526101208060e0870152850190611d19565b90838203610100850152611d19565b3461016e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57610607611c11565b61060f611c24565b67ffffffffffffffff9060443582811161016e57610631903690600401611dec565b92909160643582811161016e5761064c903690600401611dec565b91909260843590811161016e57610667903690600401611dec565b91909533600052600060205260ff604060002054166003811015610b4257600203610b1857600096604080518a815260046020820152209384549473ffffffffffffffffffffffffffffffffffffffff861615610aee5763ffffffff8660a01c16804210610ac45763ffffffff6106e58192828a60c01c1690611fb9565b1695168503610a9a578560e01c8511610a7057600101549665ffffffffffff8860101c163a11610a4657604051602081019063ffffffff8d1682528660408201526040815261073381611c4b565b5190209687600052600360205261ffff604060002054169761ffff8a168914610a1c576000526003602052604060002061ffff60018a01167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008254161790558b60405163ffffffff6020820192168252876040820152336060820152606081526107bc81611c67565b51902080600052600260205260ff604060002054166109f2576000526002602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790555a9961ffff60018a01116109c35773ffffffffffffffffffffffffffffffffffffffff88163b1561016e578c95604051998a9889987ff8eb7fbd000000000000000000000000000000000000000000000000000000008a5263ffffffff1660048a0152602489015260010161ffff1660448801523360648801526084870160e0905260e487019061089b92611fde565b908582037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160a48701526108cf92611fde565b908382037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160c485015261090392611fde565b039173ffffffffffffffffffffffffffffffffffffffff1691815a6000948591f180156109b75761099f575b5063ffffffff61dd189160401c16915a90030111610975577fc68fb0ae5cea2793405d29014d881bcda18f67122e0bcd7d0a577e118b64e4c863ffffffff3393169180a3005b60046040517fbe9179a6000000000000000000000000000000000000000000000000000000008152fd5b6109aa919350611c37565b60009163ffffffff61092f565b6040513d6000823e3d90fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517f88a21e4f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2f4ca85b000000000000000000000000000000000000000000000000000000008152fd5b60046040517f682bad5a000000000000000000000000000000000000000000000000000000008152fd5b60046040517fae6704a7000000000000000000000000000000000000000000000000000000008152fd5b60046040517f4db310c3000000000000000000000000000000000000000000000000000000008152fd5b60046040517fefb74efe000000000000000000000000000000000000000000000000000000008152fd5b60046040517f1a00354f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8741cbb8000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e578060005260006020526040600020805460ff81166003811015610b425780610c4e57506001907fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000064ffffffff004260081b169116171790556040519063ffffffff421682527fb73af334a40cdaaad72e06d597bdeed270fc94d45415863afec219108096d2e860203393a3005b83610c8b604492604051927f5acfd51800000000000000000000000000000000000000000000000000000000845260048401526024830190611c04565bfd5b3461016e576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57610cc5611c11565b610ccd611c24565b67ffffffffffffffff91826044351161016e576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6044353603011261016e57610d17611d77565b60c4359363ffffffff8516850361016e5760e43581811161016e57610d40903690600401611dec565b9290936101043583811161016e57610d5c903690600401611dec565b9290936101243590811161016e57610d78903690600401611dec565b92909733600052600060205260ff604060002054166003811015610b4257600203610b1857610db59260a4359260843592604435600401916120c2565b909790156110cf57610258945b604080518a815260046020820152209788549360009973ffffffffffffffffffffffffffffffffffffffff861615610aee5763ffffffff8660a01c16804210610ac45763ffffffff610e1b8192828a60c01c1690611fb9565b1695168503610a9a578560e01c8511610a7057600101549665ffffffffffff8860101c163a11610a465760405163ffffffff8d16602082015285604082015260408152610e6781611c4b565b602081519101209687600052600360205261ffff604060002054169761ffff8a168914610a1c576000526003602052604060002061ffff60018a01167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008254161790558c60405163ffffffff602082019216825287604082015233606082015260608152610ef481611c67565b51902080600052600260205260ff604060002054166109f2576000526002602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790555a9a61ffff60018a01116109c35773ffffffffffffffffffffffffffffffffffffffff88163b1561016e578d95604051998a9889987ff8eb7fbd000000000000000000000000000000000000000000000000000000008a5263ffffffff1660048a0152602489015260010161ffff1660448801523360648801526084870160e0905260e4870190610fd392611fde565b908582037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160a487015261100792611fde565b908382037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160c485015261103b92611fde565b039173ffffffffffffffffffffffffffffffffffffffff1691815a6000948591f180156109b7576110af575b509063ffffffff61dd189260401c16925a9003010111610975577fc68fb0ae5cea2793405d29014d881bcda18f67122e0bcd7d0a577e118b64e4c863ffffffff3393169180a3005b61dd18929194506110bf90611c37565b63ffffffff600094919250611067565b6201644094610dc2565b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526006602052602063ffffffff60406000205416604051908152f35b3461016e5760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043567ffffffffffffffff811161016e573660238201121561016e57611189903690602481600401359101611d87565b60243567ffffffffffffffff811161016e576111a9903690600401611dec565b90916044359265ffffffffffff8416840361016e576064359263ffffffff8416840361016e576084359263ffffffff8416840361016e5760a4359463ffffffff8616860361016e5760c4359061ffff8216820361016e576001549663ffffffff6001818a1601167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000089161760015563ffffffff80821681421601116109c357604051988961012081011067ffffffffffffffff6101208c0111176116b05761ffff63ffffffff94856112c19a8d60408365ffffffffffff98610120840183523384528180821681421601166020850152169101521660608d01521660808b01521660a08901521660c087015260e08601523691611d87565b61010083015263ffffffff81166000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff8351167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617815561137263ffffffff60208501511682907fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000083549260a01b169116179055565b604083015181547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1660c09190911b7bffffffff00000000000000000000000000000000000000000000000016178155606083015181547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e09190911b7fffffffff00000000000000000000000000000000000000000000000000000000161781556114d56001820161ffff6080860151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000082541617815561149365ffffffffffff60a08701511682907fffffffffffffffffffffffffffffffffffffffffffffffff000000000000ffff67ffffffffffff000083549260101b169116179055565b60c085015181547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1660409190911b6bffffffff000000000000000016179055565b6002810160e084015180519067ffffffffffffffff82116116b057611504826114fe8554611e1a565b85611f72565b602090601f83116001146116ea5791806003949261010096946000926116df575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b92861b1c19161790555b019201519081519267ffffffffffffffff84116116b0578361158460209561157e8454611e1a565b84611f72565b8493601f8211600114611611579381929394600092611606575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b63ffffffff604051918181167f04344ed7a67fec80c444d56ee1cee242f3f75b91fecc8dbce8890069c82eb48e600080a2168152f35b01519050858061159e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169483600052866000209160005b878110611699575083600195969710611662575b505050811b0190556115d0565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055858080611655565b919288600181928685015181550194019201611641565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b015190508880611525565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316918460005260206000209260005b81811061177c575092600192859261010098966003989610611746575b505050811b019055611556565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f884891b161c19169055888080611739565b9293602060018192878601518155019501930161171c565b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760206040516102588152f35b3461016e577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60c08136011261016e57611807611c11565b61180f611c24565b6044359267ffffffffffffffff841161016e5761012090843603011261016e576040926118509261183e611d77565b9060a4359360843593600401916120c2565b63ffffffff83519216825215156020820152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761016a610156611ce0565b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5763ffffffff6118da611c11565b1680600052600460205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036119ee578060005260046020526003604060002060008155600060018201556002810161192f8154611e1a565b90816119b0575b5050016119438154611e1a565b9081611972575b827ff4126e31c182db4c4109605c6d50470fc7e8ca90d62d44fd25cbe049fb9cac3e600080a2005b81601f6000931160011461198a5750555b818061194a565b9080839182526119a9601f60208420940160051c840160018501611f5b565b5555611983565b81601f600093116001146119c85750555b8380611936565b9080839182526119e7601f60208420940160051c840160018501611f5b565b55556119c1565b60046040517fa7fba711000000000000000000000000000000000000000000000000000000008152fd5b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526002602052602060ff604060002054166040519015158152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e5760005260006020526040806000205463ffffffff825191611adb8360ff8316611c04565b60081c166020820152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5733600052600060205260406000209081549060ff82166003811015610b425760018103611bd457505063ffffffff8160081c16610e1081014210611ba357507fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000166002179055337f7dc8b937d2916b130743c447af3d771fa55e66b7393105150e2e635ac3e87260600080a2005b602490604051907fc84b5bdd0000000000000000000000000000000000000000000000000000000082526004820152fd5b90610c8b6024927f33daa7f900000000000000000000000000000000000000000000000000000000835260048301905b906003821015610b425752565b6004359063ffffffff8216820361016e57565b6024359063ffffffff8216820361016e57565b67ffffffffffffffff81116116b057604052565b6060810190811067ffffffffffffffff8211176116b057604052565b6080810190811067ffffffffffffffff8211176116b057604052565b6040810190811067ffffffffffffffff8211176116b057604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176116b057604052565b60405190611ced82611c83565b601382527f496e6665726e6574436f6f7264696e61746f72000000000000000000000000006020830152565b919082519283825260005b848110611d635750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201611d24565b6064359060ff8216820361016e57565b92919267ffffffffffffffff82116116b05760405191611dcf60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611c9f565b82948184528183011161016e578281602093846000960137010152565b9181601f8401121561016e5782359167ffffffffffffffff831161016e576020838186019501011161016e57565b90600182811c92168015611e63575b6020831014611e3457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611e29565b9060009291805491611e7e83611e1a565b918282526001938481169081600014611ee05750600114611ea0575b50505050565b90919394506000526020928360002092846000945b838610611ecc575050505001019038808080611e9a565b805485870183015294019385908201611eb5565b91505060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009193501683830152151560051b01019038808080611e9a565b60405190611f2f82611c83565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b818110611f66575050565b60008155600101611f5b565b9190601f8111611f8157505050565b611fad926000526020600020906020601f840160051c83019310611faf575b601f0160051c0190611f5b565b565b9091508190611fa0565b63ffffffff8092168015611fd65782600192814216031604011690565b505050600190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361016e5790565b3563ffffffff8116810361016e5790565b3561ffff8116810361016e5790565b3565ffffffffffff8116810361016e5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561016e570180359067ffffffffffffffff821161016e5760200191813603831361016e57565b929193959490956120d28561201d565b60405173ffffffffffffffffffffffffffffffffffffffff602082019216825263ffffffff861660408201526040815261210b81611c4b565b5190209687600052600660205263ffffffff6040600020541680612b6b575063ffffffff811663ffffffff42161015612b41576121478661201d565b906121546020880161203e565b6121606040890161203e565b61216c60608a0161203e565b61217860808b0161204f565b61218460a08c0161205e565b9061219160c08d0161203e565b9261219f60e08e018e612071565b36906121aa92611d87565b80519060200120948d61010081016121c191612071565b36906121cc92611d87565b80519060200120966040519960208b017f2b24aa047bbff05c807b5ba16020ac01534fdb34947d5608264ac56133753190905273ffffffffffffffffffffffffffffffffffffffff1660408b015263ffffffff1660608a015263ffffffff16608089015263ffffffff1660a088015261ffff1660c087015265ffffffffffff1660e086015263ffffffff166101008501526101208401526101409081840152825281610160810110610160830167ffffffffffffffff10176116b057610160820160405263ffffffff82516020840120917f1950b0dfc42b437b752641a63d09bd2a7d858914bdd31db6ef0dc3e5b2bf544e6101808501528188166101a0850152166101c08301526101e08201526080610160820152610160810161020082011067ffffffffffffffff610200830111176116b0576102008101604052610160810151610180820120907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000030147f000000000000000000000000000000000000000000000000000000000000000046141615612ab0575b50671901000000000000600052601a52603a5260ff6042601820936000603a5260405194600052166020526040526060526020600160806000825afa51903d15612aa25760006060528060405260208160048173ffffffffffffffffffffffffffffffffffffffff6123f68961201d565b167f238ac9330000000000000000000000000000000000000000000000000000000082525afa9081156109b757600091612a3f575b5073ffffffffffffffffffffffffffffffffffffffff809116911603612a15576001549163ffffffff600181851601167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000084161760015563ffffffff83166000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6124b48361201d565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781556125346124eb6020840161203e565b82547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a09190911b77ffffffff000000000000000000000000000000000000000016178255565b6125906125436040840161203e565b82547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1660c09190911b7bffffffff00000000000000000000000000000000000000000000000016178255565b6125ec61259f6060840161203e565b82547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e09190911b7fffffffff0000000000000000000000000000000000000000000000000000000016178255565b6126ba6001820161ffff6126026080860161204f565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000082541617815561267261263960a0860161205e565b82547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000ffff1660109190911b67ffffffffffff000016178255565b61267e60c0850161203e565b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff6bffffffff000000000000000083549260401b169116179055565b6126c760e0830183612071565b67ffffffffffffffff81116116b05760028301916126e9826114fe8554611e1a565b600090601f831160011461296f5760039493929160009183612964575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b92861b1c19161790555b0194612747610100830183612071565b67ffffffffffffffff81989298116116b0576127678161157e8454611e1a565b6000601f82116001146128ba57819063ffffffff98996000926128af575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b600052600660205260406000208484167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008254161790558383167f04344ed7a67fec80c444d56ee1cee242f3f75b91fecc8dbce8890069c82eb48e600080a273ffffffffffffffffffffffffffffffffffffffff6128348261201d565b166000526005602052836040600020541684831611612857575b50501690600090565b61287573ffffffffffffffffffffffffffffffffffffffff9161201d565b1660005282604060002091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055388061284e565b013590503880612785565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216908360005260206000209160005b81811061294c57509983929160019463ffffffff9b9c10612914575b505050811b0190556127b7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612907565b9192602060018192868f0135815501940192016128eb565b013590503880612706565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316918460005260206000209260005b8181106129fd5750916001939185600398979694106129c7575b505050811b019055612737565b01357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83881b60f8161c191690553880806129ba565b919360206001819287870135815501950192016129a0565b60046040517f10c74b03000000000000000000000000000000000000000000000000000000008152fd5b90506020813d602011612a9a575b81612a5a60209383611c9f565b8101031261016e575173ffffffffffffffffffffffffffffffffffffffff8116810361016e5773ffffffffffffffffffffffffffffffffffffffff61242b565b3d9150612a4d565b638baa579f6000526004601cfd5b60a09150807f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610200809301527f00000000000000000000000000000000000000000000000000000000000000006102208201527f00000000000000000000000000000000000000000000000000000000000000006102408201524661026082015230610280820152012038612385565b60046040517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b97506001969550505050505056fea264697066735822122044f9e1e05ee99e4d16dd70c4e2aeb575ef9fdc3bfba4b51d1da0c9939b3a859964736f6c63430008130033

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c908163105ddd1d14611ae65750806323c2e2bc14611a67578063298f7bdc14611a1857806331e451a91461189e5780633b2fb7a81461186457806341770e9a146117cf57806341cf2b7f146117945780634d9bf22f1461112957806360ed0f61146110d9578063642012c714610c8d578063672d7a0d14610b715780636e021332146105d057806373fb5c3a146104c4578063787a08a6146104895780637fb61b271461041b578063836a6cc9146103c357806384b0196e146102e157806390b04c15146102a657806396ef592e1461023f578063af640d0f146101fd578063bc85694f146101af578063e7cab346146101735763eccec5a81461011c57600080fd5b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761016a610156611f22565b604051918291602083526020830190611d19565b0390f35b600080fd5b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576020604051620164408152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526003602052602061ffff60406000205416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602063ffffffff60015416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5733600052600060205260006040812055337fd9957750e6343405c319eb99a4ec67fa11cfd66969318cbc71aa2d45fa53a349600080a2005b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602060405161dd188152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761037161031b611ce0565b610323611f22565b906040519283927f0f00000000000000000000000000000000000000000000000000000000000000845261036360209360e08587015260e0860190611d19565b908482036040860152611d19565b90466060840152306080840152600060a084015282820360c08401528060605192838152019160809160005b8281106103ac57505050500390f35b83518552869550938101939281019260010161039d565b3461016e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57602061040d6103ff611c11565b610407611c24565b90611fb9565b63ffffffff60405191168152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e576000526005602052602063ffffffff60406000205416604051908152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576020604051610e108152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5763ffffffff80610501611c11565b166000526004602052604060002061016a60036105c183549360018101549561054f6040519261053f846105388160028501611e6d565b0385611c9f565b6105386040518097819301611e6d565b604051968673ffffffffffffffffffffffffffffffffffffffff8998168852828160a01c166020890152828160c01c16604089015260e01c606088015261ffff8116608088015265ffffffffffff8160101c1660a088015260401c1660c08601526101208060e0870152850190611d19565b90838203610100850152611d19565b3461016e5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57610607611c11565b61060f611c24565b67ffffffffffffffff9060443582811161016e57610631903690600401611dec565b92909160643582811161016e5761064c903690600401611dec565b91909260843590811161016e57610667903690600401611dec565b91909533600052600060205260ff604060002054166003811015610b4257600203610b1857600096604080518a815260046020820152209384549473ffffffffffffffffffffffffffffffffffffffff861615610aee5763ffffffff8660a01c16804210610ac45763ffffffff6106e58192828a60c01c1690611fb9565b1695168503610a9a578560e01c8511610a7057600101549665ffffffffffff8860101c163a11610a4657604051602081019063ffffffff8d1682528660408201526040815261073381611c4b565b5190209687600052600360205261ffff604060002054169761ffff8a168914610a1c576000526003602052604060002061ffff60018a01167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008254161790558b60405163ffffffff6020820192168252876040820152336060820152606081526107bc81611c67565b51902080600052600260205260ff604060002054166109f2576000526002602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790555a9961ffff60018a01116109c35773ffffffffffffffffffffffffffffffffffffffff88163b1561016e578c95604051998a9889987ff8eb7fbd000000000000000000000000000000000000000000000000000000008a5263ffffffff1660048a0152602489015260010161ffff1660448801523360648801526084870160e0905260e487019061089b92611fde565b908582037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160a48701526108cf92611fde565b908382037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160c485015261090392611fde565b039173ffffffffffffffffffffffffffffffffffffffff1691815a6000948591f180156109b75761099f575b5063ffffffff61dd189160401c16915a90030111610975577fc68fb0ae5cea2793405d29014d881bcda18f67122e0bcd7d0a577e118b64e4c863ffffffff3393169180a3005b60046040517fbe9179a6000000000000000000000000000000000000000000000000000000008152fd5b6109aa919350611c37565b60009163ffffffff61092f565b6040513d6000823e3d90fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517f88a21e4f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2f4ca85b000000000000000000000000000000000000000000000000000000008152fd5b60046040517f682bad5a000000000000000000000000000000000000000000000000000000008152fd5b60046040517fae6704a7000000000000000000000000000000000000000000000000000000008152fd5b60046040517f4db310c3000000000000000000000000000000000000000000000000000000008152fd5b60046040517fefb74efe000000000000000000000000000000000000000000000000000000008152fd5b60046040517f1a00354f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8741cbb8000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e578060005260006020526040600020805460ff81166003811015610b425780610c4e57506001907fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000064ffffffff004260081b169116171790556040519063ffffffff421682527fb73af334a40cdaaad72e06d597bdeed270fc94d45415863afec219108096d2e860203393a3005b83610c8b604492604051927f5acfd51800000000000000000000000000000000000000000000000000000000845260048401526024830190611c04565bfd5b3461016e576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e57610cc5611c11565b610ccd611c24565b67ffffffffffffffff91826044351161016e576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6044353603011261016e57610d17611d77565b60c4359363ffffffff8516850361016e5760e43581811161016e57610d40903690600401611dec565b9290936101043583811161016e57610d5c903690600401611dec565b9290936101243590811161016e57610d78903690600401611dec565b92909733600052600060205260ff604060002054166003811015610b4257600203610b1857610db59260a4359260843592604435600401916120c2565b909790156110cf57610258945b604080518a815260046020820152209788549360009973ffffffffffffffffffffffffffffffffffffffff861615610aee5763ffffffff8660a01c16804210610ac45763ffffffff610e1b8192828a60c01c1690611fb9565b1695168503610a9a578560e01c8511610a7057600101549665ffffffffffff8860101c163a11610a465760405163ffffffff8d16602082015285604082015260408152610e6781611c4b565b602081519101209687600052600360205261ffff604060002054169761ffff8a168914610a1c576000526003602052604060002061ffff60018a01167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008254161790558c60405163ffffffff602082019216825287604082015233606082015260608152610ef481611c67565b51902080600052600260205260ff604060002054166109f2576000526002602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790555a9a61ffff60018a01116109c35773ffffffffffffffffffffffffffffffffffffffff88163b1561016e578d95604051998a9889987ff8eb7fbd000000000000000000000000000000000000000000000000000000008a5263ffffffff1660048a0152602489015260010161ffff1660448801523360648801526084870160e0905260e4870190610fd392611fde565b908582037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160a487015261100792611fde565b908382037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0160c485015261103b92611fde565b039173ffffffffffffffffffffffffffffffffffffffff1691815a6000948591f180156109b7576110af575b509063ffffffff61dd189260401c16925a9003010111610975577fc68fb0ae5cea2793405d29014d881bcda18f67122e0bcd7d0a577e118b64e4c863ffffffff3393169180a3005b61dd18929194506110bf90611c37565b63ffffffff600094919250611067565b6201644094610dc2565b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526006602052602063ffffffff60406000205416604051908152f35b3461016e5760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043567ffffffffffffffff811161016e573660238201121561016e57611189903690602481600401359101611d87565b60243567ffffffffffffffff811161016e576111a9903690600401611dec565b90916044359265ffffffffffff8416840361016e576064359263ffffffff8416840361016e576084359263ffffffff8416840361016e5760a4359463ffffffff8616860361016e5760c4359061ffff8216820361016e576001549663ffffffff6001818a1601167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000089161760015563ffffffff80821681421601116109c357604051988961012081011067ffffffffffffffff6101208c0111176116b05761ffff63ffffffff94856112c19a8d60408365ffffffffffff98610120840183523384528180821681421601166020850152169101521660608d01521660808b01521660a08901521660c087015260e08601523691611d87565b61010083015263ffffffff81166000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff8351167fffffffffffffffffffffffff000000000000000000000000000000000000000082541617815561137263ffffffff60208501511682907fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000083549260a01b169116179055565b604083015181547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1660c09190911b7bffffffff00000000000000000000000000000000000000000000000016178155606083015181547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e09190911b7fffffffff00000000000000000000000000000000000000000000000000000000161781556114d56001820161ffff6080860151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000082541617815561149365ffffffffffff60a08701511682907fffffffffffffffffffffffffffffffffffffffffffffffff000000000000ffff67ffffffffffff000083549260101b169116179055565b60c085015181547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1660409190911b6bffffffff000000000000000016179055565b6002810160e084015180519067ffffffffffffffff82116116b057611504826114fe8554611e1a565b85611f72565b602090601f83116001146116ea5791806003949261010096946000926116df575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b92861b1c19161790555b019201519081519267ffffffffffffffff84116116b0578361158460209561157e8454611e1a565b84611f72565b8493601f8211600114611611579381929394600092611606575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b63ffffffff604051918181167f04344ed7a67fec80c444d56ee1cee242f3f75b91fecc8dbce8890069c82eb48e600080a2168152f35b01519050858061159e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169483600052866000209160005b878110611699575083600195969710611662575b505050811b0190556115d0565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055858080611655565b919288600181928685015181550194019201611641565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b015190508880611525565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316918460005260206000209260005b81811061177c575092600192859261010098966003989610611746575b505050811b019055611556565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f884891b161c19169055888080611739565b9293602060018192878601518155019501930161171c565b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760206040516102588152f35b3461016e577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60c08136011261016e57611807611c11565b61180f611c24565b6044359267ffffffffffffffff841161016e5761012090843603011261016e576040926118509261183e611d77565b9060a4359360843593600401916120c2565b63ffffffff83519216825215156020820152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5761016a610156611ce0565b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5763ffffffff6118da611c11565b1680600052600460205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036119ee578060005260046020526003604060002060008155600060018201556002810161192f8154611e1a565b90816119b0575b5050016119438154611e1a565b9081611972575b827ff4126e31c182db4c4109605c6d50470fc7e8ca90d62d44fd25cbe049fb9cac3e600080a2005b81601f6000931160011461198a5750555b818061194a565b9080839182526119a9601f60208420940160051c840160018501611f5b565b5555611983565b81601f600093116001146119c85750555b8380611936565b9080839182526119e7601f60208420940160051c840160018501611f5b565b55556119c1565b60046040517fa7fba711000000000000000000000000000000000000000000000000000000008152fd5b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e576004356000526002602052602060ff604060002054166040519015158152f35b3461016e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5760043573ffffffffffffffffffffffffffffffffffffffff811680910361016e5760005260006020526040806000205463ffffffff825191611adb8360ff8316611c04565b60081c166020820152f35b3461016e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016e5733600052600060205260406000209081549060ff82166003811015610b425760018103611bd457505063ffffffff8160081c16610e1081014210611ba357507fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000166002179055337f7dc8b937d2916b130743c447af3d771fa55e66b7393105150e2e635ac3e87260600080a2005b602490604051907fc84b5bdd0000000000000000000000000000000000000000000000000000000082526004820152fd5b90610c8b6024927f33daa7f900000000000000000000000000000000000000000000000000000000835260048301905b906003821015610b425752565b6004359063ffffffff8216820361016e57565b6024359063ffffffff8216820361016e57565b67ffffffffffffffff81116116b057604052565b6060810190811067ffffffffffffffff8211176116b057604052565b6080810190811067ffffffffffffffff8211176116b057604052565b6040810190811067ffffffffffffffff8211176116b057604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176116b057604052565b60405190611ced82611c83565b601382527f496e6665726e6574436f6f7264696e61746f72000000000000000000000000006020830152565b919082519283825260005b848110611d635750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201611d24565b6064359060ff8216820361016e57565b92919267ffffffffffffffff82116116b05760405191611dcf60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611c9f565b82948184528183011161016e578281602093846000960137010152565b9181601f8401121561016e5782359167ffffffffffffffff831161016e576020838186019501011161016e57565b90600182811c92168015611e63575b6020831014611e3457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611e29565b9060009291805491611e7e83611e1a565b918282526001938481169081600014611ee05750600114611ea0575b50505050565b90919394506000526020928360002092846000945b838610611ecc575050505001019038808080611e9a565b805485870183015294019385908201611eb5565b91505060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009193501683830152151560051b01019038808080611e9a565b60405190611f2f82611c83565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152565b818110611f66575050565b60008155600101611f5b565b9190601f8111611f8157505050565b611fad926000526020600020906020601f840160051c83019310611faf575b601f0160051c0190611f5b565b565b9091508190611fa0565b63ffffffff8092168015611fd65782600192814216031604011690565b505050600190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361016e5790565b3563ffffffff8116810361016e5790565b3561ffff8116810361016e5790565b3565ffffffffffff8116810361016e5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561016e570180359067ffffffffffffffff821161016e5760200191813603831361016e57565b929193959490956120d28561201d565b60405173ffffffffffffffffffffffffffffffffffffffff602082019216825263ffffffff861660408201526040815261210b81611c4b565b5190209687600052600660205263ffffffff6040600020541680612b6b575063ffffffff811663ffffffff42161015612b41576121478661201d565b906121546020880161203e565b6121606040890161203e565b61216c60608a0161203e565b61217860808b0161204f565b61218460a08c0161205e565b9061219160c08d0161203e565b9261219f60e08e018e612071565b36906121aa92611d87565b80519060200120948d61010081016121c191612071565b36906121cc92611d87565b80519060200120966040519960208b017f2b24aa047bbff05c807b5ba16020ac01534fdb34947d5608264ac56133753190905273ffffffffffffffffffffffffffffffffffffffff1660408b015263ffffffff1660608a015263ffffffff16608089015263ffffffff1660a088015261ffff1660c087015265ffffffffffff1660e086015263ffffffff166101008501526101208401526101409081840152825281610160810110610160830167ffffffffffffffff10176116b057610160820160405263ffffffff82516020840120917f1950b0dfc42b437b752641a63d09bd2a7d858914bdd31db6ef0dc3e5b2bf544e6101808501528188166101a0850152166101c08301526101e08201526080610160820152610160810161020082011067ffffffffffffffff610200830111176116b0576102008101604052610160810151610180820120907f5c72553c6419479f738b12513520a383f916a5009a85c384c1ef65b229e2c85d907f000000000000000000000000a612fca4652ef94ae3d0e0aefedb1932c5f1b61d30147f000000000000000000000000000000000000000000000000000000000000000146141615612ab0575b50671901000000000000600052601a52603a5260ff6042601820936000603a5260405194600052166020526040526060526020600160806000825afa51903d15612aa25760006060528060405260208160048173ffffffffffffffffffffffffffffffffffffffff6123f68961201d565b167f238ac9330000000000000000000000000000000000000000000000000000000082525afa9081156109b757600091612a3f575b5073ffffffffffffffffffffffffffffffffffffffff809116911603612a15576001549163ffffffff600181851601167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000084161760015563ffffffff83166000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6124b48361201d565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781556125346124eb6020840161203e565b82547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a09190911b77ffffffff000000000000000000000000000000000000000016178255565b6125906125436040840161203e565b82547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1660c09190911b7bffffffff00000000000000000000000000000000000000000000000016178255565b6125ec61259f6060840161203e565b82547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e09190911b7fffffffff0000000000000000000000000000000000000000000000000000000016178255565b6126ba6001820161ffff6126026080860161204f565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000082541617815561267261263960a0860161205e565b82547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000ffff1660109190911b67ffffffffffff000016178255565b61267e60c0850161203e565b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff6bffffffff000000000000000083549260401b169116179055565b6126c760e0830183612071565b67ffffffffffffffff81116116b05760028301916126e9826114fe8554611e1a565b600090601f831160011461296f5760039493929160009183612964575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b92861b1c19161790555b0194612747610100830183612071565b67ffffffffffffffff81989298116116b0576127678161157e8454611e1a565b6000601f82116001146128ba57819063ffffffff98996000926128af575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b600052600660205260406000208484167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008254161790558383167f04344ed7a67fec80c444d56ee1cee242f3f75b91fecc8dbce8890069c82eb48e600080a273ffffffffffffffffffffffffffffffffffffffff6128348261201d565b166000526005602052836040600020541684831611612857575b50501690600090565b61287573ffffffffffffffffffffffffffffffffffffffff9161201d565b1660005282604060002091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055388061284e565b013590503880612785565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08216908360005260206000209160005b81811061294c57509983929160019463ffffffff9b9c10612914575b505050811b0190556127b7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612907565b9192602060018192868f0135815501940192016128eb565b013590503880612706565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316918460005260206000209260005b8181106129fd5750916001939185600398979694106129c7575b505050811b019055612737565b01357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83881b60f8161c191690553880806129ba565b919360206001819287870135815501950192016129a0565b60046040517f10c74b03000000000000000000000000000000000000000000000000000000008152fd5b90506020813d602011612a9a575b81612a5a60209383611c9f565b8101031261016e575173ffffffffffffffffffffffffffffffffffffffff8116810361016e5773ffffffffffffffffffffffffffffffffffffffff61242b565b3d9150612a4d565b638baa579f6000526004601cfd5b60a09150807f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610200809301527fe7f0b77df5c5e5c7a7bc3e252dd153438c3d764ef75b93d0f9e5658cfd0afde36102208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66102408201524661026082015230610280820152012038612385565b60046040517f0819bdcd000000000000000000000000000000000000000000000000000000008152fd5b97506001969550505050505056fea264697066735822122044f9e1e05ee99e4d16dd70c4e2aeb575ef9fdc3bfba4b51d1da0c9939b3a859964736f6c63430008130033

Deployed Bytecode Sourcemap

576:10455:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;1813:10;576:10455;;;;;;;;;;;;;;;;;;5256:49:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;4568:20:2;576:10455:3;;;;;;;;;;;;;;;;;;;9108:10:4;576:10455:3;;;;;;;;;;9108:10:4;9170:27;576:10455:3;9170:27:4;;576:10455:3;;;;;;;;;;;;;;;4157:10:2;576:10455:3;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;7428:13:1;;576:10455:3;;;;7479:4:1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3195:52;576:10455;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2989:7:4;576:10455:3;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;5409:52:2;576:10455:3;;;5409:52:2;;;;576:10455:3;;;;;5409:52:2;576:10455:3;5409:52:2;576:10455:3;5409:52:2;;;;576:10455:3;:::i;:::-;;;;:::i;:::-;;;;5409:52:2;;;;;576:10455:3;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;6206:10:4;;;;576:10455:3;;;;;;;;;;;;;;;;;6228:17:4;6197:48;6193:101;;576:10455:3;11914:1349:2;576:10455:3;11914:1349:2;;;;;576:10455:3;;11914:1349:2;;;;;;;;;;;13326:22;13322:82;;11914:1349;;576:10455:3;11914:1349:2;;13470:15;;:29;13466:90;;11914:1349;13627:47;11914:1349;;;;;;;13627:47;;:::i;:::-;576:10455:3;;;13741:28:2;;13737:84;;11914:1349;576:10455:3;11914:1349:2;13877:23;;13873:84;;14103:561;;;;;;;;;14739:11;:28;14735:84;;576:10455:3;;;14930:36:2;;576:10455:3;11914:1349:2;576:10455:3;;;;;;;;;;14930:36:2;;;;;:::i;:::-;576:10455:3;14920:47:2;;576:10455:3;;;;;;;14103:561:2;576:10455:3;;;;;14103:561:2;;;;15043:39;;15039:96;;576:10455:3;;;;;;;;14103:561:2;;576:10455:3;;;;;;;;;;;;;11914:1349:2;576:10455:3;15384:48:2;;576:10455:3;;;;;;;;;6206:10:4;576:10455:3;;;;;15384:48:2;;;;;:::i;:::-;576:10455:3;15374:59:2;;576:10455:3;;;6228:17:4;576:10455:3;;;;;;;;15443:78:2;;576:10455:3;;6228:17:4;576:10455:3;;;;;14103:561:2;576:10455:3;;;;;;;15671:9:2;576:10455:3;14103:561:2;;576:10455:3;;;;;11914:1349:2;;;15690:150;;;;576:10455:3;;;;15690:150:2;;;;;576:10455:3;15690:150:2;;11914:1349;576:10455:3;;15690:150:2;;576:10455:3;;;;;14103:561:2;576:10455:3;14103:561:2;576:10455:3;;;;;6206:10:4;576:10455:3;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;15690:150:2;11914:1349;;;15690:150;;;576:10455:3;15690:150:2;;;;;;;;;;576:10455:3;14103:561:2;11914:1349;4157:10;14103:561;576:10455:3;14103:561:2;;15870:9;;576:10455:3;;;16560:30:2;16556:86;;16693:49;11914:1349;6206:10:4;576:10455:3;;16693:49:2;;;576:10455:3;16556:86:2;576:10455:3;;;16613:18:2;;;;15690:150;;;;;;:::i;:::-;576:10455:3;;11914:1349:2;15690:150;;;576:10455:3;;;;;;;;;;;;;;;;;;;15443:78:2;576:10455:3;;;15488:22:2;;;;15039:96;576:10455:3;;;15105:19:2;;;;14735:84;576:10455:3;;;14790:18:2;;;;13873:84;576:10455:3;;;13923:23:2;;;;13737:84;576:10455:3;;;13792:18:2;;;;13466:90;576:10455:3;;;13522:23:2;;;;13322:82;576:10455:3;;;13371:22:2;;;;6193:101:4;576:10455:3;;;6268:15:4;;;;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7045:34:4;7041:110;;7328:15;7219:21;7328:15;576:10455:3;;7328:15:4;576:10455:3;;;;;;;;;;;7328:15:4;576:10455:3;7328:15:4;576:10455:3;;;7399:57:4;576:10455:3;7420:10:4;7399:57;;576:10455:3;7041:110:4;576:10455:3;;;;;;7102:38:4;;;;576:10455:3;7102:38:4;;576:10455:3;;;;;;:::i;:::-;7102:38:4;576:10455:3;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;6206:10:4;;;;576:10455:3;;;;;;;;;;;;;;;;;6228:17:4;6197:48;6193:101;;10355:56:3;576:10455;;;;;;;;;;;10355:56;;:::i;:::-;10541:16;;;10567:311;;;1434:7;10567:311;;576:10455;11914:1349:2;;;;;576:10455:3;;11914:1349:2;;;;;;;-1:-1:-1;576:10455:3;11914:1349:2;;;;13326:22;13322:82;;576:10455:3;11914:1349:2;;;;13470:15;;:29;13466:90;;576:10455:3;13627:47:2;11914:1349;;;;;;;13627:47;;:::i;:::-;576:10455:3;;;13741:28:2;;13737:84;;11914:1349;576:10455:3;11914:1349:2;13877:23;;13873:84;;14103:561;;;;;;;;;14739:11;:28;14735:84;;576:10455:3;;;;;;14930:36:2;;576:10455:3;;;;;;;14930:36:2;;;;;:::i;:::-;576:10455:3;;;14930:36:2;;14920:47;576:10455:3;;;;;;;14103:561:2;576:10455:3;;;;;14103:561:2;;;;15043:39;;15039:96;;576:10455:3;;;;;;;;14103:561:2;;576:10455:3;;;;;;;;;;;;;;;15384:48:2;;576:10455:3;;;;;;;;;6206:10:4;576:10455:3;;;;;15384:48:2;;;;;:::i;:::-;576:10455:3;15374:59:2;;576:10455:3;;;6228:17:4;576:10455:3;;;;;;;;15443:78:2;;576:10455:3;;6228:17:4;576:10455:3;;;;;14103:561:2;576:10455:3;;;;;;;15671:9:2;576:10455:3;14103:561:2;;576:10455:3;;;;;11914:1349:2;;;15690:150;;;;576:10455:3;;;;15690:150:2;;;;;576:10455:3;15690:150:2;;576:10455:3;;;15690:150:2;;576:10455:3;;;;;14103:561:2;576:10455:3;14103:561:2;576:10455:3;;;;;6206:10:4;576:10455:3;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;15690:150:2;11914:1349;;;15690:150;;;576:10455:3;15690:150:2;;;;;;;;;;10567:311:3;14103:561:2;;576:10455:3;4157:10:2;14103:561;576:10455:3;14103:561:2;;15870:9;;576:10455:3;;;;16560:30:2;16556:86;;16693:49;576:10455:3;6206:10:4;576:10455:3;;16693:49:2;;;576:10455:3;15690:150:2;4157:10;15690:150;;;;;;;:::i;:::-;576:10455:3;;15690:150:2;;;;;;10567:311:3;1813:10;10567:311;;;576:10455;;;;;;;;;;;;;;;3441:52;576:10455;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;18061:4:2;576:10455:3;;;;;;;;;18061:4:2;576:10455:3;;;;;18423:15:2;;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18469:10:2;576:10455:3;;;;;;18423:15:2;;576:10455:3;;;;18152:578:2;;576:10455:3;;18152:578:2;;576:10455:3;;;18152:578:2;;576:10455:3;;;18152:578:2;;576:10455:3;;;18152:578:2;;576:10455:3;;;18152:578:2;;576:10455:3;;18152:578:2;;576:10455:3;;;;:::i;:::-;18152:578:2;;;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;18152:578:2;576:10455:3;;;;;;;;;;;18061:4:2;576:10455:3;;;;;;;;;;;;18152:578:2;;576:10455:3;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;;;;;;;;;;;;;;;;18779:35:2;576:10455:3;18779:35:2;;576:10455:3;;;;;;;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;18152:578:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18061:4:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1434:7;576:10455;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;19235:10:2;19196:49;19192:109;;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;19424:37:2;;576:10455:3;19424:37:2;;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;19192:109:2;576:10455:3;;;19268:22:2;;;;576:10455:3;;;;;;;;;;;;;;;4695:45:2;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;7901:10:4;576:10455:3;;;;;;;;;;;;;;;;;;;;;8107:21:4;8092:36;;8088:106;;576:10455:3;;;;;;;2989:7:4;576:10455:3;;8478:15:4;:29;8474:101;;-1:-1:-1;576:10455:3;;8639:17:4;576:10455:3;;;7901:10:4;8779:25;576:10455:3;;8779:25:4;576:10455:3;8474:101:4;576:10455:3;;;;8530:34:4;;;;576:10455:3;8530:34:4;;576:10455:3;8530:34:4;8088:106;8151:32;576:10455:3;;8151:32:4;;;;576:10455:3;8151:32:4;;576:10455:3;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;576:10455:3;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;576:10455:3;;;;-1:-1:-1;576:10455:3;;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::o;:::-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;576:10455:3;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;-1:-1:-1;576:10455:3;;;;19774:590:2;576:10455:3;;;;19936:11:2;;19932:50;;20305:15;20346:1;20305:15;;;576:10455:3;;;;;;19774:590:2;:::o;19932:50::-;19963:8;;;19970:1;19963:8;:::o;576:10455:3:-;;;;;;;;;;;;;;;-1:-1:-1;576:10455:3;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;1940:189::-;;576:10455;;;;;;;1940:189;:::o;:::-;;576:10455;;;;;;;1940:189;:::o;:::-;;576:10455;;;;;;;1940:189;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5664:3289::-;;;;;;;;5999:9;;;:::i;:::-;576:10455;;;5988:28;;;576:10455;;;;;;;;;;;;5988:28;;;;;:::i;:::-;576:10455;5978:39;;576:10455;;-1:-1:-1;576:10455:3;6051:18;5988:28;576:10455;;;-1:-1:-1;576:10455:3;;;6270:19;6266:79;;576:10455;;;;;6470:15;576:10455;6463:33;;6459:89;;7059:9;;;:::i;:::-;7098:12;;5988:28;7098:12;;;:::i;:::-;7140:10;576:10455;7140:10;;;:::i;:::-;7180:13;576:10455;7180:13;;;:::i;:::-;7223:14;;;;;:::i;:::-;7267:15;;;;;:::i;:::-;7312;;;;;;:::i;:::-;7424;;;;;;;:::i;:::-;576:10455;;;;;:::i;:::-;;;;5988:28;576:10455;7408:33;7481:10;;;;;;;;:::i;:::-;576:10455;;;;;:::i;:::-;;;;5988:28;576:10455;7471:21;576:10455;;;6961:557;5988:28;6961:557;;1940:189;576:10455;;;;;1940:189;;576:10455;;;;1940:189;;576:10455;;;7223:14;1940:189;;576:10455;;;7267:15;1940:189;;576:10455;;;7312:15;1940:189;;576:10455;;;7424:15;1940:189;;576:10455;;;7481:10;1940:189;;576:10455;1940:189;;;576:10455;1940:189;;;;;576:10455;6961:557;;576:10455;1940:189;576:10455;;;1940:189;576:10455;;;-1:-1:-1;576:10455:3;;;1940:189;576:10455;;;;;;;5988:28;6961:557;;6926:614;6731:827;2576:254;6731:827;;;576:10455;;;;1940:189;;;576:10455;;1940:189;;;576:10455;1940:189;;;576:10455;7223:14;1940:189;576:10455;;6731:827;1940:189;576:10455;;;;;;;;;;;;;;;;;;;1940:189;576:10455;;;6731:827;;;6636:936;6608:974;6066:22:1;9114:11;;9178:111;;9069:14;9178:111;;;;6102:73;;5664:3289:3;6238:398:1;;-1:-1:-1;6238:398:1;;;;;7600:1013:0;6238:398:1;;;;-1:-1:-1;6238:398:1;;576:10455:3;7600:1013:0;;-1:-1:-1;7600:1013:0;;5988:28:3;7600:1013:0;576:10455:3;7600:1013:0;576:10455:3;7600:1013:0;5988:28:3;7600:1013:0;7223:14:3;-1:-1:-1;7600:1013:0;;;;;;;;;-1:-1:-1;576:10455:3;7600:1013:0;;576:10455:3;7600:1013:0;5988:28:3;7896:9;7886:29;7896:9;576:10455;7896:9;;;:::i;:::-;576:10455;;7886:29;;;;;;;;;-1:-1:-1;7886:29:3;;;5664:3289;576:10455;;;;;;;8006:34;8002:88;;7600:1013:0;576:10455:3;;;7600:1013:0;576:10455:3;;;;;;;;;7600:1013:0;576:10455:3;;;;-1:-1:-1;576:10455:3;7886:29;5988:28;576:10455;;-1:-1:-1;576:10455:3;;1940:189;;;:::i;:::-;576:10455;;;;;;;;1940:189;;5988:28;7098:12;;1940:189;:::i;:::-;576:10455;;;;;;;;;;;;;;;1940:189;;;576:10455;7140:10;;1940:189;:::i;:::-;576:10455;;;;;;;;;;;;;;;1940:189;;;576:10455;7180:13;;1940:189;:::i;:::-;576:10455;;;;;;;;;;;;;;;1940:189;;7600:1013:0;1940:189:3;;576:10455;1940:189;7223:14;;;1940:189;:::i;:::-;576:10455;;;;;;;;1940:189;;7267:15;;;1940:189;:::i;:::-;576:10455;;;;;;;;;;;;;;;1940:189;;7312:15;;;1940:189;:::i;:::-;576:10455;;;;;;;;;;;;;;1940:189;;7424:15;;;1940:189;;:::i;:::-;576:10455;1940:189;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1940:189:3;;;;;;;;;;;;;-1:-1:-1;;1940:189:3;;;;576:10455;;;;7600:1013:0;576:10455:3;;;;;;;;1940:189;;;;7481:10;1940:189;7481:10;;;1940:189;;:::i;:::-;576:10455;1940:189;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1940:189:3;;;;;;;;;576:10455;1940:189;;-1:-1:-1;1940:189:3;;;;576:10455;;;;7600:1013:0;576:10455:3;;1940:189;576:10455;;;;;1940:189;;;-1:-1:-1;576:10455:3;6051:18;5988:28;576:10455;;-1:-1:-1;576:10455:3;;;;;;;;;;;;;;8598:35;-1:-1:-1;8598:35:3;;576:10455;8788:9;;;:::i;:::-;576:10455;-1:-1:-1;576:10455:3;8769:18;5988:28;576:10455;;;-1:-1:-1;576:10455:3;;;;;;8761:37;8757:105;;1940:189;576:10455;;;8916:30;-1:-1:-1;5664:3289:3;:::o;8757:105::-;8833:9;576:10455;8833:9;;:::i;:::-;576:10455;-1:-1:-1;576:10455:3;;;-1:-1:-1;576:10455:3;;;;;;;;;;8757:105;;;;1940:189;;;;-1:-1:-1;1940:189:3;;;;;5988:28;1940:189;;576:10455;;-1:-1:-1;576:10455:3;5988:28;-1:-1:-1;576:10455:3;1940:189;-1:-1:-1;1940:189:3;;;;;;;;;;;7600:1013:0;1940:189:3;576:10455;1940:189;;;;;;;;;;;;;;;;;576:10455;;;1940:189;576:10455;;;;1940:189;;;576:10455;1940:189;;;;;;;;;;5988:28;7600:1013:0;1940:189:3;;;;;;;;;;;;;;;;;;;-1:-1:-1;1940:189:3;;;;;5988:28;1940:189;;576:10455;;-1:-1:-1;576:10455:3;5988:28;-1:-1:-1;576:10455:3;1940:189;-1:-1:-1;1940:189:3;;;;;;;;7600:1013:0;1940:189:3;;;;;;;;;;;;;;;;;;;;;;;;;576:10455;;;;;;;;;1940:189;;;;;;;;;;5988:28;7600:1013:0;1940:189:3;;;;;;;;;;;;;;;8002:88;7886:29;576:10455;;8063:16;;;;7886:29;;;5988:28;7886:29;;5988:28;7886:29;;;;;;5988:28;7886:29;;;:::i;:::-;;;1940:189;;;;;576:10455;;;;;;;;7886:29;;;;;-1:-1:-1;7886:29:3;;7600:1013:0;;-1:-1:-1;7600:1013:0;;;;6102:73:1;7267:15:3;576:10455;;;8507:362:1;576:10455:3;;;;8507:362:1;8383:15;8507:362;;;;8426:18;8507:362;;;;9178:111;8507:362;;;;9178:111;8507:362;;;;576:10455:3;8507:362:1;6102:73;;;6459:89:3;6519:18;576:10455;;6519:18;;;;6266:79;6305:29;-1:-1:-1;6329:4:3;;6305:29;-1:-1:-1;;;;;;6305:29:3:o

Swarm Source

ipfs://44f9e1e05ee99e4d16dd70c4e2aeb575ef9fdc3bfba4b51d1da0c9939b3a8599

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