Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0x50f6b7d57c3d8360b7c8413d60372e861ccfa417.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
- Contract name:
- LSP3Account
- Optimization enabled
- false
- Compiler version
- v0.6.12+commit.27d51765
- Verified at
- 2021-11-11T11:52:58.873466Z
Contract source code
// 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
0x6080604052636bb56a1460e01b600360006101000a81548163ffffffff021916908360e01c021790555063c2d7bcc160e01b600360046101000a81548163ffffffff021916908360e01c02179055503480156200005b57600080fd5b50604051620031f9380380620031f983398181016040528101906200008191906200071a565b808080816200009d6301ffc9a760e01b6200037e60201b60201c565b6000620000af6200045660201b60201c565b905080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506200015e6200045e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620001a357620001a2816200048860201b60201c565b5b620001bb6344c028fe60e01b6200037e60201b60201c565b50620001cc6200045e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620002115762000210816200048860201b60201c565b5b62000229632bd57b7360e01b6200037e60201b60201c565b505060007feafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d660001b905063afdeb5d660e01b6040516020016200026d9190620008e8565b604051602081830303815290604052600260008381526020019081526020016000209080519060200190620002a49291906200065d565b50807fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b260026000848152602001908152602001600020604051620002e9919062000905565b60405180910390a262000309631626ba7e60e01b6200037e60201b60201c565b505060047feafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6908060018154018082558091505060019003906000526020600020016000909160001b90919091505562000377600360009054906101000a900460e01b6200037e60201b60201c565b5062000a4a565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415620003ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003e1906200094b565b60405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600033905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b620004986200045660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146200052a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000521906200096d565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200059d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005949062000929565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620006a057805160ff1916838001178555620006d1565b82800160010185558215620006d1579182015b82811115620006d0578251825591602001919060010190620006b3565b5b509050620006e09190620006e4565b5090565b5b80821115620006ff576000816000905550600101620006e5565b5090565b600081519050620007148162000a30565b92915050565b6000602082840312156200072d57600080fd5b60006200073d8482850162000703565b91505092915050565b6200075b6200075582620009da565b62000a26565b82525050565b600081546001811660008114620007815760018114620007aa57620007f4565b607f6002830416620007948187620009a4565b955060ff198316865260208601935050620007f4565b60028204620007ba8187620009a4565b9550620007c7856200098f565b60005b82811015620007eb57815481890152600182019150602081019050620007ca565b80880195505050505b505092915050565b60006200080b602683620009b5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600062000873601c83620009b5565b91507f4552433136353a20696e76616c696420696e74657266616365206964000000006000830152602082019050919050565b6000620008b5602083620009b5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000620008f6828462000746565b60048201915081905092915050565b6000602082019050818103600083015262000921818462000761565b905092915050565b600060208201905081810360008301526200094481620007fc565b9050919050565b60006020820190508181036000830152620009668162000864565b9050919050565b600060208201905081810360008301526200098881620008a6565b9050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000620009d38262000a06565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000a3b81620009c6565b811462000a4757600080fd5b50565b61279f8062000a5a6000396000f3fe6080604052600436106100e15760003560e01c80636bb56a141161007f5780638da5cb5b116100595780638da5cb5b14610319578063c559acef14610344578063ec89dc1c1461036f578063f2fde38b146103ac57610133565b80636bb56a141461029c578063715018a6146102d95780637f23690c146102f057610133565b8063456cc348116100bb578063456cc348146101ce57806354f6127f1461020b578063595fa1e5146102485780635da40c471461027157610133565b806301ffc9a7146101385780631626ba7e1461017557806344c028fe146101b257610133565b3661013357346100ef6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f7e71433ddf847725166244795048ecf3e3f9f35628254ecbf73605666423349360405160405180910390a3005b600080fd5b34801561014457600080fd5b5061015f600480360381019061015a9190611b19565b6103dd565b60405161016c91906121fb565b60405180910390f35b34801561018157600080fd5b5061019c60048036038101906101979190611ac5565b610444565b6040516101a991906122a6565b60405180910390f35b6101cc60048036038101906101c79190611b94565b61056e565b005b3480156101da57600080fd5b506101f560048036038101906101f09190611938565b610876565b60405161020291906121d9565b60405180910390f35b34801561021757600080fd5b50610232600480360381019061022d9190611a1b565b610926565b60405161023f91906122e5565b60405180910390f35b34801561025457600080fd5b5061026f600480360381019061026a919061197d565b6109db565b005b34801561027d57600080fd5b50610286610acd565b6040516102939190612467565b60405180910390f35b3480156102a857600080fd5b506102c360048036038101906102be9190611a6d565b610ada565b6040516102d09190612216565b60405180910390f35b3480156102e557600080fd5b506102ee610cc4565b005b3480156102fc57600080fd5b5061031760048036038101906103129190611a6d565b610e1c565b005b34801561032557600080fd5b5061032e610f6f565b60405161033b919061215c565b60405180910390f35b34801561035057600080fd5b50610359610f99565b60405161036691906121b7565b60405180910390f35b34801561037b57600080fd5b5061039660048036038101906103919190611b6b565b610ff1565b6040516103a39190612216565b60405180910390f35b3480156103b857600080fd5b506103d360048036038101906103ce919061190f565b611012565b005b600033905090565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6000610456610451610f6f565b6111d9565b801561046e575061046d631626ba7e60e01b6103dd565b5b1561050c5761047b610f6f565b73ffffffffffffffffffffffffffffffffffffffff16631626ba7e84846040518363ffffffff1660e01b81526004016104b5929190612231565b60206040518083038186803b1580156104cd57600080fd5b505afa1580156104e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105059190611b42565b9050610568565b61051683836111e6565b73ffffffffffffffffffffffffffffffffffffffff16610534610f6f565b73ffffffffffffffffffffffffffffffffffffffff161461055c5763ffffffff60e01b610565565b631626ba7e60e01b5b90505b92915050565b6105766103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fc90612407565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff16867f1f920dbda597d7bf95035464170fa58d0a4b57f13a1c315ace6793b9f63688b8858560405161064f9291906122c1565b60405180910390a460006109c45a03905060008614156106bf576106b9858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050846113d3565b5061086e565b600386141561071c576107168484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506113ec565b5061086d565b600286141561083157600061077b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050602086869050036114b1565b905060606107d585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000602088889050036114d9565b905060006107e4878484611565565b90508073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a250505061086c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086390612427565b60405180910390fd5b5b5b505050505050565b6060600083839050905060608167ffffffffffffffff8111801561089957600080fd5b506040519080825280602002602001820160405280156108cd57816020015b60608152602001906001900390816108b85790505b50905060005b8281101561091a576108f68686838181106108ea57fe5b90506020020135610926565b82828151811061090257fe5b602002602001018190525080806001019150506108d3565b50809250505092915050565b6060600260008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b50505050509050919050565b6109e36103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990612407565b60405180910390fd5b60005b84849050811015610ac657610ab9858583818110610a8f57fe5b90506020020135848484818110610aa257fe5b9050602002810190610ab49190612482565b610e1c565b8080600101915050610a75565b5050505050565b6000600480549050905090565b60006060610b0a7f0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b4760001b610926565b905060009150601481511415610c63576000610b27826000611676565b90508073ffffffffffffffffffffffffffffffffffffffff166301ffc9a7600360049054906101000a900460e01b6040518263ffffffff1660e01b8152600401610b7191906122a6565b60206040518083038186803b158015610b8957600080fd5b505afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc191906119f2565b15610c61578073ffffffffffffffffffffffffffffffffffffffff1663c2d7bcc1610bea6103d5565b8888886040518563ffffffff1660e01b8152600401610c0c9493929190612177565b602060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5e9190611a44565b92505b505b8185610c6d6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f54b98940949b5ac0325c889c84db302d4e18faec431b48bdc81706bfe482cfbd8787604051610cb49291906122c1565b60405180910390a4509392505050565b610ccc6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5290612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b610e246103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eaa90612407565b60405180910390fd5b6000600260008581526020019081526020016000208054600181600116156101000203166002900490501415610f0d5760048390806001815401808255809150506001900390600052602060002001600090919091909150555b8181600260008681526020019081526020016000209190610f2f9291906116ad565b50827fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b28383604051610f629291906122c1565b60405180910390a2505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805480602002602001604051908101604052809291908181526020018280548015610fe757602002820191906000526020600020905b815481526020019060010190808311610fd3575b5050505050905090565b60048181548110610ffe57fe5b906000526020600020016000915090505481565b61101a6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a090612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111090612367565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080823b119050919050565b6000604182511461122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122390612347565b60405180910390fd5b60008060006020850151925060408501519150606085015160001a90507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c11156112af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112a690612387565b60405180910390fd5b601b8160ff1614806112c45750601c8160ff16145b611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa906123a7565b60405180910390fd5b6000600187838686604051600081526020016040526040516113289493929190612261565b6020604051602081039080840390855afa15801561134a573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd90612307565b60405180910390fd5b8094505050505092915050565b6000806000845160208601878987f19050949350505050565b600081516020830184f09050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145f906123e7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a292915050565b600060208201835110156114c457600080fd5b60008260208501015190508091505092915050565b6060818301845110156114eb57600080fd5b606082156000811461150857604051915060208201604052611559565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156115465780518352602083019250602081019050611529565b50868552601f19601f8301166040525050505b50809150509392505050565b600080844710156115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290612447565b60405180910390fd5b6000835114156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790612327565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561166b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611662906123c7565b60405180910390fd5b809150509392505050565b6000601482018351101561168957600080fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ee57803560ff191683800117855561171c565b8280016001018555821561171c579182015b8281111561171b578235825591602001919060010190611700565b5b509050611729919061172d565b5090565b5b8082111561174657600081600090555060010161172e565b5090565b600081359050611759816126f6565b92915050565b60008083601f84011261177157600080fd5b8235905067ffffffffffffffff81111561178a57600080fd5b6020830191508360208202830111156117a257600080fd5b9250929050565b60008083601f8401126117bb57600080fd5b8235905067ffffffffffffffff8111156117d457600080fd5b6020830191508360208202830111156117ec57600080fd5b9250929050565b6000815190506118028161270d565b92915050565b60008135905061181781612724565b92915050565b60008151905061182c81612724565b92915050565b6000813590506118418161273b565b92915050565b6000815190506118568161273b565b92915050565b60008083601f84011261186e57600080fd5b8235905067ffffffffffffffff81111561188757600080fd5b60208301915083600182028301111561189f57600080fd5b9250929050565b600082601f8301126118b757600080fd5b81356118ca6118c582612506565b6124d9565b915080825260208301602083018583830111156118e657600080fd5b6118f18382846126a3565b50505092915050565b60008135905061190981612752565b92915050565b60006020828403121561192157600080fd5b600061192f8482850161174a565b91505092915050565b6000806020838503121561194b57600080fd5b600083013567ffffffffffffffff81111561196557600080fd5b6119718582860161175f565b92509250509250929050565b6000806000806040858703121561199357600080fd5b600085013567ffffffffffffffff8111156119ad57600080fd5b6119b98782880161175f565b9450945050602085013567ffffffffffffffff8111156119d857600080fd5b6119e4878288016117a9565b925092505092959194509250565b600060208284031215611a0457600080fd5b6000611a12848285016117f3565b91505092915050565b600060208284031215611a2d57600080fd5b6000611a3b84828501611808565b91505092915050565b600060208284031215611a5657600080fd5b6000611a648482850161181d565b91505092915050565b600080600060408486031215611a8257600080fd5b6000611a9086828701611808565b935050602084013567ffffffffffffffff811115611aad57600080fd5b611ab98682870161185c565b92509250509250925092565b60008060408385031215611ad857600080fd5b6000611ae685828601611808565b925050602083013567ffffffffffffffff811115611b0357600080fd5b611b0f858286016118a6565b9150509250929050565b600060208284031215611b2b57600080fd5b6000611b3984828501611832565b91505092915050565b600060208284031215611b5457600080fd5b6000611b6284828501611847565b91505092915050565b600060208284031215611b7d57600080fd5b6000611b8b848285016118fa565b91505092915050565b600080600080600060808688031215611bac57600080fd5b6000611bba888289016118fa565b9550506020611bcb8882890161174a565b9450506040611bdc888289016118fa565b935050606086013567ffffffffffffffff811115611bf957600080fd5b611c058882890161185c565b92509250509295509295909350565b6000611c208383611d40565b60208301905092915050565b6000611c388383611d9a565b905092915050565b611c498161266d565b82525050565b611c58816125e2565b82525050565b6000611c6982612552565b611c73818561258d565b9350611c7e83612532565b8060005b83811015611caf578151611c968882611c14565b9750611ca183612573565b925050600181019050611c82565b5085935050505092915050565b6000611cc78261255d565b611cd1818561259e565b935083602082028501611ce385612542565b8060005b85811015611d1f5784840389528151611d008582611c2c565b9450611d0b83612580565b925060208a01995050600181019050611ce7565b50829750879550505050505092915050565b611d3a816125f4565b82525050565b611d4981612600565b82525050565b611d5881612600565b82525050565b611d678161260a565b82525050565b6000611d7983856125c0565b9350611d868385846126a3565b611d8f836126e5565b840190509392505050565b6000611da582612568565b611daf81856125af565b9350611dbf8185602086016126b2565b611dc8816126e5565b840191505092915050565b6000611dde82612568565b611de881856125c0565b9350611df88185602086016126b2565b611e01816126e5565b840191505092915050565b6000611e196018836125d1565b91507f45434453413a20696e76616c6964207369676e617475726500000000000000006000830152602082019050919050565b6000611e596020836125d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000611e99601f836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265206c656e677468006000830152602082019050919050565b6000611ed96026836125d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611f3f6022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611fa56022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061200b6019836125d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b600061204b6019836125d1565b91507f436f756c64206e6f74206465706c6f7920636f6e7472616374000000000000006000830152602082019050919050565b600061208b6020836125d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006120cb6014836125d1565b91507f57726f6e67206f7065726174696f6e20747970650000000000000000000000006000830152602082019050919050565b600061210b601d836125d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b61214781612656565b82525050565b61215681612660565b82525050565b60006020820190506121716000830184611c4f565b92915050565b600060608201905061218c6000830187611c40565b6121996020830186611d4f565b81810360408301526121ac818486611d6d565b905095945050505050565b600060208201905081810360008301526121d18184611c5e565b905092915050565b600060208201905081810360008301526121f38184611cbc565b905092915050565b60006020820190506122106000830184611d31565b92915050565b600060208201905061222b6000830184611d4f565b92915050565b60006040820190506122466000830185611d4f565b81810360208301526122588184611dd3565b90509392505050565b60006080820190506122766000830187611d4f565b612283602083018661214d565b6122906040830185611d4f565b61229d6060830184611d4f565b95945050505050565b60006020820190506122bb6000830184611d5e565b92915050565b600060208201905081810360008301526122dc818486611d6d565b90509392505050565b600060208201905081810360008301526122ff8184611dd3565b905092915050565b6000602082019050818103600083015261232081611e0c565b9050919050565b6000602082019050818103600083015261234081611e4c565b9050919050565b6000602082019050818103600083015261236081611e8c565b9050919050565b6000602082019050818103600083015261238081611ecc565b9050919050565b600060208201905081810360008301526123a081611f32565b9050919050565b600060208201905081810360008301526123c081611f98565b9050919050565b600060208201905081810360008301526123e081611ffe565b9050919050565b600060208201905081810360008301526124008161203e565b9050919050565b600060208201905081810360008301526124208161207e565b9050919050565b60006020820190508181036000830152612440816120be565b9050919050565b60006020820190508181036000830152612460816120fe565b9050919050565b600060208201905061247c600083018461213e565b92915050565b6000808335600160200384360303811261249b57600080fd5b80840192508235915067ffffffffffffffff8211156124b957600080fd5b6020830192506001820236038313156124d157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156124fc57600080fd5b8060405250919050565b600067ffffffffffffffff82111561251d57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006125ed82612636565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60006126788261267f565b9050919050565b600061268a82612691565b9050919050565b600061269c82612636565b9050919050565b82818337600083830152505050565b60005b838110156126d05780820151818401526020810190506126b5565b838111156126df576000848401525b50505050565b6000601f19601f8301169050919050565b6126ff816125e2565b811461270a57600080fd5b50565b612716816125f4565b811461272157600080fd5b50565b61272d81612600565b811461273857600080fd5b50565b6127448161260a565b811461274f57600080fd5b50565b61275b81612656565b811461276657600080fd5b5056fea2646970667358221220d063571f68f80a45eee83a7a1c2d5fffde815fdfd49bef541518ed1f741f532664736f6c634300060c0033000000000000000000000000376b0c0490efc7f2f496c187631d5f0685fe18d0
Deployed ByteCode
0x6080604052600436106100e15760003560e01c80636bb56a141161007f5780638da5cb5b116100595780638da5cb5b14610319578063c559acef14610344578063ec89dc1c1461036f578063f2fde38b146103ac57610133565b80636bb56a141461029c578063715018a6146102d95780637f23690c146102f057610133565b8063456cc348116100bb578063456cc348146101ce57806354f6127f1461020b578063595fa1e5146102485780635da40c471461027157610133565b806301ffc9a7146101385780631626ba7e1461017557806344c028fe146101b257610133565b3661013357346100ef6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f7e71433ddf847725166244795048ecf3e3f9f35628254ecbf73605666423349360405160405180910390a3005b600080fd5b34801561014457600080fd5b5061015f600480360381019061015a9190611b19565b6103dd565b60405161016c91906121fb565b60405180910390f35b34801561018157600080fd5b5061019c60048036038101906101979190611ac5565b610444565b6040516101a991906122a6565b60405180910390f35b6101cc60048036038101906101c79190611b94565b61056e565b005b3480156101da57600080fd5b506101f560048036038101906101f09190611938565b610876565b60405161020291906121d9565b60405180910390f35b34801561021757600080fd5b50610232600480360381019061022d9190611a1b565b610926565b60405161023f91906122e5565b60405180910390f35b34801561025457600080fd5b5061026f600480360381019061026a919061197d565b6109db565b005b34801561027d57600080fd5b50610286610acd565b6040516102939190612467565b60405180910390f35b3480156102a857600080fd5b506102c360048036038101906102be9190611a6d565b610ada565b6040516102d09190612216565b60405180910390f35b3480156102e557600080fd5b506102ee610cc4565b005b3480156102fc57600080fd5b5061031760048036038101906103129190611a6d565b610e1c565b005b34801561032557600080fd5b5061032e610f6f565b60405161033b919061215c565b60405180910390f35b34801561035057600080fd5b50610359610f99565b60405161036691906121b7565b60405180910390f35b34801561037b57600080fd5b5061039660048036038101906103919190611b6b565b610ff1565b6040516103a39190612216565b60405180910390f35b3480156103b857600080fd5b506103d360048036038101906103ce919061190f565b611012565b005b600033905090565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b6000610456610451610f6f565b6111d9565b801561046e575061046d631626ba7e60e01b6103dd565b5b1561050c5761047b610f6f565b73ffffffffffffffffffffffffffffffffffffffff16631626ba7e84846040518363ffffffff1660e01b81526004016104b5929190612231565b60206040518083038186803b1580156104cd57600080fd5b505afa1580156104e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105059190611b42565b9050610568565b61051683836111e6565b73ffffffffffffffffffffffffffffffffffffffff16610534610f6f565b73ffffffffffffffffffffffffffffffffffffffff161461055c5763ffffffff60e01b610565565b631626ba7e60e01b5b90505b92915050565b6105766103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610605576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105fc90612407565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff16867f1f920dbda597d7bf95035464170fa58d0a4b57f13a1c315ace6793b9f63688b8858560405161064f9291906122c1565b60405180910390a460006109c45a03905060008614156106bf576106b9858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050846113d3565b5061086e565b600386141561071c576107168484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506113ec565b5061086d565b600286141561083157600061077b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050602086869050036114b1565b905060606107d585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000602088889050036114d9565b905060006107e4878484611565565b90508073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a250505061086c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086390612427565b60405180910390fd5b5b5b505050505050565b6060600083839050905060608167ffffffffffffffff8111801561089957600080fd5b506040519080825280602002602001820160405280156108cd57816020015b60608152602001906001900390816108b85790505b50905060005b8281101561091a576108f68686838181106108ea57fe5b90506020020135610926565b82828151811061090257fe5b602002602001018190525080806001019150506108d3565b50809250505092915050565b6060600260008381526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b50505050509050919050565b6109e36103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990612407565b60405180910390fd5b60005b84849050811015610ac657610ab9858583818110610a8f57fe5b90506020020135848484818110610aa257fe5b9050602002810190610ab49190612482565b610e1c565b8080600101915050610a75565b5050505050565b6000600480549050905090565b60006060610b0a7f0cfc51aec37c55a4d0b1a65c6255c4bf2fbdf6277f3cc0730c45b828b6db8b4760001b610926565b905060009150601481511415610c63576000610b27826000611676565b90508073ffffffffffffffffffffffffffffffffffffffff166301ffc9a7600360049054906101000a900460e01b6040518263ffffffff1660e01b8152600401610b7191906122a6565b60206040518083038186803b158015610b8957600080fd5b505afa158015610b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc191906119f2565b15610c61578073ffffffffffffffffffffffffffffffffffffffff1663c2d7bcc1610bea6103d5565b8888886040518563ffffffff1660e01b8152600401610c0c9493929190612177565b602060405180830381600087803b158015610c2657600080fd5b505af1158015610c3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5e9190611a44565b92505b505b8185610c6d6103d5565b73ffffffffffffffffffffffffffffffffffffffff167f54b98940949b5ac0325c889c84db302d4e18faec431b48bdc81706bfe482cfbd8787604051610cb49291906122c1565b60405180910390a4509392505050565b610ccc6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610d5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5290612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b610e246103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eaa90612407565b60405180910390fd5b6000600260008581526020019081526020016000208054600181600116156101000203166002900490501415610f0d5760048390806001815401808255809150506001900390600052602060002001600090919091909150555b8181600260008681526020019081526020016000209190610f2f9291906116ad565b50827fece574603820d07bc9b91f2a932baadf4628aabcb8afba49776529c14a6104b28383604051610f629291906122c1565b60405180910390a2505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606004805480602002602001604051908101604052809291908181526020018280548015610fe757602002820191906000526020600020905b815481526020019060010190808311610fd3575b5050505050905090565b60048181548110610ffe57fe5b906000526020600020016000915090505481565b61101a6103d5565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a090612407565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111090612367565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080823b119050919050565b6000604182511461122c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122390612347565b60405180910390fd5b60008060006020850151925060408501519150606085015160001a90507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c11156112af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112a690612387565b60405180910390fd5b601b8160ff1614806112c45750601c8160ff16145b611303576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fa906123a7565b60405180910390fd5b6000600187838686604051600081526020016040526040516113289493929190612261565b6020604051602081039080840390855afa15801561134a573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113bd90612307565b60405180910390fd5b8094505050505092915050565b6000806000845160208601878987f19050949350505050565b600081516020830184f09050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145f906123e7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca31260405160405180910390a292915050565b600060208201835110156114c457600080fd5b60008260208501015190508091505092915050565b6060818301845110156114eb57600080fd5b606082156000811461150857604051915060208201604052611559565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156115465780518352602083019250602081019050611529565b50868552601f19601f8301166040525050505b50809150509392505050565b600080844710156115ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a290612447565b60405180910390fd5b6000835114156115f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e790612327565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561166b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611662906123c7565b60405180910390fd5b809150509392505050565b6000601482018351101561168957600080fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116ee57803560ff191683800117855561171c565b8280016001018555821561171c579182015b8281111561171b578235825591602001919060010190611700565b5b509050611729919061172d565b5090565b5b8082111561174657600081600090555060010161172e565b5090565b600081359050611759816126f6565b92915050565b60008083601f84011261177157600080fd5b8235905067ffffffffffffffff81111561178a57600080fd5b6020830191508360208202830111156117a257600080fd5b9250929050565b60008083601f8401126117bb57600080fd5b8235905067ffffffffffffffff8111156117d457600080fd5b6020830191508360208202830111156117ec57600080fd5b9250929050565b6000815190506118028161270d565b92915050565b60008135905061181781612724565b92915050565b60008151905061182c81612724565b92915050565b6000813590506118418161273b565b92915050565b6000815190506118568161273b565b92915050565b60008083601f84011261186e57600080fd5b8235905067ffffffffffffffff81111561188757600080fd5b60208301915083600182028301111561189f57600080fd5b9250929050565b600082601f8301126118b757600080fd5b81356118ca6118c582612506565b6124d9565b915080825260208301602083018583830111156118e657600080fd5b6118f18382846126a3565b50505092915050565b60008135905061190981612752565b92915050565b60006020828403121561192157600080fd5b600061192f8482850161174a565b91505092915050565b6000806020838503121561194b57600080fd5b600083013567ffffffffffffffff81111561196557600080fd5b6119718582860161175f565b92509250509250929050565b6000806000806040858703121561199357600080fd5b600085013567ffffffffffffffff8111156119ad57600080fd5b6119b98782880161175f565b9450945050602085013567ffffffffffffffff8111156119d857600080fd5b6119e4878288016117a9565b925092505092959194509250565b600060208284031215611a0457600080fd5b6000611a12848285016117f3565b91505092915050565b600060208284031215611a2d57600080fd5b6000611a3b84828501611808565b91505092915050565b600060208284031215611a5657600080fd5b6000611a648482850161181d565b91505092915050565b600080600060408486031215611a8257600080fd5b6000611a9086828701611808565b935050602084013567ffffffffffffffff811115611aad57600080fd5b611ab98682870161185c565b92509250509250925092565b60008060408385031215611ad857600080fd5b6000611ae685828601611808565b925050602083013567ffffffffffffffff811115611b0357600080fd5b611b0f858286016118a6565b9150509250929050565b600060208284031215611b2b57600080fd5b6000611b3984828501611832565b91505092915050565b600060208284031215611b5457600080fd5b6000611b6284828501611847565b91505092915050565b600060208284031215611b7d57600080fd5b6000611b8b848285016118fa565b91505092915050565b600080600080600060808688031215611bac57600080fd5b6000611bba888289016118fa565b9550506020611bcb8882890161174a565b9450506040611bdc888289016118fa565b935050606086013567ffffffffffffffff811115611bf957600080fd5b611c058882890161185c565b92509250509295509295909350565b6000611c208383611d40565b60208301905092915050565b6000611c388383611d9a565b905092915050565b611c498161266d565b82525050565b611c58816125e2565b82525050565b6000611c6982612552565b611c73818561258d565b9350611c7e83612532565b8060005b83811015611caf578151611c968882611c14565b9750611ca183612573565b925050600181019050611c82565b5085935050505092915050565b6000611cc78261255d565b611cd1818561259e565b935083602082028501611ce385612542565b8060005b85811015611d1f5784840389528151611d008582611c2c565b9450611d0b83612580565b925060208a01995050600181019050611ce7565b50829750879550505050505092915050565b611d3a816125f4565b82525050565b611d4981612600565b82525050565b611d5881612600565b82525050565b611d678161260a565b82525050565b6000611d7983856125c0565b9350611d868385846126a3565b611d8f836126e5565b840190509392505050565b6000611da582612568565b611daf81856125af565b9350611dbf8185602086016126b2565b611dc8816126e5565b840191505092915050565b6000611dde82612568565b611de881856125c0565b9350611df88185602086016126b2565b611e01816126e5565b840191505092915050565b6000611e196018836125d1565b91507f45434453413a20696e76616c6964207369676e617475726500000000000000006000830152602082019050919050565b6000611e596020836125d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000611e99601f836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265206c656e677468006000830152602082019050919050565b6000611ed96026836125d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611f3f6022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000611fa56022836125d1565b91507f45434453413a20696e76616c6964207369676e6174757265202776272076616c60008301527f75650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061200b6019836125d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b600061204b6019836125d1565b91507f436f756c64206e6f74206465706c6f7920636f6e7472616374000000000000006000830152602082019050919050565b600061208b6020836125d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006120cb6014836125d1565b91507f57726f6e67206f7065726174696f6e20747970650000000000000000000000006000830152602082019050919050565b600061210b601d836125d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b61214781612656565b82525050565b61215681612660565b82525050565b60006020820190506121716000830184611c4f565b92915050565b600060608201905061218c6000830187611c40565b6121996020830186611d4f565b81810360408301526121ac818486611d6d565b905095945050505050565b600060208201905081810360008301526121d18184611c5e565b905092915050565b600060208201905081810360008301526121f38184611cbc565b905092915050565b60006020820190506122106000830184611d31565b92915050565b600060208201905061222b6000830184611d4f565b92915050565b60006040820190506122466000830185611d4f565b81810360208301526122588184611dd3565b90509392505050565b60006080820190506122766000830187611d4f565b612283602083018661214d565b6122906040830185611d4f565b61229d6060830184611d4f565b95945050505050565b60006020820190506122bb6000830184611d5e565b92915050565b600060208201905081810360008301526122dc818486611d6d565b90509392505050565b600060208201905081810360008301526122ff8184611dd3565b905092915050565b6000602082019050818103600083015261232081611e0c565b9050919050565b6000602082019050818103600083015261234081611e4c565b9050919050565b6000602082019050818103600083015261236081611e8c565b9050919050565b6000602082019050818103600083015261238081611ecc565b9050919050565b600060208201905081810360008301526123a081611f32565b9050919050565b600060208201905081810360008301526123c081611f98565b9050919050565b600060208201905081810360008301526123e081611ffe565b9050919050565b600060208201905081810360008301526124008161203e565b9050919050565b600060208201905081810360008301526124208161207e565b9050919050565b60006020820190508181036000830152612440816120be565b9050919050565b60006020820190508181036000830152612460816120fe565b9050919050565b600060208201905061247c600083018461213e565b92915050565b6000808335600160200384360303811261249b57600080fd5b80840192508235915067ffffffffffffffff8211156124b957600080fd5b6020830192506001820236038313156124d157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156124fc57600080fd5b8060405250919050565b600067ffffffffffffffff82111561251d57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006125ed82612636565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60006126788261267f565b9050919050565b600061268a82612691565b9050919050565b600061269c82612636565b9050919050565b82818337600083830152505050565b60005b838110156126d05780820151818401526020810190506126b5565b838111156126df576000848401525b50505050565b6000601f19601f8301169050919050565b6126ff816125e2565b811461270a57600080fd5b50565b612716816125f4565b811461272157600080fd5b50565b61272d81612600565b811461273857600080fd5b50565b6127448161260a565b811461274f57600080fd5b50565b61275b81612656565b811461276657600080fd5b5056fea2646970667358221220d063571f68f80a45eee83a7a1c2d5fffde815fdfd49bef541518ed1f741f532664736f6c634300060c0033