UNPKG

@etherspot/contracts

Version:

Etherspot Solidity contracts

107 lines 63.3 kB
{ "address": "0xB86fe0416161ded1370016c470622125a93a8218", "abi": [ { "anonymous": false, "inputs": [ { "components": [ { "internalType": "address", "name": "facetAddress", "type": "address" }, { "internalType": "enum IDiamondCut.FacetCutAction", "name": "action", "type": "uint8" }, { "internalType": "bytes4[]", "name": "functionSelectors", "type": "bytes4[]" } ], "indexed": false, "internalType": "struct IDiamondCut.FacetCut[]", "name": "_diamondCut", "type": "tuple[]" }, { "indexed": false, "internalType": "address", "name": "_init", "type": "address" }, { "indexed": false, "internalType": "bytes", "name": "_calldata", "type": "bytes" } ], "name": "DiamondCut", "type": "event" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "facetAddress", "type": "address" }, { "internalType": "enum IDiamondCut.FacetCutAction", "name": "action", "type": "uint8" }, { "internalType": "bytes4[]", "name": "functionSelectors", "type": "bytes4[]" } ], "internalType": "struct IDiamondCut.FacetCut[]", "name": "_diamondCut", "type": "tuple[]" }, { "internalType": "address", "name": "_init", "type": "address" }, { "internalType": "bytes", "name": "_calldata", "type": "bytes" } ], "name": "diamondCut", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ], "transactionHash": "0xc927a0105e52571c53e1021ee5ff8a4aec02de7b78ac825d980940a54e7a8d7f", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", "from": "0x53fE9288897e254698175740aa359E19E26c10af", "contractAddress": null, "transactionIndex": 0, "gasUsed": "2198253", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "blockHash": "0x2dbf2b5d8c1f8d2a1534fdf517a1e19ee1bd3b2f0a2862c2beccdc078c2f9ced", "transactionHash": "0xc927a0105e52571c53e1021ee5ff8a4aec02de7b78ac825d980940a54e7a8d7f", "logs": [], "blockNumber": 33445184, "cumulativeGasUsed": "2198253", "status": 1, "byzantium": true }, "args": [], "solcInputHash": "72cddffebd41bee705239522b76dca2d", "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_init\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"_init\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"diamondCut((address,uint8,bytes4[])[],address,bytes)\":{\"params\":{\"_calldata\":\"A function call, including function selector and arguments _calldata is executed with delegatecall on _init\",\"_diamondCut\":\"Contains the facet addresses and function selectors\",\"_init\":\"The address of the contract or facet to execute _calldata\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"diamondCut((address,uint8,bytes4[])[],address,bytes)\":{\"notice\":\"Add/replace/remove any number of functions and optionally execute a function with delegatecall\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/bridges/facets/DiamondCutFacet.sol\":\"DiamondCutFacet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/bridges/facets/DiamondCutFacet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity >=0.8.4 <0.9.0;\\r\\n\\r\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\r\\nimport { LibDiamond } from \\\"../libs/LibDiamond.sol\\\";\\r\\n\\r\\ncontract DiamondCutFacet is IDiamondCut {\\r\\n /// @notice Add/replace/remove any number of functions and optionally execute\\r\\n /// a function with delegatecall\\r\\n /// @param _diamondCut Contains the facet addresses and function selectors\\r\\n /// @param _init The address of the contract or facet to execute _calldata\\r\\n /// @param _calldata A function call, including function selector and arguments\\r\\n /// _calldata is executed with delegatecall on _init\\r\\n function diamondCut(\\r\\n FacetCut[] calldata _diamondCut,\\r\\n address _init,\\r\\n bytes calldata _calldata\\r\\n ) external override {\\r\\n LibDiamond.enforceIsContractOwner();\\r\\n LibDiamond.diamondCut(_diamondCut, _init, _calldata);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x4719c2a6416f26c8726710a6b64b82cb58c0b75f37025a86a399ca2ef2d25e46\",\"license\":\"MIT\"},\"src/bridges/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity >=0.8.4 <0.9.0;\\r\\n\\r\\ninterface IDiamondCut {\\r\\n enum FacetCutAction {\\r\\n Add,\\r\\n Replace,\\r\\n Remove\\r\\n }\\r\\n // Add=0, Replace=1, Remove=2\\r\\n\\r\\n struct FacetCut {\\r\\n address facetAddress;\\r\\n FacetCutAction action;\\r\\n bytes4[] functionSelectors;\\r\\n }\\r\\n\\r\\n /// @notice Add/replace/remove any number of functions and optionally execute\\r\\n /// a function with delegatecall\\r\\n /// @param _diamondCut Contains the facet addresses and function selectors\\r\\n /// @param _init The address of the contract or facet to execute _calldata\\r\\n /// @param _calldata A function call, including function selector and arguments\\r\\n /// _calldata is executed with delegatecall on _init\\r\\n function diamondCut(\\r\\n FacetCut[] calldata _diamondCut,\\r\\n address _init,\\r\\n bytes calldata _calldata\\r\\n ) external;\\r\\n\\r\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\r\\n}\\r\\n\",\"keccak256\":\"0x328c89b6fa5bae672416dbfc8b15837f6764895e563675d550edc33c706ad948\",\"license\":\"MIT\"},\"src/bridges/libs/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity >=0.8.4 <0.9.0;\\r\\n\\r\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\r\\n\\r\\nlibrary LibDiamond {\\r\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\r\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\r\\n\\r\\n struct FacetAddressAndPosition {\\r\\n address facetAddress;\\r\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\r\\n }\\r\\n\\r\\n struct FacetFunctionSelectors {\\r\\n bytes4[] functionSelectors;\\r\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\r\\n }\\r\\n\\r\\n struct DiamondStorage {\\r\\n // maps function selector to the facet address and\\r\\n // the position of the selector in the facetFunctionSelectors.selectors array\\r\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\r\\n // maps facet addresses to function selectors\\r\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\r\\n // facet addresses\\r\\n address[] facetAddresses;\\r\\n // Used to query if a contract implements an interface.\\r\\n // Used to implement ERC-165.\\r\\n mapping(bytes4 => bool) supportedInterfaces;\\r\\n // owner of the contract\\r\\n address contractOwner;\\r\\n }\\r\\n\\r\\n function diamondStorage()\\r\\n internal\\r\\n pure\\r\\n returns (DiamondStorage storage ds)\\r\\n {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n // solhint-disable-next-line no-inline-assembly\\r\\n assembly {\\r\\n ds.slot := position\\r\\n }\\r\\n }\\r\\n\\r\\n event OwnershipTransferred(\\r\\n address indexed previousOwner,\\r\\n address indexed newOwner\\r\\n );\\r\\n\\r\\n function setContractOwner(address _newOwner) internal {\\r\\n DiamondStorage storage ds = diamondStorage();\\r\\n address previousOwner = ds.contractOwner;\\r\\n ds.contractOwner = _newOwner;\\r\\n emit OwnershipTransferred(previousOwner, _newOwner);\\r\\n }\\r\\n\\r\\n function contractOwner() internal view returns (address contractOwner_) {\\r\\n contractOwner_ = diamondStorage().contractOwner;\\r\\n }\\r\\n\\r\\n function enforceIsContractOwner() internal view {\\r\\n require(\\r\\n msg.sender == diamondStorage().contractOwner,\\r\\n \\\"LibDiamond: Must be contract owner\\\"\\r\\n );\\r\\n }\\r\\n\\r\\n event DiamondCut(\\r\\n IDiamondCut.FacetCut[] _diamondCut,\\r\\n address _init,\\r\\n bytes _calldata\\r\\n );\\r\\n\\r\\n // Internal function version of diamondCut\\r\\n function diamondCut(\\r\\n IDiamondCut.FacetCut[] memory _diamondCut,\\r\\n address _init,\\r\\n bytes memory _calldata\\r\\n ) internal {\\r\\n for (\\r\\n uint256 facetIndex;\\r\\n facetIndex < _diamondCut.length;\\r\\n facetIndex++\\r\\n ) {\\r\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\r\\n if (action == IDiamondCut.FacetCutAction.Add) {\\r\\n addFunctions(\\r\\n _diamondCut[facetIndex].facetAddress,\\r\\n _diamondCut[facetIndex].functionSelectors\\r\\n );\\r\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\r\\n replaceFunctions(\\r\\n _diamondCut[facetIndex].facetAddress,\\r\\n _diamondCut[facetIndex].functionSelectors\\r\\n );\\r\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\r\\n removeFunctions(\\r\\n _diamondCut[facetIndex].facetAddress,\\r\\n _diamondCut[facetIndex].functionSelectors\\r\\n );\\r\\n } else {\\r\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\r\\n }\\r\\n }\\r\\n emit DiamondCut(_diamondCut, _init, _calldata);\\r\\n initializeDiamondCut(_init, _calldata);\\r\\n }\\r\\n\\r\\n function addFunctions(\\r\\n address _facetAddress,\\r\\n bytes4[] memory _functionSelectors\\r\\n ) internal {\\r\\n require(\\r\\n _functionSelectors.length > 0,\\r\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\r\\n );\\r\\n DiamondStorage storage ds = diamondStorage();\\r\\n require(\\r\\n _facetAddress != address(0),\\r\\n \\\"LibDiamondCut: Add facet can't be address(0)\\\"\\r\\n );\\r\\n uint96 selectorPosition = uint96(\\r\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\r\\n );\\r\\n // add new facet address if it does not exist\\r\\n if (selectorPosition == 0) {\\r\\n addFacet(ds, _facetAddress);\\r\\n }\\r\\n for (\\r\\n uint256 selectorIndex;\\r\\n selectorIndex < _functionSelectors.length;\\r\\n selectorIndex++\\r\\n ) {\\r\\n bytes4 selector = _functionSelectors[selectorIndex];\\r\\n address oldFacetAddress = ds\\r\\n .selectorToFacetAndPosition[selector]\\r\\n .facetAddress;\\r\\n require(\\r\\n oldFacetAddress == address(0),\\r\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\r\\n );\\r\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\r\\n selectorPosition++;\\r\\n }\\r\\n }\\r\\n\\r\\n function replaceFunctions(\\r\\n address _facetAddress,\\r\\n bytes4[] memory _functionSelectors\\r\\n ) internal {\\r\\n require(\\r\\n _functionSelectors.length > 0,\\r\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\r\\n );\\r\\n DiamondStorage storage ds = diamondStorage();\\r\\n require(\\r\\n _facetAddress != address(0),\\r\\n \\\"LibDiamondCut: Add facet can't be address(0)\\\"\\r\\n );\\r\\n uint96 selectorPosition = uint96(\\r\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\r\\n );\\r\\n // add new facet address if it does not exist\\r\\n if (selectorPosition == 0) {\\r\\n addFacet(ds, _facetAddress);\\r\\n }\\r\\n for (\\r\\n uint256 selectorIndex;\\r\\n selectorIndex < _functionSelectors.length;\\r\\n selectorIndex++\\r\\n ) {\\r\\n bytes4 selector = _functionSelectors[selectorIndex];\\r\\n address oldFacetAddress = ds\\r\\n .selectorToFacetAndPosition[selector]\\r\\n .facetAddress;\\r\\n require(\\r\\n oldFacetAddress != _facetAddress,\\r\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\r\\n );\\r\\n removeFunction(ds, oldFacetAddress, selector);\\r\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\r\\n selectorPosition++;\\r\\n }\\r\\n }\\r\\n\\r\\n function removeFunctions(\\r\\n address _facetAddress,\\r\\n bytes4[] memory _functionSelectors\\r\\n ) internal {\\r\\n require(\\r\\n _functionSelectors.length > 0,\\r\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\r\\n );\\r\\n DiamondStorage storage ds = diamondStorage();\\r\\n // if function does not exist then do nothing and return\\r\\n require(\\r\\n _facetAddress == address(0),\\r\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\r\\n );\\r\\n for (\\r\\n uint256 selectorIndex;\\r\\n selectorIndex < _functionSelectors.length;\\r\\n selectorIndex++\\r\\n ) {\\r\\n bytes4 selector = _functionSelectors[selectorIndex];\\r\\n address oldFacetAddress = ds\\r\\n .selectorToFacetAndPosition[selector]\\r\\n .facetAddress;\\r\\n removeFunction(ds, oldFacetAddress, selector);\\r\\n }\\r\\n }\\r\\n\\r\\n function addFacet(DiamondStorage storage ds, address _facetAddress)\\r\\n internal\\r\\n {\\r\\n enforceHasContractCode(\\r\\n _facetAddress,\\r\\n \\\"LibDiamondCut: New facet has no code\\\"\\r\\n );\\r\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\r\\n .facetAddresses\\r\\n .length;\\r\\n ds.facetAddresses.push(_facetAddress);\\r\\n }\\r\\n\\r\\n function addFunction(\\r\\n DiamondStorage storage ds,\\r\\n bytes4 _selector,\\r\\n uint96 _selectorPosition,\\r\\n address _facetAddress\\r\\n ) internal {\\r\\n ds\\r\\n .selectorToFacetAndPosition[_selector]\\r\\n .functionSelectorPosition = _selectorPosition;\\r\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\r\\n _selector\\r\\n );\\r\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\r\\n }\\r\\n\\r\\n function removeFunction(\\r\\n DiamondStorage storage ds,\\r\\n address _facetAddress,\\r\\n bytes4 _selector\\r\\n ) internal {\\r\\n require(\\r\\n _facetAddress != address(0),\\r\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\r\\n );\\r\\n // an immutable function is a function defined directly in a diamond\\r\\n require(\\r\\n _facetAddress != address(this),\\r\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\r\\n );\\r\\n // replace selector with last selector, then delete last selector\\r\\n uint256 selectorPosition = ds\\r\\n .selectorToFacetAndPosition[_selector]\\r\\n .functionSelectorPosition;\\r\\n uint256 lastSelectorPosition = ds\\r\\n .facetFunctionSelectors[_facetAddress]\\r\\n .functionSelectors\\r\\n .length - 1;\\r\\n // if not the same then replace _selector with lastSelector\\r\\n if (selectorPosition != lastSelectorPosition) {\\r\\n bytes4 lastSelector = ds\\r\\n .facetFunctionSelectors[_facetAddress]\\r\\n .functionSelectors[lastSelectorPosition];\\r\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\r\\n selectorPosition\\r\\n ] = lastSelector;\\r\\n ds\\r\\n .selectorToFacetAndPosition[lastSelector]\\r\\n .functionSelectorPosition = uint96(selectorPosition);\\r\\n }\\r\\n // delete the last selector\\r\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\r\\n delete ds.selectorToFacetAndPosition[_selector];\\r\\n\\r\\n // if no more selectors for facet address then delete the facet address\\r\\n if (lastSelectorPosition == 0) {\\r\\n // replace facet address with last facet address and delete last facet address\\r\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\r\\n uint256 facetAddressPosition = ds\\r\\n .facetFunctionSelectors[_facetAddress]\\r\\n .facetAddressPosition;\\r\\n if (facetAddressPosition != lastFacetAddressPosition) {\\r\\n address lastFacetAddress = ds.facetAddresses[\\r\\n lastFacetAddressPosition\\r\\n ];\\r\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\r\\n ds\\r\\n .facetFunctionSelectors[lastFacetAddress]\\r\\n .facetAddressPosition = facetAddressPosition;\\r\\n }\\r\\n ds.facetAddresses.pop();\\r\\n delete ds\\r\\n .facetFunctionSelectors[_facetAddress]\\r\\n .facetAddressPosition;\\r\\n }\\r\\n }\\r\\n\\r\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\r\\n internal\\r\\n {\\r\\n if (_init == address(0)) {\\r\\n require(\\r\\n _calldata.length == 0,\\r\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\r\\n );\\r\\n } else {\\r\\n require(\\r\\n _calldata.length > 0,\\r\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\r\\n );\\r\\n if (_init != address(this)) {\\r\\n enforceHasContractCode(\\r\\n _init,\\r\\n \\\"LibDiamondCut: _init address has no code\\\"\\r\\n );\\r\\n }\\r\\n // solhint-disable-next-line avoid-low-level-calls\\r\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\r\\n if (!success) {\\r\\n if (error.length > 0) {\\r\\n // bubble up the error\\r\\n revert(string(error));\\r\\n } else {\\r\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n function enforceHasContractCode(\\r\\n address _contract,\\r\\n string memory _errorMessage\\r\\n ) internal view {\\r\\n uint256 contractSize;\\r\\n // solhint-disable-next-line no-inline-assembly\\r\\n assembly {\\r\\n contractSize := extcodesize(_contract)\\r\\n }\\r\\n require(contractSize > 0, _errorMessage);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x3edf6c990e9b8e885c9c7fb000d182fc1a4fe6466ada506197a77b8e536ff657\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x608060405234801561001057600080fd5b506126ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004a600480360381019061004591906116ab565b61004c565b005b6100546100b6565b6100af8585906100649190611a49565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610151565b5050505050565b6100be610380565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461014f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014690611ae1565b60405180910390fd5b565b60005b835181101561033557600084828151811061017257610171611b01565b5b60200260200101516020015190506000600281111561019457610193611b30565b5b8160028111156101a7576101a6611b30565b5b036101f7576101f28583815181106101c2576101c1611b01565b5b6020026020010151600001518684815181106101e1576101e0611b01565b5b6020026020010151604001516103ad565b610321565b6001600281111561020b5761020a611b30565b5b81600281111561021e5761021d611b30565b5b0361026e5761026985838151811061023957610238611b01565b5b60200260200101516000015186848151811061025857610257611b01565b5b602002602001015160400151610624565b610320565b60028081111561028157610280611b30565b5b81600281111561029457610293611b30565b5b036102e4576102df8583815181106102af576102ae611b01565b5b6020026020010151600001518684815181106102ce576102cd611b01565b5b6020026020010151604001516108a5565b61031f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031690611bd1565b60405180910390fd5b5b5b50808061032d90611c2a565b915050610154565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161036993929190611f30565b60405180910390a161037b8282610a30565b505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b60008151116103f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e890611fe7565b60405180910390fd5b60006103fb610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361046c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046390612079565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036104d9576104d88285610c42565b5b60005b835181101561061d5760008482815181106104fa576104f9611b01565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e59061210b565b60405180910390fd5b6105fa8583868a610d1d565b838061060590612143565b9450505050808061061590611c2a565b9150506104dc565b5050505050565b6000815111610668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065f90611fe7565b60405180910390fd5b6000610672610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106da90612079565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036107505761074f8285610c42565b5b60005b835181101561089e57600084828151811061077157610770611b01565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610864576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161085b906121e9565b60405180910390fd5b61086f858284610eca565b61087b8583868a610d1d565b838061088690612143565b9450505050808061089690611c2a565b915050610753565b5050505050565b60008151116108e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e090611fe7565b60405180910390fd5b60006108f3610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095b9061227b565b60405180910390fd5b60005b8251811015610a2a57600083828151811061098557610984611b01565b5b602002602001015190506000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610a15848284610eca565b50508080610a2290611c2a565b915050610967565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610aad576000815114610aa8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9f9061230d565b60405180910390fd5b610c3e565b6000815111610af1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae89061239f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610b4757610b46826040518060600160405280602881526020016126926028913961152c565b5b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610b6f91906123fb565b600060405180830381855af49150503d8060008114610baa576040519150601f19603f3d011682016040523d82523d6000602084013e610baf565b606091505b509150915081610c3b57600081511115610c0057806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf79190612456565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c32906124ea565b60405180910390fd5b50505b5050565b610c64816040518060600160405280602481526020016126ba6024913961152c565b81600201805490508260010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555081600201819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b81846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508360010160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018390806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908360e01c021790555080846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f309061257c565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610fa7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9e9061260e565b60405180910390fd5b6000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060018560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905061107e919061262e565b90508082146112125760008560010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000182815481106110df576110de611b01565b5b90600052602060002090600891828204019190066004029054906101000a900460e01b9050808660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001848154811061115b5761115a611b01565b5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555082866000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505b8460010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000180548061126657611265612662565b5b60019003818190600052602060002090600891828204019190066004026101000a81549063ffffffff02191690559055846000016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a8154906bffffffffffffffffffffffff021916905550506000810361152557600060018660020180549050611350919061262e565b905060008660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015490508181146114915760008760020183815481106113ba576113b9611b01565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808860020183815481106113fe576113fd611b01565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818860010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b866002018054806114a5576114a4612662565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000905550505b5050505050565b6000823b9050600081118290611578576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156f9190612456565b60405180910390fd5b50505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f8401126115b7576115b6611592565b5b8235905067ffffffffffffffff8111156115d4576115d3611597565b5b6020830191508360208202830111156115f0576115ef61159c565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611622826115f7565b9050919050565b61163281611617565b811461163d57600080fd5b50565b60008135905061164f81611629565b92915050565b60008083601f84011261166b5761166a611592565b5b8235905067ffffffffffffffff81111561168857611687611597565b5b6020830191508360018202830111156116a4576116a361159c565b5b9250929050565b6000806000806000606086880312156116c7576116c6611588565b5b600086013567ffffffffffffffff8111156116e5576116e461158d565b5b6116f1888289016115a1565b9550955050602061170488828901611640565b935050604086013567ffffffffffffffff8111156117255761172461158d565b5b61173188828901611655565b92509250509295509295909350565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61178982611740565b810181811067ffffffffffffffff821117156117a8576117a7611751565b5b80604052505050565b60006117bb61157e565b90506117c78282611780565b919050565b600067ffffffffffffffff8211156117e7576117e6611751565b5b602082029050602081019050919050565b600080fd5b600080fd5b6003811061180f57600080fd5b50565b60008135905061182181611802565b92915050565b600067ffffffffffffffff82111561184257611841611751565b5b602082029050602081019050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61188881611853565b811461189357600080fd5b50565b6000813590506118a58161187f565b92915050565b60006118be6118b984611827565b6117b1565b905080838252602082019050602084028301858111156118e1576118e061159c565b5b835b8181101561190a57806118f68882611896565b8452602084019350506020810190506118e3565b5050509392505050565b600082601f83011261192957611928611592565b5b81356119398482602086016118ab565b91505092915050565b600060608284031215611958576119576117f8565b5b61196260606117b1565b9050600061197284828501611640565b600083015250602061198684828501611812565b602083015250604082013567ffffffffffffffff8111156119aa576119a96117fd565b5b6119b684828501611914565b60408301525092915050565b60006119d56119d0846117cc565b6117b1565b905080838252602082019050602084028301858111156119f8576119f761159c565b5b835b81811015611a3f57803567ffffffffffffffff811115611a1d57611a1c611592565b5b808601611a2a8982611942565b855260208501945050506020810190506119fa565b5050509392505050565b6000611a563684846119c2565b905092915050565b600082825260208201905092915050565b7f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000611acb602283611a5e565b9150611ad682611a6f565b604082019050919050565b60006020820190508181036000830152611afa81611abe565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560008201527f74416374696f6e00000000000000000000000000000000000000000000000000602082015250565b6000611bbb602783611a5e565b9150611bc682611b5f565b604082019050919050565b60006020820190508181036000830152611bea81611bae565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000819050919050565b6000611c3582611c20565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c6757611c66611bf1565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611ca781611617565b82525050565b60038110611cbe57611cbd611b30565b5b50565b6000819050611ccf82611cad565b919050565b6000611cdf82611cc1565b9050919050565b611cef81611cd4565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611d2a81611853565b82525050565b6000611d3c8383611d21565b60208301905092915050565b6000602082019050919050565b6000611d6082611cf5565b611d6a8185611d00565b9350611d7583611d11565b8060005b83811015611da6578151611d8d8882611d30565b9750611d9883611d48565b925050600181019050611d79565b5085935050505092915050565b6000606083016000830151611dcb6000860182611c9e565b506020830151611dde6020860182611ce6565b5060408301518482036040860152611df68282611d55565b9150508091505092915050565b6000611e0f8383611db3565b905092915050565b6000602082019050919050565b6000611e2f82611c72565b611e398185611c7d565b935083602082028501611e4b85611c8e565b8060005b85811015611e875784840389528151611e688582611e03565b9450611e7383611e17565b925060208a01995050600181019050611e4f565b50829750879550505050505092915050565b611ea281611617565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611ee2578082015181840152602081019050611ec7565b83811115611ef1576000848401525b50505050565b6000611f0282611ea8565b611f0c8185611eb3565b9350611f1c818560208601611ec4565b611f2581611740565b840191505092915050565b60006060820190508181036000830152611f4a8186611e24565b9050611f596020830185611e99565b8181036040830152611f6b8184611ef7565b9050949350505050565b7f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660008201527f6163657420746f20637574000000000000000000000000000000000000000000602082015250565b6000611fd1602b83611a5e565b9150611fdc82611f75565b604082019050919050565b6000602082019050818103600083015261200081611fc4565b9050919050565b7f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260008201527f6520616464726573732830290000000000000000000000000000000000000000602082015250565b6000612063602c83611a5e565b915061206e82612007565b604082019050919050565b6000602082019050818103600083015261209281612056565b9050919050565b7f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60008201527f6e207468617420616c7265616479206578697374730000000000000000000000602082015250565b60006120f5603583611a5e565b915061210082612099565b604082019050919050565b60006020820190508181036000830152612124816120e8565b9050919050565b60006bffffffffffffffffffffffff82169050919050565b600061214e8261212b565b91506bffffffffffffffffffffffff820361216c5761216b611bf1565b5b600182019050919050565b7f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60008201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000602082015250565b60006121d3603883611a5e565b91506121de82612177565b604082019050919050565b60006020820190508181036000830152612202816121c6565b9050919050565b7f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260008201527f657373206d757374206265206164647265737328302900000000000000000000602082015250565b6000612265603683611a5e565b915061227082612209565b604082019050919050565b6000602082019050818103600083015261229481612258565b9050919050565b7f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860008201527f3029206275745f63616c6c64617461206973206e6f7420656d70747900000000602082015250565b60006122f7603c83611a5e565b91506123028261229b565b604082019050919050565b60006020820190508181036000830152612326816122ea565b9050919050565b7f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460008201527f7920627574205f696e6974206973206e6f742061646472657373283029000000602082015250565b6000612389603d83611a5e565b91506123948261232d565b604082019050919050565b600060208201905081810360008301526123b88161237c565b9050919050565b600081905092915050565b60006123d582611ea8565b6123df81856123bf565b93506123ef818560208601611ec4565b80840191505092915050565b600061240782846123ca565b915081905092915050565b600081519050919050565b600061242882612412565b6124328185611a5e565b9350612442818560208601611ec4565b61244b81611740565b840191505092915050565b60006020820190508181036000830152612470818461241d565b905092915050565b7f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e20726560008201527f7665727465640000000000000000000000000000000000000000000000000000602082015250565b60006124d4602683611a5e565b91506124df82612478565b604082019050919050565b60006020820190508181036000830152612503816124c7565b9050919050565b7f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360008201527f74696f6e207468617420646f65736e2774206578697374000000000000000000602082015250565b6000612566603783611a5e565b91506125718261250a565b604082019050919050565b6000602082019050818103600083015261259581612559565b9050919050565b7f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560008201527f7461626c652066756e6374696f6e000000000000000000000000000000000000602082015250565b60006125f8602e83611a5e565b91506126038261259c565b604082019050919050565b60006020820190508181036000830152612627816125eb565b9050919050565b600061263982611c20565b915061264483611c20565b92508282101561265757612656611bf1565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a164736f6c634300080f000a", "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004a600480360381019061004591906116ab565b61004c565b005b6100546100b6565b6100af8585906100649190611a49565b8484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610151565b5050505050565b6100be610380565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461014f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014690611ae1565b60405180910390fd5b565b60005b835181101561033557600084828151811061017257610171611b01565b5b60200260200101516020015190506000600281111561019457610193611b30565b5b8160028111156101a7576101a6611b30565b5b036101f7576101f28583815181106101c2576101c1611b01565b5b6020026020010151600001518684815181106101e1576101e0611b01565b5b6020026020010151604001516103ad565b610321565b6001600281111561020b5761020a611b30565b5b81600281111561021e5761021d611b30565b5b0361026e5761026985838151811061023957610238611b01565b5b60200260200101516000015186848151811061025857610257611b01565b5b602002602001015160400151610624565b610320565b60028081111561028157610280611b30565b5b81600281111561029457610293611b30565b5b036102e4576102df8583815181106102af576102ae611b01565b5b6020026020010151600001518684815181106102ce576102cd611b01565b5b6020026020010151604001516108a5565b61031f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031690611bd1565b60405180910390fd5b5b5b50808061032d90611c2a565b915050610154565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161036993929190611f30565b60405180910390a161037b8282610a30565b505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b60008151116103f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e890611fe7565b60405180910390fd5b60006103fb610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361046c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046390612079565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036104d9576104d88285610c42565b5b60005b835181101561061d5760008482815181106104fa576104f9611b01565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146105ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e59061210b565b60405180910390fd5b6105fa8583868a610d1d565b838061060590612143565b9450505050808061061590611c2a565b9150506104dc565b5050505050565b6000815111610668576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065f90611fe7565b60405180910390fd5b6000610672610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036106e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106da90612079565b60405180910390fd5b60008160010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff16036107505761074f8285610c42565b5b60005b835181101561089e57600084828151811061077157610770611b01565b5b602002602001015190506000846000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610864576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161085b906121e9565b60405180910390fd5b61086f858284610eca565b61087b8583868a610d1d565b838061088690612143565b9450505050808061089690611c2a565b915050610753565b5050505050565b60008151116108e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e090611fe7565b60405180910390fd5b60006108f3610380565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610964576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161095b9061227b565b60405180910390fd5b60005b8251811015610a2a57600083828151811061098557610984611b01565b5b602002602001015190506000836000016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610a15848284610eca565b50508080610a2290611c2a565b915050610967565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610aad576000815114610aa8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a9f9061230d565b60405180910390fd5b610c3e565b6000815111610af1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae89061239f565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610b4757610b46826040518060600160405280602881526020016126926028913961152c565b5b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610b6f91906123fb565b600060405180830381855af49150503d8060008114610baa576040519150601f19603f3d011682016040523d82523d6000602084013e610baf565b606091505b509150915081610c3b57600081511115610c0057806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf79190612456565b60405180910390fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c32906124ea565b60405180910390fd5b50505b5050565b610c64816040518060600160405280602481526020016126ba6024913961152c565b81600201805490508260010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555081600201819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b81846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508360010160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018390806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908360e01c021790555080846000016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160006101000a81548173fffffffffffffffffffffffffffffffffffff