ETH Price: $1,915.70 (-5.39%)

Contract

0x07778F459D18F73Ee7723C53aD3AA66634269C98
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60c06040180101342023-08-28 2:23:11578 days ago1693189391  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WalletFactory

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion
File 1 of 13 : WalletFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "../iface/ILoopringWalletV2.sol";
import "../lib/EIP712.sol";
import "../lib/SignatureUtil.sol";
import "./WalletDeploymentLib.sol";
import "../lib/Ownable.sol";
import "../lib/AddressSet.sol";


/// @title WalletFactory
/// @dev A factory contract to create a new wallet by deploying a proxy
///      in front of a real wallet.
/// @author Daniel Wang - <[email protected]>
contract WalletFactory is WalletDeploymentLib, Ownable, AddressSet
{

    bytes32 internal constant OPERATOR = keccak256("__OPERATOR__");
    using SignatureUtil for bytes32;

    event WalletCreated (address wallet, address owner);

    event OperatorRemoved  (address indexed operator);
    event OperatorAdded(address indexed operator);

    bytes32             public immutable DOMAIN_SEPARATOR;

    bytes32 public constant CREATE_WALLET_TYPEHASH = keccak256(
        "createWallet(address owner,address[] guardians,uint256 quota,address inheritor,address feeRecipient,address feeToken,uint256 maxFeeAmount,uint256 salt)");

    ///////////////////////////////// opeartor ///////////////////
    modifier onlyOperator
    {
        require(isOperator(msg.sender), "DISALLOWED_ON_IMPLEMENTATION_CONTRACT");
        _;
    }

    function isOperator(address addr)
        public
        view
        returns (bool)
    {
        return isAddressInSet(OPERATOR, addr);
    }

    /// @dev Gets the operators.
    /// @return The list of operators.
    function operators()
        public
        view
        returns (address[] memory)
    {
        return addressesInSet(OPERATOR);
    }

    /// @dev Gets the number of operators.
    /// @return The numer of operators.
    function numOperators()
        public
        view
        returns (uint)
    {
        return numAddressesInSet(OPERATOR);
    }

    /// @dev Adds a new operator.
    /// @param operator The new address to add.
    function addOperator(address operator)
        public
        onlyOwner
    {
        addOperatorInternal(operator);
    }

    /// @dev Removes a operator.
    /// @param operator The operator to remove.
    function removeOperator(address operator)
        public
        onlyOwner
    {
        removeAddressFromSet(OPERATOR, operator);
        emit OperatorRemoved(operator);
    }

    function addOperatorInternal(address operator)
        internal
    {
        addAddressToSet(OPERATOR, operator, true);
        emit OperatorAdded(operator);
    }

    struct WalletConfig
    {
        address   owner;
        address[] guardians;
        uint      quota;
        address   inheritor;
        address   feeRecipient;
        address   feeToken;
        uint      maxFeeAmount;
        uint      salt;
        bytes     signature;
    }

    struct WalletConfigV2
    {
        address   owner;
        address   initOwner;
        address[] guardians;
        uint      quota;
        address   inheritor;
        address   feeRecipient;
        address   feeToken;
        uint      maxFeeAmount;
        uint      salt;
    }

    constructor(
        address        _walletImplementation
        )
        WalletDeploymentLib(_walletImplementation)
    {
        DOMAIN_SEPARATOR = EIP712.hash(
            EIP712.Domain("WalletFactory", "2.0.0", address(this))
        );
    }

    /// @dev Create a new wallet by deploying a proxy.
    /// @param config The wallet's config.
    /// @param feeAmount The fee amount actually paid.
    /// @return wallet The new wallet address
    function createWallet(
        WalletConfig calldata config,
        uint                  feeAmount
        )
        onlyOperator
        external
        returns (address wallet)
    {
        require(feeAmount <= config.maxFeeAmount, "INVALID_FEE_AMOUNT");

        _validateConfig(config);
        wallet = _deploy(config.owner, config.salt);
        _initializeWallet(wallet, config, feeAmount);
    }

    /// @dev Create a new wallet by deploying a proxy.
    /// @param config The wallet's config.
    /// @param feeAmount The fee amount actually paid.
    /// @return wallet The new wallet address
    function createWalletByOperator(
        WalletConfigV2 calldata config,
        uint                  feeAmount
        )
        onlyOperator
        external
        returns (address wallet)
    {
        require(feeAmount <= config.maxFeeAmount, "INVALID_FEE_AMOUNT");

        require(config.owner != address(0), "INVALID_OWNER");
        wallet = _deploy(config.initOwner, config.salt);
        ILoopringWalletV2(wallet).initialize(
            config.owner,
            config.guardians,
            config.quota,
            config.inheritor,
            config.feeRecipient,
            config.feeToken,
            feeAmount
        );

        emit WalletCreated(wallet, config.owner);
    }

    /// @dev Computes the wallet address
    /// @param salt The initial wallet owner.
    /// @param salt A salt.
    /// @return wallet The wallet address
    function computeWalletAddress(
        address owner,
        uint    salt
        )
        public
        view
        returns (address)
    {
        return _computeWalletAddress(
            owner,
            salt,
            address(this)
        );
    }

    // --- Internal functions ---

    function _initializeWallet(
        address               wallet,
        WalletConfig calldata config,
        uint                  feeAmount
        )
        internal
    {
        ILoopringWalletV2(wallet).initialize(
            config.owner,
            config.guardians,
            config.quota,
            config.inheritor,
            config.feeRecipient,
            config.feeToken,
            feeAmount
        );

        emit WalletCreated(wallet, config.owner);
    }

    function _validateConfig(
        WalletConfig calldata config
        )
        private
        view
    {
        require(config.owner != address(0), "INVALID_OWNER");

        bytes32 dataHash = keccak256(
            abi.encode(
                CREATE_WALLET_TYPEHASH,
                config.owner,
                keccak256(abi.encodePacked(config.guardians)),
                config.quota,
                config.inheritor,
                config.feeRecipient,
                config.feeToken,
                config.maxFeeAmount,
                config.salt
            )
        );

        bytes32 signHash = EIP712.hashPacked(DOMAIN_SEPARATOR, dataHash);
        require(signHash.verifySignature(config.owner, config.signature), "INVALID_SIGNATURE");
    }
}

File 2 of 13 : WalletDeploymentLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "../thirdparty/Create2.sol";
import "../thirdparty/proxies/WalletProxy.sol";


/// @title WalletDeploymentLib
/// @dev Functionality to compute wallet addresses and to deploy wallets
/// @author Brecht Devos - <[email protected]>
contract WalletDeploymentLib
{
    address public immutable walletImplementation;

    string  public constant WALLET_CREATION = "WALLET_CREATION";

    constructor(
        address _walletImplementation
        )
    {
        walletImplementation = _walletImplementation;
    }

    function getWalletCode()
        public
        view
        returns (bytes memory)
    {
        return abi.encodePacked(
            type(WalletProxy).creationCode,
            abi.encode(walletImplementation)
        );
    }

    function computeWalletSalt(
        address owner,
        uint    salt
        )
        public
        pure
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                WALLET_CREATION,
                owner,
                salt
            )
        );
    }

    function _deploy(
        address owner,
        uint    salt
        )
        internal
        returns (address payable wallet)
    {
        wallet = Create2.deploy(
            computeWalletSalt(owner, salt),
            getWalletCode()
        );
    }

    function _computeWalletAddress(
        address owner,
        uint    salt,
        address deployer
        )
        internal
        view
        returns (address)
    {
        return Create2.computeAddress(
            computeWalletSalt(owner, salt),
            getWalletCode(),
            deployer
        );
    }
}

File 3 of 13 : ILoopringWalletV2.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @title Loopring SmartWallet V2 interface
/// @author Brecht Devos - <[email protected]>
abstract contract ILoopringWalletV2
{
    /// @dev Initializes the smart wallet.
    /// @param owner The wallet owner address.
    /// @param guardians The initial wallet guardians.
    /// @param quota The initial wallet quota.
    /// @param inheritor The inheritor of the wallet.
    /// @param feeRecipient The address receiving the fee for creating the wallet.
    /// @param feeToken The token to use for the fee payment.
    /// @param feeAmount The amount of tokens paid to the fee recipient.
    function initialize(
        address             owner,
        address[] calldata  guardians,
        uint                quota,
        address             inheritor,
        address             feeRecipient,
        address             feeToken,
        uint                feeAmount
        )
        external
        virtual;

    /// @dev Returns the timestamp the wallet was created.
    /// @return The timestamp the wallet was created.
    function getCreationTimestamp()
        public
        view
        virtual
        returns (uint64);

    /// @dev Returns the current wallet owner.
    /// @return The current wallet owner.
    function getOwner()
        public
        view
        virtual
        returns (address);
}

File 4 of 13 : AddressSet.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @title AddressSet
/// @author Daniel Wang - <[email protected]>
contract AddressSet
{
    struct Set
    {
        address[] addresses;
        mapping (address => uint) positions;
        uint count;
    }
    mapping (bytes32 => Set) private sets;

    function addAddressToSet(
        bytes32 key,
        address addr,
        bool    maintainList
        ) internal
    {
        Set storage set = sets[key];
        require(set.positions[addr] == 0, "ALREADY_IN_SET");

        if (maintainList) {
            require(set.addresses.length == set.count, "PREVIOUSLY_NOT_MAINTAILED");
            set.addresses.push(addr);
        } else {
            require(set.addresses.length == 0, "MUST_MAINTAIN");
        }

        set.count += 1;
        set.positions[addr] = set.count;
    }

    function removeAddressFromSet(
        bytes32 key,
        address addr
        )
        internal
    {
        Set storage set = sets[key];
        uint pos = set.positions[addr];
        require(pos != 0, "NOT_IN_SET");

        delete set.positions[addr];
        set.count -= 1;

        if (set.addresses.length > 0) {
            address lastAddr = set.addresses[set.count];
            if (lastAddr != addr) {
                set.addresses[pos - 1] = lastAddr;
                set.positions[lastAddr] = pos;
            }
            set.addresses.pop();
        }
    }

    function removeSet(bytes32 key)
        internal
    {
        delete sets[key];
    }

    function isAddressInSet(
        bytes32 key,
        address addr
        )
        internal
        view
        returns (bool)
    {
        return sets[key].positions[addr] != 0;
    }

    function numAddressesInSet(bytes32 key)
        internal
        view
        returns (uint)
    {
        Set storage set = sets[key];
        return set.count;
    }

    function addressesInSet(bytes32 key)
        internal
        view
        returns (address[] memory)
    {
        Set storage set = sets[key];
        require(set.count == set.addresses.length, "NOT_MAINTAINED");
        return sets[key].addresses;
    }
}

File 5 of 13 : AddressUtil.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @title Utility Functions for addresses
/// @author Daniel Wang - <[email protected]>
/// @author Brecht Devos - <[email protected]>
library AddressUtil
{
    using AddressUtil for *;

    function isContract(
        address addr
        )
        internal
        view
        returns (bool)
    {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(addr) }
        return (codehash != 0x0 &&
                codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470);
    }

    function toPayable(
        address addr
        )
        internal
        pure
        returns (address payable)
    {
        return payable(addr);
    }

    // Works like address.send but with a customizable gas limit
    // Make sure your code is safe for reentrancy when using this function!
    function sendETH(
        address to,
        uint    amount,
        uint    gasLimit
        )
        internal
        returns (bool success)
    {
        if (amount == 0) {
            return true;
        }
        address payable recipient = to.toPayable();
        /* solium-disable-next-line */
        (success,) = recipient.call{value: amount, gas: gasLimit}("");
    }

    // Works like address.transfer but with a customizable gas limit
    // Make sure your code is safe for reentrancy when using this function!
    function sendETHAndVerify(
        address to,
        uint    amount,
        uint    gasLimit
        )
        internal
        returns (bool success)
    {
        success = to.sendETH(amount, gasLimit);
        require(success, "TRANSFER_FAILURE");
    }

    // Works like call but is slightly more efficient when data
    // needs to be copied from memory to do the call.
    function fastCall(
        address to,
        uint    gasLimit,
        uint    value,
        bytes   memory data
        )
        internal
        returns (bool success, bytes memory returnData)
    {
        if (to != address(0)) {
            assembly {
                // Do the call
                success := call(gasLimit, to, value, add(data, 32), mload(data), 0, 0)
                // Copy the return data
                let size := returndatasize()
                returnData := mload(0x40)
                mstore(returnData, size)
                returndatacopy(add(returnData, 32), 0, size)
                // Update free memory pointer
                mstore(0x40, add(returnData, add(32, size)))
            }
        }
    }

    // Like fastCall, but throws when the call is unsuccessful.
    function fastCallAndVerify(
        address to,
        uint    gasLimit,
        uint    value,
        bytes   memory data
        )
        internal
        returns (bytes memory returnData)
    {
        bool success;
        (success, returnData) = fastCall(to, gasLimit, value, data);
        if (!success) {
            assembly {
                revert(add(returnData, 32), mload(returnData))
            }
        }
    }
}

File 6 of 13 : EIP712.sol
// SPDX-License-Identifier: Apache-2.0
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;


library EIP712
{
    struct Domain {
        string  name;
        string  version;
        address verifyingContract;
    }

    bytes32 constant internal EIP712_DOMAIN_TYPEHASH = keccak256(
        "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
    );

    string constant internal EIP191_HEADER = "\x19\x01";

    function hash(Domain memory domain)
        internal
        pure
        returns (bytes32)
    {
        uint _chainid;
        assembly { _chainid := chainid() }

        return keccak256(
            abi.encode(
                EIP712_DOMAIN_TYPEHASH,
                keccak256(bytes(domain.name)),
                keccak256(bytes(domain.version)),
                _chainid,
                domain.verifyingContract
            )
        );
    }

    function hashPacked(
        bytes32 domainSeparator,
        bytes32 dataHash
        )
        internal
        pure
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                EIP191_HEADER,
                domainSeparator,
                dataHash
            )
        );
    }
}

File 7 of 13 : ERC1271.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;

abstract contract ERC1271 {
    // bytes4(keccak256("isValidSignature(bytes32,bytes)")
    bytes4 constant internal ERC1271_MAGICVALUE = 0x1626ba7e;

    function isValidSignature(
        bytes32      _hash,
        bytes memory _signature)
        public
        view
        virtual
        returns (bytes4 magicValue);
}

File 8 of 13 : MathUint.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @title Utility Functions for uint
/// @author Daniel Wang - <[email protected]>
library MathUint
{
    function mul(
        uint a,
        uint b
        )
        internal
        pure
        returns (uint c)
    {
        c = a * b;
        require(a == 0 || c / a == b, "MUL_OVERFLOW");
    }

    function sub(
        uint a,
        uint b
        )
        internal
        pure
        returns (uint)
    {
        require(b <= a, "SUB_UNDERFLOW");
        return a - b;
    }

    function add(
        uint a,
        uint b
        )
        internal
        pure
        returns (uint c)
    {
        c = a + b;
        require(c >= a, "ADD_OVERFLOW");
    }
}

File 9 of 13 : Ownable.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @title Ownable
/// @author Brecht Devos - <[email protected]>
/// @dev The Ownable contract has an owner address, and provides basic
///      authorization control functions, this simplifies the implementation of
///      "user permissions".
contract Ownable
{
    address public owner;

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

    /// @dev The Ownable constructor sets the original `owner` of the contract
    ///      to the sender.
    constructor()
    {
        owner = msg.sender;
    }

    /// @dev Throws if called by any account other than the owner.
    modifier onlyOwner()
    {
        require(msg.sender == owner, "UNAUTHORIZED");
        _;
    }

    /// @dev Allows the current owner to transfer control of the contract to a
    ///      new owner.
    /// @param newOwner The address to transfer ownership to.
    function transferOwnership(
        address newOwner
        )
        public
        virtual
        onlyOwner
    {
        require(newOwner != address(0), "ZERO_ADDRESS");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    function renounceOwnership()
        public
        onlyOwner
    {
        emit OwnershipTransferred(owner, address(0));
        owner = address(0);
    }
}

File 10 of 13 : SignatureUtil.sol
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "../thirdparty/BytesUtil.sol";
import "./AddressUtil.sol";
import "./ERC1271.sol";
import "./MathUint.sol";


/// @title SignatureUtil
/// @author Daniel Wang - <[email protected]>
/// @dev This method supports multihash standard. Each signature's last byte indicates
///      the signature's type.
library SignatureUtil
{
    using BytesUtil     for bytes;
    using MathUint      for uint;
    using AddressUtil   for address;

    enum SignatureType {
        ILLEGAL,
        INVALID,
        EIP_712,
        ETH_SIGN,
        WALLET   // deprecated
    }

    bytes4 constant internal ERC1271_MAGICVALUE = 0x1626ba7e;

    function verifySignatures(
        bytes32          signHash,
        address[] memory signers,
        bytes[]   memory signatures
        )
        internal
        view
        returns (bool)
    {
        require(signers.length == signatures.length, "BAD_SIGNATURE_DATA");
        address lastSigner;
        for (uint i = 0; i < signers.length; i++) {
            require(signers[i] > lastSigner, "INVALID_SIGNERS_ORDER");
            lastSigner = signers[i];
            if (!verifySignature(signHash, signers[i], signatures[i])) {
                return false;
            }
        }
        return true;
    }

    function verifySignature(
        bytes32        signHash,
        address        signer,
        bytes   memory signature
        )
        internal
        view
        returns (bool)
    {
        if (signer == address(0)) {
            return false;
        }

        return signer.isContract()?
            verifyERC1271Signature(signHash, signer, signature):
            verifyEOASignature(signHash, signer, signature);
    }

    function recoverECDSASigner(
        bytes32      signHash,
        bytes memory signature
        )
        internal
        pure
        returns (address)
    {
        if (signature.length != 65) {
            return address(0);
        }

        bytes32 r;
        bytes32 s;
        uint8   v;
        // we jump 32 (0x20) as the first slot of bytes contains the length
        // we jump 65 (0x41) per signature
        // for v we load 32 bytes ending with v (the first 31 come from s) then apply a mask
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := and(mload(add(signature, 0x41)), 0xff)
        }
        // See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return address(0);
        }
        if (v == 27 || v == 28) {
            return ecrecover(signHash, v, r, s);
        } else {
            return address(0);
        }
    }

    function verifyEOASignature(
        bytes32        signHash,
        address        signer,
        bytes   memory signature
        )
        private
        pure
        returns (bool success)
    {
        if (signer == address(0)) {
            return false;
        }

	require(signature.length == 65 || signature.length == 66, "INVALID_SIGNATURE_LENGTH");

	bool trimmed = false;
	if (signature.length == 66) {
	    // Strip off the last byte of the signature by updating the length
	    assembly {
		mstore(signature, 65)
	    }

	    trimmed = true;
	}

	success = (signer == recoverECDSASigner(signHash, signature));
	if (!success) {
            bytes32 hash = keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", signHash)
            );
            success = (signer == recoverECDSASigner(hash, signature));
        }

	if (trimmed) {
	    // Restore the signature length
	    assembly {
		mstore(signature, 66)
	    }
	}
    }

    function verifyERC1271Signature(
        bytes32 signHash,
        address signer,
        bytes   memory signature
        )
        private
        view
        returns (bool)
    {
        bytes memory callData = abi.encodeWithSelector(
            ERC1271.isValidSignature.selector,
            signHash,
            signature
        );
        (bool success, bytes memory result) = signer.staticcall(callData);
        return (
            success &&
            result.length == 32 &&
            result.toBytes4(0) == ERC1271_MAGICVALUE
        );
    }
}

File 11 of 13 : BytesUtil.sol
// SPDX-License-Identifier: UNLICENSED
// Taken from https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol
pragma solidity ^0.7.0;

library BytesUtil {
    function slice(
        bytes memory _bytes,
        uint _start,
        uint _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_bytes.length >= (_start + _length));

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint _start) internal  pure returns (address) {
        require(_bytes.length >= (_start + 20));
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint _start) internal  pure returns (uint8) {
        require(_bytes.length >= (_start + 1));
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint _start) internal  pure returns (uint16) {
        require(_bytes.length >= (_start + 2));
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint24(bytes memory _bytes, uint _start) internal  pure returns (uint24) {
        require(_bytes.length >= (_start + 3));
        uint24 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x3), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint _start) internal  pure returns (uint32) {
        require(_bytes.length >= (_start + 4));
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint _start) internal  pure returns (uint64) {
        require(_bytes.length >= (_start + 8));
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint _start) internal  pure returns (uint96) {
        require(_bytes.length >= (_start + 12));
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint _start) internal  pure returns (uint128) {
        require(_bytes.length >= (_start + 16));
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint(bytes memory _bytes, uint _start) internal  pure returns (uint256) {
        require(_bytes.length >= (_start + 32));
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes4(bytes memory _bytes, uint _start) internal  pure returns (bytes4) {
        require(_bytes.length >= (_start + 4));
        bytes4 tempBytes4;

        assembly {
            tempBytes4 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes4;
    }

    function toBytes32(bytes memory _bytes, uint _start) internal  pure returns (bytes32) {
        require(_bytes.length >= (_start + 32));
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function fastSHA256(
        bytes memory data
        )
        internal
        view
        returns (bytes32)
    {
        bytes32[] memory result = new bytes32[](1);
        bool success;
        assembly {
             let ptr := add(data, 32)
             success := staticcall(sub(gas(), 2000), 2, ptr, mload(data), add(result, 32), 32)
        }
        require(success, "SHA256_FAILED");
        return result[0];
    }
}

File 12 of 13 : Create2.sol
// SPDX-License-Identifier: UNLICENSED
// Taken from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/970f687f04d20e01138a3e8ccf9278b1d4b3997b/contracts/utils/Create2.sol

pragma solidity ^0.7.0;

/**
 * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
 * `CREATE2` can be used to compute in advance the address where a smart
 * contract will be deployed, which allows for interesting new mechanisms known
 * as 'counterfactual interactions'.
 *
 * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
 * information.
 */
library Create2 {
    /**
     * @dev Deploys a contract using `CREATE2`. The address where the contract
     * will be deployed can be known in advance via {computeAddress}. Note that
     * a contract cannot be deployed twice using the same salt.
     */
    function deploy(bytes32 salt, bytes memory bytecode) internal returns (address payable) {
        address payable addr;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
        }
        require(addr != address(0), "CREATE2_FAILED");
        return addr;
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the `bytecode`
     * or `salt` will result in a new destination address.
     */
    function computeAddress(bytes32 salt, bytes memory bytecode) internal view returns (address) {
        return computeAddress(salt, bytecode, address(this));
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
     * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
     */
    function computeAddress(bytes32 salt, bytes memory bytecodeHash, address deployer) internal pure returns (address) {
        bytes32 bytecodeHashHash = keccak256(bytecodeHash);
        bytes32 _data = keccak256(
            abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHashHash)
        );
        return address(bytes20(_data << 96));
    }
}

File 13 of 13 : WalletProxy.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
// Taken from: https://github.com/gnosis/safe-contracts/blob/development/contracts/proxies/GnosisSafeProxy.sol
pragma solidity ^0.7.0;

/// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain
/// @author Richard Meissner - <[email protected]>
interface IProxy {
    function masterCopy() external view returns (address);
}

/// @title WalletProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <[email protected]>
/// @author Richard Meissner - <[email protected]>
contract WalletProxy {

    // masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
    // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
    address internal masterCopy;

    /// @dev Constructor function sets address of master copy contract.
    /// @param _masterCopy Master copy address.
    constructor(address _masterCopy)
    {
        require(_masterCopy != address(0), "Invalid master copy address provided");
        masterCopy = _masterCopy;
    }

    /// @dev Fallback function forwards all transactions and returns all received return data.
    fallback()
        payable
        external
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            let _masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
            // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
            if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
                mstore(0, _masterCopy)
                return(0, 0x20)
            }
            calldatacopy(0, 0, calldatasize())
            let success := delegatecall(gas(), _masterCopy, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            if eq(success, 0) { revert(0, returndatasize()) }
            return(0, returndatasize())
        }
    }

    receive()
        external
        payable
    {
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_walletImplementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"WalletCreated","type":"event"},{"inputs":[],"name":"CREATE_WALLET_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WALLET_CREATION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"salt","type":"uint256"}],"name":"computeWalletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"salt","type":"uint256"}],"name":"computeWalletSalt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[]","name":"guardians","type":"address[]"},{"internalType":"uint256","name":"quota","type":"uint256"},{"internalType":"address","name":"inheritor","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"uint256","name":"maxFeeAmount","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct WalletFactory.WalletConfig","name":"config","type":"tuple"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"createWallet","outputs":[{"internalType":"address","name":"wallet","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"initOwner","type":"address"},{"internalType":"address[]","name":"guardians","type":"address[]"},{"internalType":"uint256","name":"quota","type":"uint256"},{"internalType":"address","name":"inheritor","type":"address"},{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"address","name":"feeToken","type":"address"},{"internalType":"uint256","name":"maxFeeAmount","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"}],"internalType":"struct WalletFactory.WalletConfigV2","name":"config","type":"tuple"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"createWalletByOperator","outputs":[{"internalType":"address","name":"wallet","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getWalletCode","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numOperators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b50604051620025633803806200256383398101604081905262000034916200014c565b606081811b6001600160601b031916608090815260008054336001600160a01b03199091161790556040805160a081018252600d9381019384526c57616c6c6574466163746f727960981b928101929092529181528151808301835260058152640322e302e360dc1b602080830191909152808301919091523092820192909252620000c991620000d3811b62000bb117901c565b60a05250620001a8565b6000804690507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8360000151805190602001208460200151805190602001208386604001516040516020016200012e9594939291906200017c565b60405160208183030381529060405280519060200120915050919050565b6000602082840312156200015e578081fd5b81516001600160a01b038116811462000175578182fd5b9392505050565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b60805160601c60a05161238a620001d96000398061024e528061107d5250806105d352806108ca525061238a6000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80639870d7fe116100b2578063ce15861211610081578063d92d1f5611610066578063d92d1f5614610211578063e673df8a14610224578063f2fde38b146102395761011b565b8063ce158612146101f6578063d70e2000146102095761011b565b80639870d7fe146101b5578063ac8a584a146101c8578063b6830d8f146101db578063bd820688146101ee5761011b565b8063715018a6116100ee578063715018a6146101865780638117abc1146101905780638da5cb5b1461019857806390610b0e146101a05761011b565b80633644e515146101205780634c30d6c91461013e5780635b29128f146101465780636d70f7ae14610166575b600080fd5b61012861024c565b6040516101359190611ec3565b60405180910390f35b610128610270565b610159610154366004611b8a565b610294565b6040516101359190611d73565b610179610174366004611b47565b6104a8565b6040516101359190611eb8565b61018e6104dc565b005b6101596105d1565b6101596105f5565b6101a8610611565b6040516101359190611f98565b61018e6101c3366004611b47565b61064a565b61018e6101d6366004611b47565b6106dc565b6101286101e9366004611b61565b6107d0565b61012861083b565b610159610204366004611b61565b61086b565b6101a861087f565b61015961021f366004611b8a565b610942565b61022c6109f1565b6040516101359190611e5e565b61018e610247366004611b47565b610a1c565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f4392cdd6c9d91e0896c5def13bad6473db5d21e2b0def85ab8c2475c3e60d14c81565b600061029f336104a8565b6102de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fe2565b60405180910390fd5b8260e0013582111561031c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fab565b600061032b6020850185611b47565b73ffffffffffffffffffffffffffffffffffffffff161415610379576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590612076565b61039761038c6040850160208601611b47565b846101000135610c28565b905073ffffffffffffffffffffffffffffffffffffffff811663d6bb65c26103c26020860186611b47565b6103cf60408701876120e4565b60608801356103e460a08a0160808b01611b47565b6103f460c08b0160a08c01611b47565b61040460e08c0160c08d01611b47565b8a6040518963ffffffff1660e01b8152600401610428989796959493929190611dbb565b600060405180830381600087803b15801561044257600080fd5b505af1158015610456573d6000803e3d6000fd5b507f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f081925083915061048c90506020860186611b47565b60405161049a929190611d94565b60405180910390a192915050565b60006104d47fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b0583610c44565b90505b919050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461056257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b7f000000000000000000000000000000000000000000000000000000000000000081565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600f81526020017f57414c4c45545f4352454154494f4e000000000000000000000000000000000081525081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b6106d981610c7e565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b61078c7fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b0582610cee565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d90600090a250565b60006040518060400160405280600f81526020017f57414c4c45545f4352454154494f4e0000000000000000000000000000000000815250838360405160200161081c93929190611cc9565b6040516020818303038152906040528051906020012090505b92915050565b60006108667fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b05610f09565b905090565b6000610878838330610f1e565b9392505050565b60606040518060200161089190611afe565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f9091011660408190526108f2907f000000000000000000000000000000000000000000000000000000000000000090602001611d73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261092e9291602001611c9a565b604051602081830303815290604052905090565b600061094d336104a8565b610983576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fe2565b8260c001358211156109c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fab565b6109ca83610f43565b6109e46109da6020850185611b47565b8460e00135610c28565b905061083581848461113b565b60606108667fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b05611249565b60005473ffffffffffffffffffffffffffffffffffffffff163314610aa257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610b2457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f414444524553530000000000000000000000000000000000000000604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000804690507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f836000015180519060200120846020015180519060200120838660400151604051602001610c0a959493929190611f28565b60405160208183030381529060405280519060200120915050919050565b6000610878610c3784846107d0565b610c3f61087f565b611346565b600082815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff861685529092019052902054151592915050565b610caa7fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b058260016113d7565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fac6fa858e9350a46cec16539926e0fde25b7629f84b5a72bffaae4df888ae86d90600090a250565b600082815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff861685529283019091529091205480610d8e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f494e5f53455400000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526001830160205260408120556002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055815415610f0357600082600001836002015481548110610dfc57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff908116915084168114610e9e5780836000016001840381548110610e3d57fe5b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918316815260018501909152604090208290555b8254839080610ea957fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b50505050565b60009081526001602052604090206002015490565b6000610f3b610f2d85856107d0565b610f3561087f565b846115f2565b949350505050565b6000610f526020830183611b47565b73ffffffffffffffffffffffffffffffffffffffff161415610fa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590612076565b60007f4392cdd6c9d91e0896c5def13bad6473db5d21e2b0def85ab8c2475c3e60d14c610fd06020840184611b47565b610fdd60208501856120e4565b604051602001610fee929190611c31565b60405160208183030381529060405280519060200120846040013585606001602081019061101c9190611b47565b61102c60a0880160808901611b47565b61103c60c0890160a08a01611b47565b8860c001358960e0013560405160200161105e99989796959493929190611ecc565b60405160208183030381529060405280519060200120905060006110a27f000000000000000000000000000000000000000000000000000000000000000083611691565b90506111006110b46020850185611b47565b6110c2610100860186612150565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508694939250506116dd9050565b611136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d59061203f565b505050565b73ffffffffffffffffffffffffffffffffffffffff831663d6bb65c26111646020850185611b47565b61117160208601866120e4565b60408701356111866080890160608a01611b47565b61119660a08a0160808b01611b47565b6111a660c08b0160a08c01611b47565b896040518963ffffffff1660e01b81526004016111ca989796959493929190611dbb565b600060405180830381600087803b1580156111e457600080fd5b505af11580156111f8573d6000803e3d6000fd5b507f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f081925085915061122e90506020850185611b47565b60405161123c929190611d94565b60405180910390a1505050565b60008181526001602052604090208054600282015460609291146112ce57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f4d41494e5441494e4544000000000000000000000000000000000000604482015290519081900360640190fd5b6000838152600160209081526040918290208054835181840281018401909452808452909183018282801561133957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161130e575b5050505050915050919050565b600080838351602085016000f5905073ffffffffffffffffffffffffffffffffffffffff811661087857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f435245415445325f4641494c4544000000000000000000000000000000000000604482015290519081900360640190fd5b600083815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff87168552928301909152909120541561147757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f414c52454144595f494e5f534554000000000000000000000000000000000000604482015290519081900360640190fd5b81156115455760028101548154146114f057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f50524556494f55534c595f4e4f545f4d41494e5441494c454400000000000000604482015290519081900360640190fd5b80546001810182556000828152602090200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790556115b3565b8054156115b357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4d5553545f4d41494e5441494e00000000000000000000000000000000000000604482015290519081900360640190fd5b60028101805460019081019182905573ffffffffffffffffffffffffffffffffffffffff90941660009081529190930160205260409020919091555050565b8151602092830120604080517fff000000000000000000000000000000000000000000000000000000000000008186015260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660218401526035830194909452605580830191909152835180830390910181526075909101909252815191012073ffffffffffffffffffffffffffffffffffffffff1690565b60006040518060400160405280600281526020017f1901000000000000000000000000000000000000000000000000000000000000815250838360405160200161081c93929190611d1b565b600073ffffffffffffffffffffffffffffffffffffffff831661170257506000610878565b6117218373ffffffffffffffffffffffffffffffffffffffff16611740565b61173557611730848484611777565b610f3b565b610f3b8484846118b0565b6000813f801580159061087857507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141592915050565b600073ffffffffffffffffffffffffffffffffffffffff831661179c57506000610878565b8151604114806117ad575081516042145b6117e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d5906120ad565b60008251604214156117f757506041825260015b6118018584611a0a565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161491508161189d576000856040516020016118499190611d42565b60405160208183030381529060405280519060200120905061186b8185611a0a565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16149250505b80156118a857604283525b509392505050565b600080631626ba7e60e01b85846040516024016118ce929190611f61565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000808573ffffffffffffffffffffffffffffffffffffffff16836040516119559190611c7e565b600060405180830381855afa9150503d8060008114611990576040519150601f19603f3d011682016040523d82523d6000602084013e611995565b606091505b50915091508180156119a8575080516020145b80156119ff57507f1626ba7e000000000000000000000000000000000000000000000000000000006119db826000611ae2565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b979650505050505050565b60008151604114611a1d57506000610835565b60208201516040830151604184015160ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611a635760009350505050610835565b8060ff16601b1480611a7857508060ff16601c145b15611ad65760018682858560405160008152602001604052604051611aa09493929190611f7a565b6020604051602081039080840390855afa158015611ac2573d6000803e3d6000fd5b505050602060405103519350505050610835565b60009350505050610835565b60008160040183511015611af557600080fd5b50016020015190565b610175806121e083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146104d757600080fd5b60006101208284031215611b41578081fd5b50919050565b600060208284031215611b58578081fd5b61087882611b0b565b60008060408385031215611b73578081fd5b611b7c83611b0b565b946020939093013593505050565b60008060408385031215611b9c578182fd5b823567ffffffffffffffff811115611bb2578283fd5b611bbe85828601611b2f565b95602094909401359450505050565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452611bff8160208601602086016121b3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008184825b85811015611c735773ffffffffffffffffffffffffffffffffffffffff611c5d83611b0b565b1683526020928301929190910190600101611c37565b509095945050505050565b60008251611c908184602087016121b3565b9190910192915050565b60008351611cac8184602088016121b3565b835190830190611cc08183602088016121b3565b01949350505050565b60008451611cdb8184602089016121b3565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b60008451611d2d8184602089016121b3565b91909101928352506020820152604001919050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff898116825260e060208084018290529083018990526000918a916101008501845b8c811015611e165783611e0386611b0b565b1682529382019390820190600101611df1565b5080945050505050866040830152611e316060830187611bcd565b611e3e6080830186611bcd565b611e4b60a0830185611bcd565b8260c08301529998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611eac57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611e7a565b50909695505050505050565b901515815260200190565b90815260200190565b98895273ffffffffffffffffffffffffffffffffffffffff97881660208a0152604089019690965260608801949094529185166080870152841660a086015290921660c084015260e08301919091526101008201526101200190565b94855260208501939093526040840191909152606083015273ffffffffffffffffffffffffffffffffffffffff16608082015260a00190565b600083825260406020830152610f3b6040830184611be7565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526108786020830184611be7565b60208082526012908201527f494e56414c49445f4645455f414d4f554e540000000000000000000000000000604082015260600190565b60208082526025908201527f444953414c4c4f5745445f4f4e5f494d504c454d454e544154494f4e5f434f4e60408201527f5452414354000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526011908201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604082015260600190565b6020808252600d908201527f494e56414c49445f4f574e455200000000000000000000000000000000000000604082015260600190565b60208082526018908201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604082015260600190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612118578283fd5b83018035915067ffffffffffffffff821115612132578283fd5b602090810192508102360382131561214957600080fd5b9250929050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612184578283fd5b83018035915067ffffffffffffffff82111561219e578283fd5b60200191503681900382131561214957600080fd5b60005b838110156121ce5781810151838201526020016121b6565b83811115610f03575050600091015256fe608060405234801561001057600080fd5b506040516101753803806101758339818101604052602081101561003357600080fd5b50516001600160a01b03811661007a5760405162461bcd60e51b81526004018080602001828103825260248152602001806101516024913960400191505060405180910390fd5b600080546001600160a01b039092166001600160a01b031990921691909117905560a8806100a96000396000f3fe608060405236600a57005b600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e0000000000000000000000000000000000000000000000000000000082351415605457808252602082f35b3682833781823684845af490503d82833e80606d573d82fd5b503d81f3fea26469706673582212209b39db819970ade944325e6a1f180577f0bf51c0b1c93dcdcc13bc55d62dbddd64736f6c63430007060033496e76616c6964206d617374657220636f707920616464726573732070726f7669646564a26469706673582212207118399b829f084e3ffd4c75022f62be54a83224f5f660e1ea1f7f095902706d64736f6c6343000706003300000000000000000000000023a19a97a2da581e3d66ef5fd1eea15024f55611

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061011b5760003560e01c80639870d7fe116100b2578063ce15861211610081578063d92d1f5611610066578063d92d1f5614610211578063e673df8a14610224578063f2fde38b146102395761011b565b8063ce158612146101f6578063d70e2000146102095761011b565b80639870d7fe146101b5578063ac8a584a146101c8578063b6830d8f146101db578063bd820688146101ee5761011b565b8063715018a6116100ee578063715018a6146101865780638117abc1146101905780638da5cb5b1461019857806390610b0e146101a05761011b565b80633644e515146101205780634c30d6c91461013e5780635b29128f146101465780636d70f7ae14610166575b600080fd5b61012861024c565b6040516101359190611ec3565b60405180910390f35b610128610270565b610159610154366004611b8a565b610294565b6040516101359190611d73565b610179610174366004611b47565b6104a8565b6040516101359190611eb8565b61018e6104dc565b005b6101596105d1565b6101596105f5565b6101a8610611565b6040516101359190611f98565b61018e6101c3366004611b47565b61064a565b61018e6101d6366004611b47565b6106dc565b6101286101e9366004611b61565b6107d0565b61012861083b565b610159610204366004611b61565b61086b565b6101a861087f565b61015961021f366004611b8a565b610942565b61022c6109f1565b6040516101359190611e5e565b61018e610247366004611b47565b610a1c565b7fcc7a9834df85511f8da65d2817c8095b6027cec6b3fdf4b6fe0bd6b7d30d953781565b7f4392cdd6c9d91e0896c5def13bad6473db5d21e2b0def85ab8c2475c3e60d14c81565b600061029f336104a8565b6102de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fe2565b60405180910390fd5b8260e0013582111561031c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fab565b600061032b6020850185611b47565b73ffffffffffffffffffffffffffffffffffffffff161415610379576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590612076565b61039761038c6040850160208601611b47565b846101000135610c28565b905073ffffffffffffffffffffffffffffffffffffffff811663d6bb65c26103c26020860186611b47565b6103cf60408701876120e4565b60608801356103e460a08a0160808b01611b47565b6103f460c08b0160a08c01611b47565b61040460e08c0160c08d01611b47565b8a6040518963ffffffff1660e01b8152600401610428989796959493929190611dbb565b600060405180830381600087803b15801561044257600080fd5b505af1158015610456573d6000803e3d6000fd5b507f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f081925083915061048c90506020860186611b47565b60405161049a929190611d94565b60405180910390a192915050565b60006104d47fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b0583610c44565b90505b919050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461056257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b7f00000000000000000000000023a19a97a2da581e3d66ef5fd1eea15024f5561181565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600f81526020017f57414c4c45545f4352454154494f4e000000000000000000000000000000000081525081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b6106d981610c7e565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b61078c7fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b0582610cee565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f80c0b871b97b595b16a7741c1b06fed0c6f6f558639f18ccbce50724325dc40d90600090a250565b60006040518060400160405280600f81526020017f57414c4c45545f4352454154494f4e0000000000000000000000000000000000815250838360405160200161081c93929190611cc9565b6040516020818303038152906040528051906020012090505b92915050565b60006108667fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b05610f09565b905090565b6000610878838330610f1e565b9392505050565b60606040518060200161089190611afe565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f9091011660408190526108f2907f00000000000000000000000023a19a97a2da581e3d66ef5fd1eea15024f5561190602001611d73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261092e9291602001611c9a565b604051602081830303815290604052905090565b600061094d336104a8565b610983576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fe2565b8260c001358211156109c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590611fab565b6109ca83610f43565b6109e46109da6020850185611b47565b8460e00135610c28565b905061083581848461113b565b60606108667fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b05611249565b60005473ffffffffffffffffffffffffffffffffffffffff163314610aa257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116610b2457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f414444524553530000000000000000000000000000000000000000604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000804690507f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f836000015180519060200120846020015180519060200120838660400151604051602001610c0a959493929190611f28565b60405160208183030381529060405280519060200120915050919050565b6000610878610c3784846107d0565b610c3f61087f565b611346565b600082815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff861685529092019052902054151592915050565b610caa7fe63c388d4543ca9e94c981423c48d71e347af88fa97254eee172e5d43f973b058260016113d7565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fac6fa858e9350a46cec16539926e0fde25b7629f84b5a72bffaae4df888ae86d90600090a250565b600082815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff861685529283019091529091205480610d8e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f494e5f53455400000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526001830160205260408120556002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055815415610f0357600082600001836002015481548110610dfc57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff908116915084168114610e9e5780836000016001840381548110610e3d57fe5b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055918316815260018501909152604090208290555b8254839080610ea957fe5b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b50505050565b60009081526001602052604090206002015490565b6000610f3b610f2d85856107d0565b610f3561087f565b846115f2565b949350505050565b6000610f526020830183611b47565b73ffffffffffffffffffffffffffffffffffffffff161415610fa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d590612076565b60007f4392cdd6c9d91e0896c5def13bad6473db5d21e2b0def85ab8c2475c3e60d14c610fd06020840184611b47565b610fdd60208501856120e4565b604051602001610fee929190611c31565b60405160208183030381529060405280519060200120846040013585606001602081019061101c9190611b47565b61102c60a0880160808901611b47565b61103c60c0890160a08a01611b47565b8860c001358960e0013560405160200161105e99989796959493929190611ecc565b60405160208183030381529060405280519060200120905060006110a27fcc7a9834df85511f8da65d2817c8095b6027cec6b3fdf4b6fe0bd6b7d30d953783611691565b90506111006110b46020850185611b47565b6110c2610100860186612150565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508694939250506116dd9050565b611136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d59061203f565b505050565b73ffffffffffffffffffffffffffffffffffffffff831663d6bb65c26111646020850185611b47565b61117160208601866120e4565b60408701356111866080890160608a01611b47565b61119660a08a0160808b01611b47565b6111a660c08b0160a08c01611b47565b896040518963ffffffff1660e01b81526004016111ca989796959493929190611dbb565b600060405180830381600087803b1580156111e457600080fd5b505af11580156111f8573d6000803e3d6000fd5b507f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f081925085915061122e90506020850185611b47565b60405161123c929190611d94565b60405180910390a1505050565b60008181526001602052604090208054600282015460609291146112ce57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f4d41494e5441494e4544000000000000000000000000000000000000604482015290519081900360640190fd5b6000838152600160209081526040918290208054835181840281018401909452808452909183018282801561133957602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161130e575b5050505050915050919050565b600080838351602085016000f5905073ffffffffffffffffffffffffffffffffffffffff811661087857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f435245415445325f4641494c4544000000000000000000000000000000000000604482015290519081900360640190fd5b600083815260016020818152604080842073ffffffffffffffffffffffffffffffffffffffff87168552928301909152909120541561147757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f414c52454144595f494e5f534554000000000000000000000000000000000000604482015290519081900360640190fd5b81156115455760028101548154146114f057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f50524556494f55534c595f4e4f545f4d41494e5441494c454400000000000000604482015290519081900360640190fd5b80546001810182556000828152602090200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790556115b3565b8054156115b357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4d5553545f4d41494e5441494e00000000000000000000000000000000000000604482015290519081900360640190fd5b60028101805460019081019182905573ffffffffffffffffffffffffffffffffffffffff90941660009081529190930160205260409020919091555050565b8151602092830120604080517fff000000000000000000000000000000000000000000000000000000000000008186015260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660218401526035830194909452605580830191909152835180830390910181526075909101909252815191012073ffffffffffffffffffffffffffffffffffffffff1690565b60006040518060400160405280600281526020017f1901000000000000000000000000000000000000000000000000000000000000815250838360405160200161081c93929190611d1b565b600073ffffffffffffffffffffffffffffffffffffffff831661170257506000610878565b6117218373ffffffffffffffffffffffffffffffffffffffff16611740565b61173557611730848484611777565b610f3b565b610f3b8484846118b0565b6000813f801580159061087857507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141592915050565b600073ffffffffffffffffffffffffffffffffffffffff831661179c57506000610878565b8151604114806117ad575081516042145b6117e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d5906120ad565b60008251604214156117f757506041825260015b6118018584611a0a565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161491508161189d576000856040516020016118499190611d42565b60405160208183030381529060405280519060200120905061186b8185611a0a565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16149250505b80156118a857604283525b509392505050565b600080631626ba7e60e01b85846040516024016118ce929190611f61565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000808573ffffffffffffffffffffffffffffffffffffffff16836040516119559190611c7e565b600060405180830381855afa9150503d8060008114611990576040519150601f19603f3d011682016040523d82523d6000602084013e611995565b606091505b50915091508180156119a8575080516020145b80156119ff57507f1626ba7e000000000000000000000000000000000000000000000000000000006119db826000611ae2565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b979650505050505050565b60008151604114611a1d57506000610835565b60208201516040830151604184015160ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115611a635760009350505050610835565b8060ff16601b1480611a7857508060ff16601c145b15611ad65760018682858560405160008152602001604052604051611aa09493929190611f7a565b6020604051602081039080840390855afa158015611ac2573d6000803e3d6000fd5b505050602060405103519350505050610835565b60009350505050610835565b60008160040183511015611af557600080fd5b50016020015190565b610175806121e083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146104d757600080fd5b60006101208284031215611b41578081fd5b50919050565b600060208284031215611b58578081fd5b61087882611b0b565b60008060408385031215611b73578081fd5b611b7c83611b0b565b946020939093013593505050565b60008060408385031215611b9c578182fd5b823567ffffffffffffffff811115611bb2578283fd5b611bbe85828601611b2f565b95602094909401359450505050565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452611bff8160208601602086016121b3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008184825b85811015611c735773ffffffffffffffffffffffffffffffffffffffff611c5d83611b0b565b1683526020928301929190910190600101611c37565b509095945050505050565b60008251611c908184602087016121b3565b9190910192915050565b60008351611cac8184602088016121b3565b835190830190611cc08183602088016121b3565b01949350505050565b60008451611cdb8184602089016121b3565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b60008451611d2d8184602089016121b3565b91909101928352506020820152604001919050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff898116825260e060208084018290529083018990526000918a916101008501845b8c811015611e165783611e0386611b0b565b1682529382019390820190600101611df1565b5080945050505050866040830152611e316060830187611bcd565b611e3e6080830186611bcd565b611e4b60a0830185611bcd565b8260c08301529998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611eac57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611e7a565b50909695505050505050565b901515815260200190565b90815260200190565b98895273ffffffffffffffffffffffffffffffffffffffff97881660208a0152604089019690965260608801949094529185166080870152841660a086015290921660c084015260e08301919091526101008201526101200190565b94855260208501939093526040840191909152606083015273ffffffffffffffffffffffffffffffffffffffff16608082015260a00190565b600083825260406020830152610f3b6040830184611be7565b93845260ff9290921660208401526040830152606082015260800190565b6000602082526108786020830184611be7565b60208082526012908201527f494e56414c49445f4645455f414d4f554e540000000000000000000000000000604082015260600190565b60208082526025908201527f444953414c4c4f5745445f4f4e5f494d504c454d454e544154494f4e5f434f4e60408201527f5452414354000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526011908201527f494e56414c49445f5349474e4154555245000000000000000000000000000000604082015260600190565b6020808252600d908201527f494e56414c49445f4f574e455200000000000000000000000000000000000000604082015260600190565b60208082526018908201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604082015260600190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612118578283fd5b83018035915067ffffffffffffffff821115612132578283fd5b602090810192508102360382131561214957600080fd5b9250929050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612184578283fd5b83018035915067ffffffffffffffff82111561219e578283fd5b60200191503681900382131561214957600080fd5b60005b838110156121ce5781810151838201526020016121b6565b83811115610f03575050600091015256fe608060405234801561001057600080fd5b506040516101753803806101758339818101604052602081101561003357600080fd5b50516001600160a01b03811661007a5760405162461bcd60e51b81526004018080602001828103825260248152602001806101516024913960400191505060405180910390fd5b600080546001600160a01b039092166001600160a01b031990921691909117905560a8806100a96000396000f3fe608060405236600a57005b600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e0000000000000000000000000000000000000000000000000000000082351415605457808252602082f35b3682833781823684845af490503d82833e80606d573d82fd5b503d81f3fea26469706673582212209b39db819970ade944325e6a1f180577f0bf51c0b1c93dcdcc13bc55d62dbddd64736f6c63430007060033496e76616c6964206d617374657220636f707920616464726573732070726f7669646564a26469706673582212207118399b829f084e3ffd4c75022f62be54a83224f5f660e1ea1f7f095902706d64736f6c63430007060033

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

00000000000000000000000023a19a97a2da581e3d66ef5fd1eea15024f55611

-----Decoded View---------------
Arg [0] : _walletImplementation (address): 0x23a19a97A2dA581e3d66Ef5Fd1eeA15024f55611

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000023a19a97a2da581e3d66ef5fd1eea15024f55611


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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