Sepolia Testnet

Contract

0xC512A5947Cb43d5ad540628937a0d5CC126f310B

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CommonMultiECDSA

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : CommonMultiECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {CommonSignatureChecker} from "./CommonSignatureChecker.sol";

/**
 * @title MultiSigModule - EIP-4337 compatible multi sig module. Contract signatures are not covered.
 * @author Akash Mishra - <[email protected]>
 */

contract CommonMultiECDSA is BaseAuthorizationModule, CommonSignatureChecker {
    /**
     * @notice The EIP-712 type-hash for the domain separator used for verifying Safe operation signatures.
     */
    bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH =
        keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");

    /**
     * @notice The EIP-712 type-hash for a SafeOp, representing the structure of a User Operation for the Safe.
     *  {address} safe - The address of the safe on which the operation is performed.
     *  {uint256} nonce - A unique number associated with the user operation, preventing replay attacks by ensuring each operation is unique.
     *  {bytes} initCode - The packed encoding of a factory address and its factory-specific data for creating a new Safe account.
     *  {bytes} callData - The bytes representing the data of the function call to be executed.
     *  {uint256} callGasLimit - The maximum amount of gas allowed for executing the function call.
     *  {uint256} verificationGasLimit - The maximum amount of gas allowed for the verification process.
     *  {uint256} preVerificationGas - The amount of gas allocated for pre-verification steps before executing the main operation.
     *  {uint256} maxFeePerGas - The maximum fee per gas that the user is willing to pay for the transaction.
     *  {uint256} maxPriorityFeePerGas - The maximum priority fee per gas that the user is willing to pay for the transaction.
     *  {bytes} paymasterAndData - The packed encoding of a paymaster address and its paymaster-specific data for sponsoring the user operation.
     *  {uint48} validAfter - A timestamp representing from when the user operation is valid.
     *  {uint48} validUntil - A timestamp representing until when the user operation is valid, or 0 to indicated "forever".
     *  {address} entryPoint - The address of the entry point that will execute the user operation.
     * @dev When validating the user operation, the signature timestamps are pre-pended to the signature bytes.
     */
    bytes32 private constant SAFE_OP_TYPEHASH =
        keccak256(
            "SafeOp(address safe,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,uint48 validAfter,uint48 validUntil,address entryPoint)"
        );

    /**
     * @dev A structure used internally for manually encoding a Safe operation for when computing the EIP-712 struct hash.
     */
    struct EncodedSafeOpStruct {
        bytes32 typeHash;
        address safe;
        uint256 nonce;
        bytes32 initCodeHash;
        bytes32 callDataHash;
        uint256 callGasLimit;
        uint256 verificationGasLimit;
        uint256 preVerificationGas;
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
        bytes32 paymasterAndDataHash;
        uint48 validAfter;
        uint48 validUntil;
        address entryPoint;
    }

    address public immutable SUPPORTED_ENTRYPOINT;

    constructor(address entryPoint) {
        require(entryPoint != address(0), "Invalid entry point");
        SUPPORTED_ENTRYPOINT = entryPoint;
    }

    /**
     * @notice Validates a user operation provided by the entry point.
     */
    function validateUserOp(
        UserOperation calldata userOp,
        bytes32 userOpHash
    ) external view returns (uint256 validationData) {
        isSmartAccount(msg.sender);

        // The userOp nonce is validated in the entry point (for 0.6.0+), therefore we will not check it again
        // validationData = _validateSignatures(userOp);
        // if (_validateSignatures(userOp) == VALIDATION_SUCCESS) {
        //     return VALIDATION_SUCCESS;
        // }
        return _validateSignatures(userOp);
    }

    /**
     * @dev Validates a signature for a message signed by address.
     * @dev Also try dataHash.toEthSignedMessageHash()
     * @param operationDataHash hash of the data
     * @param operationDataPack abi.encode(operationData,validAfter, validUntil, signatures)
     * @return EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
     */
    function isValidSignature(
        bytes32 operationDataHash,
        bytes memory operationDataPack
    ) public view virtual override returns (bytes4) {
        return
            isValidSignatureForAddress(operationDataHash, operationDataPack, msg.sender);
    }

    /**
     * @dev Validates a signature for a message signed by address.
     * @dev Also try dataHash.toEthSignedMessageHash()
     * @param operationDataHash hash of the data
     * @param operationDataPack abi.encode(operationData,validAfter, validUntil, signatures)
     * @param smartAccount expected signer Smart Account address.
     * @return EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
     */
    function isValidSignatureForAddress(
        bytes32 operationDataHash,
        bytes memory operationDataPack,
        address smartAccount
    ) public view virtual returns (bytes4) {
        if (_validateSignatures(operationDataPack) == VALIDATION_SUCCESS) {
            return EIP1271_MAGIC_VALUE;
        }
        return bytes4(0xffffffff);
    }

    /**
     * @notice Computes the 32-byte domain separator used in EIP-712 signature verification for Safe operations.
     * @return The EIP-712 domain separator hash for this contract.
     */
    function domainSeparator() public view returns (bytes32) {
        return
            keccak256(
                abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this)
            );
    }

    /**
     * @notice Returns the 32-byte Safe operation hash to be signed by owners for the specified ERC-4337 user operation.
     * @dev The Safe operation timestamps are pre-pended to the signature bytes as `abi.encodePacked(validAfter, validUntil, signatures)`.
     * @param userOp The ERC-4337 user operation.
     * @return operationHash Operation hash.
     */
    function getOperationHash(
        UserOperation calldata userOp
    ) external view returns (bytes32 operationHash) {
        (bytes memory operationData, , , ) = _getSafeOp(userOp);
        operationHash = keccak256(operationData);
    }

    /**
     * @dev Validates that the user operation is correctly signed and returns an ERC-4337 packed validation data
     * of `validAfter || validUntil || authorizer`:
     *  - `authorizer`: 20-byte address, 0 for valid signature or 1 to mark signature failure (this module does not make use of signature aggregators).
     *  - `validUntil`: 6-byte timestamp value, or zero for "infinite". The user operation is valid only up to this time.
     *  - `validAfter`: 6-byte timestamp. The user operation is valid only after this time.
     * @param userOp User operation struct.
     * @return validationData An integer indicating the result of the validation.
     */
    function _validateSignatures(
        UserOperation calldata userOp
    ) internal view returns (uint256 validationData) {
        
        (
            bytes memory operationData,
            uint48 validAfter,
            uint48 validUntil,
            bytes calldata signatures
        ) = _getSafeOp(userOp);
        bool success = checkSignatures(
            keccak256(operationData),
            operationData,
            signatures
        );
        // The timestamps are validated by the entry point, therefore we will not check them again
        if (success) validationData = _packValidationData(false, validUntil, validAfter);
        else validationData = _packValidationData(true, validUntil, validAfter);
    }

    /**
     * @dev Validates a signature for a message signed by address.
     * @dev Also try dataHash.toEthSignedMessageHash()
     * @param operationDataPack abi.encode(operationData,validAfter, validUntil, signatures)
     * @return validationData EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
     */
    function _validateSignatures(
        bytes memory operationDataPack
    ) internal view returns (uint256 validationData)    {
        // (bytes memory operationData, uint48 validAfter, uint48 validUntil, bytes calldata signatures) = _getSafeOp(userOp);
        (
            bytes memory operationData,
            uint48 validAfter,
            uint48 validUntil,
            bytes memory signatures
        ) = abi.decode(operationDataPack, (bytes, uint48, uint48, bytes));
        bool success = checkSignatures(
            keccak256(operationData),
            operationData,
            signatures
        );
        // The timestamps are validated by the entry point, therefore we will not check them again
        // if (success)
        //     validationData = _packValidationData(false, validUntil, validAfter);
        // else validationData = _packValidationData(true, validUntil, validAfter);

        if (success) validationData = VALIDATION_SUCCESS;
        else validationData = SIG_VALIDATION_FAILED;
    }

    /**
     * @dev Decodes an ERC-4337 user operation into a Safe operation.
     * @param userOp The ERC-4337 user operation.
     * @return operationData Encoded EIP-712 Safe operation data bytes used for signature verification.
     * @return validAfter The timestamp the user operation is valid from.
     * @return validUntil The timestamp the user operation is valid until.
     * @return signatures The Safe owner signatures extracted from the user operation.
     */
    function _getSafeOp(
        UserOperation calldata userOp
    )
        internal
        view
        returns (
            bytes memory operationData,
            uint48 validAfter,
            uint48 validUntil,
            bytes calldata signatures
        )   
    {
        // Extract additional Safe operation fields from the user operation signature which is encoded as:
        // `abi.encodePacked(validAfter, validUntil, signatures)`
        {

            bytes calldata sig = userOp.signature;

            validAfter = uint48(bytes6(sig[0:6]));
            validUntil = uint48(bytes6(sig[6:12]));
            bytes calldata signaturesWithModule = sig[12:];
            signatures = signaturesWithModule[:signaturesWithModule.length-20];

        }

        // It is important that **all** user operation fields are represented in the `SafeOp` data somehow, to prevent
        // user operations from being submitted that do not fully respect the user preferences. The only exception is
        // the `signature` bytes. Note that even `initCode` needs to be represented in the operation data, otherwise
        // it can be replaced with a more expensive initialization that would charge the user additional fees.
        {
            // In order to work around Solidity "stack too deep" errors related to too many stack variables, manually
            // encode the `SafeOp` fields into a memory `struct` for computing the EIP-712 struct-hash. This works
            // because the `EncodedSafeOpStruct` struct has no "dynamic" fields so its memory layout is identical to the
            // result of `abi.encode`-ing the individual fields.
            EncodedSafeOpStruct memory encodedSafeOp = EncodedSafeOpStruct({
                typeHash: SAFE_OP_TYPEHASH,
                safe: userOp.sender,
                nonce: userOp.nonce,
                initCodeHash: keccak256(userOp.initCode),
                callDataHash: keccak256(userOp.callData),
                callGasLimit: userOp.callGasLimit,
                verificationGasLimit: userOp.verificationGasLimit,
                preVerificationGas: userOp.preVerificationGas,
                maxFeePerGas: userOp.maxFeePerGas,
                maxPriorityFeePerGas: userOp.maxPriorityFeePerGas,
                paymasterAndDataHash: keccak256(userOp.paymasterAndData),
                validAfter: validAfter,
                validUntil: validUntil,
                entryPoint: SUPPORTED_ENTRYPOINT
            });

            bytes32 safeOpStructHash;
            // solhint-disable-next-line no-inline-assembly
            assembly ("memory-safe") {
                // Since the `encodedSafeOp` value's memory layout is identical to the result of `abi.encode`-ing the
                // individual `SafeOp` fields, we can pass it directly to `keccak256`. Additionally, there are 14
                // 32-byte fields to hash, for a length of `14 * 32 = 448` bytes.
                safeOpStructHash := keccak256(encodedSafeOp, 448)
            }

            operationData = abi.encodePacked(
                bytes1(0x19),
                bytes1(0x01),
                domainSeparator(),
                safeOpStructHash
            );
        }
    }

    function _packValidationData(
        bool sigFailed,
        uint48 validUntil,
        uint48 validAfter
    ) internal pure returns (uint256) {
        return
            (sigFailed ? 1 : 0) |
            (uint256(validUntil) << 160) |
            (uint256(validAfter) << (160 + 48));
    }
}

File 2 of 10 : Helpers.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

/* solhint-disable no-inline-assembly */

/**
 * returned data from validateUserOp.
 * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`
 * @param aggregator - address(0) - the account validated the signature by itself.
 *              address(1) - the account failed to validate the signature.
 *              otherwise - this is an address of a signature aggregator that must be used to validate the signature.
 * @param validAfter - this UserOp is valid only after this timestamp.
 * @param validaUntil - this UserOp is valid only up to this timestamp.
 */
    struct ValidationData {
        address aggregator;
        uint48 validAfter;
        uint48 validUntil;
    }

//extract sigFailed, validAfter, validUntil.
// also convert zero validUntil to type(uint48).max
    function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {
        address aggregator = address(uint160(validationData));
        uint48 validUntil = uint48(validationData >> 160);
        if (validUntil == 0) {
            validUntil = type(uint48).max;
        }
        uint48 validAfter = uint48(validationData >> (48 + 160));
        return ValidationData(aggregator, validAfter, validUntil);
    }

// intersect account and paymaster ranges.
    function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {
        ValidationData memory accountValidationData = _parseValidationData(validationData);
        ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);
        address aggregator = accountValidationData.aggregator;
        if (aggregator == address(0)) {
            aggregator = pmValidationData.aggregator;
        }
        uint48 validAfter = accountValidationData.validAfter;
        uint48 validUntil = accountValidationData.validUntil;
        uint48 pmValidAfter = pmValidationData.validAfter;
        uint48 pmValidUntil = pmValidationData.validUntil;

        if (validAfter < pmValidAfter) validAfter = pmValidAfter;
        if (validUntil > pmValidUntil) validUntil = pmValidUntil;
        return ValidationData(aggregator, validAfter, validUntil);
    }

/**
 * helper to pack the return value for validateUserOp
 * @param data - the ValidationData to pack
 */
    function _packValidationData(ValidationData memory data) pure returns (uint256) {
        return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));
    }

/**
 * helper to pack the return value for validateUserOp, when not using an aggregator
 * @param sigFailed - true for signature failure, false for success
 * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)
 * @param validAfter first timestamp this UserOperation is valid
 */
    function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {
        return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));
    }

/**
 * keccak function over calldata.
 * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
 */
    function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
        assembly {
            let mem := mload(0x40)
            let len := data.length
            calldatacopy(mem, data.offset, len)
            ret := keccak256(mem, len)
        }
    }

File 3 of 10 : UserOperation.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

/* solhint-disable no-inline-assembly */

import {calldataKeccak} from "../core/Helpers.sol";

/**
 * User Operation struct
 * @param sender the sender account of this request.
     * @param nonce unique value the sender uses to verify it is not a replay.
     * @param initCode if set, the account contract will be created by this constructor/
     * @param callData the method call to execute on this account.
     * @param callGasLimit the gas limit passed to the callData method call.
     * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.
     * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.
     * @param maxFeePerGas same as EIP-1559 gas parameter.
     * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.
     * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.
     * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.
     */
    struct UserOperation {

        address sender;
        uint256 nonce;
        bytes initCode;
        bytes callData;
        uint256 callGasLimit;
        uint256 verificationGasLimit;
        uint256 preVerificationGas;
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
        bytes paymasterAndData;
        bytes signature;
    }

/**
 * Utility functions helpful when working with UserOperation structs.
 */
library UserOperationLib {

    function getSender(UserOperation calldata userOp) internal pure returns (address) {
        address data;
        //read sender from userOp, which is first userOp member (saves 800 gas...)
        assembly {data := calldataload(userOp)}
        return address(uint160(data));
    }

    //relayer/block builder might submit the TX with higher priorityFee, but the user should not
    // pay above what he signed for.
    function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {
    unchecked {
        uint256 maxFeePerGas = userOp.maxFeePerGas;
        uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
        if (maxFeePerGas == maxPriorityFeePerGas) {
            //legacy mode (for networks that don't support basefee opcode)
            return maxFeePerGas;
        }
        return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
    }
    }

    function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {
        address sender = getSender(userOp);
        uint256 nonce = userOp.nonce;
        bytes32 hashInitCode = calldataKeccak(userOp.initCode);
        bytes32 hashCallData = calldataKeccak(userOp.callData);
        uint256 callGasLimit = userOp.callGasLimit;
        uint256 verificationGasLimit = userOp.verificationGasLimit;
        uint256 preVerificationGas = userOp.preVerificationGas;
        uint256 maxFeePerGas = userOp.maxFeePerGas;
        uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
        bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);

        return abi.encode(
            sender, nonce,
            hashInitCode, hashCallData,
            callGasLimit, verificationGasLimit, preVerificationGas,
            maxFeePerGas, maxPriorityFeePerGas,
            hashPaymasterAndData
        );
    }

    function hash(UserOperation calldata userOp) internal pure returns (bytes32) {
        return keccak256(pack(userOp));
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }
}

File 4 of 10 : BaseAuthorizationModule.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

/* solhint-disable no-empty-blocks */

import {IAuthorizationModule} from "./interfaces/IAuthorizationModule.sol";
import {ISignatureValidator} from "./interfaces/ISignatureValidator.sol";

contract AuthorizationModulesConstants {
    uint256 internal constant VALIDATION_SUCCESS = 0;
    uint256 internal constant SIG_VALIDATION_FAILED = 1;
}

abstract contract BaseAuthorizationModule is
    IAuthorizationModule,
    ISignatureValidator,
    AuthorizationModulesConstants
{}

File 5 of 10 : CommonSignatureChecker.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

import "./MultiSig/CommonOwnerManager.sol";
import "./MultiSig/SignatureDecoder.sol";
import "./MultiSig/GnosisSafeMath.sol";


contract CommonSignatureChecker is CommonOwnerManager, SignatureDecoder
{
    using GnosisSafeMath for uint256;

    event SafeSetup(address indexed initiator, address[] owners, uint256 threshold);
    
    /// @dev Setup function sets initial storage of contract.
    /// @param _owners List of Safe owners.
    /// @param _threshold Number of required confirmations for a Safe transaction.
    function setup(
        address[] calldata _owners,
        uint256 _threshold
    ) external returns(address) {
        // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
        setupOwners(_owners, _threshold);
        // As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules
        accountSupported[msg.sender] =true;
        emit SafeSetup(msg.sender, _owners, _threshold);
        return address(this);
    }

    function checkSignatures(
        bytes32 dataHash,
        bytes memory data,
        bytes memory signatures
    ) public view returns(bool) {
        // Load threshold to avoid multiple storage loads
        uint256 _threshold = smartAccountToOwners[msg.sender].threshold;
        // Check that a threshold is set
        require(_threshold > 0, "Threshold is zero");
        checkNSignatures(dataHash, data, signatures, _threshold);
        return true;
    }

    /**
     * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
     * @param dataHash Hash of the data (could be either a message hash or transaction hash)
     * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
     * @param requiredSignatures Amount of required valid signatures.
     */
    function checkNSignatures(
        bytes32 dataHash,bytes memory,
        bytes memory signatures,
        uint256 requiredSignatures
    ) public view {
        // Check that the provided signature data is not too short
        require(signatures.length >= requiredSignatures.mul(65), "Invalid inputs");
        // There cannot be an owner with address 0.
        address lastOwner = address(0);
        address currentOwner;
        uint8 v;
        bytes32 r;
        bytes32 s;
        uint256 i;
        for (i = 0; i < requiredSignatures; i++) {
            (v, r, s) = signatureSplit(signatures, i);
           if (v > 30) {
                // If v > 30 then default va (27,28) has been adjusted for eth_sign flow
                // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
                currentOwner = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", dataHash)), v - 4, r, s);
            } else {
                // Default is the ecrecover flow with the provided data hash
                // Use ecrecover with the messageHash for EOA signatures
                currentOwner = ecrecover(dataHash, v, r, s);
            }
            require(currentOwner > lastOwner && smartAccountToOwners[msg.sender].owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "Not a owner");
            lastOwner = currentOwner;
        }
    }
    
}

File 6 of 10 : IAuthorizationModule.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";

// interface for modules to verify singatures signed over userOpHash
interface IAuthorizationModule {
    function validateUserOp(
        UserOperation calldata userOp,
        bytes32 userOpHash
    ) external returns (uint256 validationData);
}

File 7 of 10 : ISignatureValidator.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.0 <0.9.0;

contract ISignatureValidatorConstants {
    // bytes4(keccak256("isValidSignature(bytes32,bytes)")
    bytes4 internal constant EIP1271_MAGIC_VALUE = 0x1626ba7e;
}

abstract contract ISignatureValidator is ISignatureValidatorConstants {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param _dataHash Arbitrary length data signed on behalf of address(this)
     * @param _signature Signature byte array associated with _data
     *
     * MUST return the bytes4 magic value 0x1626ba7e when function passes.
     * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
     * MUST allow external calls
     */
    function isValidSignature(
        bytes32 _dataHash,
        bytes memory _signature
    ) public view virtual returns (bytes4);
}

File 8 of 10 : CommonOwnerManager.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/// @title OwnerManager - Manages a set of owners and a threshold to perform actions.

contract CommonOwnerManager {
    event AddedOwner(address owner);
    event RemovedOwner(address owner);
    event ChangedThreshold(uint256 threshold);
    event SmartAcountAdded(address _account);

    address internal constant SENTINEL_OWNERS = address(0x1);
    
    struct Details {
        mapping(address => address) owners;
        uint256 threshold;
        uint256 ownerCount;
    }

    // mapping(address => address) internal owners;
    mapping(address => bool) public accountSupported;

    mapping(address => Details) public smartAccountToOwners;    

    // uint256 internal ownerCount;
    // uint256 internal threshold;

    function isSmartAccount(address _account) internal view {
        require(accountSupported[_account], "Smart account not supported");
    }

    /// @dev Setup function sets initial storage of contract.
    /// @param _owners List of Safe owners.
    /// @param _threshold Number of required confirmations for a Safe transaction.
    function setupOwners(address[] memory _owners, uint256 _threshold) internal {
        // Threshold can only be 0 at initialization.
        // Check ensures that setup function can only be called once.
        require(smartAccountToOwners[msg.sender].threshold == 0, "Already initialized");
        // Validate that threshold is smaller than number of added owners.
        require(_threshold <= _owners.length, "Decrease threshold");
        // There has to be at least one Safe owner.
        require(_threshold >= 1, "Threshold should be one atleast");
        // Initializing Safe owners.
        address currentOwner = SENTINEL_OWNERS;
        for (uint256 i = 0; i < _owners.length; i++) {
            // Owner address cannot be null.
            address owner = _owners[i];
            require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "Invalid owner");
            // No duplicate owners allowed.
            require(smartAccountToOwners[msg.sender].owners[owner] == address(0), "Owner already present");
            smartAccountToOwners[msg.sender].owners[currentOwner] = owner;
            currentOwner = owner;
        }
        smartAccountToOwners[msg.sender].owners[currentOwner] = SENTINEL_OWNERS;
        smartAccountToOwners[msg.sender].ownerCount = _owners.length;
        smartAccountToOwners[msg.sender].threshold = _threshold;
    }

    /// @dev Allows to add a new owner to the Safe and update the threshold at the same time.
    ///      This can only be done via a Safe transaction.
    /// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
    /// @param owner New owner address.
    /// @param _threshold New threshold.
    function addOwnerWithThreshold(address owner, uint256 _threshold) public {
        isSmartAccount(msg.sender);
        // Owner address cannot be null, the sentinel or the Safe itself.
        require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "Invalid owner");
        // No duplicate owners allowed.
        require(smartAccountToOwners[msg.sender].owners[owner] == address(0), "Duplicate owner");
        smartAccountToOwners[msg.sender].owners[owner] = smartAccountToOwners[msg.sender].owners[SENTINEL_OWNERS];
        smartAccountToOwners[msg.sender].owners[SENTINEL_OWNERS] = owner;
        smartAccountToOwners[msg.sender].ownerCount++;
        emit AddedOwner(owner);
        // Change threshold if threshold was changed.
        if (smartAccountToOwners[msg.sender].threshold != _threshold) changeThreshold(_threshold);
    }

    /// @dev Allows to remove an owner from the Safe and update the threshold at the same time.
    ///      This can only be done via a Safe transaction.
    /// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
    /// @param prevOwner Owner that pointed to the owner to be removed in the linked list
    /// @param owner Owner address to be removed.
    /// @param _threshold New threshold.
    function removeOwner(
        address prevOwner,
        address owner,
        uint256 _threshold
    ) public {
        isSmartAccount(msg.sender);
        // Only allow to remove an owner, if threshold can still be reached.
        require(smartAccountToOwners[msg.sender].ownerCount - 1 >= _threshold, "Violating owner");
        // Validate owner address and check that it corresponds to owner index.
        require(owner != address(0) && owner != SENTINEL_OWNERS, "Owner invalid");
        require(smartAccountToOwners[msg.sender].owners[prevOwner] == owner, "Invalid previous owner");
        smartAccountToOwners[msg.sender].owners[prevOwner] = smartAccountToOwners[msg.sender].owners[owner];
        smartAccountToOwners[msg.sender].owners[owner] = address(0);
        smartAccountToOwners[msg.sender].ownerCount--;
        emit RemovedOwner(owner);
        // Change threshold if threshold was changed.
        if (smartAccountToOwners[msg.sender].threshold != _threshold) changeThreshold(_threshold);
    }

    /// @dev Allows to swap/replace an owner from the Safe with another address.
    ///      This can only be done via a Safe transaction.
    /// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
    /// @param prevOwner Owner that pointed to the owner to be replaced in the linked list
    /// @param oldOwner Owner address to be replaced.
    /// @param newOwner New owner address.
    function swapOwner(
        address prevOwner,
        address oldOwner,
        address newOwner
    ) public {
        isSmartAccount(msg.sender);
        // Owner address cannot be null, the sentinel or the Safe itself.
        require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "Invalid address");
        // No duplicate owners allowed.
        require(smartAccountToOwners[msg.sender].owners[newOwner] == address(0), "Already a owner");
        // Validate oldOwner address and check that it corresponds to owner index.
        require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "Invalid address");
        require(smartAccountToOwners[msg.sender].owners[prevOwner] == oldOwner, "Invalid pointer address");
        smartAccountToOwners[msg.sender].owners[newOwner] = smartAccountToOwners[msg.sender].owners[oldOwner];
        smartAccountToOwners[msg.sender].owners[prevOwner] = newOwner;
        smartAccountToOwners[msg.sender].owners[oldOwner] = address(0);
        emit RemovedOwner(oldOwner);
        emit AddedOwner(newOwner);
    }

    /// @dev Allows to update the number of required confirmations by Safe owners.
    ///      This can only be done via a Safe transaction.
    /// @notice Changes the threshold of the Safe to `_threshold`.
    /// @param _threshold New threshold.
    function changeThreshold(uint256 _threshold) public {
        isSmartAccount(msg.sender);
        // Validate that threshold is smaller than number of owners.
        require(_threshold <= smartAccountToOwners[msg.sender].ownerCount, "Threshold should be less than owners count");
        // There has to be at least one Safe owner.
        require(_threshold >= 1, "Threshold should be atleast one");
        smartAccountToOwners[msg.sender].threshold = _threshold;
        emit ChangedThreshold(smartAccountToOwners[msg.sender].threshold);
    }

    function getThreshold(address _account) public view returns (uint256) {
        return smartAccountToOwners[_account].threshold;
    }

    function isOwner(address _account, address owner) public view returns (bool) {
        return owner != SENTINEL_OWNERS && smartAccountToOwners[_account].owners[owner] != address(0);
    }

    /// @dev Returns array of owners.
    /// @return Array of Safe owners.
    function getOwners(address _account) public view returns (address[] memory) {
        address[] memory array = new address[](smartAccountToOwners[_account].ownerCount);

        // populate return array
        uint256 index = 0;
        address currentOwner = smartAccountToOwners[_account].owners[SENTINEL_OWNERS];
        while (currentOwner != SENTINEL_OWNERS) {
            array[index] = currentOwner;
            currentOwner = smartAccountToOwners[_account].owners[currentOwner];
            index++;
        }
        return array;
    }

    function addAccount(address _account) public {
        isSmartAccount(msg.sender);
        require(_account != address(0), "Zero address");
        require(_account.code.length > 0, "Not a contract");
        accountSupported[_account] = true;

        emit SmartAcountAdded(_account);
    }

}

File 9 of 10 : GnosisSafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;

/**
 * @title GnosisSafeMath
 * @dev Math operations with safety checks that revert on error
 * Renamed from SafeMath to GnosisSafeMath to avoid conflicts
 * TODO: remove once open zeppelin update to solc 0.5.0
 */
library GnosisSafeMath {
    /**
     * @dev Multiplies two numbers, reverts on overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
     * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Adds two numbers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }
}

File 10 of 10 : SignatureDecoder.sol
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/// @title SignatureDecoder - Decodes signatures that a encoded as bytes
contract SignatureDecoder {
    /// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.
    /// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures
    /// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
    /// @param signatures concatenated rsv signatures
    function signatureSplit(bytes memory signatures, uint256 pos)
        internal
        pure
        returns (
            uint8 v,
            bytes32 r,
            bytes32 s
        )
    {
        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let signaturePos := mul(0x41, pos)
            r := mload(add(signatures, add(signaturePos, 0x20)))
            s := mload(add(signatures, add(signaturePos, 0x40)))
            // Here we are loading the last 32 bytes, including 31 bytes
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
        }
    }
}

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

Contract ABI

[{"inputs":[{"internalType":"address","name":"entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"AddedOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"ChangedThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"RemovedOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":false,"internalType":"address[]","name":"owners","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"SafeSetup","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_account","type":"address"}],"name":"SmartAcountAdded","type":"event"},{"inputs":[],"name":"SUPPORTED_ENTRYPOINT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accountSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"addOwnerWithThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"changeThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"},{"internalType":"uint256","name":"requiredSignatures","type":"uint256"}],"name":"checkNSignatures","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"name":"checkSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"}],"name":"getOperationHash","outputs":[{"internalType":"bytes32","name":"operationHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getOwners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"operationDataHash","type":"bytes32"},{"internalType":"bytes","name":"operationDataPack","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"operationDataHash","type":"bytes32"},{"internalType":"bytes","name":"operationDataPack","type":"bytes"},{"internalType":"address","name":"smartAccount","type":"address"}],"name":"isValidSignatureForAddress","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"prevOwner","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"removeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"setup","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"smartAccountToOwners","outputs":[{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"ownerCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"prevOwner","type":"address"},{"internalType":"address","name":"oldOwner","type":"address"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"swapOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a06040523480156200001157600080fd5b506040516200294a3803806200294a8339810160408190526200003491620000a1565b6001600160a01b0381166200008f5760405162461bcd60e51b815260206004820152601360248201527f496e76616c696420656e74727920706f696e7400000000000000000000000000604482015260640160405180910390fd5b6001600160a01b0316608052620000d3565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b608051612854620000f6600039600081816101830152611cf501526128546000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063934f3a11116100cd578063f44c339d11610081578063f8dc5dd911610066578063f8dc5dd9146103c3578063fd8b84b1146103d6578063fff35b72146103f657600080fd5b8063f44c339d14610354578063f698da251461036757600080fd5b8063cc1b5475116100b2578063cc1b5475146102ed578063e318b52b1461032e578063e89b0e1e1461034157600080fd5b8063934f3a11146102c7578063b25f3776146102da57600080fd5b80631d65ea0511610124578063694e80c311610109578063694e80c314610259578063789771681461026c5780637ddc02d4146102b457600080fd5b80631d65ea05146102135780634ab884271461024657600080fd5b80630d582f131461015657806312fb68e01461016b578063137e051e1461017e5780631626ba7e146101cf575b600080fd5b610169610164366004611f75565b610409565b005b6101696101793660046120b9565b610671565b6101a57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101e26101dd36600461212e565b610951565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016101c6565b610236610221366004612175565b60006020819052908152604090205460ff1681565b60405190151581526020016101c6565b6101a5610254366004612190565b610967565b61016961026736600461220b565b610a25565b6102a661027a366004612175565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160208190526040909120015490565b6040519081526020016101c6565b6102366102c2366004612224565b610b8d565b6102366102d5366004612257565b610beb565b6102a66102e83660046122dd565b610c7c565b6103196102fb366004612175565b60016020819052600091825260409091209081015460029091015482565b604080519283526020830191909152016101c6565b61016961033c36600461231a565b610c9e565b61016961034f366004612175565b611048565b6101e261036236600461235d565b6111cc565b6102a6604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6101696103d13660046123ab565b61122d565b6103e96103e4366004612175565b6114fc565b6040516101c691906123e7565b6102a6610404366004612441565b611636565b6104123361164a565b73ffffffffffffffffffffffffffffffffffffffff82161580159061044e575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015610470575073ffffffffffffffffffffffffffffffffffffffff82163014155b6104db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206f776e65720000000000000000000000000000000000000060448201526064015b60405180910390fd5b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86811685529252909120541615610575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4475706c6963617465206f776e6572000000000000000000000000000000000060448201526064016104d2565b336000818152600160208181526040808420838552808352818520805473ffffffffffffffffffffffffffffffffffffffff8a81168089529488208054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091558154169092179091559383525260029091018054916105fc836124b5565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a13360009081526001602081905260409091200154811461066d5761066d81610a25565b5050565b61067c8160416116dc565b825110156106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c696420696e7075747300000000000000000000000000000000000060448201526064016104d2565b6000808060008060005b86811015610945576041818102890160208101516040820151919092015160ff1695509093509150601e8411156107da576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c016040516020818303038152906040528051906020012060048661077a91906124ed565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156107c9573d6000803e3d6000fd5b50505060206040510351945061083a565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561082d573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161180156108a6575033600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff89811685529252909120541615155b80156108c9575073ffffffffffffffffffffffffffffffffffffffff8516600114155b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e6f742061206f776e657200000000000000000000000000000000000000000060448201526064016104d2565b849550808061093d906124b5565b9150506106f0565b50505050505050505050565b600061095e8383336111cc565b90505b92915050565b60006109a7848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250869250611711915050565b336000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f9f7ea12b584e639128b2cae69de6ca3335a28b01235291afa40ce814fdf65f3590610a1390879087908790612506565b60405180910390a250305b9392505050565b610a2e3361164a565b33600090815260016020526040902060020154811115610ad0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5468726573686f6c642073686f756c64206265206c657373207468616e206f7760448201527f6e65727320636f756e740000000000000000000000000000000000000000000060648201526084016104d2565b6001811015610b3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5468726573686f6c642073686f756c642062652061746c65617374206f6e650060448201526064016104d2565b3360009081526001602081905260409182902001829055517f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c9390610b829083815260200190565b60405180910390a150565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061095e57505073ffffffffffffffffffffffffffffffffffffffff91821660009081526001602090815260408083209385168352929052205416151590565b3360009081526001602081905260408220015480610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5468726573686f6c64206973207a65726f00000000000000000000000000000060448201526064016104d2565b610c7185858584610671565b506001949350505050565b600080610c8883611b1d565b5050505090508080519060200120915050919050565b610ca73361164a565b73ffffffffffffffffffffffffffffffffffffffff811615801590610ce3575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015610d05575073ffffffffffffffffffffffffffffffffffffffff81163014155b610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529252909120541615610e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f416c72656164792061206f776e6572000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff821615801590610e41575073ffffffffffffffffffffffffffffffffffffffff8216600114155b610ea7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8781168552925290912054811690831614610f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420706f696e746572206164647265737300000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff868116808652918452828520805487831680885285882080549285167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179055928a1687528487208054821690931790925594829052845416909355519182527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf910160405180910390a160405173ffffffffffffffffffffffffffffffffffffffff821681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a1505050565b6110513361164a565b73ffffffffffffffffffffffffffffffffffffffff81166110ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f2061646472657373000000000000000000000000000000000000000060448201526064016104d2565b60008173ffffffffffffffffffffffffffffffffffffffff163b1161114f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f74206120636f6e747261637400000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff81166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182527f016c6c81185d9d57ee95b405e66dcd24b95197e63995a3c3fdf91d58dbf912d89101610b82565b6000806111d884611e21565b0361120457507f1626ba7e00000000000000000000000000000000000000000000000000000000610a1e565b507fffffffff000000000000000000000000000000000000000000000000000000009392505050565b6112363361164a565b33600090815260016020819052604090912060020154829161125791612567565b10156112bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f56696f6c6174696e67206f776e6572000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff8216158015906112fb575073ffffffffffffffffffffffffffffffffffffffff8216600114155b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4f776e657220696e76616c69640000000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87811685529252909120548116908316146113ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642070726576696f7573206f776e65720000000000000000000060448201526064016104d2565b33600081815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff888116865281845282862080548b831688529387208054949092167fffffffffffffffffffffffff00000000000000000000000000000000000000009485161790915580549092169091559383525260029091018054916114868361257a565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf9060200160405180910390a1336000908152600160208190526040909120015481146114f7576114f781610a25565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600160205260408120600201546060919067ffffffffffffffff81111561154157611541611f9f565b60405190808252806020026020018201604052801561156a578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808516600090815260016020818152604080842092845291905281205492935091165b73ffffffffffffffffffffffffffffffffffffffff811660011461162d57808383815181106115d4576115d46125af565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152868216600090815260018252604080822094841682529390915291909120541681611625816124b5565b9250506115a3565b50909392505050565b60006116413361164a565b61095e83611e79565b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff166116d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536d617274206163636f756e74206e6f7420737570706f72746564000000000060448201526064016104d2565b50565b6000826000036116ee57506000610961565b60006116fa83856125de565b90508261170785836125f5565b1461095e57600080fd5b33600090815260016020819052604090912001541561178c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f416c726561647920696e697469616c697a65640000000000000000000000000060448201526064016104d2565b81518111156117f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4465637265617365207468726573686f6c64000000000000000000000000000060448201526064016104d2565b6001811015611862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5468726573686f6c642073686f756c64206265206f6e652061746c656173740060448201526064016104d2565b600160005b8351811015611aad576000848281518110611884576118846125af565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156118e2575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015611904575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561193c57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b6119a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206f776e65720000000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529252909120541615611a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4f776e657220616c72656164792070726573656e74000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff9687168452909152902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169382169390931790925580611aa5816124b5565b915050611867565b5033600081815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff969096168452858252832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168317905595519290915293849052600282015590910155565b606060008036818181611b34610140890189612630565b9092509050611b4760066000838561269c565b611b50916126c6565b60d01c9550611b63600c6006838561269c565b611b6c916126c6565b60d01c9450366000611b8183600c818761269c565b909250905081600082611b95601482612567565b92611ba29392919061269c565b95509550505050506000604051806101c001604052807f84aa190356f56b8c87825f54884392a9907c23ee0f8e1ea86336b763faf021bd8152602001886000016020810190611bf19190612175565b73ffffffffffffffffffffffffffffffffffffffff16815260200188602001358152602001888060400190611c269190612630565b604051611c3492919061270e565b6040519081900390208152602001611c4f60608a018a612630565b604051611c5d92919061270e565b60405180910390208152602001886080013581526020018860a0013581526020018860c0013581526020018860e001358152602001886101000135815260200188806101200190611cae9190612630565b604051611cbc92919061270e565b6040805191829003909120825265ffffffffffff808916602084015287169082015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166060909101526101c081209091507f19000000000000000000000000000000000000000000000000000000000000007f0100000000000000000000000000000000000000000000000000000000000000611dc1604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529650505091939590929450565b600080600080600085806020019051810190611e3d9190612799565b93509350935093506000611e5985805190602001208684610beb565b90508015611e6a5760009550611e6f565b600195505b5050505050919050565b600080600080366000611e8b87611b1d565b945094509450945094506000611edf86805190602001208785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610beb92505050565b90508015611efa57611ef360008587611f14565b9650611f09565b611f0660018587611f14565b96505b505050505050919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85611f3c576000611f3f565b60015b60ff161717949350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611f7057600080fd5b919050565b60008060408385031215611f8857600080fd5b611f9183611f4c565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561201557612015611f9f565b604052919050565b600067ffffffffffffffff82111561203757612037611f9f565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261207457600080fd5b81356120876120828261201d565b611fce565b81815284602083860101111561209c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156120cf57600080fd5b84359350602085013567ffffffffffffffff808211156120ee57600080fd5b6120fa88838901612063565b9450604087013591508082111561211057600080fd5b5061211d87828801612063565b949793965093946060013593505050565b6000806040838503121561214157600080fd5b82359150602083013567ffffffffffffffff81111561215f57600080fd5b61216b85828601612063565b9150509250929050565b60006020828403121561218757600080fd5b61095e82611f4c565b6000806000604084860312156121a557600080fd5b833567ffffffffffffffff808211156121bd57600080fd5b818601915086601f8301126121d157600080fd5b8135818111156121e057600080fd5b8760208260051b85010111156121f557600080fd5b6020928301989097509590910135949350505050565b60006020828403121561221d57600080fd5b5035919050565b6000806040838503121561223757600080fd5b61224083611f4c565b915061224e60208401611f4c565b90509250929050565b60008060006060848603121561226c57600080fd5b83359250602084013567ffffffffffffffff8082111561228b57600080fd5b61229787838801612063565b935060408601359150808211156122ad57600080fd5b506122ba86828701612063565b9150509250925092565b600061016082840312156122d757600080fd5b50919050565b6000602082840312156122ef57600080fd5b813567ffffffffffffffff81111561230657600080fd5b612312848285016122c4565b949350505050565b60008060006060848603121561232f57600080fd5b61233884611f4c565b925061234660208501611f4c565b915061235460408501611f4c565b90509250925092565b60008060006060848603121561237257600080fd5b83359250602084013567ffffffffffffffff81111561239057600080fd5b61239c86828701612063565b92505061235460408501611f4c565b6000806000606084860312156123c057600080fd5b6123c984611f4c565b92506123d760208501611f4c565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561243557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612403565b50909695505050505050565b6000806040838503121561245457600080fd5b823567ffffffffffffffff81111561246b57600080fd5b612477858286016122c4565b95602094909401359450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036124e6576124e6612486565b5060010190565b60ff828116828216039081111561096157610961612486565b6040808252810183905260008460608301825b868110156125545773ffffffffffffffffffffffffffffffffffffffff61253f84611f4c565b16825260209283019290910190600101612519565b5060209390930193909352509392505050565b8181038181111561096157610961612486565b60008161258957612589612486565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808202811582820484141761096157610961612486565b60008261262b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261266557600080fd5b83018035915067ffffffffffffffff82111561268057600080fd5b60200191503681900382131561269557600080fd5b9250929050565b600080858511156126ac57600080fd5b838611156126b957600080fd5b5050820193919092039150565b7fffffffffffff000000000000000000000000000000000000000000000000000081358181169160068510156127065780818660060360031b1b83161692505b505092915050565b8183823760009101908152919050565b600082601f83011261272f57600080fd5b815161273d6120828261201d565b8181526020858184870101111561275357600080fd5b60005b83811015612771578581018201518382018301528101612756565b50600092820101919091529392505050565b805165ffffffffffff81168114611f7057600080fd5b600080600080608085870312156127af57600080fd5b845167ffffffffffffffff808211156127c757600080fd5b6127d38883890161271e565b95506127e160208801612783565b94506127ef60408801612783565b9350606087015191508082111561280557600080fd5b506128128782880161271e565b9150509295919450925056fea26469706673582212203b668abc8bac7f0eae5c009377c2ccd3ba23dcdb9c4b8a148d6951d50fe2f4ef64736f6c634300081400330000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063934f3a11116100cd578063f44c339d11610081578063f8dc5dd911610066578063f8dc5dd9146103c3578063fd8b84b1146103d6578063fff35b72146103f657600080fd5b8063f44c339d14610354578063f698da251461036757600080fd5b8063cc1b5475116100b2578063cc1b5475146102ed578063e318b52b1461032e578063e89b0e1e1461034157600080fd5b8063934f3a11146102c7578063b25f3776146102da57600080fd5b80631d65ea0511610124578063694e80c311610109578063694e80c314610259578063789771681461026c5780637ddc02d4146102b457600080fd5b80631d65ea05146102135780634ab884271461024657600080fd5b80630d582f131461015657806312fb68e01461016b578063137e051e1461017e5780631626ba7e146101cf575b600080fd5b610169610164366004611f75565b610409565b005b6101696101793660046120b9565b610671565b6101a57f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278981565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101e26101dd36600461212e565b610951565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016101c6565b610236610221366004612175565b60006020819052908152604090205460ff1681565b60405190151581526020016101c6565b6101a5610254366004612190565b610967565b61016961026736600461220b565b610a25565b6102a661027a366004612175565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160208190526040909120015490565b6040519081526020016101c6565b6102366102c2366004612224565b610b8d565b6102366102d5366004612257565b610beb565b6102a66102e83660046122dd565b610c7c565b6103196102fb366004612175565b60016020819052600091825260409091209081015460029091015482565b604080519283526020830191909152016101c6565b61016961033c36600461231a565b610c9e565b61016961034f366004612175565b611048565b6101e261036236600461235d565b6111cc565b6102a6604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6101696103d13660046123ab565b61122d565b6103e96103e4366004612175565b6114fc565b6040516101c691906123e7565b6102a6610404366004612441565b611636565b6104123361164a565b73ffffffffffffffffffffffffffffffffffffffff82161580159061044e575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015610470575073ffffffffffffffffffffffffffffffffffffffff82163014155b6104db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206f776e65720000000000000000000000000000000000000060448201526064015b60405180910390fd5b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff86811685529252909120541615610575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4475706c6963617465206f776e6572000000000000000000000000000000000060448201526064016104d2565b336000818152600160208181526040808420838552808352818520805473ffffffffffffffffffffffffffffffffffffffff8a81168089529488208054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091558154169092179091559383525260029091018054916105fc836124b5565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a13360009081526001602081905260409091200154811461066d5761066d81610a25565b5050565b61067c8160416116dc565b825110156106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c696420696e7075747300000000000000000000000000000000000060448201526064016104d2565b6000808060008060005b86811015610945576041818102890160208101516040820151919092015160ff1695509093509150601e8411156107da576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c016040516020818303038152906040528051906020012060048661077a91906124ed565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156107c9573d6000803e3d6000fd5b50505060206040510351945061083a565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561082d573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161180156108a6575033600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff89811685529252909120541615155b80156108c9575073ffffffffffffffffffffffffffffffffffffffff8516600114155b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e6f742061206f776e657200000000000000000000000000000000000000000060448201526064016104d2565b849550808061093d906124b5565b9150506106f0565b50505050505050505050565b600061095e8383336111cc565b90505b92915050565b60006109a7848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250869250611711915050565b336000818152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f9f7ea12b584e639128b2cae69de6ca3335a28b01235291afa40ce814fdf65f3590610a1390879087908790612506565b60405180910390a250305b9392505050565b610a2e3361164a565b33600090815260016020526040902060020154811115610ad0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5468726573686f6c642073686f756c64206265206c657373207468616e206f7760448201527f6e65727320636f756e740000000000000000000000000000000000000000000060648201526084016104d2565b6001811015610b3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5468726573686f6c642073686f756c642062652061746c65617374206f6e650060448201526064016104d2565b3360009081526001602081905260409182902001829055517f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c9390610b829083815260200190565b60405180910390a150565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061095e57505073ffffffffffffffffffffffffffffffffffffffff91821660009081526001602090815260408083209385168352929052205416151590565b3360009081526001602081905260408220015480610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5468726573686f6c64206973207a65726f00000000000000000000000000000060448201526064016104d2565b610c7185858584610671565b506001949350505050565b600080610c8883611b1d565b5050505090508080519060200120915050919050565b610ca73361164a565b73ffffffffffffffffffffffffffffffffffffffff811615801590610ce3575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015610d05575073ffffffffffffffffffffffffffffffffffffffff81163014155b610d6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529252909120541615610e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f416c72656164792061206f776e6572000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff821615801590610e41575073ffffffffffffffffffffffffffffffffffffffff8216600114155b610ea7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8781168552925290912054811690831614610f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c696420706f696e746572206164647265737300000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff868116808652918452828520805487831680885285882080549285167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179055928a1687528487208054821690931790925594829052845416909355519182527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf910160405180910390a160405173ffffffffffffffffffffffffffffffffffffffff821681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a1505050565b6110513361164a565b73ffffffffffffffffffffffffffffffffffffffff81166110ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a65726f2061646472657373000000000000000000000000000000000000000060448201526064016104d2565b60008173ffffffffffffffffffffffffffffffffffffffff163b1161114f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f74206120636f6e747261637400000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff81166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182527f016c6c81185d9d57ee95b405e66dcd24b95197e63995a3c3fdf91d58dbf912d89101610b82565b6000806111d884611e21565b0361120457507f1626ba7e00000000000000000000000000000000000000000000000000000000610a1e565b507fffffffff000000000000000000000000000000000000000000000000000000009392505050565b6112363361164a565b33600090815260016020819052604090912060020154829161125791612567565b10156112bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f56696f6c6174696e67206f776e6572000000000000000000000000000000000060448201526064016104d2565b73ffffffffffffffffffffffffffffffffffffffff8216158015906112fb575073ffffffffffffffffffffffffffffffffffffffff8216600114155b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4f776e657220696e76616c69640000000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87811685529252909120548116908316146113ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642070726576696f7573206f776e65720000000000000000000060448201526064016104d2565b33600081815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff888116865281845282862080548b831688529387208054949092167fffffffffffffffffffffffff00000000000000000000000000000000000000009485161790915580549092169091559383525260029091018054916114868361257a565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf9060200160405180910390a1336000908152600160208190526040909120015481146114f7576114f781610a25565b505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600160205260408120600201546060919067ffffffffffffffff81111561154157611541611f9f565b60405190808252806020026020018201604052801561156a578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808516600090815260016020818152604080842092845291905281205492935091165b73ffffffffffffffffffffffffffffffffffffffff811660011461162d57808383815181106115d4576115d46125af565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152868216600090815260018252604080822094841682529390915291909120541681611625816124b5565b9250506115a3565b50909392505050565b60006116413361164a565b61095e83611e79565b73ffffffffffffffffffffffffffffffffffffffff811660009081526020819052604090205460ff166116d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536d617274206163636f756e74206e6f7420737570706f72746564000000000060448201526064016104d2565b50565b6000826000036116ee57506000610961565b60006116fa83856125de565b90508261170785836125f5565b1461095e57600080fd5b33600090815260016020819052604090912001541561178c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f416c726561647920696e697469616c697a65640000000000000000000000000060448201526064016104d2565b81518111156117f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4465637265617365207468726573686f6c64000000000000000000000000000060448201526064016104d2565b6001811015611862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5468726573686f6c642073686f756c64206265206f6e652061746c656173740060448201526064016104d2565b600160005b8351811015611aad576000848281518110611884576118846125af565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156118e2575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015611904575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561193c57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b6119a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c6964206f776e65720000000000000000000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529252909120541615611a3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4f776e657220616c72656164792070726573656e74000000000000000000000060448201526064016104d2565b33600090815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff9687168452909152902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169382169390931790925580611aa5816124b5565b915050611867565b5033600081815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff969096168452858252832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168317905595519290915293849052600282015590910155565b606060008036818181611b34610140890189612630565b9092509050611b4760066000838561269c565b611b50916126c6565b60d01c9550611b63600c6006838561269c565b611b6c916126c6565b60d01c9450366000611b8183600c818761269c565b909250905081600082611b95601482612567565b92611ba29392919061269c565b95509550505050506000604051806101c001604052807f84aa190356f56b8c87825f54884392a9907c23ee0f8e1ea86336b763faf021bd8152602001886000016020810190611bf19190612175565b73ffffffffffffffffffffffffffffffffffffffff16815260200188602001358152602001888060400190611c269190612630565b604051611c3492919061270e565b6040519081900390208152602001611c4f60608a018a612630565b604051611c5d92919061270e565b60405180910390208152602001886080013581526020018860a0013581526020018860c0013581526020018860e001358152602001886101000135815260200188806101200190611cae9190612630565b604051611cbc92919061270e565b6040805191829003909120825265ffffffffffff808916602084015287169082015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789166060909101526101c081209091507f19000000000000000000000000000000000000000000000000000000000000007f0100000000000000000000000000000000000000000000000000000000000000611dc1604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529650505091939590929450565b600080600080600085806020019051810190611e3d9190612799565b93509350935093506000611e5985805190602001208684610beb565b90508015611e6a5760009550611e6f565b600195505b5050505050919050565b600080600080366000611e8b87611b1d565b945094509450945094506000611edf86805190602001208785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610beb92505050565b90508015611efa57611ef360008587611f14565b9650611f09565b611f0660018587611f14565b96505b505050505050919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85611f3c576000611f3f565b60015b60ff161717949350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611f7057600080fd5b919050565b60008060408385031215611f8857600080fd5b611f9183611f4c565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561201557612015611f9f565b604052919050565b600067ffffffffffffffff82111561203757612037611f9f565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261207457600080fd5b81356120876120828261201d565b611fce565b81815284602083860101111561209c57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080608085870312156120cf57600080fd5b84359350602085013567ffffffffffffffff808211156120ee57600080fd5b6120fa88838901612063565b9450604087013591508082111561211057600080fd5b5061211d87828801612063565b949793965093946060013593505050565b6000806040838503121561214157600080fd5b82359150602083013567ffffffffffffffff81111561215f57600080fd5b61216b85828601612063565b9150509250929050565b60006020828403121561218757600080fd5b61095e82611f4c565b6000806000604084860312156121a557600080fd5b833567ffffffffffffffff808211156121bd57600080fd5b818601915086601f8301126121d157600080fd5b8135818111156121e057600080fd5b8760208260051b85010111156121f557600080fd5b6020928301989097509590910135949350505050565b60006020828403121561221d57600080fd5b5035919050565b6000806040838503121561223757600080fd5b61224083611f4c565b915061224e60208401611f4c565b90509250929050565b60008060006060848603121561226c57600080fd5b83359250602084013567ffffffffffffffff8082111561228b57600080fd5b61229787838801612063565b935060408601359150808211156122ad57600080fd5b506122ba86828701612063565b9150509250925092565b600061016082840312156122d757600080fd5b50919050565b6000602082840312156122ef57600080fd5b813567ffffffffffffffff81111561230657600080fd5b612312848285016122c4565b949350505050565b60008060006060848603121561232f57600080fd5b61233884611f4c565b925061234660208501611f4c565b915061235460408501611f4c565b90509250925092565b60008060006060848603121561237257600080fd5b83359250602084013567ffffffffffffffff81111561239057600080fd5b61239c86828701612063565b92505061235460408501611f4c565b6000806000606084860312156123c057600080fd5b6123c984611f4c565b92506123d760208501611f4c565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561243557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612403565b50909695505050505050565b6000806040838503121561245457600080fd5b823567ffffffffffffffff81111561246b57600080fd5b612477858286016122c4565b95602094909401359450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036124e6576124e6612486565b5060010190565b60ff828116828216039081111561096157610961612486565b6040808252810183905260008460608301825b868110156125545773ffffffffffffffffffffffffffffffffffffffff61253f84611f4c565b16825260209283019290910190600101612519565b5060209390930193909352509392505050565b8181038181111561096157610961612486565b60008161258957612589612486565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b808202811582820484141761096157610961612486565b60008261262b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261266557600080fd5b83018035915067ffffffffffffffff82111561268057600080fd5b60200191503681900382131561269557600080fd5b9250929050565b600080858511156126ac57600080fd5b838611156126b957600080fd5b5050820193919092039150565b7fffffffffffff000000000000000000000000000000000000000000000000000081358181169160068510156127065780818660060360031b1b83161692505b505092915050565b8183823760009101908152919050565b600082601f83011261272f57600080fd5b815161273d6120828261201d565b8181526020858184870101111561275357600080fd5b60005b83811015612771578581018201518382018301528101612756565b50600092820101919091529392505050565b805165ffffffffffff81168114611f7057600080fd5b600080600080608085870312156127af57600080fd5b845167ffffffffffffffff808211156127c757600080fd5b6127d38883890161271e565b95506127e160208801612783565b94506127ef60408801612783565b9350606087015191508082111561280557600080fd5b506128128782880161271e565b9150509295919450925056fea26469706673582212203b668abc8bac7f0eae5c009377c2ccd3ba23dcdb9c4b8a148d6951d50fe2f4ef64736f6c63430008140033

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

0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789

-----Decoded View---------------
Arg [0] : entryPoint (address): 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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.