false
false

Contract Address Details

0x343ae8cb5a78CdbE40bDB02FF903ef0Eb31c6dC5

Contract Name
LSP3Account
Creator
0xc2f81d–807315 at 0x33756c–68e7e2
Balance
0 LYX
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
356 Transfers
Gas Used
82,715
Last Balance Update
18728076
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x47ed323d03cd3fff423f1200af2e2e3d823e8d0a.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
Contract name:
LSP3Account




Optimization enabled
false
Compiler version
v0.6.12+commit.27d51765




Verified at
2020-12-07T17:10:22.917765Z

Contract source code

Sol2uml
new
// SPDX-License-Identifier: CC0-1.0 AND MIT AND Apache-2.0
// File: contracts/_LSPs/ILSP1_UniversalReceiver.sol

pragma solidity >=0.5.0 <0.7.0;

/**
 * @dev Contract module that allows to receive arbitrary messages when assets are sent or received.
 *
 * ERC 165 interface id: 0x6bb56a14
 */
interface ILSP1  /* is ERC165 */ {
    event UniversalReceiver(address indexed from, bytes32 indexed typeId, bytes32 indexed returnedValue, bytes receivedData);

    function universalReceiver(bytes32 typeId, bytes calldata data) external returns (bytes32);
}

// File: contracts/_LSPs/ILSP1_UniversalReceiverDelegate.sol

pragma solidity >=0.5.0 <0.7.0;

/**
 * @dev Contract module that allows for an external universal receiver smart contract, that is the delegate of the initial universal receiver
 *
 * ERC 165 interface id: 0xc2d7bcc1
 */
interface ILSP1Delegate  /* is ERC165 */ {

    function universalReceiverDelegate(address sender, bytes32 typeId, bytes memory data) external returns (bytes32);

}

// File: erc725/contracts/ERC725/IERC725X.sol

pragma solidity >=0.5.0 <0.7.0;

/**
 * @dev Contract module which provides the ability to call arbitrary functions at any other smart contract and itself,
 * including using `delegatecall`, as well creating contracts using `create` and `create2`.
 * This is the basis for a smart contract based account system, but could also be used as a proxy account system.
 *
 * ERC 165 interface id: 0x44c028fe
 *
 * `execute` should only be callable by the owner of the contract set via ERC173.
 */
interface IERC725X  /* is ERC165, ERC173 */ {

    /**
    * @dev Emitted when a contract is created.
    */
    event ContractCreated(address indexed contractAddress);

    /**
    * @dev Emitted when a contract executed.
    */
    event Executed(uint256 indexed _operation, address indexed _to, uint256 indexed  _value, bytes _data);


    /**
     * @dev Executes any other smart contract.
     * SHOULD only be callable by the owner of the contract set via ERC173.
     *
     * Requirements:
     *
     * - `operationType`, the operation to execute. So far defined is:
     *     CALL = 0;
     *     DELEGATECALL = 1;
     *     CREATE2 = 2;
     *     CREATE = 3;
     *
     * - `data` the call data that will be used with the contract at `to`
     *
     * Emits a {ContractCreated} event, when a contract is created under `operationType` 2 and 3.
     */
    function execute(uint256 operationType, address to, uint256 value, bytes calldata data) external payable;
}

// File: @openzeppelin/contracts/GSN/Context.sol


pragma solidity >=0.6.0 <0.8.0;

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

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


pragma solidity >=0.6.0 <0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

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

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

// File: @openzeppelin/contracts/introspection/IERC165.sol


pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/introspection/ERC165.sol


pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor () internal {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// File: @openzeppelin/contracts/utils/Create2.sol


pragma solidity >=0.6.0 <0.8.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}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already.
     * - the factory must have a balance of at least `amount`.
     * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
     */
    function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {
        address addr;
        require(address(this).balance >= amount, "Create2: insufficient balance");
        require(bytecode.length != 0, "Create2: bytecode length is zero");
        // solhint-disable-next-line no-inline-assembly
        assembly {
            addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
        }
        require(addr != address(0), "Create2: Failed on deploy");
        return addr;
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
     * `bytecodeHash` or `salt` will result in a new destination address.
     */
    function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
        return computeAddress(salt, bytecodeHash, 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, bytes32 bytecodeHash, address deployer) internal pure returns (address) {
        bytes32 _data = keccak256(
            abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)
        );
        return address(uint256(_data));
    }
}

// File: solidity-bytes-utils/contracts/BytesLib.sol

/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */

pragma solidity ^0.6.0;


library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

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

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add 
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes_slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes_slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))
                
                for { 
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    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 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 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 equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes_slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes_slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

// File: erc725/contracts/ERC725/ERC725X.sol

pragma solidity ^0.6.0;

// interfaces


// modules



// libraries



/**
 * @title ERC725 X executor
 * @dev Implementation of a contract module which provides the ability to call arbitrary functions at any other smart contract and itself,
 * including using `delegatecall`, as well creating contracts using `create` and `create2`.
 * This is the basis for a smart contract based account system, but could also be used as a proxy account system.
 *
 * `execute` MUST only be called by the owner of the contract set via ERC173.
 *
 *  @author Fabian Vogelsteller <[email protected]>
 */
contract ERC725X is ERC165, Ownable, IERC725X  {

    bytes4 internal constant _INTERFACE_ID_ERC725X = 0x44c028fe;

    uint256 constant OPERATION_CALL = 0;
    uint256 constant OPERATION_DELEGATECALL = 1;
    uint256 constant OPERATION_CREATE2 = 2;
    uint256 constant OPERATION_CREATE = 3;

    /**
     * @notice Sets the owner of the contract
     * @param _newOwner the owner of the contract.
     */
    constructor(address _newOwner) public {
        // This is necessary to prevent a contract that implements both ERC725X and ERC725Y to call both constructors
        if(_newOwner != owner()) {
            transferOwnership(_newOwner);
        }

        _registerInterface(_INTERFACE_ID_ERC725X);
    }

    /* Public functions */

    /**
     * @notice Executes any other smart contract. Is only callable by the owner.
     *
     *
     * @param _operation the operation to execute: CALL = 0; DELEGATECALL = 1; CREATE2 = 2; CREATE = 3;
     * @param _to the smart contract or address to interact with. `_to` will be unused if a contract is created (operation 2 and 3)
     * @param _value the value of ETH to transfer
     * @param _data the call data, or the contract data to deploy
     */
    function execute(uint256 _operation, address _to, uint256 _value, bytes calldata _data)
    external
    payable
    override
    onlyOwner
    {
        // emit event
        emit Executed(_operation, _to, _value, _data);

        uint256 txGas = gasleft() - 2500;

        // CALL
        if (_operation == OPERATION_CALL) {
            executeCall(_to, _value, _data, txGas);

        // DELEGATE CALL
        // TODO: risky as storage slots can be overridden, remove?
//        } else if (_operation == OPERATION_DELEGATECALL) {
//            address currentOwner = owner();
//            executeDelegateCall(_to, _data, txGas);
//            // Check that the owner was not overridden
//            require(owner() == currentOwner, "Delegate call is not allowed to modify the owner!");

        // CREATE
        } else if (_operation == OPERATION_CREATE) {
            performCreate(_value, _data);

        // CREATE2
        } else if (_operation == OPERATION_CREATE2) {
            bytes32 salt = BytesLib.toBytes32(_data, _data.length - 32);
            bytes memory data = BytesLib.slice(_data, 0, _data.length - 32);

            address contractAddress = Create2.deploy(_value, salt, data);

            emit ContractCreated(contractAddress);

        } else {
            revert("Wrong operation type");
        }
    }

    /* Internal functions */

    // Taken from GnosisSafe
    // https://github.com/gnosis/safe-contracts/blob/development/contracts/base/Executor.sol
    function executeCall(address to, uint256 value, bytes memory data, uint256 txGas)
    internal
    returns (bool success)
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
        }
    }

    // Taken from GnosisSafe
    // https://github.com/gnosis/safe-contracts/blob/development/contracts/base/Executor.sol
    function executeDelegateCall(address to, bytes memory data, uint256 txGas)
    internal
    returns (bool success)
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
        }
    }

    // Taken from GnosisSafe
    // https://github.com/gnosis/safe-contracts/blob/development/contracts/libraries/CreateCall.sol
    function performCreate(uint256 value, bytes memory deploymentData)
    internal
    returns (address newContract)
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            newContract := create(value, add(deploymentData, 0x20), mload(deploymentData))
        }
        require(newContract != address(0), "Could not deploy contract");
        emit ContractCreated(newContract);
    }

    /* Modifiers */

}

// File: erc725/contracts/ERC725/IERC725Y.sol

pragma solidity >=0.5.0 <0.7.0;

/**
 * @title ERC725 Y data store
 * @dev Contract module which provides the ability to set arbitrary key value sets that can be changed over time.
 * It is intended to standardise certain keys value pairs to allow automated retrievals and interactions
 * from interfaces and other smart contracts.
 *
 * ERC 165 interface id: 0x2bd57b73
 *
 * `setData` should only be callable by the owner of the contract set via ERC173.
 */
interface IERC725Y /* is ERC165, ERC173 */ {

    /**
    * @dev Emitted when data at a key is changed.
    */
    event DataChanged(bytes32 indexed key, bytes value);

    /**
     * @dev Gets data at a given `key`
     */
    function getData(bytes32 key) external view returns (bytes memory value);

    /**
     * @dev Sets data at a given `key`.
     * SHOULD only be callable by the owner of the contract set via ERC173.
     *
     * Emits a {DataChanged} event.
     */
    function setData(bytes32 key, bytes calldata value) external;
}

// File: erc725/contracts/ERC725/ERC725Y.sol

pragma solidity ^0.6.0;

// interfaces


// modules



/**
 * @title ERC725 Y data store
 * @dev Contract module which provides the ability to set arbitrary key value sets that can be changed over time.
 * It is intended to standardise certain keys value pairs to allow automated retrievals and interactions
 * from interfaces and other smart contracts.
 *
 * `setData` should only be callable by the owner of the contract set via ERC173.
 *
 *  @author Fabian Vogelsteller <[email protected]>
 */
contract ERC725Y is ERC165, Ownable, IERC725Y {

    bytes4 internal constant _INTERFACE_ID_ERC725Y = 0x2bd57b73;

    mapping(bytes32 => bytes) internal store;

    /**
     * @notice Sets the owner of the contract
     * @param _newOwner the owner of the contract.
     */
    constructor(address _newOwner) public {
        // This is necessary to prevent a contract that implements both ERC725X and ERC725Y to call both constructors
        if(_newOwner != owner()) {
            transferOwnership(_newOwner);
        }

        _registerInterface(_INTERFACE_ID_ERC725Y);
    }

    /* Public functions */

    /**
     * @notice Gets data at a given `key`
     * @param _key the key which value to retrieve
     * @return _value The date stored at the key
     */
    function getData(bytes32 _key)
    public
    view
    override
    virtual
    returns (bytes memory _value)
    {
        return store[_key];
    }

    /**
     * @notice Sets data at a given `key`
     * @param _key the key which value to retrieve
     * @param _value the bytes to set.
     */
    function setData(bytes32 _key, bytes calldata _value)
    external
    override
    virtual
    onlyOwner
    {
        store[_key] = _value;
        emit DataChanged(_key, _value);
    }


    /* Modifiers */

}

// File: erc725/contracts/ERC725/ERC725.sol

pragma solidity ^0.6.0;

// modules



/**
 * @title ERC725 bundle
 * @dev Bundles ERC725X and ERC725Y together into one smart contract
 *
 *  @author Fabian Vogelsteller <[email protected]>
 */
contract ERC725 is ERC725X, ERC725Y  {

    /**
     * @notice Sets the owner of the contract
     * @param _newOwner the owner of the contract.
     */
    constructor(address _newOwner)
    ERC725X(_newOwner)
    ERC725Y(_newOwner)
    public {}

    // NOTE this implementation has not by default: receive() external payable {}
}

// File: erc725/contracts/IERC1271.sol

pragma solidity >=0.5.0 <0.7.0;

/**
 * @notice ERC-1271: Standard Signature Validation Method for Contracts
 */
interface IERC1271 {

//    bytes4 internal constant _ERC1271MAGICVALUE = 0x1626ba7e;
//    bytes4 internal constant _ERC1271FAILVALUE = 0xffffffff;

    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param _hash hash of the data signed//Arbitrary length data signed on the behalf of address(this)
     * @param _signature Signature byte array associated with _data
     *
     * @return magicValue either 0x1626ba7e on success or 0xffffffff failure
     */
    function isValidSignature(
        bytes32 _hash, //bytes memory _data,
        bytes memory _signature
    )
    external
    view
    returns (bytes4 magicValue);
}

// File: @openzeppelin/contracts/cryptography/ECDSA.sol


pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            revert("ECDSA: invalid signature length");
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

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

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

// File: erc725/contracts/helpers/UtilsLib.sol

/*
 * @title Solidity Utils
 * @author Fabian Vogelsteller <[email protected]>
 *
 * @dev Utils functions
 */

pragma solidity >=0.5.0 <0.7.0;


library UtilsLib {

    /**
     * @dev Internal function to determine if an address is a contract
     * @param _target The address being queried
     *
     * @return result Returns TRUE if `_target` is a contract
     */
    function isContract(address _target) internal view returns(bool result) {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            result := gt(extcodesize(_target), 0)
        }
    }
}

// File: erc725/contracts/ERC725/ERC725Account.sol

pragma solidity ^0.6.0;

// modules



// libraries



/**
 * @title ERC725Account
 * @dev Bundles ERC725X and ERC725Y, and ERC1271 and allows receiving native tokens.
 *
 *  @author Fabian Vogelsteller <[email protected]>
 */

// TODO add ERC777, ERC223, ERC721 functions?

contract ERC725Account is ERC725, IERC1271  {

    bytes4 internal constant _INTERFACE_ID_ERC1271 = 0x1626ba7e;
    bytes4 internal constant _ERC1271FAILVALUE = 0xffffffff;

    event ValueReceived(address indexed sender, uint256 indexed value);

    /**
     * @notice Sets the owner of the contract
     * @param _newOwner the owner of the contract.
     */
    constructor(address _newOwner)
    ERC725(_newOwner)
    public
    {
        // set SupportedStandards > ERC725Account
        bytes32 key = bytes32(0xeafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6); // SupportedStandards > ERC725Account
        store[key] = abi.encodePacked(bytes4(0xafdeb5d6)); // bytes4(keccak256('ERC725Account')
        emit DataChanged(key, store[key]);

        _registerInterface(_INTERFACE_ID_ERC1271);
    }

    receive()
    external
    payable
    {
        emit ValueReceived(_msgSender(), msg.value);
    }

//    TODO to be discussed
//    function fallback()
//    public
//    {
//        address to = owner();
//        assembly {
//            calldatacopy(0, 0, calldatasize())
//            let result := staticcall(gas(), to, 0, calldatasize(), 0, 0)
//            returndatacopy(0, 0, returndatasize())
//            switch result
//            case 0  { revert (0, returndatasize()) }
//            default { return (0, returndatasize()) }
//        }
//    }


    /**
    * @notice Checks if an owner signed `_data`.
    * ERC1271 interface.
    *
    * @param _hash hash of the data signed//Arbitrary length data signed on the behalf of address(this)
    * @param _signature owner's signature(s) of the data
    */
    function isValidSignature(bytes32 _hash, bytes memory _signature)
    override
    public
    view
    returns (bytes4 magicValue)
    {
        if (
            UtilsLib.isContract(owner()) &&
            supportsInterface(_INTERFACE_ID_ERC1271)
        ){
            return IERC1271(owner()).isValidSignature(_hash, _signature);
        } else {
            return owner() == ECDSA.recover(_hash, _signature)
            ? _INTERFACE_ID_ERC1271
            : _ERC1271FAILVALUE;
        }
    }
}

// File: contracts/Accounts/LSP3Account.sol

/*
 * @title ERC725Account implementation for LUKSO
 * @author Fabian Vogelsteller <[email protected]>
 *
 * @dev Implementation of the ERC725Account + LSP1 universalReceiver
 */
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;

// interfaces



// modules



contract LSP3Account is ERC165, ERC725Account, ILSP1 {

    bytes4 _INTERFACE_ID_LSP1 = 0x6bb56a14;
    bytes4 _INTERFACE_ID_LSP1DELEGATE = 0xc2d7bcc1;

    bytes32 constant private _UNIVERSAL_RECEIVER_DELEGATE_KEY =
    0x0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b47; // keccak256("LSP1UniversalReceiverDelegate")

    bytes32[] public dataKeys;

    constructor(address _newOwner) ERC725Account(_newOwner) public {

        // Add the key of the SupportedStandards:ERC725Account set in the constructor of ERC725Account.sol
        dataKeys.push(0xeafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6);

        _registerInterface(_INTERFACE_ID_LSP1);
    }

    /* non-standard public functions */

    function dataCount() public view returns (uint256) {
        return dataKeys.length;
    }

    function allDataKeys() public view returns (bytes32[] memory) {
        return dataKeys;
    }

    function setDataMultiple(bytes32[] calldata _keys, bytes[] calldata _values)
    public
    onlyOwner
    {
        for (uint256 i = 0; i < _keys.length; i++) {
            setData(_keys[i], _values[i]);
        }
    }

    function getDataMultiple(bytes32[] calldata _keys)
    public
    view
    returns(bytes[] memory)
    {
        uint256 length = _keys.length;
        bytes[] memory values = new bytes[](length);

        for (uint256 i=0; i < length; i++) {
            values[i] = getData(_keys[i]);
        }

        return values;
    }

    /* Public functions */

    function setData(bytes32 _key, bytes calldata _value)
    public
    override
    onlyOwner
    {
        if(store[_key].length == 0) {
            dataKeys.push(_key); // 30k more gas on initial set
        }
        store[_key] = _value;
        emit DataChanged(_key, _value);
    }

    /**
    * @notice Notify the smart contract about any received asset
    * LSP1 interface

    * @param _typeId The type of transfer received
    * @param _data The data received
    */
    function universalReceiver(bytes32 _typeId, bytes calldata _data)
    external
    override
    virtual
    returns (bytes32 returnValue)
    {
        bytes memory receiverData = getData(_UNIVERSAL_RECEIVER_DELEGATE_KEY);
        returnValue = "";

        // call external contract
        if (receiverData.length == 20) {
            address universalReceiverAddress = BytesLib.toAddress(receiverData, 0);

            if(ERC165(universalReceiverAddress).supportsInterface(_INTERFACE_ID_LSP1DELEGATE)) {
                returnValue = ILSP1Delegate(universalReceiverAddress).universalReceiverDelegate(_msgSender(), _typeId, _data);
            }
        }

        emit UniversalReceiver(_msgSender(), _typeId, returnValue, _data);

        return returnValue;
    }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_newOwner","internalType":"address"}]},{"type":"event","name":"ContractCreated","inputs":[{"type":"address","name":"contractAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"DataChanged","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":true},{"type":"bytes","name":"value","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"Executed","inputs":[{"type":"uint256","name":"_operation","internalType":"uint256","indexed":true},{"type":"address","name":"_to","internalType":"address","indexed":true},{"type":"uint256","name":"_value","internalType":"uint256","indexed":true},{"type":"bytes","name":"_data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"UniversalReceiver","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"bytes32","name":"typeId","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"returnedValue","internalType":"bytes32","indexed":true},{"type":"bytes","name":"receivedData","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"ValueReceived","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"allDataKeys","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dataCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"dataKeys","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"execute","inputs":[{"type":"uint256","name":"_operation","internalType":"uint256"},{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"_value","internalType":"bytes"}],"name":"getData","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes[]","name":"","internalType":"bytes[]"}],"name":"getDataMultiple","inputs":[{"type":"bytes32[]","name":"_keys","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes4","name":"magicValue","internalType":"bytes4"}],"name":"isValidSignature","inputs":[{"type":"bytes32","name":"_hash","internalType":"bytes32"},{"type":"bytes","name":"_signature","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setData","inputs":[{"type":"bytes32","name":"_key","internalType":"bytes32"},{"type":"bytes","name":"_value","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDataMultiple","inputs":[{"type":"bytes32[]","name":"_keys","internalType":"bytes32[]"},{"type":"bytes[]","name":"_values","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes32","name":"returnValue","internalType":"bytes32"}],"name":"universalReceiver","inputs":[{"type":"bytes32","name":"_typeId","internalType":"bytes32"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x6080604052636bb56a1460e01b600360006101000a81548163ffffffff021916908360e01c021790555063c2d7bcc160e01b600360046101000a81548163ffffffff021916908360e01c02179055503480156200005b57600080fd5b50604051620031f9380380620031f983398181016040528101906200008191906200071a565b808080816200009d6301ffc9a760e01b6200037e60201b60201c565b6000620000af6200045660201b60201c565b905080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506200015e6200045e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620001a357620001a2816200048860201b60201c565b5b620001bb6344c028fe60e01b6200037e60201b60201c565b50620001cc6200045e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620002115762000210816200048860201b60201c565b5b62000229632bd57b7360e01b6200037e60201b60201c565b505060007feafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d660001b905063afdeb5d660e01b6040516020016200026d9190620008e8565b604051602081830303815290604052600260008381526020019081526020016000209080519060200190620002a49291906200065d565b50807fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b260026000848152602001908152602001600020604051620002e9919062000905565b60405180910390a262000309631626ba7e60e01b6200037e60201b60201c565b505060047feafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6908060018154018082558091505060019003906000526020600020016000909160001b90919091505562000377600360009054906101000a900460e01b6200037e60201b60201c565b5062000a4a565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415620003ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1906200094b565b60405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600033905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b620004986200045660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146200052a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000521906200096d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200059d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005949062000929565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620006a057805160ff1916838001178555620006d1565b82800160010185558215620006d1579182015b82811115620006d0578251825591602001919060010190620006b3565b5b509050620006e09190620006e4565b5090565b5b80821115620006ff576000816000905550600101620006e5565b5090565b600081519050620007148162000a30565b92915050565b6000602082840312156200072d57600080fd5b60006200073d8482850162000703565b91505092915050565b6200075b6200075582620009da565b62000a26565b82525050565b600081546001811660008114620007815760018114620007aa57620007f4565b607f6002830416620007948187620009a4565b955060ff198316865260208601935050620007f4565b60028204620007ba8187620009a4565b9550620007c7856200098f565b60005b82811015620007eb57815481890152600182019150602081019050620007ca565b80880195505050505b505092915050565b60006200080b602683620009b5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600062000873601c83620009b5565b91507f4552433136353a20696e76616c696420696e74657266616365206964000000006000830152602082019050919050565b6000620008b5602083620009b5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000620008f6828462000746565b60048201915081905092915050565b6000602082019050818103600083015262000921818462000761565b905092915050565b600060208201905081810360008301526200094481620007fc565b9050919050565b60006020820190508181036000830152620009668162000864565b9050919050565b600060208201905081810360008301526200098881620008a6565b9050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000620009d38262000a06565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000a3b81620009c6565b811462000a4757600080fd5b50565b61279f8062000a5a6000396000f3fe6080604052600436106100e15760003560e01c80636bb56a141161007f5780638da5cb5b116100595780638da5cb5b14610319578063c559acef14610344578063ec89dc1c1461036f578063f2fde38b146103ac57610133565b80636bb56a141461029c578063715018a6146102d95780637f23690c146102f057610133565b8063456cc348116100bb578063456cc348146101ce57806354f6127f1461020b578063595fa1e5146102485780635da40c471461027157610133565b806301ffc9a7146101385780631626ba7e1461017557806344c028fe146101b257610133565b3661013357346100ef6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f7e71433ddf847725166244795048ecf3e3f9f35628254ecbf73605666423349360405160405180910390a3005b600080fd5b34801561014457600080fd5b5061015f600480360381019061015a9190611b19565b6103dd565b60405161016c91906121fb565b60405180910390f35b34801561018157600080fd5b5061019c60048036038101906101979190611ac5565b610444565b6040516101a991906122a6565b60405180910390f35b6101cc60048036038101906101c79190611b94565b61056e565b005b3480156101da57600080fd5b506101f560048036038101906101f09190611938565b610876565b60405161020291906121d9565b60405180910390f35b34801561021757600080fd5b50610232600480360381019061022d9190611a1b565b610926565b60405161023f91906122e5565b60405180910390f35b34801561025457600080fd5b5061026f600480360381019061026a919061197d565b6109db565b005b34801561027d57600080fd5b50610286610acd565b6040516102939190612467565b60405180910390f35b3480156102a857600080fd5b506102c360048036038101906102be9190611a6d565b610ada565b6040516102d09190612216565b60405180910390f35b3480156102e557600080fd5b506102ee610cc4565b005b3480156102fc57600080fd5b5061031760048036038101906103129190611a6d565b610e1c565b005b34801561032557600080fd5b5061032e610f6f565b60405161033b919061215c565b60405180910390f35b34801561035057600080fd5b50610359610f99565b60405161036691906121b7565b60405180910390f35b34801561037b57600080fd5b5061039660048036038101906103919190611b6b565b610ff1565b6040516103a39190612216565b60405180910390f35b3480156103b857600080fd5b506103d360048036038101906103ce919061190f565b611012565b005b600033905090565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6000610456610451610f6f565b6111d9565b801561046e575061046d631626ba7e60e01b6103dd565b5b1561050c5761047b610f6f565b73ffffffffffffffffffffffffffffffffffffffff16631626ba7e84846040518363ffffffff1660e01b81526004016104b5929190612231565b60206040518083038186803b1580156104cd57600080fd5b505afa1580156104e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105059190611b42565b9050610568565b61051683836111e6565b73ffffffffffffffffffffffffffffffffffffffff16610534610f6f565b73ffffffffffffffffffffffffffffffffffffffff161461055c5763ffffffff60e01b610565565b631626ba7e60e01b5b90505b92915050565b6105766103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fc90612407565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff16867f1f920dbda597d7bf95035464170fa58d0a4b57f13a1c315ace6793b9f63688b8858560405161064f9291906122c1565b60405180910390a460006109c45a03905060008614156106bf576106b9858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050846113d3565b5061086e565b600386141561071c576107168484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506113ec565b5061086d565b600286141561083157600061077b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050602086869050036114b1565b905060606107d585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000602088889050036114d9565b905060006107e4878484611565565b90508073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a250505061086c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086390612427565b60405180910390fd5b5b5b505050505050565b6060600083839050905060608167ffffffffffffffff8111801561089957600080fd5b506040519080825280602002602001820160405280156108cd57816020015b60608152602001906001900390816108b85790505b50905060005b8281101561091a576108f68686838181106108ea57fe5b90506020020135610926565b82828151811061090257fe5b602002602001018190525080806001019150506108d3565b50809250505092915050565b6060600260008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b50505050509050919050565b6109e36103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990612407565b60405180910390fd5b60005b84849050811015610ac657610ab9858583818110610a8f57fe5b90506020020135848484818110610aa257fe5b9050602002810190610ab49190612482565b610e1c565b8080600101915050610a75565b5050505050565b6000600480549050905090565b60006060610b0a7f0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b4760001b610926565b905060009150601481511415610c63576000610b27826000611676565b90508073ffffffffffffffffffffffffffffffffffffffff166301ffc9a7600360049054906101000a900460e01b6040518263ffffffff1660e01b8152600401610b7191906122a6565b60206040518083038186803b158015610b8957600080fd5b505afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc191906119f2565b15610c61578073ffffffffffffffffffffffffffffffffffffffff1663c2d7bcc1610bea6103d5565b8888886040518563ffffffff1660e01b8152600401610c0c9493929190612177565b602060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5e9190611a44565b92505b505b8185610c6d6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f54b98940949b5ac0325c889c84db302d4e18faec431b48bdc81706bfe482cfbd8787604051610cb49291906122c1565b60405180910390a4509392505050565b610ccc6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5290612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b610e246103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eaa90612407565b60405180910390fd5b6000600260008581526020019081526020016000208054600181600116156101000203166002900490501415610f0d5760048390806001815401808255809150506001900390600052602060002001600090919091909150555b8181600260008681526020019081526020016000209190610f2f9291906116ad565b50827fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b28383604051610f629291906122c1565b60405180910390a2505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805480602002602001604051908101604052809291908181526020018280548015610fe757602002820191906000526020600020905b815481526020019060010190808311610fd3575b5050505050905090565b60048181548110610ffe57fe5b906000526020600020016000915090505481565b61101a6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a090612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111090612367565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080823b119050919050565b6000604182511461122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122390612347565b60405180910390fd5b60008060006020850151925060408501519150606085015160001a90507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c11156112af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112a690612387565b60405180910390fd5b601b8160ff1614806112c45750601c8160ff16145b611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa906123a7565b60405180910390fd5b6000600187838686604051600081526020016040526040516113289493929190612261565b6020604051602081039080840390855afa15801561134a573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd90612307565b60405180910390fd5b8094505050505092915050565b6000806000845160208601878987f19050949350505050565b600081516020830184f09050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145f906123e7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a292915050565b600060208201835110156114c457600080fd5b60008260208501015190508091505092915050565b6060818301845110156114eb57600080fd5b606082156000811461150857604051915060208201604052611559565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156115465780518352602083019250602081019050611529565b50868552601f19601f8301166040525050505b50809150509392505050565b600080844710156115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290612447565b60405180910390fd5b6000835114156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790612327565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561166b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611662906123c7565b60405180910390fd5b809150509392505050565b6000601482018351101561168957600080fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ee57803560ff191683800117855561171c565b8280016001018555821561171c579182015b8281111561171b578235825591602001919060010190611700565b5b509050611729919061172d565b5090565b5b8082111561174657600081600090555060010161172e565b5090565b600081359050611759816126f6565b92915050565b60008083601f84011261177157600080fd5b8235905067ffffffffffffffff81111561178a57600080fd5b6020830191508360208202830111156117a257600080fd5b9250929050565b60008083601f8401126117bb57600080fd5b8235905067ffffffffffffffff8111156117d457600080fd5b6020830191508360208202830111156117ec57600080fd5b9250929050565b6000815190506118028161270d565b92915050565b60008135905061181781612724565b92915050565b60008151905061182c81612724565b92915050565b6000813590506118418161273b565b92915050565b6000815190506118568161273b565b92915050565b60008083601f84011261186e57600080fd5b8235905067ffffffffffffffff81111561188757600080fd5b60208301915083600182028301111561189f57600080fd5b9250929050565b600082601f8301126118b757600080fd5b81356118ca6118c582612506565b6124d9565b915080825260208301602083018583830111156118e657600080fd5b6118f18382846126a3565b50505092915050565b60008135905061190981612752565b92915050565b60006020828403121561192157600080fd5b600061192f8482850161174a565b91505092915050565b6000806020838503121561194b57600080fd5b600083013567ffffffffffffffff81111561196557600080fd5b6119718582860161175f565b92509250509250929050565b6000806000806040858703121561199357600080fd5b600085013567ffffffffffffffff8111156119ad57600080fd5b6119b98782880161175f565b9450945050602085013567ffffffffffffffff8111156119d857600080fd5b6119e4878288016117a9565b925092505092959194509250565b600060208284031215611a0457600080fd5b6000611a12848285016117f3565b91505092915050565b600060208284031215611a2d57600080fd5b6000611a3b84828501611808565b91505092915050565b600060208284031215611a5657600080fd5b6000611a648482850161181d565b91505092915050565b600080600060408486031215611a8257600080fd5b6000611a9086828701611808565b935050602084013567ffffffffffffffff811115611aad57600080fd5b611ab98682870161185c565b92509250509250925092565b60008060408385031215611ad857600080fd5b6000611ae685828601611808565b925050602083013567ffffffffffffffff811115611b0357600080fd5b611b0f858286016118a6565b9150509250929050565b600060208284031215611b2b57600080fd5b6000611b3984828501611832565b91505092915050565b600060208284031215611b5457600080fd5b6000611b6284828501611847565b91505092915050565b600060208284031215611b7d57600080fd5b6000611b8b848285016118fa565b91505092915050565b600080600080600060808688031215611bac57600080fd5b6000611bba888289016118fa565b9550506020611bcb8882890161174a565b9450506040611bdc888289016118fa565b935050606086013567ffffffffffffffff811115611bf957600080fd5b611c058882890161185c565b92509250509295509295909350565b6000611c208383611d40565b60208301905092915050565b6000611c388383611d9a565b905092915050565b611c498161266d565b82525050565b611c58816125e2565b82525050565b6000611c6982612552565b611c73818561258d565b9350611c7e83612532565b8060005b83811015611caf578151611c968882611c14565b9750611ca183612573565b925050600181019050611c82565b5085935050505092915050565b6000611cc78261255d565b611cd1818561259e565b935083602082028501611ce385612542565b8060005b85811015611d1f5784840389528151611d008582611c2c565b9450611d0b83612580565b925060208a01995050600181019050611ce7565b50829750879550505050505092915050565b611d3a816125f4565b82525050565b611d4981612600565b82525050565b611d5881612600565b82525050565b611d678161260a565b82525050565b6000611d7983856125c0565b9350611d868385846126a3565b611d8f836126e5565b840190509392505050565b6000611da582612568565b611daf81856125af565b9350611dbf8185602086016126b2565b611dc8816126e5565b840191505092915050565b6000611dde82612568565b611de881856125c0565b9350611df88185602086016126b2565b611e01816126e5565b840191505092915050565b6000611e196018836125d1565b91507f45434453413a20696e76616c6964207369676e617475726500000000000000006000830152602082019050919050565b6000611e596020836125d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000611e99601f836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265206c656e677468006000830152602082019050919050565b6000611ed96026836125d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611f3f6022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611fa56022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061200b6019836125d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b600061204b6019836125d1565b91507f436f756c64206e6f74206465706c6f7920636f6e7472616374000000000000006000830152602082019050919050565b600061208b6020836125d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006120cb6014836125d1565b91507f57726f6e67206f7065726174696f6e20747970650000000000000000000000006000830152602082019050919050565b600061210b601d836125d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b61214781612656565b82525050565b61215681612660565b82525050565b60006020820190506121716000830184611c4f565b92915050565b600060608201905061218c6000830187611c40565b6121996020830186611d4f565b81810360408301526121ac818486611d6d565b905095945050505050565b600060208201905081810360008301526121d18184611c5e565b905092915050565b600060208201905081810360008301526121f38184611cbc565b905092915050565b60006020820190506122106000830184611d31565b92915050565b600060208201905061222b6000830184611d4f565b92915050565b60006040820190506122466000830185611d4f565b81810360208301526122588184611dd3565b90509392505050565b60006080820190506122766000830187611d4f565b612283602083018661214d565b6122906040830185611d4f565b61229d6060830184611d4f565b95945050505050565b60006020820190506122bb6000830184611d5e565b92915050565b600060208201905081810360008301526122dc818486611d6d565b90509392505050565b600060208201905081810360008301526122ff8184611dd3565b905092915050565b6000602082019050818103600083015261232081611e0c565b9050919050565b6000602082019050818103600083015261234081611e4c565b9050919050565b6000602082019050818103600083015261236081611e8c565b9050919050565b6000602082019050818103600083015261238081611ecc565b9050919050565b600060208201905081810360008301526123a081611f32565b9050919050565b600060208201905081810360008301526123c081611f98565b9050919050565b600060208201905081810360008301526123e081611ffe565b9050919050565b600060208201905081810360008301526124008161203e565b9050919050565b600060208201905081810360008301526124208161207e565b9050919050565b60006020820190508181036000830152612440816120be565b9050919050565b60006020820190508181036000830152612460816120fe565b9050919050565b600060208201905061247c600083018461213e565b92915050565b6000808335600160200384360303811261249b57600080fd5b80840192508235915067ffffffffffffffff8211156124b957600080fd5b6020830192506001820236038313156124d157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156124fc57600080fd5b8060405250919050565b600067ffffffffffffffff82111561251d57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006125ed82612636565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60006126788261267f565b9050919050565b600061268a82612691565b9050919050565b600061269c82612636565b9050919050565b82818337600083830152505050565b60005b838110156126d05780820151818401526020810190506126b5565b838111156126df576000848401525b50505050565b6000601f19601f8301169050919050565b6126ff816125e2565b811461270a57600080fd5b50565b612716816125f4565b811461272157600080fd5b50565b61272d81612600565b811461273857600080fd5b50565b6127448161260a565b811461274f57600080fd5b50565b61275b81612656565b811461276657600080fd5b5056fea2646970667358221220d063571f68f80a45eee83a7a1c2d5fffde815fdfd49bef541518ed1f741f532664736f6c634300060c0033000000000000000000000000376b0c0490efc7f2f496c187631d5f0685fe18d0

Deployed ByteCode

0x6080604052600436106100e15760003560e01c80636bb56a141161007f5780638da5cb5b116100595780638da5cb5b14610319578063c559acef14610344578063ec89dc1c1461036f578063f2fde38b146103ac57610133565b80636bb56a141461029c578063715018a6146102d95780637f23690c146102f057610133565b8063456cc348116100bb578063456cc348146101ce57806354f6127f1461020b578063595fa1e5146102485780635da40c471461027157610133565b806301ffc9a7146101385780631626ba7e1461017557806344c028fe146101b257610133565b3661013357346100ef6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f7e71433ddf847725166244795048ecf3e3f9f35628254ecbf73605666423349360405160405180910390a3005b600080fd5b34801561014457600080fd5b5061015f600480360381019061015a9190611b19565b6103dd565b60405161016c91906121fb565b60405180910390f35b34801561018157600080fd5b5061019c60048036038101906101979190611ac5565b610444565b6040516101a991906122a6565b60405180910390f35b6101cc60048036038101906101c79190611b94565b61056e565b005b3480156101da57600080fd5b506101f560048036038101906101f09190611938565b610876565b60405161020291906121d9565b60405180910390f35b34801561021757600080fd5b50610232600480360381019061022d9190611a1b565b610926565b60405161023f91906122e5565b60405180910390f35b34801561025457600080fd5b5061026f600480360381019061026a919061197d565b6109db565b005b34801561027d57600080fd5b50610286610acd565b6040516102939190612467565b60405180910390f35b3480156102a857600080fd5b506102c360048036038101906102be9190611a6d565b610ada565b6040516102d09190612216565b60405180910390f35b3480156102e557600080fd5b506102ee610cc4565b005b3480156102fc57600080fd5b5061031760048036038101906103129190611a6d565b610e1c565b005b34801561032557600080fd5b5061032e610f6f565b60405161033b919061215c565b60405180910390f35b34801561035057600080fd5b50610359610f99565b60405161036691906121b7565b60405180910390f35b34801561037b57600080fd5b5061039660048036038101906103919190611b6b565b610ff1565b6040516103a39190612216565b60405180910390f35b3480156103b857600080fd5b506103d360048036038101906103ce919061190f565b611012565b005b600033905090565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6000610456610451610f6f565b6111d9565b801561046e575061046d631626ba7e60e01b6103dd565b5b1561050c5761047b610f6f565b73ffffffffffffffffffffffffffffffffffffffff16631626ba7e84846040518363ffffffff1660e01b81526004016104b5929190612231565b60206040518083038186803b1580156104cd57600080fd5b505afa1580156104e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105059190611b42565b9050610568565b61051683836111e6565b73ffffffffffffffffffffffffffffffffffffffff16610534610f6f565b73ffffffffffffffffffffffffffffffffffffffff161461055c5763ffffffff60e01b610565565b631626ba7e60e01b5b90505b92915050565b6105766103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fc90612407565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff16867f1f920dbda597d7bf95035464170fa58d0a4b57f13a1c315ace6793b9f63688b8858560405161064f9291906122c1565b60405180910390a460006109c45a03905060008614156106bf576106b9858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050846113d3565b5061086e565b600386141561071c576107168484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506113ec565b5061086d565b600286141561083157600061077b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050602086869050036114b1565b905060606107d585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000602088889050036114d9565b905060006107e4878484611565565b90508073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a250505061086c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086390612427565b60405180910390fd5b5b5b505050505050565b6060600083839050905060608167ffffffffffffffff8111801561089957600080fd5b506040519080825280602002602001820160405280156108cd57816020015b60608152602001906001900390816108b85790505b50905060005b8281101561091a576108f68686838181106108ea57fe5b90506020020135610926565b82828151811061090257fe5b602002602001018190525080806001019150506108d3565b50809250505092915050565b6060600260008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b50505050509050919050565b6109e36103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990612407565b60405180910390fd5b60005b84849050811015610ac657610ab9858583818110610a8f57fe5b90506020020135848484818110610aa257fe5b9050602002810190610ab49190612482565b610e1c565b8080600101915050610a75565b5050505050565b6000600480549050905090565b60006060610b0a7f0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b4760001b610926565b905060009150601481511415610c63576000610b27826000611676565b90508073ffffffffffffffffffffffffffffffffffffffff166301ffc9a7600360049054906101000a900460e01b6040518263ffffffff1660e01b8152600401610b7191906122a6565b60206040518083038186803b158015610b8957600080fd5b505afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc191906119f2565b15610c61578073ffffffffffffffffffffffffffffffffffffffff1663c2d7bcc1610bea6103d5565b8888886040518563ffffffff1660e01b8152600401610c0c9493929190612177565b602060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5e9190611a44565b92505b505b8185610c6d6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f54b98940949b5ac0325c889c84db302d4e18faec431b48bdc81706bfe482cfbd8787604051610cb49291906122c1565b60405180910390a4509392505050565b610ccc6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5290612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b610e246103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eaa90612407565b60405180910390fd5b6000600260008581526020019081526020016000208054600181600116156101000203166002900490501415610f0d5760048390806001815401808255809150506001900390600052602060002001600090919091909150555b8181600260008681526020019081526020016000209190610f2f9291906116ad565b50827fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b28383604051610f629291906122c1565b60405180910390a2505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805480602002602001604051908101604052809291908181526020018280548015610fe757602002820191906000526020600020905b815481526020019060010190808311610fd3575b5050505050905090565b60048181548110610ffe57fe5b906000526020600020016000915090505481565b61101a6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a090612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111090612367565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080823b119050919050565b6000604182511461122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122390612347565b60405180910390fd5b60008060006020850151925060408501519150606085015160001a90507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c11156112af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112a690612387565b60405180910390fd5b601b8160ff1614806112c45750601c8160ff16145b611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa906123a7565b60405180910390fd5b6000600187838686604051600081526020016040526040516113289493929190612261565b6020604051602081039080840390855afa15801561134a573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd90612307565b60405180910390fd5b8094505050505092915050565b6000806000845160208601878987f19050949350505050565b600081516020830184f09050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145f906123e7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a292915050565b600060208201835110156114c457600080fd5b60008260208501015190508091505092915050565b6060818301845110156114eb57600080fd5b606082156000811461150857604051915060208201604052611559565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156115465780518352602083019250602081019050611529565b50868552601f19601f8301166040525050505b50809150509392505050565b600080844710156115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290612447565b60405180910390fd5b6000835114156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790612327565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561166b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611662906123c7565b60405180910390fd5b809150509392505050565b6000601482018351101561168957600080fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ee57803560ff191683800117855561171c565b8280016001018555821561171c579182015b8281111561171b578235825591602001919060010190611700565b5b509050611729919061172d565b5090565b5b8082111561174657600081600090555060010161172e565b5090565b600081359050611759816126f6565b92915050565b60008083601f84011261177157600080fd5b8235905067ffffffffffffffff81111561178a57600080fd5b6020830191508360208202830111156117a257600080fd5b9250929050565b60008083601f8401126117bb57600080fd5b8235905067ffffffffffffffff8111156117d457600080fd5b6020830191508360208202830111156117ec57600080fd5b9250929050565b6000815190506118028161270d565b92915050565b60008135905061181781612724565b92915050565b60008151905061182c81612724565b92915050565b6000813590506118418161273b565b92915050565b6000815190506118568161273b565b92915050565b60008083601f84011261186e57600080fd5b8235905067ffffffffffffffff81111561188757600080fd5b60208301915083600182028301111561189f57600080fd5b9250929050565b600082601f8301126118b757600080fd5b81356118ca6118c582612506565b6124d9565b915080825260208301602083018583830111156118e657600080fd5b6118f18382846126a3565b50505092915050565b60008135905061190981612752565b92915050565b60006020828403121561192157600080fd5b600061192f8482850161174a565b91505092915050565b6000806020838503121561194b57600080fd5b600083013567ffffffffffffffff81111561196557600080fd5b6119718582860161175f565b92509250509250929050565b6000806000806040858703121561199357600080fd5b600085013567ffffffffffffffff8111156119ad57600080fd5b6119b98782880161175f565b9450945050602085013567ffffffffffffffff8111156119d857600080fd5b6119e4878288016117a9565b925092505092959194509250565b600060208284031215611a0457600080fd5b6000611a12848285016117f3565b91505092915050565b600060208284031215611a2d57600080fd5b6000611a3b84828501611808565b91505092915050565b600060208284031215611a5657600080fd5b6000611a648482850161181d565b91505092915050565b600080600060408486031215611a8257600080fd5b6000611a9086828701611808565b935050602084013567ffffffffffffffff811115611aad57600080fd5b611ab98682870161185c565b92509250509250925092565b60008060408385031215611ad857600080fd5b6000611ae685828601611808565b925050602083013567ffffffffffffffff811115611b0357600080fd5b611b0f858286016118a6565b9150509250929050565b600060208284031215611b2b57600080fd5b6000611b3984828501611832565b91505092915050565b600060208284031215611b5457600080fd5b6000611b6284828501611847565b91505092915050565b600060208284031215611b7d57600080fd5b6000611b8b848285016118fa565b91505092915050565b600080600080600060808688031215611bac57600080fd5b6000611bba888289016118fa565b9550506020611bcb8882890161174a565b9450506040611bdc888289016118fa565b935050606086013567ffffffffffffffff811115611bf957600080fd5b611c058882890161185c565b92509250509295509295909350565b6000611c208383611d40565b60208301905092915050565b6000611c388383611d9a565b905092915050565b611c498161266d565b82525050565b611c58816125e2565b82525050565b6000611c6982612552565b611c73818561258d565b9350611c7e83612532565b8060005b83811015611caf578151611c968882611c14565b9750611ca183612573565b925050600181019050611c82565b5085935050505092915050565b6000611cc78261255d565b611cd1818561259e565b935083602082028501611ce385612542565b8060005b85811015611d1f5784840389528151611d008582611c2c565b9450611d0b83612580565b925060208a01995050600181019050611ce7565b50829750879550505050505092915050565b611d3a816125f4565b82525050565b611d4981612600565b82525050565b611d5881612600565b82525050565b611d678161260a565b82525050565b6000611d7983856125c0565b9350611d868385846126a3565b611d8f836126e5565b840190509392505050565b6000611da582612568565b611daf81856125af565b9350611dbf8185602086016126b2565b611dc8816126e5565b840191505092915050565b6000611dde82612568565b611de881856125c0565b9350611df88185602086016126b2565b611e01816126e5565b840191505092915050565b6000611e196018836125d1565b91507f45434453413a20696e76616c6964207369676e617475726500000000000000006000830152602082019050919050565b6000611e596020836125d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000611e99601f836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265206c656e677468006000830152602082019050919050565b6000611ed96026836125d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611f3f6022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611fa56022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061200b6019836125d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b600061204b6019836125d1565b91507f436f756c64206e6f74206465706c6f7920636f6e7472616374000000000000006000830152602082019050919050565b600061208b6020836125d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006120cb6014836125d1565b91507f57726f6e67206f7065726174696f6e20747970650000000000000000000000006000830152602082019050919050565b600061210b601d836125d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b61214781612656565b82525050565b61215681612660565b82525050565b60006020820190506121716000830184611c4f565b92915050565b600060608201905061218c6000830187611c40565b6121996020830186611d4f565b81810360408301526121ac818486611d6d565b905095945050505050565b600060208201905081810360008301526121d18184611c5e565b905092915050565b600060208201905081810360008301526121f38184611cbc565b905092915050565b60006020820190506122106000830184611d31565b92915050565b600060208201905061222b6000830184611d4f565b92915050565b60006040820190506122466000830185611d4f565b81810360208301526122588184611dd3565b90509392505050565b60006080820190506122766000830187611d4f565b612283602083018661214d565b6122906040830185611d4f565b61229d6060830184611d4f565b95945050505050565b60006020820190506122bb6000830184611d5e565b92915050565b600060208201905081810360008301526122dc818486611d6d565b90509392505050565b600060208201905081810360008301526122ff8184611dd3565b905092915050565b6000602082019050818103600083015261232081611e0c565b9050919050565b6000602082019050818103600083015261234081611e4c565b9050919050565b6000602082019050818103600083015261236081611e8c565b9050919050565b6000602082019050818103600083015261238081611ecc565b9050919050565b600060208201905081810360008301526123a081611f32565b9050919050565b600060208201905081810360008301526123c081611f98565b9050919050565b600060208201905081810360008301526123e081611ffe565b9050919050565b600060208201905081810360008301526124008161203e565b9050919050565b600060208201905081810360008301526124208161207e565b9050919050565b60006020820190508181036000830152612440816120be565b9050919050565b60006020820190508181036000830152612460816120fe565b9050919050565b600060208201905061247c600083018461213e565b92915050565b6000808335600160200384360303811261249b57600080fd5b80840192508235915067ffffffffffffffff8211156124b957600080fd5b6020830192506001820236038313156124d157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156124fc57600080fd5b8060405250919050565b600067ffffffffffffffff82111561251d57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006125ed82612636565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60006126788261267f565b9050919050565b600061268a82612691565b9050919050565b600061269c82612636565b9050919050565b82818337600083830152505050565b60005b838110156126d05780820151818401526020810190506126b5565b838111156126df576000848401525b50505050565b6000601f19601f8301169050919050565b6126ff816125e2565b811461270a57600080fd5b50565b612716816125f4565b811461272157600080fd5b50565b61272d81612600565b811461273857600080fd5b50565b6127448161260a565b811461274f57600080fd5b50565b61275b81612656565b811461276657600080fd5b5056fea2646970667358221220d063571f68f80a45eee83a7a1c2d5fffde815fdfd49bef541518ed1f741f532664736f6c634300060c0033