ETH Price: $1,896.55 (-1.85%)

Contract

0xfea230Ee243f88BC698dD8f1aE93F8301B6cdfaE
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute166887842025-03-17 4:56:231 hr ago1742187383IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009643
Execute166885762025-03-17 4:49:271 hr ago1742186967IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00010018
Execute166885262025-03-17 4:47:471 hr ago1742186867IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009815
Execute166877092025-03-17 4:20:331 hr ago1742185233IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009646
Execute166877092025-03-17 4:20:331 hr ago1742185233IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009646
Execute166875712025-03-17 4:15:571 hr ago1742184957IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009748
Execute166875682025-03-17 4:15:511 hr ago1742184951IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009786
Execute166872602025-03-17 4:05:351 hr ago1742184335IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00010401
Execute166871382025-03-17 4:01:311 hr ago1742184091IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00010498
Execute166868282025-03-17 3:51:112 hrs ago1742183471IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009847
Execute166868282025-03-17 3:51:112 hrs ago1742183471IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009847
Execute166865602025-03-17 3:42:152 hrs ago1742182935IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009514
Execute166865602025-03-17 3:42:152 hrs ago1742182935IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009514
Execute166860172025-03-17 3:24:092 hrs ago1742181849IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009446
Execute166854482025-03-17 3:05:112 hrs ago1742180711IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009979
Execute166852492025-03-17 2:58:332 hrs ago1742180313IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.0000976
Execute166850302025-03-17 2:51:153 hrs ago1742179875IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009789
Execute166847722025-03-17 2:42:393 hrs ago1742179359IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009516
Execute166846402025-03-17 2:38:153 hrs ago1742179095IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009626
Execute166844592025-03-17 2:32:133 hrs ago1742178733IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009507
Execute166844342025-03-17 2:31:233 hrs ago1742178683IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009877
Execute166843752025-03-17 2:29:253 hrs ago1742178565IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009812
Execute166843742025-03-17 2:29:233 hrs ago1742178563IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.0000982
Execute166837982025-03-17 2:10:113 hrs ago1742177411IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009794
Execute166837002025-03-17 2:06:553 hrs ago1742177215IN
0xfea230Ee...01B6cdfaE
0 ETH0.000000020.00009586
View all transactions

Latest 1 internal transaction

Parent Transaction Hash Block From To
64778882024-07-23 20:13:11236 days ago1721765591  Contract Creation0 ETH

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GuestModule

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 500000 runs

Other Settings:
default evmVersion
File 1 of 22 : GuestModule.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "../utils/LibOptim.sol";

import "./commons/submodules/auth/SequenceBaseSig.sol";

import "./commons/ModuleAuth.sol";
import "./commons/ModuleCalls.sol";
import "./commons/ModuleCreator.sol";


/**
 * GuestModule implements a Sequence wallet without signatures, nonce or replay protection.
 * executing transactions using this wallet is not an authenticated process, and can be done by any address.
 *
 * @notice This contract is completely public with no security, designed to execute pre-signed transactions
 *   and use Sequence tools without using the wallets.
 */
contract GuestModule is
  ModuleAuth,
  ModuleCalls,
  ModuleCreator
{
  error DelegateCallNotAllowed(uint256 _index);
  error NotSupported();

  /**
   * @notice Allow any caller to execute an action
   * @param _txs Transactions to process
   */
  function execute(
    Transaction[] calldata _txs,
    uint256,
    bytes calldata
  ) public override {
    // Hash transaction bundle
    bytes32 txHash = SequenceBaseSig.subdigest(keccak256(abi.encode('guest:', _txs)));

    // Execute the transactions
    _executeGuest(txHash, _txs);
  }

  /**
   * @notice Allow any caller to execute an action
   * @param _txs Transactions to process
   */
  function selfExecute(
    Transaction[] calldata _txs
  ) public override {
    // Hash transaction bundle
    bytes32 txHash = SequenceBaseSig.subdigest(keccak256(abi.encode('self:', _txs)));

    // Execute the transactions
    _executeGuest(txHash, _txs);
  }

  /**
   * @notice Executes a list of transactions
   * @param _txHash  Hash of the batch of transactions
   * @param _txs  Transactions to execute
   */
  function _executeGuest(
    bytes32 _txHash,
    Transaction[] calldata _txs
  ) private {
    // Execute transaction
    uint256 size = _txs.length;
    for (uint256 i = 0; i < size; i++) {
      Transaction calldata transaction = _txs[i];

      if (transaction.delegateCall) revert DelegateCallNotAllowed(i);

      uint256 gasLimit = transaction.gasLimit;
      if (gasleft() < gasLimit) revert NotEnoughGas(i, gasLimit, gasleft());

      bool success = LibOptim.call(
        transaction.target,
        transaction.value,
        gasLimit == 0 ? gasleft() : gasLimit,
        transaction.data
      );

      if (success) {
        emit TxExecuted(_txHash, i);
      } else {
        _revertBytes(
          transaction.revertOnError,
          _txHash,
          i,
          LibOptim.returnData()
        );
      }
    }
  }

  /**
   * @notice Validates any signature image, because the wallet is public and has no owner.
   * @return true, all signatures are valid.
   */
  function _isValidImage(bytes32) internal override pure returns (bool) {
    return true;
  }

  /**
   * Not supported.
   */
  function _updateImageHash(bytes32) internal override virtual {
    revert NotSupported();
  }

  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(
    bytes4 _interfaceID
  ) public override (
    ModuleAuth,
    ModuleCalls,
    ModuleCreator
  ) pure returns (bool) {
    return super.supportsInterface(_interfaceID);
  }
}

File 2 of 22 : IERC1271Wallet.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


interface IERC1271Wallet {

  /**
   * @notice Verifies whether the provided signature is valid with respect to the provided data
   * @dev MUST return the correct magic value if the signature provided is valid for the provided data
   *   > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)")
   *   > This function MAY modify Ethereum's state
   * @param _data       Arbitrary length data signed on the behalf of address(this)
   * @param _signature  Signature byte array associated with _data
   * @return magicValue Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise
   */
  function isValidSignature(
    bytes calldata _data,
    bytes calldata _signature)
    external
    view
    returns (bytes4 magicValue);

  /**
   * @notice Verifies whether the provided signature is valid with respect to the provided hash
   * @dev MUST return the correct magic value if the signature provided is valid for the provided hash
   *   > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)")
   *   > This function MAY modify Ethereum's state
   * @param _hash       keccak256 hash that was signed
   * @param _signature  Signature byte array associated with _data
   * @return magicValue Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise
   */
  function isValidSignature(
    bytes32 _hash,
    bytes calldata _signature)
    external
    view
    returns (bytes4 magicValue);
}

File 3 of 22 : IModuleAuth.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


abstract contract IModuleAuth {
  //                        IMAGE_HASH_KEY = keccak256("org.arcadeum.module.auth.upgradable.image.hash");
  bytes32 internal constant IMAGE_HASH_KEY = bytes32(0xea7157fa25e3aa17d0ae2d5280fa4e24d421c61842aa85e45194e1145aa72bf8);

  event ImageHashUpdated(bytes32 newImageHash);

  // Errors
  error ImageHashIsZero();
  error InvalidSignatureType(bytes1 _type);

  function _signatureValidation(
    bytes32 _digest,
    bytes calldata _signature
  ) internal virtual view returns (
    bool isValid,
    bytes32 subdigest
  );

  function signatureRecovery(
    bytes32 _digest,
    bytes calldata _signature
  ) public virtual view returns (
    uint256 threshold,
    uint256 weight,
    bytes32 imageHash,
    bytes32 subdigest,
    uint256 checkpoint
  );

  /**
   * @notice Validates the signature image
   * @return true if the signature image is valid
   */
  function _isValidImage(bytes32) internal virtual view returns (bool) {
    return false;
  }

  /**
   * @notice Updates the signers configuration of the wallet
   * @param _imageHash New required image hash of the signature
   */
  function updateImageHash(bytes32 _imageHash) external virtual;

  /**
   * @notice Updates the signers configuration of the wallet
   * @param _imageHash New required image hash of the signature
   */
  function _updateImageHash(bytes32 _imageHash) internal virtual;
}

File 4 of 22 : IModuleCalls.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


interface IModuleCalls {
  // Events
  event TxFailed(bytes32 indexed _tx, uint256 _index, bytes _reason);
  event TxExecuted(bytes32 indexed _tx, uint256 _index);

  // Errors
  error NotEnoughGas(uint256 _index, uint256 _requested, uint256 _available);
  error InvalidSignature(bytes32 _hash, bytes _signature);

  // Transaction structure
  struct Transaction {
    bool delegateCall;   // Performs delegatecall
    bool revertOnError;  // Reverts transaction bundle if tx fails
    uint256 gasLimit;    // Maximum gas to be forwarded
    address target;      // Address of the contract to call
    uint256 value;       // Amount of ETH to pass with the call
    bytes data;          // calldata to pass
  }

  /**
   * @notice Allow wallet owner to execute an action
   * @param _txs        Transactions to process
   * @param _nonce      Signature nonce (may contain an encoded space)
   * @param _signature  Encoded signature
   */
  function execute(
    Transaction[] calldata _txs,
    uint256 _nonce,
    bytes calldata _signature
  ) external;

  /**
   * @notice Allow wallet to execute an action
   *   without signing the message
   * @param _txs  Transactions to execute
   */
  function selfExecute(
    Transaction[] calldata _txs
  ) external;
}

File 5 of 22 : IModuleCreator.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


interface IModuleCreator {
  error CreateFailed(bytes _code);

  /**
   * @notice Creates a contract forwarding eth value
   * @param _code Creation code of the contract
   * @return addr The address of the created contract
   */
  function createContract(bytes calldata _code) external payable returns (address addr);
}

File 6 of 22 : ModuleAuth.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "../../utils/LibBytes.sol";
import "../../interfaces/IERC1271Wallet.sol";

import "./interfaces/IModuleAuth.sol";

import "./ModuleERC165.sol";

import "./submodules/auth/SequenceBaseSig.sol";
import "./submodules/auth/SequenceDynamicSig.sol";
import "./submodules/auth/SequenceNoChainIdSig.sol";
import "./submodules/auth/SequenceChainedSig.sol";


abstract contract ModuleAuth is
  IModuleAuth,
  ModuleERC165,
  IERC1271Wallet,
  SequenceChainedSig
{
  using LibBytes for bytes;

  bytes1 internal constant LEGACY_TYPE = hex"00";
  bytes1 internal constant DYNAMIC_TYPE = hex"01";
  bytes1 internal constant NO_CHAIN_ID_TYPE = hex"02";
  bytes1 internal constant CHAINED_TYPE = hex"03";

  bytes4 internal constant SELECTOR_ERC1271_BYTES_BYTES = 0x20c13b0b;
  bytes4 internal constant SELECTOR_ERC1271_BYTES32_BYTES = 0x1626ba7e;

  /**
   * @notice Recovers the threshold, weight, imageHash, subdigest, and checkpoint of a signature.
   * @dev The signature must be prefixed with a type byte, which is used to determine the recovery method.
   *
   * @param _digest Digest of the signed data.
   * @param _signature A Sequence signature.
   *
   * @return threshold The required number of signatures needed to consider the signature valid.
   * @return weight The actual number of signatures collected in the signature.
   * @return imageHash The imageHash of the configuration that signed the message.
   * @return subdigest A modified version of the original digest, unique for each wallet/network.
   * @return checkpoint A nonce that is incremented every time a new configuration is set.
   */
  function signatureRecovery(
    bytes32 _digest,
    bytes calldata _signature
  ) public override virtual view returns (
    uint256 threshold,
    uint256 weight,
    bytes32 imageHash,
    bytes32 subdigest,
    uint256 checkpoint
  ) {
    bytes1 signatureType = _signature[0];

    if (signatureType == LEGACY_TYPE) {
      // networkId digest + base recover
      subdigest = SequenceBaseSig.subdigest(_digest);
      (threshold, weight, imageHash, checkpoint) = SequenceBaseSig.recover(subdigest, _signature);
      return (threshold, weight, imageHash, subdigest, checkpoint);
    }

    if (signatureType == DYNAMIC_TYPE) {
      // networkId digest + dynamic recover
      subdigest = SequenceBaseSig.subdigest(_digest);
      (threshold, weight, imageHash, checkpoint) = SequenceDynamicSig.recover(subdigest, _signature);
      return (threshold, weight, imageHash, subdigest, checkpoint);
    }

    if (signatureType == NO_CHAIN_ID_TYPE) {
      // noChainId digest + dynamic recover
      subdigest = SequenceNoChainIdSig.subdigest(_digest);
      (threshold, weight, imageHash, checkpoint) = SequenceDynamicSig.recover(subdigest, _signature);
      return (threshold, weight, imageHash, subdigest, checkpoint);
    }

    if (signatureType == CHAINED_TYPE) {
      // original digest + chained recover
      // (subdigest will be computed in the chained recover)
      return chainedRecover(_digest, _signature);
    }

    revert InvalidSignatureType(signatureType);
  }

  /**
   * @dev Validates a signature.
   *
   * @param _digest Digest of the signed data.
   * @param _signature A Sequence signature.
   *
   * @return isValid Indicates whether the signature is valid or not.
   * @return subdigest A modified version of the original digest, unique for each wallet/network.
   */
  function _signatureValidation(
    bytes32 _digest,
    bytes calldata _signature
  ) internal override virtual view returns (
    bool isValid,
    bytes32 subdigest
  ) {
    uint256 threshold; uint256 weight; bytes32 imageHash;
    (threshold, weight, imageHash, subdigest,) = signatureRecovery(_digest, _signature);
    isValid = weight >= threshold && _isValidImage(imageHash);
  }

  /**
   * @notice Verifies whether the provided signature is valid with respect to the provided data
   * @dev MUST return the correct magic value if the signature provided is valid for the provided data
   *   > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)"))
   * @param _data       Arbitrary length data signed on the behalf of address(this)
   * @param _signatures Signature byte array associated with _data.
   *                    Encoded as abi.encode(Signature[], Configs)
   * @return magicValue Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise
   */
  function isValidSignature(
    bytes calldata _data,
    bytes calldata _signatures
  ) public override virtual view returns (bytes4) {
    // Validate signatures
    (bool isValid,) = _signatureValidation(keccak256(_data), _signatures);
    if (isValid) {
      return SELECTOR_ERC1271_BYTES_BYTES;
    }

    return bytes4(0);
  }

  /**
   * @notice Verifies whether the provided signature is valid with respect to the provided hash
   * @dev MUST return the correct magic value if the signature provided is valid for the provided hash
   *   > The bytes4 magic value to return when signature is valid is 0x1626ba7e : bytes4(keccak256("isValidSignature(bytes32,bytes)"))
   * @param _hash       keccak256 hash that was signed
   * @param _signatures Signature byte array associated with _data.
   *                    Encoded as abi.encode(Signature[], Configs)
   * @return magicValue Magic value 0x1626ba7e if the signature is valid and 0x0 otherwise
   */
  function isValidSignature(
    bytes32 _hash,
    bytes calldata _signatures
  ) public override virtual view returns (bytes4) {
    // Validate signatures
    (bool isValid,) = _signatureValidation(_hash, _signatures);
    if (isValid) {
      return SELECTOR_ERC1271_BYTES32_BYTES;
    }

    return bytes4(0);
  }

  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(bytes4 _interfaceID) public override virtual pure returns (bool) {
    if (
      _interfaceID == type(IModuleAuth).interfaceId ||
      _interfaceID == type(IERC1271Wallet).interfaceId
    ) {
      return true;
    }

    return super.supportsInterface(_interfaceID);
  }

  /**
   * @notice Updates the signers configuration of the wallet
   * @param _imageHash New required image hash of the signature
   */
  function updateImageHash(bytes32 _imageHash) external override virtual onlySelf {
    _updateImageHash(_imageHash);
  }
}

File 7 of 22 : ModuleCalls.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "./ModuleSelfAuth.sol";
import "./ModuleStorage.sol";
import "./ModuleERC165.sol";
import "./ModuleNonce.sol";
import "./ModuleOnlyDelegatecall.sol";

import "./interfaces/IModuleCalls.sol";
import "./interfaces/IModuleAuth.sol";

import "./submodules/nonce/SubModuleNonce.sol";
import "./submodules/auth/SequenceBaseSig.sol";

import "../../utils/LibOptim.sol";


abstract contract ModuleCalls is IModuleCalls, IModuleAuth, ModuleERC165, ModuleOnlyDelegatecall, ModuleSelfAuth, ModuleNonce {
  /**
   * @notice Allow wallet owner to execute an action
   * @dev Relayers must ensure that the gasLimit specified for each transaction
   *      is acceptable to them. A user could specify large enough that it could
   *      consume all the gas available.
   * @param _txs        Transactions to process
   * @param _nonce      Signature nonce (may contain an encoded space)
   * @param _signature  Encoded signature
   */
  function execute(
    Transaction[] calldata _txs,
    uint256 _nonce,
    bytes calldata _signature
  ) external override virtual onlyDelegatecall {
    // Validate and update nonce
    _validateNonce(_nonce);

    // Hash and verify transaction bundle
    (bool isValid, bytes32 txHash) = _signatureValidation(
      keccak256(
        abi.encode(
          _nonce,
          _txs
        )
      ),
      _signature
    );

    if (!isValid) {
      revert InvalidSignature(txHash, _signature);
    }

    // Execute the transactions
    _execute(txHash, _txs);
  }

  /**
   * @notice Allow wallet to execute an action
   *   without signing the message
   * @param _txs  Transactions to execute
   */
  function selfExecute(
    Transaction[] calldata _txs
  ) external override virtual onlySelf {
    // Hash transaction bundle
    bytes32 txHash = SequenceBaseSig.subdigest(
      keccak256(
        abi.encode('self:', _txs)
      )
    );

    // Execute the transactions
    _execute(txHash, _txs);
  }

  /**
   * @notice Executes a list of transactions
   * @param _txHash  Hash of the batch of transactions
   * @param _txs  Transactions to execute
   */
  function _execute(
    bytes32 _txHash,
    Transaction[] calldata _txs
  ) private {
    unchecked {
      // Execute transaction
      uint256 size = _txs.length;
      for (uint256 i = 0; i < size; i++) {
        Transaction calldata transaction = _txs[i];
        uint256 gasLimit = transaction.gasLimit;

        if (gasleft() < gasLimit) revert NotEnoughGas(i, gasLimit, gasleft());

        bool success;
        if (transaction.delegateCall) {
          success = LibOptim.delegatecall(
            transaction.target,
            gasLimit == 0 ? gasleft() : gasLimit,
            transaction.data
          );
        } else {
          success = LibOptim.call(
            transaction.target,
            transaction.value,
            gasLimit == 0 ? gasleft() : gasLimit,
            transaction.data
          );
        }

        if (success) {
          emit TxExecuted(_txHash, i);
        } else {
          // Avoid copy of return data until neccesary
          _revertBytes(
            transaction.revertOnError,
            _txHash,
            i,
            LibOptim.returnData()
          );
        }
      }
    }
  }

  /**
   * @notice Logs a failed transaction, reverts if the transaction is not optional
   * @param _revertOnError  Signals if it should revert or just log
   * @param _txHash         Hash of the transaction
   * @param _index          Index of the transaction in the batch
   * @param _reason         Encoded revert message
   */
  function _revertBytes(
    bool _revertOnError,
    bytes32 _txHash,
    uint256 _index,
    bytes memory _reason
  ) internal {
    if (_revertOnError) {
      assembly { revert(add(_reason, 0x20), mload(_reason)) }
    } else {
      emit TxFailed(_txHash, _index, _reason);
    }
  }

  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(bytes4 _interfaceID) public override virtual pure returns (bool) {
    if (_interfaceID == type(IModuleCalls).interfaceId) {
      return true;
    }

    return super.supportsInterface(_interfaceID);
  }
}

File 8 of 22 : ModuleCreator.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "./interfaces/IModuleCreator.sol";

import "./ModuleSelfAuth.sol";
import "./ModuleERC165.sol";


contract ModuleCreator is IModuleCreator, ModuleERC165, ModuleSelfAuth {
  event CreatedContract(address _contract);

  /**
   * @notice Creates a contract forwarding eth value
   * @param _code Creation code of the contract
   * @return addr The address of the created contract
   */
  function createContract(bytes memory _code) public override virtual payable onlySelf returns (address addr) {
    assembly { addr := create(callvalue(), add(_code, 32), mload(_code)) }
    if (addr == address(0)) revert CreateFailed(_code);
    emit CreatedContract(addr);
  }

  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(bytes4 _interfaceID) public override virtual pure returns (bool) {
    if (_interfaceID == type(IModuleCreator).interfaceId) {
      return true;
    }

    return super.supportsInterface(_interfaceID);
  }
}

File 9 of 22 : ModuleERC165.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


abstract contract ModuleERC165 {
  /**
   * @notice Query if a contract implements an interface
   * @param _interfaceID The interface identifier, as specified in ERC-165
   * @dev Adding new hooks will not lead to them being reported by this function
   *      without upgrading the wallet. In addition, developers must ensure that
   *      all inherited contracts by the main module don't conflict and are accounted
   *      to be supported by the supportsInterface method.
   * @return `true` if the contract implements `_interfaceID`
   */
  function supportsInterface(bytes4 _interfaceID) virtual public pure returns (bool) {
    return _interfaceID == this.supportsInterface.selector;
  }
}

File 10 of 22 : ModuleNonce.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "./ModuleStorage.sol";

import "./submodules/nonce/SubModuleNonce.sol";


contract ModuleNonce {
  // Events
  event NonceChange(uint256 _space, uint256 _newNonce);

  // Errors
  error BadNonce(uint256 _space, uint256 _provided, uint256 _current);

  //                       NONCE_KEY = keccak256("org.arcadeum.module.calls.nonce");
  bytes32 private constant NONCE_KEY = bytes32(0x8d0bf1fd623d628c741362c1289948e57b3e2905218c676d3e69abee36d6ae2e);

  /**
   * @notice Returns the next nonce of the default nonce space
   * @dev The default nonce space is 0x00
   * @return The next nonce
   */
  function nonce() external virtual view returns (uint256) {
    return readNonce(0);
  }

  /**
   * @notice Returns the next nonce of the given nonce space
   * @param _space Nonce space, each space keeps an independent nonce count
   * @return The next nonce
   */
  function readNonce(uint256 _space) public virtual view returns (uint256) {
    return uint256(ModuleStorage.readBytes32Map(NONCE_KEY, bytes32(_space)));
  }

  /**
   * @notice Changes the next nonce of the given nonce space
   * @param _space Nonce space, each space keeps an independent nonce count
   * @param _nonce Nonce to write on the space
   */
  function _writeNonce(uint256 _space, uint256 _nonce) internal {
    ModuleStorage.writeBytes32Map(NONCE_KEY, bytes32(_space), bytes32(_nonce));
  }

  /**
   * @notice Verify if a nonce is valid
   * @param _rawNonce Nonce to validate (may contain an encoded space)
   */
  function _validateNonce(uint256 _rawNonce) internal virtual {
    // Retrieve current nonce for this wallet
    (uint256 space, uint256 providedNonce) = SubModuleNonce.decodeNonce(_rawNonce);

    uint256 currentNonce = readNonce(space);
    if (currentNonce != providedNonce) {
      revert BadNonce(space, providedNonce, currentNonce);
    }

    unchecked {
      uint256 newNonce = providedNonce + 1;

      _writeNonce(space, newNonce);
      emit NonceChange(space, newNonce);
      return;
    }
  }
}

File 11 of 22 : ModuleOnlyDelegatecall.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


contract ModuleOnlyDelegatecall {
  address private immutable self;

  error OnlyDelegatecall();

  constructor() {
    self = address(this);
  }

  /**
   * @notice Modifier that only allows functions to be called via delegatecall.
   */
  modifier onlyDelegatecall() {
    if (address(this) == self) {
      revert OnlyDelegatecall();
    }
    _;
  }
}

File 12 of 22 : ModuleSelfAuth.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


contract ModuleSelfAuth {
  error OnlySelfAuth(address _sender, address _self);

  modifier onlySelf() {
    if (msg.sender != address(this)) {
      revert OnlySelfAuth(msg.sender, address(this));
    }
    _;
  }
}

File 13 of 22 : ModuleStorage.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


library ModuleStorage {
  function writeBytes32(bytes32 _key, bytes32 _val) internal {
    assembly { sstore(_key, _val) }
  }

  function readBytes32(bytes32 _key) internal view returns (bytes32 val) {
    assembly { val := sload(_key) }
  }

  function writeBytes32Map(bytes32 _key, bytes32 _subKey, bytes32 _val) internal {
    bytes32 key = keccak256(abi.encode(_key, _subKey));
    assembly { sstore(key, _val) }
  }

  function readBytes32Map(bytes32 _key, bytes32 _subKey) internal view returns (bytes32 val) {
    bytes32 key = keccak256(abi.encode(_key, _subKey));
    assembly { val := sload(key) }
  }
}

File 14 of 22 : SequenceBaseSig.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "../../../../utils/SignatureValidator.sol";
import "../../../../utils/LibBytesPointer.sol";
import "../../../../utils/LibBytes.sol";
import "../../../../utils/LibOptim.sol";


/**
 * @title SequenceBaseSig Library
 * @author Agustin Aguilar ([email protected])
 * @notice A Solidity implementation for handling signatures in the Sequence protocol.
 */
library SequenceBaseSig {
  using LibBytesPointer for bytes;

  uint256 private constant FLAG_SIGNATURE = 0;
  uint256 private constant FLAG_ADDRESS = 1;
  uint256 private constant FLAG_DYNAMIC_SIGNATURE = 2;
  uint256 private constant FLAG_NODE = 3;
  uint256 private constant FLAG_BRANCH = 4;
  uint256 private constant FLAG_SUBDIGEST = 5;
  uint256 private constant FLAG_NESTED = 6;

  error InvalidNestedSignature(bytes32 _hash, address _addr, bytes _signature);
  error InvalidSignatureFlag(uint256 _flag);

  /**
  * @notice Generates a subdigest for the input digest (unique for this wallet and network).
  * @param _digest The input digest to generate the subdigest from.
  * @return bytes32 The subdigest generated from the input digest.
  */
  function subdigest(
    bytes32 _digest
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        block.chainid,
        address(this),
        _digest
      )
    );
  }

  /**
  * @notice Generates the leaf for an address and weight.
  * @dev The leaf is generated by concatenating the address and weight.
  *
  * @param _addr The address to generate the leaf for.
  * @param _weight The weight to generate the leaf for.
  * @return bytes32 The leaf generated from the address and weight.
  */
  function _leafForAddressAndWeight(
    address _addr,
    uint96 _weight
  ) internal pure returns (bytes32) {
    unchecked {
      return bytes32(uint256(_weight) << 160 | uint256(uint160(_addr)));
    }
  }

  /**
  * @notice Generates the leaf for a hardcoded subdigest.
  * @dev The leaf is generated by hashing 'Sequence static digest:\n' and the subdigest.
  * @param _subdigest The subdigest to generate the leaf for.
  * @return bytes32 The leaf generated from the hardcoded subdigest.
  */
  function _leafForHardcodedSubdigest(
    bytes32 _subdigest
  ) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked('Sequence static digest:\n', _subdigest));
  }

  /**
  * @notice Generates the leaf for a nested tree node.
  * @dev The leaf is generated by hashing 'Sequence nested config:\n', the node, the threshold and the weight.
  *
  * @param _node The root of the node to generate the leaf for.
  * @param _threshold The internal threshold of the tree.
  * @param _weight The external weight of the tree.
  * @return bytes32 The leaf generated from the nested tree.
  */
  function _leafForNested(
    bytes32 _node,
    uint256 _threshold,
    uint256 _weight
  ) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked('Sequence nested config:\n', _node, _threshold, _weight));
  }

  /**
   * @notice Returns the weight and root of a signature branch.
   * @dev If the signature contains a hardcoded subdigest, and it matches the input digest, then the weight is set to 2 ** 256 - 1.
   *
   * @param _subdigest The digest to verify the signature against.
   * @param _signature The signature branch to recover.
   * @return weight The total weight of the recovered signatures.
   * @return root The root hash of the recovered configuration.
   */
  function recoverBranch(
    bytes32 _subdigest,
    bytes calldata _signature
  ) internal view returns (
    uint256 weight,
    bytes32 root
  ) {
    unchecked {
      uint256 rindex;

      // Iterate until the image is completed
      while (rindex < _signature.length) {
        // Read next item type
        uint256 flag;
        (flag, rindex) = _signature.readUint8(rindex);

        if (flag == FLAG_ADDRESS) {
          // Read plain address
          uint8 addrWeight; address addr;
          (addrWeight, addr, rindex) = _signature.readUint8Address(rindex);

          // Write weight and address to image
          bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
          continue;
        }

        if (flag == FLAG_SIGNATURE) {
          // Read weight
          uint8 addrWeight;
          (addrWeight, rindex) = _signature.readUint8(rindex);

          // Read single signature and recover signer
          uint256 nrindex = rindex + 66;
          address addr = SignatureValidator.recoverSigner(_subdigest, _signature[rindex:nrindex]);
          rindex = nrindex;

          // Acumulate total weight of the signature
          weight += addrWeight;

          // Write weight and address to image
          bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
          continue;
        }

        if (flag == FLAG_DYNAMIC_SIGNATURE) {
          // Read signer and weight
          uint8 addrWeight; address addr;
          (addrWeight, addr, rindex) = _signature.readUint8Address(rindex);

          // Read signature size
          uint256 size;
          (size, rindex) = _signature.readUint24(rindex);

          // Read dynamic size signature
          uint256 nrindex = rindex + size;
          if (!SignatureValidator.isValidSignature(_subdigest, addr, _signature[rindex:nrindex])) {
            revert InvalidNestedSignature(_subdigest, addr, _signature[rindex:nrindex]);
          }
          rindex = nrindex;

          // Acumulate total weight of the signature
          weight += addrWeight;

          // Write weight and address to image
          bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
          continue;
        }

        if (flag == FLAG_NODE) {
          // Read node hash
          bytes32 node;
          (node, rindex) = _signature.readBytes32(rindex);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
          continue;
        }

        if (flag == FLAG_BRANCH) {
          // Enter a branch of the signature merkle tree
          uint256 size;
          (size, rindex) = _signature.readUint24(rindex);
          uint256 nrindex = rindex + size;

          uint256 nweight; bytes32 node;
          (nweight, node) = recoverBranch(_subdigest, _signature[rindex:nrindex]);

          weight += nweight;
          root = LibOptim.fkeccak256(root, node);

          rindex = nrindex;
          continue;
        }

        if (flag == FLAG_NESTED) {
          // Enter a branch of the signature merkle tree
          // but with an internal threshold and an external fixed weight
          uint256 externalWeight;
          (externalWeight, rindex) = _signature.readUint8(rindex);

          uint256 internalThreshold;
          (internalThreshold, rindex) = _signature.readUint16(rindex);

          uint256 size;
          (size, rindex) = _signature.readUint24(rindex);
          uint256 nrindex = rindex + size;

          uint256 internalWeight; bytes32 internalRoot;
          (internalWeight, internalRoot) = recoverBranch(_subdigest, _signature[rindex:nrindex]);
          rindex = nrindex;

          if (internalWeight >= internalThreshold) {
            weight += externalWeight;
          }

          bytes32 node = _leafForNested(internalRoot, internalThreshold, externalWeight);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;

          continue;
        }

        if (flag == FLAG_SUBDIGEST) {
          // A hardcoded always accepted digest
          // it pushes the weight to the maximum
          bytes32 hardcoded;
          (hardcoded, rindex) = _signature.readBytes32(rindex);
          if (hardcoded == _subdigest) {
            weight = type(uint256).max;
          }

          bytes32 node = _leafForHardcodedSubdigest(hardcoded);
          root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
          continue;
        }

        revert InvalidSignatureFlag(flag);
      }
    }
  }

  /**
   * @notice Returns the threshold, weight, root, and checkpoint of a signature.
   * @dev To verify the signature, the weight must be greater than or equal to the threshold, and the root
   *      must match the expected `imageHash` of the wallet.
   *
   * @param _subdigest The digest to verify the signature against.
   * @param _signature The signature to recover.
   * @return threshold The minimum weight required for the signature to be valid.
   * @return weight The total weight of the recovered signatures.
   * @return imageHash The root hash of the recovered configuration
   * @return checkpoint The checkpoint of the signature.
   */
  function recover(
    bytes32 _subdigest,
    bytes calldata _signature
  ) internal view returns (
    uint256 threshold,
    uint256 weight,
    bytes32 imageHash,
    uint256 checkpoint
  ) {
    unchecked {
      (weight, imageHash) = recoverBranch(_subdigest, _signature[6:]);

      // Threshold & checkpoint are the top nodes
      // (but they are first on the signature)
      threshold = LibBytes.readFirstUint16(_signature);
      checkpoint = LibBytes.readUint32(_signature, 2);

      imageHash = LibOptim.fkeccak256(imageHash, bytes32(threshold));
      imageHash = LibOptim.fkeccak256(imageHash, bytes32(checkpoint));
    }
  }
}

File 15 of 22 : SequenceChainedSig.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "./SequenceBaseSig.sol";

import "../../interfaces/IModuleAuth.sol";

import "../../ModuleSelfAuth.sol";
import "../../ModuleStorage.sol";

import "../../../../utils/LibBytesPointer.sol";
import "../../../../utils/LibOptim.sol";

/**
 * @title Sequence chained auth recovery submodule
 * @author Agustin Aguilar ([email protected])
 * @notice Defines Sequence signatures that work by delegating control to new configurations.
 * @dev The delegations can be chained together, the first signature is the one that is used to validate
 *      the message, the last signature must match the current on-chain configuration of the wallet.
 */
abstract contract SequenceChainedSig is IModuleAuth, ModuleSelfAuth {
  using LibBytesPointer for bytes;

  bytes32 public constant SET_IMAGE_HASH_TYPE_HASH = keccak256("SetImageHash(bytes32 imageHash)");

  error LowWeightChainedSignature(bytes _signature, uint256 threshold, uint256 _weight);
  error WrongChainedCheckpointOrder(uint256 _current, uint256 _prev);

  /**
   * @notice Defined the special token that must be signed to delegate control to a new configuration.
   * @param _imageHash The hash of the new configuration.
   * @return bytes32 The message hash to be signed.
   */
  function _hashSetImageHashStruct(bytes32 _imageHash) internal pure returns (bytes32) {
    return LibOptim.fkeccak256(SET_IMAGE_HASH_TYPE_HASH, _imageHash);
  }

  /**
   * @notice Returns the threshold, weight, root, and checkpoint of a (chained) signature.
   * 
   * @dev This method return the `threshold`, `weight` and `imageHash` of the last signature in the chain.
   *      Intermediate signatures are validated directly in this method. The `subdigest` is the one of the
   *      first signature in the chain (since that's the one that is used to validate the message).
   *
   * @param _digest The digest to recover the signature from.
   * @param _signature The signature to recover.
   * @return threshold The threshold of the (last) signature.
   * @return weight The weight of the (last) signature.
   * @return imageHash The image hash of the (last) signature.
   * @return subdigest The subdigest of the (first) signature in the chain.
   * @return checkpoint The checkpoint of the (last) signature.
   */
  function chainedRecover(
    bytes32 _digest,
    bytes calldata _signature
  ) internal view returns (
    uint256 threshold,
    uint256 weight,
    bytes32 imageHash,
    bytes32 subdigest,
    uint256 checkpoint
  ) {
    uint256 rindex = 1;
    uint256 sigSize;

    //
    // First signature out of the loop
    //

    // First uint24 is the size of the signature
    (sigSize, rindex) = _signature.readUint24(rindex);
    uint256 nrindex = sigSize + rindex;

    (
      threshold,
      weight,
      imageHash,
      subdigest,
      checkpoint
    ) = signatureRecovery(
      _digest,
      _signature[rindex:nrindex]
    );

    if (weight < threshold) {
      revert LowWeightChainedSignature(_signature[rindex:nrindex], threshold, weight);
    }

    rindex = nrindex;

    // The following signatures are handled by this loop.
    // This is done this way because the first signature does not have a
    // checkpoint to be validated against.
    while (rindex < _signature.length) {
      // First uint24 is the size of the signature
      (sigSize, rindex) = _signature.readUint24(rindex);
      nrindex = sigSize + rindex;

      uint256 nextCheckpoint;

      (
        threshold,
        weight,
        imageHash,,
        // Do not change the subdigest;
        // it should remain that of the first signature.
        nextCheckpoint
      ) = signatureRecovery(
        _hashSetImageHashStruct(imageHash),
        _signature[rindex:nrindex]
      );

      // Validate signature
      if (weight < threshold) {
        revert LowWeightChainedSignature(_signature[rindex:nrindex], threshold, weight);
      }

      // Checkpoints must be provided in descending order
      // since the first signature is the one that is used to validate the message
      // and the last signature is the one that is used to validate the current configuration
      if (nextCheckpoint >= checkpoint) {
        revert WrongChainedCheckpointOrder(nextCheckpoint, checkpoint);
      }

      checkpoint = nextCheckpoint;
      rindex = nrindex;
    }
  }
}

File 16 of 22 : SequenceDynamicSig.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "./SequenceBaseSig.sol";


library SequenceDynamicSig {

  /**
   * @notice Recover a "dynamically encoded" Sequence signature.
   * @dev The Signature is stripped of the first byte, which is the encoding flag.
   *
   * @param _subdigest The digest of the signature.
   * @param _signature The Sequence signature.
   * @return threshold The threshold weight required to validate the signature.
   * @return weight The weight of the signature.
   * @return imageHash The hash of the recovered configuration.
   * @return checkpoint The checkpoint of the configuration.
   */
  function recover(
    bytes32 _subdigest,
    bytes calldata _signature
  ) internal view returns (
    uint256 threshold,
    uint256 weight,
    bytes32 imageHash,
    uint256 checkpoint
  ) {
    return SequenceBaseSig.recover(_subdigest, _signature[1:]);
  }
}

File 17 of 22 : SequenceNoChainIdSig.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


library SequenceNoChainIdSig {

  /**
   * @notice Computes a subdigest for a Sequence signature that works on all chains.
   * @dev The subdigest is computed by removing the chain ID from the digest (using 0 instead).
   * @param _digest The digest of the chain of signatures.
   * @return bytes32 The subdigest with no chain ID.
   */
  function subdigest(bytes32 _digest) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        uint256(0),
        address(this),
        _digest
      )
    );
  }
}

File 18 of 22 : SubModuleNonce.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


library SubModuleNonce {
  // Nonce schema
  //
  // - space[160]:nonce[96]
  //
  uint256 internal constant NONCE_BITS = 96;
  bytes32 internal constant NONCE_MASK = bytes32(uint256(type(uint96).max));

  /**
   * @notice Decodes a raw nonce
   * @dev Schema: space[160]:type[96]
   * @param _rawNonce Nonce to be decoded
   * @return _space The nonce space of the raw nonce
   * @return _nonce The nonce of the raw nonce
   */
  function decodeNonce(uint256 _rawNonce) internal pure returns (
    uint256 _space,
    uint256 _nonce
  ) {
    unchecked {
      // Decode nonce
      _space = _rawNonce >> NONCE_BITS;
      _nonce = uint256(bytes32(_rawNonce) & NONCE_MASK);
    }
  }
}

File 19 of 22 : LibBytes.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


/**
 * @title Library for reading data from bytes arrays
 * @author Agustin Aguilar ([email protected])
 * @notice This library contains functions for reading data from bytes arrays.
 *
 * @dev These functions do not check if the input index is within the bounds of the data array.
 *         Reading out of bounds may return dirty values.
 */
library LibBytes {

  /**
   * @notice Returns the bytes32 value at the given index in the input data.
   * @param data The input data.
   * @param index The index of the value to retrieve.
   * @return a The bytes32 value at the given index.
   */
  function readBytes32(
    bytes calldata data,
    uint256 index
  ) internal pure returns (
    bytes32 a
  ) {
    assembly {
      a := calldataload(add(data.offset, index))
    }
  }

  /**
   * @notice Returns the uint8 value at the given index in the input data.
   * @param data The input data.
   * @param index The index of the value to retrieve.
   * @return a The uint8 value at the given index.
   */
  function readUint8(
    bytes calldata data,
    uint256 index
  ) internal pure returns (
    uint8 a
  ) {
    assembly {
      let word := calldataload(add(index, data.offset))
      a := shr(248, word)
    }
  }

  /**
   * @notice Returns the first uint16 value in the input data.
   * @param data The input data.
   * @return a The first uint16 value in the input data.
   */
  function readFirstUint16(
    bytes calldata data
  ) internal pure returns (
    uint16 a
  ) {
    assembly {
      let word := calldataload(data.offset)
      a := shr(240, word)
    }
  }

  /**
   * @notice Returns the uint32 value at the given index in the input data.
   * @param data The input data.
   * @param index The index of the value to retrieve.
   * @return a The uint32 value at the given index.
   */
  function readUint32(
    bytes calldata data,
    uint256 index
  ) internal pure returns (
    uint32 a
  ) {
    assembly {
      let word := calldataload(add(index, data.offset))
      a := shr(224, word)
    }
  }
}

File 20 of 22 : LibBytesPointer.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;


/**
 * @title Library for reading data from bytes arrays with a pointer
 * @author Agustin Aguilar ([email protected])
 * @notice This library contains functions for reading data from bytes arrays with a pointer.
 *
 * @dev These functions do not check if the input index is within the bounds of the data array.
 *         Reading out of bounds may return dirty values.
 */
library LibBytesPointer {

  /**
   * @dev Returns the first uint16 value in the input data and updates the pointer.
   * @param _data The input data.
   * @return a The first uint16 value.
   * @return newPointer The new pointer.
   */
  function readFirstUint16(
    bytes calldata _data
  ) internal pure returns (
    uint16 a,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(_data.offset)
      a := shr(240, word)
      newPointer := 2
    }
  }

  /**
   * @notice Returns the uint8 value at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _index The index of the value to retrieve.
   * @return a The uint8 value at the given index.
   * @return newPointer The new pointer.
   */
  function readUint8(
    bytes calldata _data,
    uint256 _index
  ) internal pure returns (
    uint8 a,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(add(_index, _data.offset))
      a := shr(248, word)
      newPointer := add(_index, 1)
    }
  }

  /**
   * @notice Returns the uint8 value and the address at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _index The index of the value to retrieve.
   * @return a The uint8 value at the given index.
   * @return b The following address value.
   * @return newPointer The new pointer.
   */
  function readUint8Address(
    bytes calldata _data,
    uint256 _index
  ) internal pure returns (
    uint8 a,
    address b,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(add(_index, _data.offset))
      a := shr(248, word)
      b := and(shr(88, word), 0xffffffffffffffffffffffffffffffffffffffff)
      newPointer := add(_index, 21)
    }
  }

  /**
   * @notice Returns the uint16 value at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _index The index of the value to retrieve.
   * @return a The uint16 value at the given index.
   * @return newPointer The new pointer.
   */
  function readUint16(
    bytes calldata _data,
    uint256 _index
  ) internal pure returns (
    uint16 a,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(add(_index, _data.offset))
      a := and(shr(240, word), 0xffff)
      newPointer := add(_index, 2)
    }
  }

  /**
   * @notice Returns the uint24 value at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _index The index of the value to retrieve.
   * @return a The uint24 value at the given index.
   * @return newPointer The new pointer.
   */
  function readUint24(
    bytes calldata _data,
    uint256 _index
  ) internal pure returns (
    uint24 a,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(add(_index, _data.offset))
      a := and(shr(232, word), 0xffffff)
      newPointer := add(_index, 3)
    }
  }

  /**
   * @notice Returns the uint64 value at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _index The index of the value to retrieve.
   * @return a The uint64 value at the given index.
   * @return newPointer The new pointer.
   */
  function readUint64(
    bytes calldata _data,
    uint256 _index
  ) internal pure returns (
    uint64 a,
    uint256 newPointer
  ) {
    assembly {
      let word := calldataload(add(_index, _data.offset))
      a := and(shr(192, word), 0xffffffffffffffff)
      newPointer := add(_index, 8)
    }
  }

  /**
   * @notice Returns the bytes32 value at the given index in the input data and updates the pointer.
   * @param _data The input data.
   * @param _pointer The index of the value to retrieve.
   * @return a The bytes32 value at the given index.
   * @return newPointer The new pointer.
   */
  function readBytes32(
    bytes calldata _data,
    uint256 _pointer
  ) internal pure returns (
    bytes32 a,
    uint256 newPointer
  ) {
    assembly {
      a := calldataload(add(_pointer, _data.offset))
      newPointer := add(_pointer, 32)
    }
  }
}

File 21 of 22 : LibOptim.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

/**
 * @title Library for optimized EVM operations
 * @author Agustin Aguilar ([email protected])
 * @notice This library contains functions for optimizing certain EVM operations.
 */
library LibOptim {

  /**
   * @notice Computes the keccak256 hash of two 32-byte inputs.
   * @dev It uses only scratch memory space.
   * @param _a The first 32 bytes of the hash.
   * @param _b The second 32 bytes of the hash.
   * @return c The keccak256 hash of the two 32-byte inputs.
   */
  function fkeccak256(
    bytes32 _a,
    bytes32 _b
  ) internal pure returns (bytes32 c) {
    assembly {
      mstore(0, _a)
      mstore(32, _b)
      c := keccak256(0, 64)
    }
  }

  /**
   * @notice Returns the return data from the last call.
   * @return r The return data from the last call.
   */
  function returnData() internal pure returns (bytes memory r) {
    assembly {
      let size := returndatasize()
      r := mload(0x40)
      let start := add(r, 32)
      mstore(0x40, add(start, size))
      mstore(r, size)
      returndatacopy(start, 0, size)
    }
  }

  /**
   * @notice Calls another contract with the given parameters.
   * @dev This method doesn't increase the memory pointer.
   * @param _to The address of the contract to call.
   * @param _val The value to send to the contract.
   * @param _gas The amount of gas to provide for the call.
   * @param _data The data to send to the contract.
   * @return r The success status of the call.
   */
  function call(
    address _to,
    uint256 _val,
    uint256 _gas,
    bytes calldata _data
  ) internal returns (bool r) {
    assembly {
      let tmp := mload(0x40)
      calldatacopy(tmp, _data.offset, _data.length)

      r := call(
        _gas,
        _to,
        _val,
        tmp,
        _data.length,
        0,
        0
      )
    }
  }

  /**
   * @notice Calls another contract with the given parameters, using delegatecall.
   * @dev This method doesn't increase the memory pointer.
   * @param _to The address of the contract to call.
   * @param _gas The amount of gas to provide for the call.
   * @param _data The data to send to the contract.
   * @return r The success status of the call.
   */
  function delegatecall(
    address _to,
    uint256 _gas,
    bytes calldata _data
  ) internal returns (bool r) {
    assembly {
      let tmp := mload(0x40)
      calldatacopy(tmp, _data.offset, _data.length)

      r := delegatecall(
        _gas,
        _to,
        tmp,
        _data.length,
        0,
        0
      )
    }
  }
}

File 22 of 22 : SignatureValidator.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;

import "../interfaces/IERC1271Wallet.sol";

import "./LibBytes.sol";

/**
 * @dev Contains logic for signature validation.
 * Signatures from wallet contracts assume ERC-1271 support (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md)
 * Notes: Methods are strongly inspired by contracts in https://github.com/0xProject/0x-monorepo/blob/development/
 */
library SignatureValidator {
  // Errors
  error InvalidSignatureLength(bytes _signature);
  error EmptySignature();
  error InvalidSValue(bytes _signature, bytes32 _s);
  error InvalidVValue(bytes _signature, uint256 _v);
  error UnsupportedSignatureType(bytes _signature, uint256 _type, bool _recoverMode);
  error SignerIsAddress0(bytes _signature);

  using LibBytes for bytes;

  /***********************************|
  |             Variables             |
  |__________________________________*/

  // bytes4(keccak256("isValidSignature(bytes,bytes)"))
  bytes4 constant internal ERC1271_MAGICVALUE = 0x20c13b0b;

  // bytes4(keccak256("isValidSignature(bytes32,bytes)"))
  bytes4 constant internal ERC1271_MAGICVALUE_BYTES32 = 0x1626ba7e;

  // Allowed signature types.
  uint256 private constant SIG_TYPE_EIP712 = 1;
  uint256 private constant SIG_TYPE_ETH_SIGN = 2;
  uint256 private constant SIG_TYPE_WALLET_BYTES32 = 3;

  /***********************************|
  |        Signature Functions        |
  |__________________________________*/

 /**
   * @notice Recover the signer of hash, assuming it's an EOA account
   * @dev Only for SignatureType.EIP712 and SignatureType.EthSign signatures
   * @param _hash      Hash that was signed
   *   encoded as (bytes32 r, bytes32 s, uint8 v, ... , SignatureType sigType)
   */
  function recoverSigner(
    bytes32 _hash,
    bytes calldata _signature
  ) internal pure returns (address signer) {
    if (_signature.length != 66) revert InvalidSignatureLength(_signature);
    uint256 signatureType = _signature.readUint8(_signature.length - 1);

    // Variables are not scoped in Solidity.
    uint8 v = _signature.readUint8(64);
    bytes32 r = _signature.readBytes32(0);
    bytes32 s = _signature.readBytes32(32);

    // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
    // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
    // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
    // signatures from current libraries generate a unique signature with an s-value in the lower half order.
    //
    // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
    // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
    // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
    // these malleable signatures as well.
    //
    // Source OpenZeppelin
    // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol

    if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
      revert InvalidSValue(_signature, s);
    }

    if (v != 27 && v != 28) {
      revert InvalidVValue(_signature, v);
    }

    // Signature using EIP712
    if (signatureType == SIG_TYPE_EIP712) {
      signer = ecrecover(_hash, v, r, s);

    // Signed using web3.eth_sign() or Ethers wallet.signMessage()
    } else if (signatureType == SIG_TYPE_ETH_SIGN) {
      signer = ecrecover(
        keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)),
        v,
        r,
        s
      );

    } else {
      // We cannot recover the signer for any other signature type.
      revert UnsupportedSignatureType(_signature, signatureType, true);
    }

    // Prevent signer from being 0x0
    if (signer == address(0x0)) revert SignerIsAddress0(_signature);

    return signer;
  }

 /**
   * @notice Returns true if the provided signature is valid for the given signer.
   * @dev Supports SignatureType.EIP712, SignatureType.EthSign, and ERC1271 signatures
   * @param _hash      Hash that was signed
   * @param _signer    Address of the signer candidate
   * @param _signature Signature byte array
   */
  function isValidSignature(
    bytes32 _hash,
    address _signer,
    bytes calldata _signature
  ) internal view returns (bool valid) {
    if (_signature.length == 0) {
      revert EmptySignature();
    }

    uint256 signatureType = uint8(_signature[_signature.length - 1]);
    if (signatureType == SIG_TYPE_EIP712 || signatureType == SIG_TYPE_ETH_SIGN) {
      // Recover signer and compare with provided
      valid = recoverSigner(_hash, _signature) == _signer;

    } else if (signatureType == SIG_TYPE_WALLET_BYTES32) {
      // Remove signature type before calling ERC1271, restore after call
      valid = ERC1271_MAGICVALUE_BYTES32 == IERC1271Wallet(_signer).isValidSignature(_hash, _signature[0:_signature.length - 1]);

    } else {
      // We cannot validate any other signature type.
      // We revert because we can say nothing about its validity.
      revert UnsupportedSignatureType(_signature, signatureType, false);
    }
  }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"_space","type":"uint256"},{"internalType":"uint256","name":"_provided","type":"uint256"},{"internalType":"uint256","name":"_current","type":"uint256"}],"name":"BadNonce","type":"error"},{"inputs":[{"internalType":"bytes","name":"_code","type":"bytes"}],"name":"CreateFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"DelegateCallNotAllowed","type":"error"},{"inputs":[],"name":"EmptySignature","type":"error"},{"inputs":[],"name":"ImageHashIsZero","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"address","name":"_addr","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"InvalidNestedSignature","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"InvalidSValue","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"_flag","type":"uint256"}],"name":"InvalidSignatureFlag","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"InvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes1","name":"_type","type":"bytes1"}],"name":"InvalidSignatureType","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_v","type":"uint256"}],"name":"InvalidVValue","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"_weight","type":"uint256"}],"name":"LowWeightChainedSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_requested","type":"uint256"},{"internalType":"uint256","name":"_available","type":"uint256"}],"name":"NotEnoughGas","type":"error"},{"inputs":[],"name":"NotSupported","type":"error"},{"inputs":[],"name":"OnlyDelegatecall","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_self","type":"address"}],"name":"OnlySelfAuth","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"SignerIsAddress0","type":"error"},{"inputs":[{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"uint256","name":"_type","type":"uint256"},{"internalType":"bool","name":"_recoverMode","type":"bool"}],"name":"UnsupportedSignatureType","type":"error"},{"inputs":[{"internalType":"uint256","name":"_current","type":"uint256"},{"internalType":"uint256","name":"_prev","type":"uint256"}],"name":"WrongChainedCheckpointOrder","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_contract","type":"address"}],"name":"CreatedContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"newImageHash","type":"bytes32"}],"name":"ImageHashUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_space","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newNonce","type":"uint256"}],"name":"NonceChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_tx","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_index","type":"uint256"}],"name":"TxExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_tx","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_index","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"TxFailed","type":"event"},{"inputs":[],"name":"SET_IMAGE_HASH_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_code","type":"bytes"}],"name":"createContract","outputs":[{"internalType":"address","name":"addr","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"delegateCall","type":"bool"},{"internalType":"bool","name":"revertOnError","type":"bool"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IModuleCalls.Transaction[]","name":"_txs","type":"tuple[]"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signatures","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_signatures","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_space","type":"uint256"}],"name":"readNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"delegateCall","type":"bool"},{"internalType":"bool","name":"revertOnError","type":"bool"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IModuleCalls.Transaction[]","name":"_txs","type":"tuple[]"}],"name":"selfExecute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_digest","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"signatureRecovery","outputs":[{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"bytes32","name":"imageHash","type":"bytes32"},{"internalType":"bytes32","name":"subdigest","type":"bytes32"},{"internalType":"uint256","name":"checkpoint","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_imageHash","type":"bytes32"}],"name":"updateImageHash","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801561001057600080fd5b50306080526080516121de61002d600039600050506121de6000f3fe6080604052600436106100bc5760003560e01c806361c2926c116100745780638c3f55631161004e5780638c3f55631461025357806390042baf14610273578063affed0e0146102ab57600080fd5b806361c2926c146101cb5780637a9a1628146101eb578063853c50681461020b57600080fd5b806320c13b0b116100a557806320c13b0b14610147578063295614261461016757806357c56d6b1461018957600080fd5b806301ffc9a7146100c15780631626ba7e146100f6575b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611880565b6102c0565b60405190151581526020015b60405180910390f35b34801561010257600080fd5b506101166101113660046118e6565b6102d1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100ed565b34801561015357600080fd5b50610116610162366004611932565b61031e565b34801561017357600080fd5b5061018761018236600461199e565b610383565b005b34801561019557600080fd5b506101bd7f8713a7c4465f6fbee2b6e9d6646d1d9f83fec929edfc4baf661f3c865bdd04d181565b6040519081526020016100ed565b3480156101d757600080fd5b506101876101e63660046119fc565b6103d5565b3480156101f757600080fd5b50610187610206366004611a3e565b61041a565b34801561021757600080fd5b5061022b6102263660046118e6565b610447565b604080519586526020860194909452928401919091526060830152608082015260a0016100ed565b34801561025f57600080fd5b506101bd61026e36600461199e565b61060f565b610286610281366004611ae7565b61063b565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b3480156102b757600080fd5b506101bd610725565b60006102cb82610736565b92915050565b6000806102df858585610792565b509050801561031157507f1626ba7e000000000000000000000000000000000000000000000000000000009050610317565b50600090505b9392505050565b6000806103438686604051610334929190611bb6565b60405180910390208585610792565b509050801561037557507f20c13b0b00000000000000000000000000000000000000000000000000000000905061037b565b50600090505b949350505050565b3330146103c9576040517fe12588940000000000000000000000000000000000000000000000000000000081523360048201523060248201526044015b60405180910390fd5b6103d2816107ca565b50565b600061040883836040516020016103ed929190611d97565b604051602081830303815290604052805190602001206107fc565b9050610415818484610881565b505050565b600061043286866040516020016103ed929190611ddf565b905061043f818787610881565b505050505050565b6000806000806000808787600081811061046357610463611e27565b909101357fff000000000000000000000000000000000000000000000000000000000000001691508190506104b95761049b896107fc565b92506104a8838989610a0e565b929850909650945091506106049050565b7fff00000000000000000000000000000000000000000000000000000000000000818116016104f8576104eb896107fc565b92506104a8838989610a5f565b7ffe000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000082160161054a576104eb89610a8b565b7ffd000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216016105ae5761059e898989610af8565b9550955095509550955050610604565b6040517f6085cd820000000000000000000000000000000000000000000000000000000081527fff00000000000000000000000000000000000000000000000000000000000000821660048201526024016103c0565b939792965093509350565b60006102cb7f8d0bf1fd623d628c741362c1289948e57b3e2905218c676d3e69abee36d6ae2e83610c75565b600033301461067e576040517fe12588940000000000000000000000000000000000000000000000000000000081523360048201523060248201526044016103c0565b81516020830134f0905073ffffffffffffffffffffffffffffffffffffffff81166106d757816040517f0d2571910000000000000000000000000000000000000000000000000000000081526004016103c09190611eba565b60405173ffffffffffffffffffffffffffffffffffffffff821681527fa506ad4e7f05eceba62a023c3219e5bd98a615f4fa87e2afb08a2da5cf62bf0c9060200160405180910390a1919050565b6000610731600061060f565b905090565b60007f6ffbd451000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161078957506001919050565b6102cb82610cd3565b60008060008060006107a5888888610447565b509650919450925090508282108015906107bd575060015b9450505050935093915050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f190100000000000000000000000000000000000000000000000000000000000060208201524660228201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b166042820152605681018290526000906076015b604051602081830303815290604052805190602001209050919050565b8060005b81811015610a0757368484838181106108a0576108a0611e27565b90506020028101906108b29190611ecd565b90506108c16020820182611f0b565b156108fb576040517f230d1ccc000000000000000000000000000000000000000000000000000000008152600481018390526024016103c0565b6040810135805a101561094e5782815a6040517f2bb3e3ba0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016103c0565b60006109886109636080850160608601611f26565b608085013584156109745784610976565b5a5b61098360a0880188611f41565b610d2f565b905080156109cf57877f5c4eeb02dabf8976016ab414d617f9a162936dcace3cdef8c69ef6e262ad5ae7856040516109c291815260200190565b60405180910390a26109f1565b6109f16109e26040850160208601611f0b565b89866109ec610d4c565b610d6b565b50505080806109ff90611fd5565b915050610885565b5050505050565b6000808080610a2987610a24876006818b61200d565b610db9565b6000908152873560f01c6020818152604080842084526002909a013560e01c908190529890912090999198509695509350505050565b6000808080610a7a87610a75876001818b61200d565b610a0e565b935093509350935093509350935093565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526000602282018190527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660428301526056820183905290607601610864565b6000808080806004600188013560e81c82610b138383612037565b9050610b258b61022683868d8f61200d565b939b5091995097509550935087871015610b7d57610b4581848b8d61200d565b89896040517fb006aba00000000000000000000000000000000000000000000000000000000081526004016103c0949392919061204a565b8092505b88831015610c675760038301928a013560e81c9150610ba08383612037565b90506000610bc2610bb08861124f565b8c8c879086926102269392919061200d565b939c50919a5098509091505088881015610c1a57610be282858c8e61200d565b8a8a6040517fb006aba00000000000000000000000000000000000000000000000000000000081526004016103c0949392919061204a565b848110610c5d576040517f37daf62b00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016103c0565b9350915081610b81565b505050939792965093509350565b6000808383604051602001610c94929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012054949350505050565b60007fe4a77bbc000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610d2657506001919050565b6102cb82611283565b6000604051828482376000808483898b8af1979650505050505050565b60603d604051915060208201818101604052818352816000823e505090565b8315610d7957805160208201fd5b827fab46c69f7f32e1bf09b0725853da82a211e5402a0600296ab499a2fb5ea3b4198383604051610dab929190612071565b60405180910390a250505050565b60008060005b8381101561124657600181019085013560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101610e6057601582019186013560f881901c9060581c73ffffffffffffffffffffffffffffffffffffffff81169074ff000000000000000000000000000000000000000016811785610e465780610e55565b60008681526020829052604090205b955050505050610dbf565b80610ef65760018201918681013560f81c906043016000610e8c8a610e8784888c8e61200d565b61136d565b60ff841697909701969194508491905060a083901b74ff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff82161786610edb5780610eea565b60008781526020829052604090205b96505050505050610dbf565b6002810361101e576000808784013560f881901c9060581c73ffffffffffffffffffffffffffffffffffffffff16601586019550909250905060008885013560e81c600386018162ffffff169150809650819250505060008186019050610f6f8b848c8c8a908692610f6a9392919061200d565b611630565b610fb7578a83610f8183898d8f61200d565b6040517f9a9462320000000000000000000000000000000000000000000000000000000081526004016103c0949392919061208a565b60ff8416979097019694508460a084901b74ff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617876110025780611011565b60008881526020829052604090205b9750505050505050610dbf565b60038103611051576020820191860135836110395780611048565b60008481526020829052604090205b93505050610dbf565b6004810361109d576003808301928781013560e81c919082010160008061107e8b610a2485898d8f61200d565b60009889526020526040909720969097019650909350610dbf92505050565b600681036111a55760008287013560f81c60018401935060ff16905060008784013560f01c60028501945061ffff16905060008885013560e81c600386018162ffffff16915080965081925050506000818601905060008061110b8d8d8d8b908792610a249392919061200d565b9398508893909250905084821061112157988501985b604080517f53657175656e6365206e657374656420636f6e6669673a0a0000000000000000602080830191909152603882018490526058820188905260788083018a90528351808403909101815260989092019092528051910120896111875780611196565b60008a81526020829052604090205b99505050505050505050610dbf565b600581036112115760208201918601358781036111e0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b60006111eb82611817565b9050846111f85780611207565b60008581526020829052604090205b9450505050610dbf565b6040517fb2505f7c000000000000000000000000000000000000000000000000000000008152600481018290526024016103c0565b50935093915050565b7f8713a7c4465f6fbee2b6e9d6646d1d9f83fec929edfc4baf661f3c865bdd04d160009081526020829052604081206102cb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fac6a444e00000000000000000000000000000000000000000000000000000000148061131657507fffffffff0000000000000000000000000000000000000000000000000000000082167f36e7817500000000000000000000000000000000000000000000000000000000145b1561132357506001919050565b7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146102cb565b6000604282146113ad5782826040517f2ee17a3d0000000000000000000000000000000000000000000000000000000081526004016103c09291906120ca565b60006113c66113bd6001856120de565b85013560f81c90565b60ff169050604084013560f81c843560208601357f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a081111561143a578686826040517fad4aac760000000000000000000000000000000000000000000000000000000081526004016103c0939291906120f1565b8260ff16601b1415801561145257508260ff16601c14155b1561148f578686846040517fe578897e0000000000000000000000000000000000000000000000000000000081526004016103c093929190612115565b600184036114fc576040805160008152602081018083528a905260ff851691810191909152606081018390526080810182905260019060a0015b6020604051602081039080840390855afa1580156114eb573d6000803e3d6000fd5b5050506020604051035194506115d4565b60028403611599576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101899052600190605c01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff861690820152606081018490526080810183905260a0016114c9565b86868560016040517f9dfba8520000000000000000000000000000000000000000000000000000000081526004016103c0949392919061213c565b73ffffffffffffffffffffffffffffffffffffffff85166116255786866040517f6c1719d20000000000000000000000000000000000000000000000000000000081526004016103c09291906120ca565b505050509392505050565b600081810361166b576040517fac241e1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838361167a6001826120de565b81811061168957611689611e27565b919091013560f81c91505060018114806116a35750600281145b156116e8578473ffffffffffffffffffffffffffffffffffffffff166116ca87868661136d565b73ffffffffffffffffffffffffffffffffffffffff1614915061180e565b600381036117d35773ffffffffffffffffffffffffffffffffffffffff8516631626ba7e878660008761171c6001826120de565b926117299392919061200d565b6040518463ffffffff1660e01b815260040161174793929190612168565b602060405180830381865afa158015611764573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611788919061218b565b7fffffffff00000000000000000000000000000000000000000000000000000000167f1626ba7e0000000000000000000000000000000000000000000000000000000014915061180e565b83838260006040517f9dfba8520000000000000000000000000000000000000000000000000000000081526004016103c0949392919061213c565b50949350505050565b6040517f53657175656e636520737461746963206469676573743a0a0000000000000000602082015260388101829052600090605801610864565b7fffffffff00000000000000000000000000000000000000000000000000000000811681146103d257600080fd5b60006020828403121561189257600080fd5b813561031781611852565b60008083601f8401126118af57600080fd5b50813567ffffffffffffffff8111156118c757600080fd5b6020830191508360208285010111156118df57600080fd5b9250929050565b6000806000604084860312156118fb57600080fd5b83359250602084013567ffffffffffffffff81111561191957600080fd5b6119258682870161189d565b9497909650939450505050565b6000806000806040858703121561194857600080fd5b843567ffffffffffffffff8082111561196057600080fd5b61196c8883890161189d565b9096509450602087013591508082111561198557600080fd5b506119928782880161189d565b95989497509550505050565b6000602082840312156119b057600080fd5b5035919050565b60008083601f8401126119c957600080fd5b50813567ffffffffffffffff8111156119e157600080fd5b6020830191508360208260051b85010111156118df57600080fd5b60008060208385031215611a0f57600080fd5b823567ffffffffffffffff811115611a2657600080fd5b611a32858286016119b7565b90969095509350505050565b600080600080600060608688031215611a5657600080fd5b853567ffffffffffffffff80821115611a6e57600080fd5b611a7a89838a016119b7565b9097509550602088013594506040880135915080821115611a9a57600080fd5b50611aa78882890161189d565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215611af957600080fd5b813567ffffffffffffffff80821115611b1157600080fd5b818401915084601f830112611b2557600080fd5b813581811115611b3757611b37611ab8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611b7d57611b7d611ab8565b81604052828152876020848701011115611b9657600080fd5b826020860160208301376000928101602001929092525095945050505050565b8183823760009101908152919050565b80358015158114611bd657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bd657600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b81835260006020808501808196508560051b810191508460005b87811015611d8a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41883603018112611ca157600080fd5b870160c0611cae82611bc6565b15158652611cbd878301611bc6565b15158688015260408281013590870152606073ffffffffffffffffffffffffffffffffffffffff611cef828501611bdb565b16908701526080828101359087015260a080830135368490037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112611d3557600080fd5b90920187810192903567ffffffffffffffff811115611d5357600080fd5b803603841315611d6257600080fd5b8282890152611d748389018286611bff565b9c89019c97505050928601925050600101611c62565b5091979650505050505050565b60408152600560408201527f73656c663a000000000000000000000000000000000000000000000000000000606082015260806020820152600061037b608083018486611c48565b60408152600660408201527f67756573743a0000000000000000000000000000000000000000000000000000606082015260806020820152600061037b608083018486611c48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815180845260005b81811015611e7c57602081850181015186830182015201611e60565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006103176020830184611e56565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41833603018112611f0157600080fd5b9190910192915050565b600060208284031215611f1d57600080fd5b61031782611bc6565b600060208284031215611f3857600080fd5b61031782611bdb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611f7657600080fd5b83018035915067ffffffffffffffff821115611f9157600080fd5b6020019150368190038213156118df57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361200657612006611fa6565b5060010190565b6000808585111561201d57600080fd5b8386111561202a57600080fd5b5050820193919092039150565b808201808211156102cb576102cb611fa6565b60608152600061205e606083018688611bff565b6020830194909452506040015292915050565b82815260406020820152600061037b6040830184611e56565b84815273ffffffffffffffffffffffffffffffffffffffff841660208201526060604082015260006120c0606083018486611bff565b9695505050505050565b60208152600061037b602083018486611bff565b818103818111156102cb576102cb611fa6565b604081526000612105604083018587611bff565b9050826020830152949350505050565b604081526000612129604083018587611bff565b905060ff83166020830152949350505050565b606081526000612150606083018688611bff565b60208301949094525090151560409091015292915050565b838152604060208201526000612182604083018486611bff565b95945050505050565b60006020828403121561219d57600080fd5b81516103178161185256fea26469706673582212200896636ab1dae9ad33c5080d1044c3c12105a6d4bc196fd0009bf12ed3b0f85364736f6c63430008120033

Deployed Bytecode

0x6080604052600436106100bc5760003560e01c806361c2926c116100745780638c3f55631161004e5780638c3f55631461025357806390042baf14610273578063affed0e0146102ab57600080fd5b806361c2926c146101cb5780637a9a1628146101eb578063853c50681461020b57600080fd5b806320c13b0b116100a557806320c13b0b14610147578063295614261461016757806357c56d6b1461018957600080fd5b806301ffc9a7146100c15780631626ba7e146100f6575b600080fd5b3480156100cd57600080fd5b506100e16100dc366004611880565b6102c0565b60405190151581526020015b60405180910390f35b34801561010257600080fd5b506101166101113660046118e6565b6102d1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100ed565b34801561015357600080fd5b50610116610162366004611932565b61031e565b34801561017357600080fd5b5061018761018236600461199e565b610383565b005b34801561019557600080fd5b506101bd7f8713a7c4465f6fbee2b6e9d6646d1d9f83fec929edfc4baf661f3c865bdd04d181565b6040519081526020016100ed565b3480156101d757600080fd5b506101876101e63660046119fc565b6103d5565b3480156101f757600080fd5b50610187610206366004611a3e565b61041a565b34801561021757600080fd5b5061022b6102263660046118e6565b610447565b604080519586526020860194909452928401919091526060830152608082015260a0016100ed565b34801561025f57600080fd5b506101bd61026e36600461199e565b61060f565b610286610281366004611ae7565b61063b565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b3480156102b757600080fd5b506101bd610725565b60006102cb82610736565b92915050565b6000806102df858585610792565b509050801561031157507f1626ba7e000000000000000000000000000000000000000000000000000000009050610317565b50600090505b9392505050565b6000806103438686604051610334929190611bb6565b60405180910390208585610792565b509050801561037557507f20c13b0b00000000000000000000000000000000000000000000000000000000905061037b565b50600090505b949350505050565b3330146103c9576040517fe12588940000000000000000000000000000000000000000000000000000000081523360048201523060248201526044015b60405180910390fd5b6103d2816107ca565b50565b600061040883836040516020016103ed929190611d97565b604051602081830303815290604052805190602001206107fc565b9050610415818484610881565b505050565b600061043286866040516020016103ed929190611ddf565b905061043f818787610881565b505050505050565b6000806000806000808787600081811061046357610463611e27565b909101357fff000000000000000000000000000000000000000000000000000000000000001691508190506104b95761049b896107fc565b92506104a8838989610a0e565b929850909650945091506106049050565b7fff00000000000000000000000000000000000000000000000000000000000000818116016104f8576104eb896107fc565b92506104a8838989610a5f565b7ffe000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000082160161054a576104eb89610a8b565b7ffd000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216016105ae5761059e898989610af8565b9550955095509550955050610604565b6040517f6085cd820000000000000000000000000000000000000000000000000000000081527fff00000000000000000000000000000000000000000000000000000000000000821660048201526024016103c0565b939792965093509350565b60006102cb7f8d0bf1fd623d628c741362c1289948e57b3e2905218c676d3e69abee36d6ae2e83610c75565b600033301461067e576040517fe12588940000000000000000000000000000000000000000000000000000000081523360048201523060248201526044016103c0565b81516020830134f0905073ffffffffffffffffffffffffffffffffffffffff81166106d757816040517f0d2571910000000000000000000000000000000000000000000000000000000081526004016103c09190611eba565b60405173ffffffffffffffffffffffffffffffffffffffff821681527fa506ad4e7f05eceba62a023c3219e5bd98a615f4fa87e2afb08a2da5cf62bf0c9060200160405180910390a1919050565b6000610731600061060f565b905090565b60007f6ffbd451000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161078957506001919050565b6102cb82610cd3565b60008060008060006107a5888888610447565b509650919450925090508282108015906107bd575060015b9450505050935093915050565b6040517fa038794000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f190100000000000000000000000000000000000000000000000000000000000060208201524660228201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b166042820152605681018290526000906076015b604051602081830303815290604052805190602001209050919050565b8060005b81811015610a0757368484838181106108a0576108a0611e27565b90506020028101906108b29190611ecd565b90506108c16020820182611f0b565b156108fb576040517f230d1ccc000000000000000000000000000000000000000000000000000000008152600481018390526024016103c0565b6040810135805a101561094e5782815a6040517f2bb3e3ba0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016103c0565b60006109886109636080850160608601611f26565b608085013584156109745784610976565b5a5b61098360a0880188611f41565b610d2f565b905080156109cf57877f5c4eeb02dabf8976016ab414d617f9a162936dcace3cdef8c69ef6e262ad5ae7856040516109c291815260200190565b60405180910390a26109f1565b6109f16109e26040850160208601611f0b565b89866109ec610d4c565b610d6b565b50505080806109ff90611fd5565b915050610885565b5050505050565b6000808080610a2987610a24876006818b61200d565b610db9565b6000908152873560f01c6020818152604080842084526002909a013560e01c908190529890912090999198509695509350505050565b6000808080610a7a87610a75876001818b61200d565b610a0e565b935093509350935093509350935093565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526000602282018190527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660428301526056820183905290607601610864565b6000808080806004600188013560e81c82610b138383612037565b9050610b258b61022683868d8f61200d565b939b5091995097509550935087871015610b7d57610b4581848b8d61200d565b89896040517fb006aba00000000000000000000000000000000000000000000000000000000081526004016103c0949392919061204a565b8092505b88831015610c675760038301928a013560e81c9150610ba08383612037565b90506000610bc2610bb08861124f565b8c8c879086926102269392919061200d565b939c50919a5098509091505088881015610c1a57610be282858c8e61200d565b8a8a6040517fb006aba00000000000000000000000000000000000000000000000000000000081526004016103c0949392919061204a565b848110610c5d576040517f37daf62b00000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016103c0565b9350915081610b81565b505050939792965093509350565b6000808383604051602001610c94929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012054949350505050565b60007fe4a77bbc000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610d2657506001919050565b6102cb82611283565b6000604051828482376000808483898b8af1979650505050505050565b60603d604051915060208201818101604052818352816000823e505090565b8315610d7957805160208201fd5b827fab46c69f7f32e1bf09b0725853da82a211e5402a0600296ab499a2fb5ea3b4198383604051610dab929190612071565b60405180910390a250505050565b60008060005b8381101561124657600181019085013560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101610e6057601582019186013560f881901c9060581c73ffffffffffffffffffffffffffffffffffffffff81169074ff000000000000000000000000000000000000000016811785610e465780610e55565b60008681526020829052604090205b955050505050610dbf565b80610ef65760018201918681013560f81c906043016000610e8c8a610e8784888c8e61200d565b61136d565b60ff841697909701969194508491905060a083901b74ff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff82161786610edb5780610eea565b60008781526020829052604090205b96505050505050610dbf565b6002810361101e576000808784013560f881901c9060581c73ffffffffffffffffffffffffffffffffffffffff16601586019550909250905060008885013560e81c600386018162ffffff169150809650819250505060008186019050610f6f8b848c8c8a908692610f6a9392919061200d565b611630565b610fb7578a83610f8183898d8f61200d565b6040517f9a9462320000000000000000000000000000000000000000000000000000000081526004016103c0949392919061208a565b60ff8416979097019694508460a084901b74ff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617876110025780611011565b60008881526020829052604090205b9750505050505050610dbf565b60038103611051576020820191860135836110395780611048565b60008481526020829052604090205b93505050610dbf565b6004810361109d576003808301928781013560e81c919082010160008061107e8b610a2485898d8f61200d565b60009889526020526040909720969097019650909350610dbf92505050565b600681036111a55760008287013560f81c60018401935060ff16905060008784013560f01c60028501945061ffff16905060008885013560e81c600386018162ffffff16915080965081925050506000818601905060008061110b8d8d8d8b908792610a249392919061200d565b9398508893909250905084821061112157988501985b604080517f53657175656e6365206e657374656420636f6e6669673a0a0000000000000000602080830191909152603882018490526058820188905260788083018a90528351808403909101815260989092019092528051910120896111875780611196565b60008a81526020829052604090205b99505050505050505050610dbf565b600581036112115760208201918601358781036111e0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b60006111eb82611817565b9050846111f85780611207565b60008581526020829052604090205b9450505050610dbf565b6040517fb2505f7c000000000000000000000000000000000000000000000000000000008152600481018290526024016103c0565b50935093915050565b7f8713a7c4465f6fbee2b6e9d6646d1d9f83fec929edfc4baf661f3c865bdd04d160009081526020829052604081206102cb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fac6a444e00000000000000000000000000000000000000000000000000000000148061131657507fffffffff0000000000000000000000000000000000000000000000000000000082167f36e7817500000000000000000000000000000000000000000000000000000000145b1561132357506001919050565b7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146102cb565b6000604282146113ad5782826040517f2ee17a3d0000000000000000000000000000000000000000000000000000000081526004016103c09291906120ca565b60006113c66113bd6001856120de565b85013560f81c90565b60ff169050604084013560f81c843560208601357f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a081111561143a578686826040517fad4aac760000000000000000000000000000000000000000000000000000000081526004016103c0939291906120f1565b8260ff16601b1415801561145257508260ff16601c14155b1561148f578686846040517fe578897e0000000000000000000000000000000000000000000000000000000081526004016103c093929190612115565b600184036114fc576040805160008152602081018083528a905260ff851691810191909152606081018390526080810182905260019060a0015b6020604051602081039080840390855afa1580156114eb573d6000803e3d6000fd5b5050506020604051035194506115d4565b60028403611599576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101899052600190605c01604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff861690820152606081018490526080810183905260a0016114c9565b86868560016040517f9dfba8520000000000000000000000000000000000000000000000000000000081526004016103c0949392919061213c565b73ffffffffffffffffffffffffffffffffffffffff85166116255786866040517f6c1719d20000000000000000000000000000000000000000000000000000000081526004016103c09291906120ca565b505050509392505050565b600081810361166b576040517fac241e1100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838361167a6001826120de565b81811061168957611689611e27565b919091013560f81c91505060018114806116a35750600281145b156116e8578473ffffffffffffffffffffffffffffffffffffffff166116ca87868661136d565b73ffffffffffffffffffffffffffffffffffffffff1614915061180e565b600381036117d35773ffffffffffffffffffffffffffffffffffffffff8516631626ba7e878660008761171c6001826120de565b926117299392919061200d565b6040518463ffffffff1660e01b815260040161174793929190612168565b602060405180830381865afa158015611764573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611788919061218b565b7fffffffff00000000000000000000000000000000000000000000000000000000167f1626ba7e0000000000000000000000000000000000000000000000000000000014915061180e565b83838260006040517f9dfba8520000000000000000000000000000000000000000000000000000000081526004016103c0949392919061213c565b50949350505050565b6040517f53657175656e636520737461746963206469676573743a0a0000000000000000602082015260388101829052600090605801610864565b7fffffffff00000000000000000000000000000000000000000000000000000000811681146103d257600080fd5b60006020828403121561189257600080fd5b813561031781611852565b60008083601f8401126118af57600080fd5b50813567ffffffffffffffff8111156118c757600080fd5b6020830191508360208285010111156118df57600080fd5b9250929050565b6000806000604084860312156118fb57600080fd5b83359250602084013567ffffffffffffffff81111561191957600080fd5b6119258682870161189d565b9497909650939450505050565b6000806000806040858703121561194857600080fd5b843567ffffffffffffffff8082111561196057600080fd5b61196c8883890161189d565b9096509450602087013591508082111561198557600080fd5b506119928782880161189d565b95989497509550505050565b6000602082840312156119b057600080fd5b5035919050565b60008083601f8401126119c957600080fd5b50813567ffffffffffffffff8111156119e157600080fd5b6020830191508360208260051b85010111156118df57600080fd5b60008060208385031215611a0f57600080fd5b823567ffffffffffffffff811115611a2657600080fd5b611a32858286016119b7565b90969095509350505050565b600080600080600060608688031215611a5657600080fd5b853567ffffffffffffffff80821115611a6e57600080fd5b611a7a89838a016119b7565b9097509550602088013594506040880135915080821115611a9a57600080fd5b50611aa78882890161189d565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215611af957600080fd5b813567ffffffffffffffff80821115611b1157600080fd5b818401915084601f830112611b2557600080fd5b813581811115611b3757611b37611ab8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611b7d57611b7d611ab8565b81604052828152876020848701011115611b9657600080fd5b826020860160208301376000928101602001929092525095945050505050565b8183823760009101908152919050565b80358015158114611bd657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bd657600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b81835260006020808501808196508560051b810191508460005b87811015611d8a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41883603018112611ca157600080fd5b870160c0611cae82611bc6565b15158652611cbd878301611bc6565b15158688015260408281013590870152606073ffffffffffffffffffffffffffffffffffffffff611cef828501611bdb565b16908701526080828101359087015260a080830135368490037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112611d3557600080fd5b90920187810192903567ffffffffffffffff811115611d5357600080fd5b803603841315611d6257600080fd5b8282890152611d748389018286611bff565b9c89019c97505050928601925050600101611c62565b5091979650505050505050565b60408152600560408201527f73656c663a000000000000000000000000000000000000000000000000000000606082015260806020820152600061037b608083018486611c48565b60408152600660408201527f67756573743a0000000000000000000000000000000000000000000000000000606082015260806020820152600061037b608083018486611c48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815180845260005b81811015611e7c57602081850181015186830182015201611e60565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006103176020830184611e56565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41833603018112611f0157600080fd5b9190910192915050565b600060208284031215611f1d57600080fd5b61031782611bc6565b600060208284031215611f3857600080fd5b61031782611bdb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611f7657600080fd5b83018035915067ffffffffffffffff821115611f9157600080fd5b6020019150368190038213156118df57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361200657612006611fa6565b5060010190565b6000808585111561201d57600080fd5b8386111561202a57600080fd5b5050820193919092039150565b808201808211156102cb576102cb611fa6565b60608152600061205e606083018688611bff565b6020830194909452506040015292915050565b82815260406020820152600061037b6040830184611e56565b84815273ffffffffffffffffffffffffffffffffffffffff841660208201526060604082015260006120c0606083018486611bff565b9695505050505050565b60208152600061037b602083018486611bff565b818103818111156102cb576102cb611fa6565b604081526000612105604083018587611bff565b9050826020830152949350505050565b604081526000612129604083018587611bff565b905060ff83166020830152949350505050565b606081526000612150606083018688611bff565b60208301949094525090151560409091015292915050565b838152604060208201526000612182604083018486611bff565b95945050505050565b60006020828403121561219d57600080fd5b81516103178161185256fea26469706673582212200896636ab1dae9ad33c5080d1044c3c12105a6d4bc196fd0009bf12ed3b0f85364736f6c63430008120033

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