From 6874aa50f77903bd8c047358b97b41b262c9ddaa Mon Sep 17 00:00:00 2001 From: veeso Date: Tue, 10 Dec 2024 16:47:22 +0100 Subject: [PATCH] feat: search contracts --- Cargo.lock | 1 + docs/canisters/deferred-data.md | 38 +++ integration-tests/src/abi/Deferred.json | 58 +++- .../deferred_data/deferred_data.did | 2 +- .../deferred_data/deferred_data.did.d.ts | 1 + .../deferred_data/deferred_data.did.js | 1 + .../deferred_minter/deferred_minter.did | 2 +- .../deferred_minter/deferred_minter.did.d.ts | 1 + .../deferred_minter/deferred_minter.did.js | 1 + src/deferred_data/Cargo.toml | 1 + src/deferred_data/deferred_data.did | 2 +- src/deferred_data/src/app.rs | 8 +- .../src/app/storage/contracts.rs | 50 ++++ src/deferred_data/src/http.rs | 249 +++++++++++++++++- src/deferred_data/src/http/contract_filter.rs | 145 ++++++++++ src/deferred_minter/deferred_minter.did | 2 +- src/did/src/deferred/contract.rs | 2 + .../src/deferred/contract/generic_value.rs | 90 +++++++ 18 files changed, 639 insertions(+), 15 deletions(-) create mode 100644 src/deferred_data/src/http/contract_filter.rs diff --git a/Cargo.lock b/Cargo.lock index a760133..7db37b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -769,6 +769,7 @@ dependencies = [ "pretty_assertions", "route-recognizer", "serde", + "serde_json", "thiserror 2.0.3", "time", "tokio", diff --git a/docs/canisters/deferred-data.md b/docs/canisters/deferred-data.md index b95d354..1ebcf66 100644 --- a/docs/canisters/deferred-data.md +++ b/docs/canisters/deferred-data.md @@ -5,6 +5,7 @@ - [HTTP Endpoint](#http-endpoint) - [Get contracts](#get-contracts) - [Get contract by id](#get-contract-by-id) + - [Contract Properties](#contract-properties) ## Introduction @@ -38,6 +39,13 @@ Response: ] ``` +It is also possible to filter contracts using query params: + +- seller: seller ETH address +- buyer: buyer ETH address +- agency: agency principal +- contract_property: name of the contract property followed by the value (e.g. `contract:garden` => `garden=true`). + ### Get contract by id Get a contract by id @@ -83,3 +91,33 @@ Response: ``` > Restricted properties are redacted based on your permissions + +## Contract Properties + +These are the Properties that may be inserted into the Contract. + +| Property | Type | Description | +|-----------------------|--------------|------------------------------------------------| +| contract:name | TextContent | A title for the property | +| contract:description | TextContent | A description for the property | +| contract:image | TextContent | URL or base64 encoded image | +| contract:address | TextContent | Address where the property is located | +| contract:country | TextContent | Country where the property is located | +| contract:continent | TextContent | Continent where the property is located | +| contract:region | TextContent | Region where the property is located | +| contract:zipCode | TextContent | Zip code where the property is located | +| contract:latitude | TextContent | Latitude where the property is located | +| contract:longitude | TextContent | Longitude where the property is located | +| contract:zone | TextContent | Zone of the city where the property is located | +| contract:city | TextContent | City where the property is located | +| contract:squareMeters | Nat64Content | Property square meters | +| contract:rooms | Nat64Content | Amount of rooms | +| contract:bathrooms | Nat64Content | Amount of Bathrooms | +| contract:floors | Nat64Content | Floors | +| contract:balconies | Nat64Content | Amount of balconies | +| contract:garden | BoolContent | Has garden | +| contract:pool | BoolContent | Has pool | +| contract:garage | BoolContent | Has garage | +| contract:parking | BoolContent | Has a private parking | +| contract:energyClass | TextContent | Optional energy class | +| contract:youtubeUrl | TextContent | URL to a YouTube video showcasing the property | diff --git a/integration-tests/src/abi/Deferred.json b/integration-tests/src/abi/Deferred.json index 8d38ede..bff74d5 100644 --- a/integration-tests/src/abi/Deferred.json +++ b/integration-tests/src/abi/Deferred.json @@ -234,6 +234,37 @@ "name": "OwnershipTransferred", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "sellContractId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "TokenTransferred", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -511,6 +542,11 @@ "outputs": [ { "components": [ + { + "internalType": "uint256", + "name": "contractId", + "type": "uint256" + }, { "internalType": "string", "name": "metadataUri", @@ -840,6 +876,11 @@ "outputs": [ { "components": [ + { + "internalType": "uint256", + "name": "contractId", + "type": "uint256" + }, { "internalType": "string", "name": "metadataUri", @@ -949,6 +990,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1015,8 +1069,8 @@ "type": "function" } ], - "bytecode": "0x60806040526000600d55600e80546001600160a01b0319908116909155600f80548216905560108054909116905534801561003957600080fd5b50604051613bdd380380613bdd8339810160408190526100589161014a565b8060405180604001604052806008815260200167111959995c9c995960c21b81525060405180604001604052806008815260200167111151915494915160c21b81525081600090816100aa9190610219565b5060016100b78282610219565b5050506001600160a01b0381166100e857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100f1816100f8565b50506102d7565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006020828403121561015c57600080fd5b81516001600160a01b038116811461017357600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806101a457607f821691505b6020821081036101c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561021457806000526020600020601f840160051c810160208510156101f15750805b601f840160051c820191505b8181101561021157600081556001016101fd565b50505b505050565b81516001600160401b038111156102325761023261017a565b610246816102408454610190565b846101ca565b6020601f82116001811461027a57600083156102625750848201515b600019600385901b1c1916600184901b178455610211565b600084815260208120601f198516915b828110156102aa578785015182556020948501946001909201910161028a565b50848210156102c85786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b6138f7806102e66000396000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610455578063d0ce736014610468578063d471cf5d1461047b578063e985e9c51461048e578063f2fde38b146104a157600080fd5b8063a30fb02014610409578063abc8c7af1461041c578063b7e62e5d1461042f578063b88d4fde1461044257600080fd5b80638da5cb5b116100e95780638da5cb5b146103ca57806395d89b41146103db5780639be78f05146103e3578063a22cb465146103f657600080fd5b806370a0823114610389578063715018a61461039c57806375229c55146103a457806382558c2a146103b757600080fd5b806342842e0e116101925780635a6aef60116101615780635a6aef60146103235780636352211e1461034357806366666aa9146103565780636ebc8c861461036957600080fd5b806342842e0e146102c95780634a2a1fb0146102dc578063559de7b8146102fd578063592691221461031057600080fd5b8063095ea7b3116101ce578063095ea7b31461027b5780631892dd9f1461029057806323b872dd146102a35780633a043242146102b657600080fd5b8063017d6f991461020057806301ffc9a71461023057806306fdde0314610253578063081812fc14610268575b600080fd5b601054610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024361023e366004612e76565b6104b4565b6040519015158152602001610227565b61025b610506565b6040516102279190612ed9565b610213610276366004612eec565b610598565b61028e610289366004612f1a565b6105c2565b005b61028e61029e366004612f46565b61060f565b61028e6102b1366004612f63565b610639565b6102136102c4366004612eec565b61068f565b61028e6102d7366004612f63565b61069a565b6102ef6102ea366004612fa4565b6106ba565b604051908152602001610227565b61024361030b366004612eec565b610b83565b6102ef61031e366004612eec565b610dbb565b6102ef610331366004612eec565b6000908152600b602052604090205490565b610213610351366004612eec565b610dd0565b600f54610213906001600160a01b031681565b61037c610377366004612eec565b610dfb565b604051610227919061307f565b6102ef610397366004612f46565b610fff565b61028e61102b565b6102ef6103b2366004612eec565b61103f565b61028e6103c5366004612f46565b61104b565b6006546001600160a01b0316610213565b61025b611075565b61028e6103f1366004612f46565b611084565b61028e61040436600461312f565b6110ae565b61037c610417366004612eec565b611109565b600e54610213906001600160a01b031681565b6102ef61043d36600461316d565b61134c565b61028e610450366004613281565b611632565b61025b610463366004612eec565b61168c565b61028e610476366004612eec565b61169e565b61028e61048936600461345b565b6117e4565b61024361049c36600461354e565b611f9f565b61028e6104af366004612f46565b611fcb565b60006001600160e01b031982166380ac58cd60e01b14806104e557506001600160e01b03198216635b5e139f60e01b145b8061050057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600080546105159061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546105419061357c565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b5050505050905090565b60006105a382612009565b156105b9575050600e546001600160a01b031690565b61050082612079565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b6106176120a2565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610606565b6000610500826120cf565b6106b583838360405180602001604052806000815250611632565b505050565b600e546000906001600160a01b0316331480156106e15750600e546001600160a01b031615155b61073d5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610606565b600084815260076020526040808220815161012081019092528054829082906107659061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546107919061357c565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610861576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161080c565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c09091015290506000610921868561134c565b9050846001600160a01b031661093682610dd0565b6001600160a01b0316146109a15760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610606565b6000805b8360400151518110156109f957836040015181815181106109c8576109c86135b6565b60200260200101516001600160a01b0316866001600160a01b0316036109f157600191506109f9565b6001016109a5565b508015610a89576000878152600960205260408120805460019290610a1f9084906135e2565b90915550506000878152600b60205260408120805460019290610a439084906135e2565b9091555050600087815260096020908152604080832054600a9092529091205411610a8457600087815260096020908152604080832054600a909252909120555b610aae565b6000878152600a60205260408120805460019290610aa89084906135e2565b90915550505b610ab782612009565b15610b3357610ac682866120da565b6001600160a01b03861660009081526008602052604090205415610b13576001600160a01b0386166000908152600860205260408120805460019290610b0d9084906135f5565b90915550505b600e54610b29906001600160a01b0316836120e8565b509150610b7c9050565b600e546001600160a01b0316610b4883612079565b6001600160a01b031614610b6c57600e54610b6c906001600160a01b0316836120e8565b610b778686846120f3565b509150505b9392505050565b6000818152600760205260408082208151610120810190925280548392919082908290610baf9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdb9061357c565b8015610c285780601f10610bfd57610100808354040283529160200191610c28565b820191906000526020600020905b815481529060010190602001808311610c0b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610cab576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610c56565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610d0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cee575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c090920191909152810151909150610d835760405162461bcd60e51b815260040161060690613608565b8060a001518160c00151610d9791906135f5565b610da29060016135e2565b6000938452600b60205260409093205490921492915050565b6000610dc682611109565b6080015192915050565b6000610ddb82612009565b15610df257610500610dec8361217e565b836123e0565b610500826120cf565b610e03612d48565b60008281526007602052604080822081516101208101909252805482908290610e2b9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e579061357c565b8015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610f27576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610ed2565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610f8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6a575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c0909201919091528101519091506105005760405162461bcd60e51b815260040161060690613608565b6001600160a01b038116600090815260086020526040812054611021836127e0565b61050091906135e2565b6110336120a2565b61103d6000612828565b565b6000610500823361134c565b6110536120a2565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180546105159061357c565b61108c6120a2565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610606565b611111612d48565b600061111c8361217e565b90506000811161116e5760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610606565b60008181526007602052604090819020815161012081019092528054829082906111979061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546111c39061357c565b80156112105780601f106111e557610100808354040283529160200191611210565b820191906000526020600020905b8154815290600101906020018083116111f357829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611293576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161123e565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156112f457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112d6575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b60008281526007602052604080822081516101208101909252805483929190829082906113789061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546113a49061357c565b80156113f15780601f106113c6576101008083540402835291602001916113f1565b820191906000526020600020905b8154815290600101906020018083116113d457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611474576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161141f565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156114d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114b7575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c09092019190915281015190915061154c5760405162461bcd60e51b815260040161060690613608565b60008060005b8360400151518110156115a65783604001518181518110611575576115756135b6565b60200260200101516001600160a01b0316866001600160a01b03160361159e57600191506115a6565b600101611552565b5080156115c35760008681526009602052604090205491506115d5565b6000868152600a602052604090205491505b8260c001518211156116295760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610606565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610606565b606061169782611109565b5192915050565b6010546001600160a01b0316331480156116c257506010546001600160a01b031615155b6116de5760405162461bcd60e51b815260040161060690613649565b600081116116fe5760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff166117355760405162461bcd60e51b815260040161060690613608565b60008181526007602081905260409091209081015460ff16156117a65760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610606565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b03163314801561180857506010546001600160a01b031615155b6118245760405162461bcd60e51b815260040161060690613649565b8051806118435760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff16156118b95760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610606565b600f546001600160a01b03166119115760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610606565b60008260c001511161197b5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610606565b6000805b836040015151811015611a465760006001600160a01b0316846040015182815181106119ad576119ad6135b6565b6020026020010151600001516001600160a01b031603611a0f5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610606565b83604001518181518110611a2557611a256135b6565b60200260200101516020015182611a3c91906136d6565b915060010161197f565b508060ff16606414611aa45760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610606565b60008360a0015111611b0f5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610606565b60648360c00151611b209190613705565b15611b855760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610606565b608083015115611bfe57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611c1690846135e2565b611c2091906135f5565b9050600085604001515167ffffffffffffffff811115611c4257611c42613192565b604051908082528060200260200182016040528015611ca057816020015b611c8d604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611c605790505b5090506000839050600060648860c00151611cbb9190613719565b905060005b886040015151811015611df557600089604001518281518110611ce557611ce56135b6565b602002602001015190506000816020015160ff1684611d04919061372d565b905060006001611d1483886135e2565b611d1e91906135f5565b905060405180606001604052808d604001518681518110611d4157611d416135b6565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611d7757611d776135b6565b6020908102919091010152611d8d8160016135e2565b95508160086000898781518110611da657611da66135b6565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611de191906135e2565b909155505060019093019250611cc0915050565b506000878152600760209081526040909120908901518190611e17908261378b565b5060608901518051611e33916002840191602090910190612d98565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff1916610100179055611e75600182016000612dfd565b60005b8451811015611ef25781600101858281518110611e9757611e976135b6565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611e78565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d805491929091611f339084906135e2565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610b7c5750506001600160a01b0390811691161490565b611fd36120a2565b6001600160a01b038116611ffd57604051631e4fbdf760e01b815260006004820152602401610606565b61200681612828565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612064575060408051601f3d908101601f191682019092526120619181019061384a565b60015b61207057506001919050565b50600092915050565b60006120848261287a565b506000828152600460205260409020546001600160a01b0316610500565b6006546001600160a01b0316331461103d5760405163118cdaa760e01b8152336004820152602401610606565b60006105008261287a565b6120e481836128b3565b5050565b6120e48282336128cd565b6001600160a01b03821661211d57604051633250574960e11b815260006004820152602401610606565b600061212a8383336128da565b9050836001600160a01b0316816001600160a01b031614612178576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610606565b50505050565b6000805b600c54811015612070576000600c82815481106121a1576121a16135b6565b90600052602060002001549050600060076000838152602001908152602001600020604051806101200160405290816000820180546121df9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461220b9061357c565b80156122585780601f1061222d57610100808354040283529160200191612258565b820191906000526020600020905b81548152906001019060200180831161223b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156122db576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612286565b5050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561233c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161231e575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c09092019190915281015190915085108015906123ad57508060c001518511155b80156123bb57508060e00151155b80156123c957508061010001515b156123d657509392505050565b5050600101612182565b60008083116124015760405162461bcd60e51b81526004016106069061368b565b60008381526007602081905260409091200154610100900460ff166124385760405162461bcd60e51b815260040161060690613608565b6000838152600760205260409020600501548210156124bf5760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610606565b6000838152600760205260409020600601548211156125465760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610606565b6000838152600760205260408082208151610120810190925280548290829061256e9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461259a9061357c565b80156125e75780601f106125bc576101008083540402835291602001916125e7565b820191906000526020600020905b8154815290600101906020018083116125ca57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b8282101561266a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612615565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156126cb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126ad575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b81602001515181101561278157600082602001518281518110612746576127466135b6565b6020026020010151905084816020015111158015612768575080604001518511155b1561277857519250610500915050565b50600101612721565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610606565b60006001600160a01b03821661280c576040516322718ad960e21b815260006004820152602401610606565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050057604051637e27328960e01b815260048101849052602401610606565b6120e48282604051806020016040528060008152506129d3565b6106b583838360016129ea565b6000828152600260205260408120546001600160a01b039081169083161561290757612907818486612af0565b6001600160a01b03811615612945576129246000856000806129ea565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612974576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6129dd8383612b54565b6106b56000848484612bb9565b80806129fe57506001600160a01b03821615155b15612ac0576000612a0e8461287a565b90506001600160a01b03831615801590612a3a5750826001600160a01b0316816001600160a01b031614155b8015612a4d5750612a4b8184611f9f565b155b15612a765760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610606565b8115612abe5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612afb838383612ce2565b6106b5576001600160a01b038316612b2957604051637e27328960e01b815260048101829052602401610606565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610606565b6001600160a01b038216612b7e57604051633250574960e11b815260006004820152602401610606565b6000612b8c838360006128da565b90506001600160a01b038116156106b5576040516339e3563760e11b815260006004820152602401610606565b6001600160a01b0383163b1561217857604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612bfb903390889087908790600401613867565b6020604051808303816000875af1925050508015612c36575060408051601f3d908101601f19168201909252612c33918101906138a4565b60015b612c9f573d808015612c64576040519150601f19603f3d011682016040523d82523d6000602084013e612c69565b606091505b508051600003612c9757604051633250574960e11b81526001600160a01b0385166004820152602401610606565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612cdb57604051633250574960e11b81526001600160a01b0385166004820152602401610606565b5050505050565b60006001600160a01b03831615801590612d405750826001600160a01b0316846001600160a01b03161480612d1c5750612d1c8484611f9f565b80612d4057506000828152600460205260409020546001600160a01b038481169116145b949350505050565b604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612ded579160200282015b82811115612ded57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612db8565b50612df9929150612e1e565b5090565b50805460008255600302906000526020600020908101906120069190612e33565b5b80821115612df95760008155600101612e1f565b5b80821115612df95780546001600160a01b03191681556000600182018190556002820155600301612e34565b6001600160e01b03198116811461200657600080fd5b600060208284031215612e8857600080fd5b8135610b7c81612e60565b6000815180845260005b81811015612eb957602081850181015186830182015201612e9d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b7c6020830184612e93565b600060208284031215612efe57600080fd5b5035919050565b6001600160a01b038116811461200657600080fd5b60008060408385031215612f2d57600080fd5b8235612f3881612f05565b946020939093013593505050565b600060208284031215612f5857600080fd5b8135610b7c81612f05565b600080600060608486031215612f7857600080fd5b8335612f8381612f05565b92506020840135612f9381612f05565b929592945050506040919091013590565b600080600060608486031215612fb957600080fd5b833592506020840135612fcb81612f05565b91506040840135612fdb81612f05565b809150509250925092565b600081518084526020840193506020830160005b8281101561303a57815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612ffa565b5093949350505050565b600081518084526020840193506020830160005b8281101561303a5781516001600160a01b0316865260209586019590910190600101613058565b6020815260008251610120602084015261309d610140840182612e93565b90506020840151601f198483030160408501526130ba8282612fe6565b9150506040840151601f198483030160608501526130d88282613044565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161311761010085018215159052565b50610100840151801515610120850152509392505050565b6000806040838503121561314257600080fd5b823561314d81612f05565b91506020830135801515811461316257600080fd5b809150509250929050565b6000806040838503121561318057600080fd5b82359150602083013561316281612f05565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156131cb576131cb613192565b60405290565b60405160e0810167ffffffffffffffff811182821017156131cb576131cb613192565b604051601f8201601f1916810167ffffffffffffffff8111828210171561321d5761321d613192565b604052919050565b60008067ffffffffffffffff84111561324057613240613192565b50601f8301601f1916602001613255816131f4565b91505082815283838301111561326a57600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561329757600080fd5b84356132a281612f05565b935060208501356132b281612f05565b925060408501359150606085013567ffffffffffffffff8111156132d557600080fd5b8501601f810187136132e657600080fd5b6132f587823560208401613225565b91505092959194509250565b600082601f83011261331257600080fd5b610b7c83833560208501613225565b600067ffffffffffffffff82111561333b5761333b613192565b5060051b60200190565b600082601f83011261335657600080fd5b813561336961336482613321565b6131f4565b8082825260208201915060208360061b86010192508583111561338b57600080fd5b602085015b838110156133ea57604081880312156133a857600080fd5b6133b06131a8565b81356133bb81612f05565b8152602082013560ff811681146133d157600080fd5b6020828101919091529084529290920191604001613390565b5095945050505050565b600082601f83011261340557600080fd5b813561341361336482613321565b8082825260208201915060208360051b86010192508583111561343557600080fd5b602085015b838110156133ea57803561344d81612f05565b83526020928301920161343a565b60006020828403121561346d57600080fd5b813567ffffffffffffffff81111561348457600080fd5b820160e0818503121561349657600080fd5b61349e6131d1565b81358152602082013567ffffffffffffffff8111156134bc57600080fd5b6134c886828501613301565b602083015250604082013567ffffffffffffffff8111156134e857600080fd5b6134f486828501613345565b604083015250606082013567ffffffffffffffff81111561351457600080fd5b613520868285016133f4565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561356157600080fd5b823561356c81612f05565b9150602083013561316281612f05565b600181811c9082168061359057607f821691505b6020821081036135b057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610500576105006135cc565b81810381811115610500576105006135cc565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff8181168382160190811115610500576105006135cc565b634e487b7160e01b600052601260045260246000fd5b600082613714576137146136ef565b500690565b600082613728576137286136ef565b500490565b8082028115828204841417610500576105006135cc565b601f8211156106b557806000526020600020601f840160051c8101602085101561376b5750805b601f840160051c820191505b81811015612cdb5760008155600101613777565b815167ffffffffffffffff8111156137a5576137a5613192565b6137b9816137b3845461357c565b84613744565b6020601f8211600181146137ed57600083156137d55750848201515b600019600385901b1c1916600184901b178455612cdb565b600084815260208120601f198516915b8281101561381d57878501518255602094850194600190920191016137fd565b508482101561383b5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561385c57600080fd5b8151610b7c81612f05565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061389a90830184612e93565b9695505050505050565b6000602082840312156138b657600080fd5b8151610b7c81612e6056fea264697066735822122081d142e672a5c1bd713bf7f477cbdbaf8b7a5a31564697b13fcbb666bbbc162c64736f6c634300081c0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610455578063d0ce736014610468578063d471cf5d1461047b578063e985e9c51461048e578063f2fde38b146104a157600080fd5b8063a30fb02014610409578063abc8c7af1461041c578063b7e62e5d1461042f578063b88d4fde1461044257600080fd5b80638da5cb5b116100e95780638da5cb5b146103ca57806395d89b41146103db5780639be78f05146103e3578063a22cb465146103f657600080fd5b806370a0823114610389578063715018a61461039c57806375229c55146103a457806382558c2a146103b757600080fd5b806342842e0e116101925780635a6aef60116101615780635a6aef60146103235780636352211e1461034357806366666aa9146103565780636ebc8c861461036957600080fd5b806342842e0e146102c95780634a2a1fb0146102dc578063559de7b8146102fd578063592691221461031057600080fd5b8063095ea7b3116101ce578063095ea7b31461027b5780631892dd9f1461029057806323b872dd146102a35780633a043242146102b657600080fd5b8063017d6f991461020057806301ffc9a71461023057806306fdde0314610253578063081812fc14610268575b600080fd5b601054610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024361023e366004612e76565b6104b4565b6040519015158152602001610227565b61025b610506565b6040516102279190612ed9565b610213610276366004612eec565b610598565b61028e610289366004612f1a565b6105c2565b005b61028e61029e366004612f46565b61060f565b61028e6102b1366004612f63565b610639565b6102136102c4366004612eec565b61068f565b61028e6102d7366004612f63565b61069a565b6102ef6102ea366004612fa4565b6106ba565b604051908152602001610227565b61024361030b366004612eec565b610b83565b6102ef61031e366004612eec565b610dbb565b6102ef610331366004612eec565b6000908152600b602052604090205490565b610213610351366004612eec565b610dd0565b600f54610213906001600160a01b031681565b61037c610377366004612eec565b610dfb565b604051610227919061307f565b6102ef610397366004612f46565b610fff565b61028e61102b565b6102ef6103b2366004612eec565b61103f565b61028e6103c5366004612f46565b61104b565b6006546001600160a01b0316610213565b61025b611075565b61028e6103f1366004612f46565b611084565b61028e61040436600461312f565b6110ae565b61037c610417366004612eec565b611109565b600e54610213906001600160a01b031681565b6102ef61043d36600461316d565b61134c565b61028e610450366004613281565b611632565b61025b610463366004612eec565b61168c565b61028e610476366004612eec565b61169e565b61028e61048936600461345b565b6117e4565b61024361049c36600461354e565b611f9f565b61028e6104af366004612f46565b611fcb565b60006001600160e01b031982166380ac58cd60e01b14806104e557506001600160e01b03198216635b5e139f60e01b145b8061050057506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600080546105159061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546105419061357c565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b5050505050905090565b60006105a382612009565b156105b9575050600e546001600160a01b031690565b61050082612079565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b6106176120a2565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610606565b6000610500826120cf565b6106b583838360405180602001604052806000815250611632565b505050565b600e546000906001600160a01b0316331480156106e15750600e546001600160a01b031615155b61073d5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610606565b600084815260076020526040808220815161012081019092528054829082906107659061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546107919061357c565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610861576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161080c565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c09091015290506000610921868561134c565b9050846001600160a01b031661093682610dd0565b6001600160a01b0316146109a15760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610606565b6000805b8360400151518110156109f957836040015181815181106109c8576109c86135b6565b60200260200101516001600160a01b0316866001600160a01b0316036109f157600191506109f9565b6001016109a5565b508015610a89576000878152600960205260408120805460019290610a1f9084906135e2565b90915550506000878152600b60205260408120805460019290610a439084906135e2565b9091555050600087815260096020908152604080832054600a9092529091205411610a8457600087815260096020908152604080832054600a909252909120555b610aae565b6000878152600a60205260408120805460019290610aa89084906135e2565b90915550505b610ab782612009565b15610b3357610ac682866120da565b6001600160a01b03861660009081526008602052604090205415610b13576001600160a01b0386166000908152600860205260408120805460019290610b0d9084906135f5565b90915550505b600e54610b29906001600160a01b0316836120e8565b509150610b7c9050565b600e546001600160a01b0316610b4883612079565b6001600160a01b031614610b6c57600e54610b6c906001600160a01b0316836120e8565b610b778686846120f3565b509150505b9392505050565b6000818152600760205260408082208151610120810190925280548392919082908290610baf9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdb9061357c565b8015610c285780601f10610bfd57610100808354040283529160200191610c28565b820191906000526020600020905b815481529060010190602001808311610c0b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610cab576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610c56565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610d0c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cee575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c090920191909152810151909150610d835760405162461bcd60e51b815260040161060690613608565b8060a001518160c00151610d9791906135f5565b610da29060016135e2565b6000938452600b60205260409093205490921492915050565b6000610dc682611109565b6080015192915050565b6000610ddb82612009565b15610df257610500610dec8361217e565b836123e0565b610500826120cf565b610e03612d48565b60008281526007602052604080822081516101208101909252805482908290610e2b9061357c565b80601f0160208091040260200160405190810160405280929190818152602001828054610e579061357c565b8015610ea45780601f10610e7957610100808354040283529160200191610ea4565b820191906000526020600020905b815481529060010190602001808311610e8757829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015610f27576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610ed2565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610f8857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f6a575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c0909201919091528101519091506105005760405162461bcd60e51b815260040161060690613608565b6001600160a01b038116600090815260086020526040812054611021836127e0565b61050091906135e2565b6110336120a2565b61103d6000612828565b565b6000610500823361134c565b6110536120a2565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600180546105159061357c565b61108c6120a2565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610606565b611111612d48565b600061111c8361217e565b90506000811161116e5760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610606565b60008181526007602052604090819020815161012081019092528054829082906111979061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546111c39061357c565b80156112105780601f106111e557610100808354040283529160200191611210565b820191906000526020600020905b8154815290600101906020018083116111f357829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611293576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161123e565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156112f457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112d6575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c0909101529392505050565b60008281526007602052604080822081516101208101909252805483929190829082906113789061357c565b80601f01602080910402602001604051908101604052809291908181526020018280546113a49061357c565b80156113f15780601f106113c6576101008083540402835291602001916113f1565b820191906000526020600020905b8154815290600101906020018083116113d457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611474576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161141f565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156114d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114b7575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08401526101009182900416151560c09092019190915281015190915061154c5760405162461bcd60e51b815260040161060690613608565b60008060005b8360400151518110156115a65783604001518181518110611575576115756135b6565b60200260200101516001600160a01b0316866001600160a01b03160361159e57600191506115a6565b600101611552565b5080156115c35760008681526009602052604090205491506115d5565b6000868152600a602052604090205491505b8260c001518211156116295760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610606565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610606565b606061169782611109565b5192915050565b6010546001600160a01b0316331480156116c257506010546001600160a01b031615155b6116de5760405162461bcd60e51b815260040161060690613649565b600081116116fe5760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff166117355760405162461bcd60e51b815260040161060690613608565b60008181526007602081905260409091209081015460ff16156117a65760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610606565b60078101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b03163314801561180857506010546001600160a01b031615155b6118245760405162461bcd60e51b815260040161060690613649565b8051806118435760405162461bcd60e51b81526004016106069061368b565b60008181526007602081905260409091200154610100900460ff16156118b95760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610606565b600f546001600160a01b03166119115760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610606565b60008260c001511161197b5760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610606565b6000805b836040015151811015611a465760006001600160a01b0316846040015182815181106119ad576119ad6135b6565b6020026020010151600001516001600160a01b031603611a0f5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610606565b83604001518181518110611a2557611a256135b6565b60200260200101516020015182611a3c91906136d6565b915060010161197f565b508060ff16606414611aa45760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610606565b60008360a0015111611b0f5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610606565b60648360c00151611b209190613705565b15611b855760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610606565b608083015115611bfe57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611be557600080fd5b505af1158015611bf9573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611c1690846135e2565b611c2091906135f5565b9050600085604001515167ffffffffffffffff811115611c4257611c42613192565b604051908082528060200260200182016040528015611ca057816020015b611c8d604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611c605790505b5090506000839050600060648860c00151611cbb9190613719565b905060005b886040015151811015611df557600089604001518281518110611ce557611ce56135b6565b602002602001015190506000816020015160ff1684611d04919061372d565b905060006001611d1483886135e2565b611d1e91906135f5565b905060405180606001604052808d604001518681518110611d4157611d416135b6565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611d7757611d776135b6565b6020908102919091010152611d8d8160016135e2565b95508160086000898781518110611da657611da66135b6565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611de191906135e2565b909155505060019093019250611cc0915050565b506000878152600760209081526040909120908901518190611e17908261378b565b5060608901518051611e33916002840191602090910190612d98565b506080890151600382015560a08901516004820155600581018690556006810185905560078101805461ffff1916610100179055611e75600182016000612dfd565b60005b8451811015611ef25781600101858281518110611e9757611e976135b6565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611e78565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d805491929091611f339084906135e2565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610b7c5750506001600160a01b0390811691161490565b611fd36120a2565b6001600160a01b038116611ffd57604051631e4fbdf760e01b815260006004820152602401610606565b61200681612828565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612064575060408051601f3d908101601f191682019092526120619181019061384a565b60015b61207057506001919050565b50600092915050565b60006120848261287a565b506000828152600460205260409020546001600160a01b0316610500565b6006546001600160a01b0316331461103d5760405163118cdaa760e01b8152336004820152602401610606565b60006105008261287a565b6120e481836128b3565b5050565b6120e48282336128cd565b6001600160a01b03821661211d57604051633250574960e11b815260006004820152602401610606565b600061212a8383336128da565b9050836001600160a01b0316816001600160a01b031614612178576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610606565b50505050565b6000805b600c54811015612070576000600c82815481106121a1576121a16135b6565b90600052602060002001549050600060076000838152602001908152602001600020604051806101200160405290816000820180546121df9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461220b9061357c565b80156122585780601f1061222d57610100808354040283529160200191612258565b820191906000526020600020905b81548152906001019060200180831161223b57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156122db576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612286565b5050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561233c57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161231e575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a08085019190915261010090920416151560c09092019190915281015190915085108015906123ad57508060c001518511155b80156123bb57508060e00151155b80156123c957508061010001515b156123d657509392505050565b5050600101612182565b60008083116124015760405162461bcd60e51b81526004016106069061368b565b60008381526007602081905260409091200154610100900460ff166124385760405162461bcd60e51b815260040161060690613608565b6000838152600760205260409020600501548210156124bf5760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610606565b6000838152600760205260409020600601548211156125465760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610606565b6000838152600760205260408082208151610120810190925280548290829061256e9061357c565b80601f016020809104026020016040519081016040528092919081815260200182805461259a9061357c565b80156125e75780601f106125bc576101008083540402835291602001916125e7565b820191906000526020600020905b8154815290600101906020018083116125ca57829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b8282101561266a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612615565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156126cb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126ad575b50505091835250506003820154602082015260048201546040820152600582015460608201526006820154608082015260079091015460ff808216151560a084015261010090910416151560c090910152905060005b81602001515181101561278157600082602001518281518110612746576127466135b6565b6020026020010151905084816020015111158015612768575080604001518511155b1561277857519250610500915050565b50600101612721565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610606565b60006001600160a01b03821661280c576040516322718ad960e21b815260006004820152602401610606565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050057604051637e27328960e01b815260048101849052602401610606565b6120e48282604051806020016040528060008152506129d3565b6106b583838360016129ea565b6000828152600260205260408120546001600160a01b039081169083161561290757612907818486612af0565b6001600160a01b03811615612945576129246000856000806129ea565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612974576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b6129dd8383612b54565b6106b56000848484612bb9565b80806129fe57506001600160a01b03821615155b15612ac0576000612a0e8461287a565b90506001600160a01b03831615801590612a3a5750826001600160a01b0316816001600160a01b031614155b8015612a4d5750612a4b8184611f9f565b155b15612a765760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610606565b8115612abe5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612afb838383612ce2565b6106b5576001600160a01b038316612b2957604051637e27328960e01b815260048101829052602401610606565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610606565b6001600160a01b038216612b7e57604051633250574960e11b815260006004820152602401610606565b6000612b8c838360006128da565b90506001600160a01b038116156106b5576040516339e3563760e11b815260006004820152602401610606565b6001600160a01b0383163b1561217857604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612bfb903390889087908790600401613867565b6020604051808303816000875af1925050508015612c36575060408051601f3d908101601f19168201909252612c33918101906138a4565b60015b612c9f573d808015612c64576040519150601f19603f3d011682016040523d82523d6000602084013e612c69565b606091505b508051600003612c9757604051633250574960e11b81526001600160a01b0385166004820152602401610606565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612cdb57604051633250574960e11b81526001600160a01b0385166004820152602401610606565b5050505050565b60006001600160a01b03831615801590612d405750826001600160a01b0316846001600160a01b03161480612d1c5750612d1c8484611f9f565b80612d4057506000828152600460205260409020546001600160a01b038481169116145b949350505050565b604051806101200160405280606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612ded579160200282015b82811115612ded57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612db8565b50612df9929150612e1e565b5090565b50805460008255600302906000526020600020908101906120069190612e33565b5b80821115612df95760008155600101612e1f565b5b80821115612df95780546001600160a01b03191681556000600182018190556002820155600301612e34565b6001600160e01b03198116811461200657600080fd5b600060208284031215612e8857600080fd5b8135610b7c81612e60565b6000815180845260005b81811015612eb957602081850181015186830182015201612e9d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610b7c6020830184612e93565b600060208284031215612efe57600080fd5b5035919050565b6001600160a01b038116811461200657600080fd5b60008060408385031215612f2d57600080fd5b8235612f3881612f05565b946020939093013593505050565b600060208284031215612f5857600080fd5b8135610b7c81612f05565b600080600060608486031215612f7857600080fd5b8335612f8381612f05565b92506020840135612f9381612f05565b929592945050506040919091013590565b600080600060608486031215612fb957600080fd5b833592506020840135612fcb81612f05565b91506040840135612fdb81612f05565b809150509250925092565b600081518084526020840193506020830160005b8281101561303a57815180516001600160a01b03168752602080820151818901526040918201519188019190915260609096019590910190600101612ffa565b5093949350505050565b600081518084526020840193506020830160005b8281101561303a5781516001600160a01b0316865260209586019590910190600101613058565b6020815260008251610120602084015261309d610140840182612e93565b90506020840151601f198483030160408501526130ba8282612fe6565b9150506040840151601f198483030160608501526130d88282613044565b91505060608401516080840152608084015160a084015260a084015160c084015260c084015160e084015260e084015161311761010085018215159052565b50610100840151801515610120850152509392505050565b6000806040838503121561314257600080fd5b823561314d81612f05565b91506020830135801515811461316257600080fd5b809150509250929050565b6000806040838503121561318057600080fd5b82359150602083013561316281612f05565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156131cb576131cb613192565b60405290565b60405160e0810167ffffffffffffffff811182821017156131cb576131cb613192565b604051601f8201601f1916810167ffffffffffffffff8111828210171561321d5761321d613192565b604052919050565b60008067ffffffffffffffff84111561324057613240613192565b50601f8301601f1916602001613255816131f4565b91505082815283838301111561326a57600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561329757600080fd5b84356132a281612f05565b935060208501356132b281612f05565b925060408501359150606085013567ffffffffffffffff8111156132d557600080fd5b8501601f810187136132e657600080fd5b6132f587823560208401613225565b91505092959194509250565b600082601f83011261331257600080fd5b610b7c83833560208501613225565b600067ffffffffffffffff82111561333b5761333b613192565b5060051b60200190565b600082601f83011261335657600080fd5b813561336961336482613321565b6131f4565b8082825260208201915060208360061b86010192508583111561338b57600080fd5b602085015b838110156133ea57604081880312156133a857600080fd5b6133b06131a8565b81356133bb81612f05565b8152602082013560ff811681146133d157600080fd5b6020828101919091529084529290920191604001613390565b5095945050505050565b600082601f83011261340557600080fd5b813561341361336482613321565b8082825260208201915060208360051b86010192508583111561343557600080fd5b602085015b838110156133ea57803561344d81612f05565b83526020928301920161343a565b60006020828403121561346d57600080fd5b813567ffffffffffffffff81111561348457600080fd5b820160e0818503121561349657600080fd5b61349e6131d1565b81358152602082013567ffffffffffffffff8111156134bc57600080fd5b6134c886828501613301565b602083015250604082013567ffffffffffffffff8111156134e857600080fd5b6134f486828501613345565b604083015250606082013567ffffffffffffffff81111561351457600080fd5b613520868285016133f4565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561356157600080fd5b823561356c81612f05565b9150602083013561316281612f05565b600181811c9082168061359057607f821691505b6020821081036135b057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610500576105006135cc565b81810381811115610500576105006135cc565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff8181168382160190811115610500576105006135cc565b634e487b7160e01b600052601260045260246000fd5b600082613714576137146136ef565b500690565b600082613728576137286136ef565b500490565b8082028115828204841417610500576105006135cc565b601f8211156106b557806000526020600020601f840160051c8101602085101561376b5750805b601f840160051c820191505b81811015612cdb5760008155600101613777565b815167ffffffffffffffff8111156137a5576137a5613192565b6137b9816137b3845461357c565b84613744565b6020601f8211600181146137ed57600083156137d55750848201515b600019600385901b1c1916600184901b178455612cdb565b600084815260208120601f198516915b8281101561381d57878501518255602094850194600190920191016137fd565b508482101561383b5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561385c57600080fd5b8151610b7c81612f05565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061389a90830184612e93565b9695505050505050565b6000602082840312156138b657600080fd5b8151610b7c81612e6056fea264697066735822122081d142e672a5c1bd713bf7f477cbdbaf8b7a5a31564697b13fcbb666bbbc162c64736f6c634300081c0033", + "bytecode": "0x60806040526000600d55600e80546001600160a01b0319908116909155600f80548216905560108054909116905534801561003957600080fd5b50604051613cfa380380613cfa8339810160408190526100589161014a565b8060405180604001604052806008815260200167111959995c9c995960c21b81525060405180604001604052806008815260200167111151915494915160c21b81525081600090816100aa9190610219565b5060016100b78282610219565b5050506001600160a01b0381166100e857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6100f1816100f8565b50506102d7565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006020828403121561015c57600080fd5b81516001600160a01b038116811461017357600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806101a457607f821691505b6020821081036101c457634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561021457806000526020600020601f840160051c810160208510156101f15750805b601f840160051c820191505b8181101561021157600081556001016101fd565b50505b505050565b81516001600160401b038111156102325761023261017a565b610246816102408454610190565b846101ca565b6020601f82116001811461027a57600083156102625750848201515b600019600385901b1c1916600184901b178455610211565b600084815260208120601f198516915b828110156102aa578785015182556020948501946001909201910161028a565b50848210156102c85786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b613a14806102e66000396000f3fe608060405234801561001057600080fd5b50600436106102065760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610464578063d0ce736014610477578063d471cf5d1461048a578063e985e9c51461049d578063f2fde38b146104b057600080fd5b8063a30fb02014610418578063abc8c7af1461042b578063b7e62e5d1461043e578063b88d4fde1461045157600080fd5b80638da5cb5b116100e95780638da5cb5b146103d957806395d89b41146103ea5780639be78f05146103f2578063a22cb4651461040557600080fd5b806370a0823114610398578063715018a6146103ab57806375229c55146103b357806382558c2a146103c657600080fd5b80633a0432421161019d578063592691221161016c578063592691221461031f5780635a6aef60146103325780636352211e1461035257806366666aa9146103655780636ebc8c861461037857600080fd5b80633a043242146102d357806342842e0e146102e65780634a2a1fb0146102f9578063559de7b81461030c57600080fd5b8063095ea7b3116101d9578063095ea7b31461028657806318160ddd1461029b5780631892dd9f146102ad57806323b872dd146102c057600080fd5b8063017d6f991461020b57806301ffc9a71461023b57806306fdde031461025e578063081812fc14610273575b600080fd5b60105461021e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024e610249366004612f87565b6104c3565b6040519015158152602001610232565b610266610515565b6040516102329190612fea565b61021e610281366004612ffd565b6105a7565b61029961029436600461302b565b6105d1565b005b600d545b604051908152602001610232565b6102996102bb366004613057565b61061e565b6102996102ce366004613074565b610648565b61021e6102e1366004612ffd565b61069e565b6102996102f4366004613074565b6106a9565b61029f6103073660046130b5565b6106c9565b61024e61031a366004612ffd565b610c41565b61029f61032d366004612ffd565b610e80565b61029f610340366004612ffd565b6000908152600b602052604090205490565b61021e610360366004612ffd565b610e95565b600f5461021e906001600160a01b031681565b61038b610386366004612ffd565b610ec0565b6040516102329190613190565b61029f6103a6366004613057565b6110d6565b610299611102565b61029f6103c1366004612ffd565b611116565b6102996103d4366004613057565b611122565b6006546001600160a01b031661021e565b61026661114c565b610299610400366004613057565b61115b565b61029961041336600461324c565b611185565b61038b610426366004612ffd565b6111e0565b600e5461021e906001600160a01b031681565b61029f61044c36600461328a565b611433565b61029961045f36600461339e565b611720565b610266610472366004612ffd565b61177a565b610299610485366004612ffd565b61178f565b610299610498366004613578565b6118d2565b61024e6104ab36600461366b565b612092565b6102996104be366004613057565b6120be565b60006001600160e01b031982166380ac58cd60e01b14806104f457506001600160e01b03198216635b5e139f60e01b145b8061050f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461052490613699565b80601f016020809104026020016040519081016040528092919081815260200182805461055090613699565b801561059d5780601f106105725761010080835404028352916020019161059d565b820191906000526020600020905b81548152906001019060200180831161058057829003601f168201915b5050505050905090565b60006105b2826120fc565b156105c8575050600e546001600160a01b031690565b61050f8261216c565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b610626612195565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610615565b600061050f826121c2565b6106c483838360405180602001604052806000815250611720565b505050565b600e546000906001600160a01b0316331480156106f05750600e546001600160a01b031615155b61074c5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610615565b600060076000868152602001908152602001600020604051806101400160405290816000820154815260200160018201805461078790613699565b80601f01602080910402602001604051908101604052809291908181526020018280546107b390613699565b80156108005780601f106107d557610100808354040283529160200191610800565b820191906000526020600020905b8154815290600101906020018083116107e357829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610883576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161082e565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156108e457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108c6575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152905060006109438685611433565b9050846001600160a01b031661095882610e95565b6001600160a01b0316146109c35760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610615565b6000805b836060015151811015610a1b57836060015181815181106109ea576109ea6136d3565b60200260200101516001600160a01b0316866001600160a01b031603610a135760019150610a1b565b6001016109c7565b508015610aab576000878152600960205260408120805460019290610a419084906136ff565b90915550506000878152600b60205260408120805460019290610a659084906136ff565b9091555050600087815260096020908152604080832054600a9092529091205411610aa657600087815260096020908152604080832054600a909252909120555b610ad0565b6000878152600a60205260408120805460019290610aca9084906136ff565b90915550505b610ad9826120fc565b15610ba357610ae882866121cd565b6001600160a01b03861660009081526008602052604090205415610b35576001600160a01b0386166000908152600860205260408120805460019290610b2f908490613712565b90915550505b600e54610b4b906001600160a01b0316836121db565b846001600160a01b0316866001600160a01b0316887fdc5e8cc6b36001921ea942b2d0334e09fcc347e33b47a83d9a6c5c2a521d329c85604051610b9191815260200190565b60405180910390a4509150610c3a9050565b600e546001600160a01b0316610bb88361216c565b6001600160a01b031614610bdc57600e54610bdc906001600160a01b0316836121db565b610be78686846121e6565b846001600160a01b0316866001600160a01b0316887fdc5e8cc6b36001921ea942b2d0334e09fcc347e33b47a83d9a6c5c2a521d329c85604051610c2d91815260200190565b60405180910390a4509150505b9392505050565b60008181526007602090815260408083208151610140810190925280548252600181018054859484019190610c7590613699565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca190613699565b8015610cee5780601f10610cc357610100808354040283529160200191610cee565b820191906000526020600020905b815481529060010190602001808311610cd157829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610d71576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610d1c565b50505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610dd257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610db4575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152610120810151909150610e485760405162461bcd60e51b815260040161061590613725565b8060c001518160e00151610e5c9190613712565b610e679060016136ff565b6000938452600b60205260409093205490921492915050565b6000610e8b826111e0565b60a0015192915050565b6000610ea0826120fc565b15610eb75761050f610eb183612271565b836124d7565b61050f826121c2565b610ec8612e52565b6000600760008481526020019081526020016000206040518061014001604052908160008201548152602001600182018054610f0390613699565b80601f0160208091040260200160405190810160405280929190818152602001828054610f2f90613699565b8015610f7c5780601f10610f5157610100808354040283529160200191610f7c565b820191906000526020600020905b815481529060010190602001808311610f5f57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610fff576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610faa565b5050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561106057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611042575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09091015261012081015190915061050f5760405162461bcd60e51b815260040161061590613725565b6001600160a01b0381166000908152600860205260408120546110f8836128ea565b61050f91906136ff565b61110a612195565b6111146000612932565b565b600061050f8233611433565b61112a612195565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b60606001805461052490613699565b611163612195565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610615565b6111e8612e52565b60006111f383612271565b9050600081116112455760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610615565b60076000828152602001908152602001600020604051806101400160405290816000820154815260200160018201805461127e90613699565b80601f01602080910402602001604051908101604052809291908181526020018280546112aa90613699565b80156112f75780601f106112cc576101008083540402835291602001916112f7565b820191906000526020600020905b8154815290600101906020018083116112da57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b8282101561137a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611325565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156113db57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113bd575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c0909101529392505050565b6000828152600760209081526040808320815161014081019092528054825260018101805485948401919061146790613699565b80601f016020809104026020016040519081016040528092919081815260200182805461149390613699565b80156114e05780601f106114b5576101008083540402835291602001916114e0565b820191906000526020600020905b8154815290600101906020018083116114c357829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015611563576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161150e565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115a6575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09091015261012081015190915061163a5760405162461bcd60e51b815260040161061590613725565b60008060005b8360600151518110156116945783606001518181518110611663576116636136d3565b60200260200101516001600160a01b0316866001600160a01b03160361168c5760019150611694565b600101611640565b5080156116b15760008681526009602052604090205491506116c3565b6000868152600a602052604090205491505b8260e001518211156117175760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610615565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610615565b6060611785826111e0565b6020015192915050565b6010546001600160a01b0316331480156117b357506010546001600160a01b031615155b6117cf5760405162461bcd60e51b815260040161061590613766565b600081116117ef5760405162461bcd60e51b8152600401610615906137a8565b600081815260076020526040902060080154610100900460ff166118255760405162461bcd60e51b815260040161061590613725565b6000818152600760205260409020600881015460ff16156118945760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610615565b60088101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b0316331480156118f657506010546001600160a01b031615155b6119125760405162461bcd60e51b815260040161061590613766565b8051806119315760405162461bcd60e51b8152600401610615906137a8565b600081815260076020526040902060080154610100900460ff16156119a65760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610615565b600f546001600160a01b03166119fe5760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610615565b60008260c0015111611a685760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610615565b6000805b836040015151811015611b335760006001600160a01b031684604001518281518110611a9a57611a9a6136d3565b6020026020010151600001516001600160a01b031603611afc5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610615565b83604001518181518110611b1257611b126136d3565b60200260200101516020015182611b2991906137f3565b9150600101611a6c565b508060ff16606414611b915760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610615565b60008360a0015111611bfc5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610615565b60648360c00151611c0d9190613822565b15611c725760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610615565b608083015115611ceb57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611cd257600080fd5b505af1158015611ce6573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611d0390846136ff565b611d0d9190613712565b9050600085604001515167ffffffffffffffff811115611d2f57611d2f6132af565b604051908082528060200260200182016040528015611d8d57816020015b611d7a604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611d4d5790505b5090506000839050600060648860c00151611da89190613836565b905060005b886040015151811015611ee257600089604001518281518110611dd257611dd26136d3565b602002602001015190506000816020015160ff1684611df1919061384a565b905060006001611e0183886136ff565b611e0b9190613712565b905060405180606001604052808d604001518681518110611e2e57611e2e6136d3565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611e6457611e646136d3565b6020908102919091010152611e7a8160016136ff565b95508160086000898781518110611e9357611e936136d3565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611ece91906136ff565b909155505060019093019250611dad915050565b506000878152600760209081526040909120888155908901516001820190611f0a90826138a8565b5060608901518051611f26916003840191602090910190612ea9565b506080890151600482015560a08901516005820155600681018690556007810185905560088101805461ffff1916610100179055611f68600282016000612f0e565b60005b8451811015611fe55781600201858281518110611f8a57611f8a6136d3565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611f6b565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d8054919290916120269084906136ff565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610c3a5750506001600160a01b0390811691161490565b6120c6612195565b6001600160a01b0381166120f057604051631e4fbdf760e01b815260006004820152602401610615565b6120f981612932565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612157575060408051601f3d908101601f1916820190925261215491810190613967565b60015b61216357506001919050565b50600092915050565b600061217782612984565b506000828152600460205260409020546001600160a01b031661050f565b6006546001600160a01b031633146111145760405163118cdaa760e01b8152336004820152602401610615565b600061050f82612984565b6121d781836129bd565b5050565b6121d78282336129d7565b6001600160a01b03821661221057604051633250574960e11b815260006004820152602401610615565b600061221d8383336129e4565b9050836001600160a01b0316816001600160a01b03161461226b576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610615565b50505050565b6000805b600c54811015612163576000600c8281548110612294576122946136d3565b9060005260206000200154905060006007600083815260200190815260200160002060405180610140016040529081600082015481526020016001820180546122dc90613699565b80601f016020809104026020016040519081016040528092919081815260200182805461230890613699565b80156123555780601f1061232a57610100808354040283529160200191612355565b820191906000526020600020905b81548152906001019060200180831161233857829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b828210156123d8576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612383565b5050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561243957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161241b575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09182015281015190915085108015906124a357508060e001518511155b80156124b25750806101000151155b80156124c057508061012001515b156124cd57509392505050565b5050600101612275565b60008083116124f85760405162461bcd60e51b8152600401610615906137a8565b600083815260076020526040902060080154610100900460ff1661252e5760405162461bcd60e51b815260040161061590613725565b6000838152600760205260409020600601548210156125b55760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610615565b6000838152600760208190526040909120015482111561263d5760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610615565b600060076000858152602001908152602001600020604051806101400160405290816000820154815260200160018201805461267890613699565b80601f01602080910402602001604051908101604052809291908181526020018280546126a490613699565b80156126f15780601f106126c6576101008083540402835291602001916126f1565b820191906000526020600020905b8154815290600101906020018083116126d457829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015612774576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161271f565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156127d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116127b7575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152905060005b81604001515181101561288b57600082604001518281518110612850576128506136d3565b6020026020010151905084816020015111158015612872575080604001518511155b156128825751925061050f915050565b5060010161282b565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610615565b60006001600160a01b038216612916576040516322718ad960e21b815260006004820152602401610615565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050f57604051637e27328960e01b815260048101849052602401610615565b6121d7828260405180602001604052806000815250612add565b6106c48383836001612af4565b6000828152600260205260408120546001600160a01b0390811690831615612a1157612a11818486612bfa565b6001600160a01b03811615612a4f57612a2e600085600080612af4565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612a7e576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b612ae78383612c5e565b6106c46000848484612cc3565b8080612b0857506001600160a01b03821615155b15612bca576000612b1884612984565b90506001600160a01b03831615801590612b445750826001600160a01b0316816001600160a01b031614155b8015612b575750612b558184612092565b155b15612b805760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610615565b8115612bc85783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612c05838383612dec565b6106c4576001600160a01b038316612c3357604051637e27328960e01b815260048101829052602401610615565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610615565b6001600160a01b038216612c8857604051633250574960e11b815260006004820152602401610615565b6000612c96838360006129e4565b90506001600160a01b038116156106c4576040516339e3563760e11b815260006004820152602401610615565b6001600160a01b0383163b1561226b57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612d05903390889087908790600401613984565b6020604051808303816000875af1925050508015612d40575060408051601f3d908101601f19168201909252612d3d918101906139c1565b60015b612da9573d808015612d6e576040519150601f19603f3d011682016040523d82523d6000602084013e612d73565b606091505b508051600003612da157604051633250574960e11b81526001600160a01b0385166004820152602401610615565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612de557604051633250574960e11b81526001600160a01b0385166004820152602401610615565b5050505050565b60006001600160a01b03831615801590612e4a5750826001600160a01b0316846001600160a01b03161480612e265750612e268484612092565b80612e4a57506000828152600460205260409020546001600160a01b038481169116145b949350505050565b60405180610140016040528060008152602001606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612efe579160200282015b82811115612efe57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612ec9565b50612f0a929150612f2f565b5090565b50805460008255600302906000526020600020908101906120f99190612f44565b5b80821115612f0a5760008155600101612f30565b5b80821115612f0a5780546001600160a01b03191681556000600182018190556002820155600301612f45565b6001600160e01b0319811681146120f957600080fd5b600060208284031215612f9957600080fd5b8135610c3a81612f71565b6000815180845260005b81811015612fca57602081850181015186830182015201612fae565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610c3a6020830184612fa4565b60006020828403121561300f57600080fd5b5035919050565b6001600160a01b03811681146120f957600080fd5b6000806040838503121561303e57600080fd5b823561304981613016565b946020939093013593505050565b60006020828403121561306957600080fd5b8135610c3a81613016565b60008060006060848603121561308957600080fd5b833561309481613016565b925060208401356130a481613016565b929592945050506040919091013590565b6000806000606084860312156130ca57600080fd5b8335925060208401356130dc81613016565b915060408401356130ec81613016565b809150509250925092565b600081518084526020840193506020830160005b8281101561314b57815180516001600160a01b0316875260208082015181890152604091820151918801919091526060909601959091019060010161310b565b5093949350505050565b600081518084526020840193506020830160005b8281101561314b5781516001600160a01b0316865260209586019590910190600101613169565b60208152815160208201526000602083015161014060408401526131b8610160840182612fa4565b90506040840151601f198483030160608501526131d582826130f7565b9150506060840151601f198483030160808501526131f38282613155565b915050608084015160a084015260a084015160c084015260c084015160e084015260e084015161010084015261010084015161323461012085018215159052565b50610120840151801515610140850152509392505050565b6000806040838503121561325f57600080fd5b823561326a81613016565b91506020830135801515811461327f57600080fd5b809150509250929050565b6000806040838503121561329d57600080fd5b82359150602083013561327f81613016565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156132e8576132e86132af565b60405290565b60405160e0810167ffffffffffffffff811182821017156132e8576132e86132af565b604051601f8201601f1916810167ffffffffffffffff8111828210171561333a5761333a6132af565b604052919050565b60008067ffffffffffffffff84111561335d5761335d6132af565b50601f8301601f191660200161337281613311565b91505082815283838301111561338757600080fd5b828260208301376000602084830101529392505050565b600080600080608085870312156133b457600080fd5b84356133bf81613016565b935060208501356133cf81613016565b925060408501359150606085013567ffffffffffffffff8111156133f257600080fd5b8501601f8101871361340357600080fd5b61341287823560208401613342565b91505092959194509250565b600082601f83011261342f57600080fd5b610c3a83833560208501613342565b600067ffffffffffffffff821115613458576134586132af565b5060051b60200190565b600082601f83011261347357600080fd5b81356134866134818261343e565b613311565b8082825260208201915060208360061b8601019250858311156134a857600080fd5b602085015b8381101561350757604081880312156134c557600080fd5b6134cd6132c5565b81356134d881613016565b8152602082013560ff811681146134ee57600080fd5b60208281019190915290845292909201916040016134ad565b5095945050505050565b600082601f83011261352257600080fd5b81356135306134818261343e565b8082825260208201915060208360051b86010192508583111561355257600080fd5b602085015b8381101561350757803561356a81613016565b835260209283019201613557565b60006020828403121561358a57600080fd5b813567ffffffffffffffff8111156135a157600080fd5b820160e081850312156135b357600080fd5b6135bb6132ee565b81358152602082013567ffffffffffffffff8111156135d957600080fd5b6135e58682850161341e565b602083015250604082013567ffffffffffffffff81111561360557600080fd5b61361186828501613462565b604083015250606082013567ffffffffffffffff81111561363157600080fd5b61363d86828501613511565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561367e57600080fd5b823561368981613016565b9150602083013561327f81613016565b600181811c908216806136ad57607f821691505b6020821081036136cd57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561050f5761050f6136e9565b8181038181111561050f5761050f6136e9565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff818116838216019081111561050f5761050f6136e9565b634e487b7160e01b600052601260045260246000fd5b6000826138315761383161380c565b500690565b6000826138455761384561380c565b500490565b808202811582820484141761050f5761050f6136e9565b601f8211156106c457806000526020600020601f840160051c810160208510156138885750805b601f840160051c820191505b81811015612de55760008155600101613894565b815167ffffffffffffffff8111156138c2576138c26132af565b6138d6816138d08454613699565b84613861565b6020601f82116001811461390a57600083156138f25750848201515b600019600385901b1c1916600184901b178455612de5565b600084815260208120601f198516915b8281101561393a578785015182556020948501946001909201910161391a565b50848210156139585786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561397957600080fd5b8151610c3a81613016565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139b790830184612fa4565b9695505050505050565b6000602082840312156139d357600080fd5b8151610c3a81612f7156fea264697066735822122033d4a55275ac94cb3e1fd081e9686d64d6647dd5108a0a3edad70a9eb9798ece64736f6c634300081c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102065760003560e01c806370a082311161011a578063a30fb020116100ad578063c87b56dd1161007c578063c87b56dd14610464578063d0ce736014610477578063d471cf5d1461048a578063e985e9c51461049d578063f2fde38b146104b057600080fd5b8063a30fb02014610418578063abc8c7af1461042b578063b7e62e5d1461043e578063b88d4fde1461045157600080fd5b80638da5cb5b116100e95780638da5cb5b146103d957806395d89b41146103ea5780639be78f05146103f2578063a22cb4651461040557600080fd5b806370a0823114610398578063715018a6146103ab57806375229c55146103b357806382558c2a146103c657600080fd5b80633a0432421161019d578063592691221161016c578063592691221461031f5780635a6aef60146103325780636352211e1461035257806366666aa9146103655780636ebc8c861461037857600080fd5b80633a043242146102d357806342842e0e146102e65780634a2a1fb0146102f9578063559de7b81461030c57600080fd5b8063095ea7b3116101d9578063095ea7b31461028657806318160ddd1461029b5780631892dd9f146102ad57806323b872dd146102c057600080fd5b8063017d6f991461020b57806301ffc9a71461023b57806306fdde031461025e578063081812fc14610273575b600080fd5b60105461021e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61024e610249366004612f87565b6104c3565b6040519015158152602001610232565b610266610515565b6040516102329190612fea565b61021e610281366004612ffd565b6105a7565b61029961029436600461302b565b6105d1565b005b600d545b604051908152602001610232565b6102996102bb366004613057565b61061e565b6102996102ce366004613074565b610648565b61021e6102e1366004612ffd565b61069e565b6102996102f4366004613074565b6106a9565b61029f6103073660046130b5565b6106c9565b61024e61031a366004612ffd565b610c41565b61029f61032d366004612ffd565b610e80565b61029f610340366004612ffd565b6000908152600b602052604090205490565b61021e610360366004612ffd565b610e95565b600f5461021e906001600160a01b031681565b61038b610386366004612ffd565b610ec0565b6040516102329190613190565b61029f6103a6366004613057565b6110d6565b610299611102565b61029f6103c1366004612ffd565b611116565b6102996103d4366004613057565b611122565b6006546001600160a01b031661021e565b61026661114c565b610299610400366004613057565b61115b565b61029961041336600461324c565b611185565b61038b610426366004612ffd565b6111e0565b600e5461021e906001600160a01b031681565b61029f61044c36600461328a565b611433565b61029961045f36600461339e565b611720565b610266610472366004612ffd565b61177a565b610299610485366004612ffd565b61178f565b610299610498366004613578565b6118d2565b61024e6104ab36600461366b565b612092565b6102996104be366004613057565b6120be565b60006001600160e01b031982166380ac58cd60e01b14806104f457506001600160e01b03198216635b5e139f60e01b145b8061050f57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606000805461052490613699565b80601f016020809104026020016040519081016040528092919081815260200182805461055090613699565b801561059d5780601f106105725761010080835404028352916020019161059d565b820191906000526020600020905b81548152906001019060200180831161058057829003601f168201915b5050505050905090565b60006105b2826120fc565b156105c8575050600e546001600160a01b031690565b61050f8261216c565b60405162461bcd60e51b815260206004820181905260248201527f44656665727265643a20617070726f7665206973206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b610626612195565b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602560248201527f44656665727265643a207472616e7366657246726f6d206973206e6f7420616c6044820152641b1bddd95960da1b6064820152608401610615565b600061050f826121c2565b6106c483838360405180602001604052806000815250611720565b505050565b600e546000906001600160a01b0316331480156106f05750600e546001600160a01b031615155b61074c5760405162461bcd60e51b815260206004820152602760248201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d61726b6044820152666574706c61636560c81b6064820152608401610615565b600060076000868152602001908152602001600020604051806101400160405290816000820154815260200160018201805461078790613699565b80601f01602080910402602001604051908101604052809291908181526020018280546107b390613699565b80156108005780601f106107d557610100808354040283529160200191610800565b820191906000526020600020905b8154815290600101906020018083116107e357829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610883576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161082e565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156108e457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108c6575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152905060006109438685611433565b9050846001600160a01b031661095882610e95565b6001600160a01b0316146109c35760405162461bcd60e51b815260206004820152602c60248201527f44656665727265643a2066726f6d206973206e6f7420746865206f776e65722060448201526b37b3103a3432903a37b5b2b760a11b6064820152608401610615565b6000805b836060015151811015610a1b57836060015181815181106109ea576109ea6136d3565b60200260200101516001600160a01b0316866001600160a01b031603610a135760019150610a1b565b6001016109c7565b508015610aab576000878152600960205260408120805460019290610a419084906136ff565b90915550506000878152600b60205260408120805460019290610a659084906136ff565b9091555050600087815260096020908152604080832054600a9092529091205411610aa657600087815260096020908152604080832054600a909252909120555b610ad0565b6000878152600a60205260408120805460019290610aca9084906136ff565b90915550505b610ad9826120fc565b15610ba357610ae882866121cd565b6001600160a01b03861660009081526008602052604090205415610b35576001600160a01b0386166000908152600860205260408120805460019290610b2f908490613712565b90915550505b600e54610b4b906001600160a01b0316836121db565b846001600160a01b0316866001600160a01b0316887fdc5e8cc6b36001921ea942b2d0334e09fcc347e33b47a83d9a6c5c2a521d329c85604051610b9191815260200190565b60405180910390a4509150610c3a9050565b600e546001600160a01b0316610bb88361216c565b6001600160a01b031614610bdc57600e54610bdc906001600160a01b0316836121db565b610be78686846121e6565b846001600160a01b0316866001600160a01b0316887fdc5e8cc6b36001921ea942b2d0334e09fcc347e33b47a83d9a6c5c2a521d329c85604051610c2d91815260200190565b60405180910390a4509150505b9392505050565b60008181526007602090815260408083208151610140810190925280548252600181018054859484019190610c7590613699565b80601f0160208091040260200160405190810160405280929190818152602001828054610ca190613699565b8015610cee5780601f10610cc357610100808354040283529160200191610cee565b820191906000526020600020905b815481529060010190602001808311610cd157829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610d71576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610d1c565b50505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610dd257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610db4575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152610120810151909150610e485760405162461bcd60e51b815260040161061590613725565b8060c001518160e00151610e5c9190613712565b610e679060016136ff565b6000938452600b60205260409093205490921492915050565b6000610e8b826111e0565b60a0015192915050565b6000610ea0826120fc565b15610eb75761050f610eb183612271565b836124d7565b61050f826121c2565b610ec8612e52565b6000600760008481526020019081526020016000206040518061014001604052908160008201548152602001600182018054610f0390613699565b80601f0160208091040260200160405190810160405280929190818152602001828054610f2f90613699565b8015610f7c5780601f10610f5157610100808354040283529160200191610f7c565b820191906000526020600020905b815481529060010190602001808311610f5f57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015610fff576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101610faa565b5050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561106057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611042575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09091015261012081015190915061050f5760405162461bcd60e51b815260040161061590613725565b6001600160a01b0381166000908152600860205260408120546110f8836128ea565b61050f91906136ff565b61110a612195565b6111146000612932565b565b600061050f8233611433565b61112a612195565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b60606001805461052490613699565b611163612195565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602a60248201527f44656665727265643a20736574417070726f76616c466f72416c6c206973206e6044820152691bdd08185b1b1bddd95960b21b6064820152608401610615565b6111e8612e52565b60006111f383612271565b9050600081116112455760405162461bcd60e51b815260206004820152601e60248201527f44656665727265643a20746f6b656e20646f6573206e6f7420657869737400006044820152606401610615565b60076000828152602001908152602001600020604051806101400160405290816000820154815260200160018201805461127e90613699565b80601f01602080910402602001604051908101604052809291908181526020018280546112aa90613699565b80156112f75780601f106112cc576101008083540402835291602001916112f7565b820191906000526020600020905b8154815290600101906020018083116112da57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b8282101561137a576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101611325565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156113db57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116113bd575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c0909101529392505050565b6000828152600760209081526040808320815161014081019092528054825260018101805485948401919061146790613699565b80601f016020809104026020016040519081016040528092919081815260200182805461149390613699565b80156114e05780601f106114b5576101008083540402835291602001916114e0565b820191906000526020600020905b8154815290600101906020018083116114c357829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015611563576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161150e565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115a6575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09091015261012081015190915061163a5760405162461bcd60e51b815260040161061590613725565b60008060005b8360600151518110156116945783606001518181518110611663576116636136d3565b60200260200101516001600160a01b0316866001600160a01b03160361168c5760019150611694565b600101611640565b5080156116b15760008681526009602052604090205491506116c3565b6000868152600a602052604090205491505b8260e001518211156117175760405162461bcd60e51b815260206004820152601f60248201527f44656665727265643a206e6f206d6f726520746f6b656e7320746f20627579006044820152606401610615565b50949350505050565b60405162461bcd60e51b815260206004820152602960248201527f44656665727265643a20736166655472616e7366657246726f6d206973206e6f6044820152681d08185b1b1bddd95960ba1b6064820152608401610615565b6060611785826111e0565b6020015192915050565b6010546001600160a01b0316331480156117b357506010546001600160a01b031615155b6117cf5760405162461bcd60e51b815260040161061590613766565b600081116117ef5760405162461bcd60e51b8152600401610615906137a8565b600081815260076020526040902060080154610100900460ff166118255760405162461bcd60e51b815260040161061590613725565b6000818152600760205260409020600881015460ff16156118945760405162461bcd60e51b8152602060048201526024808201527f44656665727265643a20636f6e747261637420697320616c726561647920636c6044820152631bdcd95960e21b6064820152608401610615565b60088101805460ff1916600117905560405182907fd79ef0d7f68df3d827e7c4b6a13ec4570e9a30515c4717bbaa647da58ca68be190600090a25050565b6010546001600160a01b0316331480156118f657506010546001600160a01b031615155b6119125760405162461bcd60e51b815260040161061590613766565b8051806119315760405162461bcd60e51b8152600401610615906137a8565b600081815260076020526040902060080154610100900460ff16156119a65760405162461bcd60e51b815260206004820152602560248201527f44656665727265643a20636f6e747261637420697320616c726561647920637260448201526419585d195960da1b6064820152608401610615565b600f546001600160a01b03166119fe5760405162461bcd60e51b815260206004820181905260248201527f44656665727265643a2072657761726420706f6f6c206973206e6f74207365746044820152606401610615565b60008260c0015111611a685760405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206760448201526c0726561746572207468616e203609c1b6064820152608401610615565b6000805b836040015151811015611b335760006001600160a01b031684604001518281518110611a9a57611a9a6136d3565b6020026020010151600001516001600160a01b031603611afc5760405162461bcd60e51b815260206004820152601c60248201527f44656665727265643a2073656c6c6572206d75737420626520736574000000006044820152606401610615565b83604001518181518110611b1257611b126136d3565b60200260200101516020015182611b2991906137f3565b9150600101611a6c565b508060ff16606414611b915760405162461bcd60e51b815260206004820152602160248201527f44656665727265643a20746f74616c2071756f7461206d7573742062652031306044820152600360fc1b6064820152608401610615565b60008360a0015111611bfc5760405162461bcd60e51b815260206004820152602e60248201527f44656665727265643a20746f6b656e5072696365557364206d7573742062652060448201526d067726561746572207468616e20360941b6064820152608401610615565b60648360c00151611c0d9190613822565b15611c725760405162461bcd60e51b815260206004820152602f60248201527f44656665727265643a20746f6b656e73416d6f756e74206d757374206265206460448201526e06976697369626c652062792031303608c1b6064820152608401610615565b608083015115611ceb57600f54608084015160c08501516040516376b88f1160e11b8152600481019290925260248201526001600160a01b039091169063ed711e2290604401600060405180830381600087803b158015611cd257600080fd5b505af1158015611ce6573d6000803e3d6000fd5b505050505b600d5460c0840151600090600190611d0390846136ff565b611d0d9190613712565b9050600085604001515167ffffffffffffffff811115611d2f57611d2f6132af565b604051908082528060200260200182016040528015611d8d57816020015b611d7a604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b815260200190600190039081611d4d5790505b5090506000839050600060648860c00151611da89190613836565b905060005b886040015151811015611ee257600089604001518281518110611dd257611dd26136d3565b602002602001015190506000816020015160ff1684611df1919061384a565b905060006001611e0183886136ff565b611e0b9190613712565b905060405180606001604052808d604001518681518110611e2e57611e2e6136d3565b6020026020010151600001516001600160a01b0316815260200187815260200182815250878581518110611e6457611e646136d3565b6020908102919091010152611e7a8160016136ff565b95508160086000898781518110611e9357611e936136d3565b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000206000828254611ece91906136ff565b909155505060019093019250611dad915050565b506000878152600760209081526040909120888155908901516001820190611f0a90826138a8565b5060608901518051611f26916003840191602090910190612ea9565b506080890151600482015560a08901516005820155600681018690556007810185905560088101805461ffff1916610100179055611f68600282016000612f0e565b60005b8451811015611fe55781600201858281518110611f8a57611f8a6136d3565b602090810291909101810151825460018082018555600094855293839020825160039092020180546001600160a01b0319166001600160a01b0390921691909117815591810151828401556040015160029091015501611f6b565b506000888152600960209081526040808320899055600a8252808320899055600b909152812081905560c08a0151600d8054919290916120269084906136ff565b9091555050600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70189905560405189917f9e3c7e008a15a3c864482ee94fd7315bcc9d0c04f3a9041ab922f816acffbe0691a2505050505050505050565b600e546000906001600160a01b0383811691161480610c3a5750506001600160a01b0390811691161490565b6120c6612195565b6001600160a01b0381166120f057604051631e4fbdf760e01b815260006004820152602401610615565b6120f981612932565b50565b604051631d02192160e11b8152600481018290526000903090633a04324290602401602060405180830381865afa925050508015612157575060408051601f3d908101601f1916820190925261215491810190613967565b60015b61216357506001919050565b50600092915050565b600061217782612984565b506000828152600460205260409020546001600160a01b031661050f565b6006546001600160a01b031633146111145760405163118cdaa760e01b8152336004820152602401610615565b600061050f82612984565b6121d781836129bd565b5050565b6121d78282336129d7565b6001600160a01b03821661221057604051633250574960e11b815260006004820152602401610615565b600061221d8383336129e4565b9050836001600160a01b0316816001600160a01b03161461226b576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610615565b50505050565b6000805b600c54811015612163576000600c8281548110612294576122946136d3565b9060005260206000200154905060006007600083815260200190815260200160002060405180610140016040529081600082015481526020016001820180546122dc90613699565b80601f016020809104026020016040519081016040528092919081815260200182805461230890613699565b80156123555780601f1061232a57610100808354040283529160200191612355565b820191906000526020600020905b81548152906001019060200180831161233857829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b828210156123d8576000848152602090819020604080516060810182526003860290920180546001600160a01b0316835260018082015484860152600290910154918301919091529083529092019101612383565b5050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561243957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161241b575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c09182015281015190915085108015906124a357508060e001518511155b80156124b25750806101000151155b80156124c057508061012001515b156124cd57509392505050565b5050600101612275565b60008083116124f85760405162461bcd60e51b8152600401610615906137a8565b600083815260076020526040902060080154610100900460ff1661252e5760405162461bcd60e51b815260040161061590613725565b6000838152600760205260409020600601548210156125b55760405162461bcd60e51b815260206004820152603e60248201527f44656665727265643a20746f6b656e4964206d7573742062652067726561746560448201527f72207468616e206f7220657175616c20746f20746f6b656e46726f6d496400006064820152608401610615565b6000838152600760208190526040909120015482111561263d5760405162461bcd60e51b815260206004820152603960248201527f44656665727265643a20746f6b656e4964206d757374206265206c657373207460448201527f68616e206f7220657175616c20746f20746f6b656e546f4964000000000000006064820152608401610615565b600060076000858152602001908152602001600020604051806101400160405290816000820154815260200160018201805461267890613699565b80601f01602080910402602001604051908101604052809291908181526020018280546126a490613699565b80156126f15780601f106126c6576101008083540402835291602001916126f1565b820191906000526020600020905b8154815290600101906020018083116126d457829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b82821015612774576000848152602090819020604080516060810182526003860290920180546001600160a01b031683526001808201548486015260029091015491830191909152908352909201910161271f565b505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156127d557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116127b7575b50505091835250506004820154602082015260058201546040820152600682015460608201526007820154608082015260089091015460ff808216151560a084015261010090910416151560c090910152905060005b81604001515181101561288b57600082604001518281518110612850576128506136d3565b6020026020010151905084816020015111158015612872575080604001518511155b156128825751925061050f915050565b5060010161282b565b5060405162461bcd60e51b815260206004820152602d60248201527f44656665727265643a20746f6b656e20646f6573206e6f742062656c6f6e672060448201526c3a379030b73c9039b2b63632b960991b6064820152608401610615565b60006001600160a01b038216612916576040516322718ad960e21b815260006004820152602401610615565b506001600160a01b031660009081526003602052604090205490565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000818152600260205260408120546001600160a01b03168061050f57604051637e27328960e01b815260048101849052602401610615565b6121d7828260405180602001604052806000815250612add565b6106c48383836001612af4565b6000828152600260205260408120546001600160a01b0390811690831615612a1157612a11818486612bfa565b6001600160a01b03811615612a4f57612a2e600085600080612af4565b6001600160a01b038116600090815260036020526040902080546000190190555b6001600160a01b03851615612a7e576001600160a01b0385166000908152600360205260409020805460010190555b60008481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b612ae78383612c5e565b6106c46000848484612cc3565b8080612b0857506001600160a01b03821615155b15612bca576000612b1884612984565b90506001600160a01b03831615801590612b445750826001600160a01b0316816001600160a01b031614155b8015612b575750612b558184612092565b155b15612b805760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610615565b8115612bc85783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b5050600090815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b612c05838383612dec565b6106c4576001600160a01b038316612c3357604051637e27328960e01b815260048101829052602401610615565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610615565b6001600160a01b038216612c8857604051633250574960e11b815260006004820152602401610615565b6000612c96838360006129e4565b90506001600160a01b038116156106c4576040516339e3563760e11b815260006004820152602401610615565b6001600160a01b0383163b1561226b57604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290612d05903390889087908790600401613984565b6020604051808303816000875af1925050508015612d40575060408051601f3d908101601f19168201909252612d3d918101906139c1565b60015b612da9573d808015612d6e576040519150601f19603f3d011682016040523d82523d6000602084013e612d73565b606091505b508051600003612da157604051633250574960e11b81526001600160a01b0385166004820152602401610615565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b14612de557604051633250574960e11b81526001600160a01b0385166004820152602401610615565b5050505050565b60006001600160a01b03831615801590612e4a5750826001600160a01b0316846001600160a01b03161480612e265750612e268484612092565b80612e4a57506000828152600460205260409020546001600160a01b038481169116145b949350505050565b60405180610140016040528060008152602001606081526020016060815260200160608152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b828054828255906000526020600020908101928215612efe579160200282015b82811115612efe57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612ec9565b50612f0a929150612f2f565b5090565b50805460008255600302906000526020600020908101906120f99190612f44565b5b80821115612f0a5760008155600101612f30565b5b80821115612f0a5780546001600160a01b03191681556000600182018190556002820155600301612f45565b6001600160e01b0319811681146120f957600080fd5b600060208284031215612f9957600080fd5b8135610c3a81612f71565b6000815180845260005b81811015612fca57602081850181015186830182015201612fae565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610c3a6020830184612fa4565b60006020828403121561300f57600080fd5b5035919050565b6001600160a01b03811681146120f957600080fd5b6000806040838503121561303e57600080fd5b823561304981613016565b946020939093013593505050565b60006020828403121561306957600080fd5b8135610c3a81613016565b60008060006060848603121561308957600080fd5b833561309481613016565b925060208401356130a481613016565b929592945050506040919091013590565b6000806000606084860312156130ca57600080fd5b8335925060208401356130dc81613016565b915060408401356130ec81613016565b809150509250925092565b600081518084526020840193506020830160005b8281101561314b57815180516001600160a01b0316875260208082015181890152604091820151918801919091526060909601959091019060010161310b565b5093949350505050565b600081518084526020840193506020830160005b8281101561314b5781516001600160a01b0316865260209586019590910190600101613169565b60208152815160208201526000602083015161014060408401526131b8610160840182612fa4565b90506040840151601f198483030160608501526131d582826130f7565b9150506060840151601f198483030160808501526131f38282613155565b915050608084015160a084015260a084015160c084015260c084015160e084015260e084015161010084015261010084015161323461012085018215159052565b50610120840151801515610140850152509392505050565b6000806040838503121561325f57600080fd5b823561326a81613016565b91506020830135801515811461327f57600080fd5b809150509250929050565b6000806040838503121561329d57600080fd5b82359150602083013561327f81613016565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156132e8576132e86132af565b60405290565b60405160e0810167ffffffffffffffff811182821017156132e8576132e86132af565b604051601f8201601f1916810167ffffffffffffffff8111828210171561333a5761333a6132af565b604052919050565b60008067ffffffffffffffff84111561335d5761335d6132af565b50601f8301601f191660200161337281613311565b91505082815283838301111561338757600080fd5b828260208301376000602084830101529392505050565b600080600080608085870312156133b457600080fd5b84356133bf81613016565b935060208501356133cf81613016565b925060408501359150606085013567ffffffffffffffff8111156133f257600080fd5b8501601f8101871361340357600080fd5b61341287823560208401613342565b91505092959194509250565b600082601f83011261342f57600080fd5b610c3a83833560208501613342565b600067ffffffffffffffff821115613458576134586132af565b5060051b60200190565b600082601f83011261347357600080fd5b81356134866134818261343e565b613311565b8082825260208201915060208360061b8601019250858311156134a857600080fd5b602085015b8381101561350757604081880312156134c557600080fd5b6134cd6132c5565b81356134d881613016565b8152602082013560ff811681146134ee57600080fd5b60208281019190915290845292909201916040016134ad565b5095945050505050565b600082601f83011261352257600080fd5b81356135306134818261343e565b8082825260208201915060208360051b86010192508583111561355257600080fd5b602085015b8381101561350757803561356a81613016565b835260209283019201613557565b60006020828403121561358a57600080fd5b813567ffffffffffffffff8111156135a157600080fd5b820160e081850312156135b357600080fd5b6135bb6132ee565b81358152602082013567ffffffffffffffff8111156135d957600080fd5b6135e58682850161341e565b602083015250604082013567ffffffffffffffff81111561360557600080fd5b61361186828501613462565b604083015250606082013567ffffffffffffffff81111561363157600080fd5b61363d86828501613511565b6060830152506080828101359082015260a0808301359082015260c091820135918101919091529392505050565b6000806040838503121561367e57600080fd5b823561368981613016565b9150602083013561327f81613016565b600181811c908216806136ad57607f821691505b6020821081036136cd57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561050f5761050f6136e9565b8181038181111561050f5761050f6136e9565b60208082526021908201527f44656665727265643a20636f6e747261637420646f6573206e6f7420657869736040820152601d60fa1b606082015260800190565b60208082526022908201527f44656665727265643a2063616c6c6572206973206e6f7420746865206d696e7460408201526132b960f11b606082015260800190565b6020808252602b908201527f44656665727265643a20636f6e74726163744964206d7573742062652067726560408201526a061746572207468616e20360ac1b606082015260800190565b60ff818116838216019081111561050f5761050f6136e9565b634e487b7160e01b600052601260045260246000fd5b6000826138315761383161380c565b500690565b6000826138455761384561380c565b500490565b808202811582820484141761050f5761050f6136e9565b601f8211156106c457806000526020600020601f840160051c810160208510156138885750805b601f840160051c820191505b81811015612de55760008155600101613894565b815167ffffffffffffffff8111156138c2576138c26132af565b6138d6816138d08454613699565b84613861565b6020601f82116001811461390a57600083156138f25750848201515b600019600385901b1c1916600184901b178455612de5565b600084815260208120601f198516915b8281101561393a578785015182556020948501946001909201910161391a565b50848210156139585786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b60006020828403121561397957600080fd5b8151610c3a81613016565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139b790830184612fa4565b9695505050505050565b6000602082840312156139d357600080fd5b8151610c3a81612f7156fea264697066735822122033d4a55275ac94cb3e1fd081e9686d64d6647dd5108a0a3edad70a9eb9798ece64736f6c634300081c0033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/src/declarations/deferred_data/deferred_data.did b/src/declarations/deferred_data/deferred_data.did index 465d344..6a5d626 100644 --- a/src/declarations/deferred_data/deferred_data.did +++ b/src/declarations/deferred_data/deferred_data.did @@ -113,7 +113,7 @@ type RestrictedProperty = record { value : GenericValue; access_list : vec RestrictionLevel; }; -type RestrictionLevel = variant { Buyer; Seller; Agent }; +type RestrictionLevel = variant { Buyer; Public; Seller; Agent }; type Result = variant { Ok; Err : DeferredDataError }; type Result_1 = variant { Ok : ContractDocumentData; Err : DeferredDataError }; type Result_2 = variant { Ok : nat64; Err : DeferredDataError }; diff --git a/src/declarations/deferred_data/deferred_data.did.d.ts b/src/declarations/deferred_data/deferred_data.did.d.ts index e7f8f9d..b08d929 100644 --- a/src/declarations/deferred_data/deferred_data.did.d.ts +++ b/src/declarations/deferred_data/deferred_data.did.d.ts @@ -113,6 +113,7 @@ export interface RestrictedProperty { 'access_list' : Array, } export type RestrictionLevel = { 'Buyer' : null } | + { 'Public' : null } | { 'Seller' : null } | { 'Agent' : null }; export type Result = { 'Ok' : null } | diff --git a/src/declarations/deferred_data/deferred_data.did.js b/src/declarations/deferred_data/deferred_data.did.js index d6c6755..11fc53f 100644 --- a/src/declarations/deferred_data/deferred_data.did.js +++ b/src/declarations/deferred_data/deferred_data.did.js @@ -44,6 +44,7 @@ export const idlFactory = ({ IDL }) => { const Result = IDL.Variant({ 'Ok' : IDL.Null, 'Err' : DeferredDataError }); const RestrictionLevel = IDL.Variant({ 'Buyer' : IDL.Null, + 'Public' : IDL.Null, 'Seller' : IDL.Null, 'Agent' : IDL.Null, }); diff --git a/src/declarations/deferred_minter/deferred_minter.did b/src/declarations/deferred_minter/deferred_minter.did index 0a55d33..daf197d 100644 --- a/src/declarations/deferred_minter/deferred_minter.did +++ b/src/declarations/deferred_minter/deferred_minter.did @@ -150,7 +150,7 @@ type RestrictedProperty = record { value : GenericValue; access_list : vec RestrictionLevel; }; -type RestrictionLevel = variant { Buyer; Seller; Agent }; +type RestrictionLevel = variant { Buyer; Public; Seller; Agent }; type Result = variant { Ok; Err : DeferredMinterError }; type Result_1 = variant { Ok : nat; Err : DeferredMinterError }; type Result_2 = variant { Ok : text; Err : DeferredMinterError }; diff --git a/src/declarations/deferred_minter/deferred_minter.did.d.ts b/src/declarations/deferred_minter/deferred_minter.did.d.ts index eaacfc6..d41ba2b 100644 --- a/src/declarations/deferred_minter/deferred_minter.did.d.ts +++ b/src/declarations/deferred_minter/deferred_minter.did.d.ts @@ -142,6 +142,7 @@ export interface RestrictedProperty { 'access_list' : Array, } export type RestrictionLevel = { 'Buyer' : null } | + { 'Public' : null } | { 'Seller' : null } | { 'Agent' : null }; export type Result = { 'Ok' : null } | diff --git a/src/declarations/deferred_minter/deferred_minter.did.js b/src/declarations/deferred_minter/deferred_minter.did.js index d5db81a..0882f46 100644 --- a/src/declarations/deferred_minter/deferred_minter.did.js +++ b/src/declarations/deferred_minter/deferred_minter.did.js @@ -146,6 +146,7 @@ export const idlFactory = ({ IDL }) => { }); const RestrictionLevel = IDL.Variant({ 'Buyer' : IDL.Null, + 'Public' : IDL.Null, 'Seller' : IDL.Null, 'Agent' : IDL.Null, }); diff --git a/src/deferred_data/Cargo.toml b/src/deferred_data/Cargo.toml index a4af122..473085b 100644 --- a/src/deferred_data/Cargo.toml +++ b/src/deferred_data/Cargo.toml @@ -35,4 +35,5 @@ url = { workspace = true } [dev-dependencies] pretty_assertions = "1" +serde_json = { workspace = true } tokio = { version = "1", features = ["full"] } diff --git a/src/deferred_data/deferred_data.did b/src/deferred_data/deferred_data.did index 465d344..6a5d626 100644 --- a/src/deferred_data/deferred_data.did +++ b/src/deferred_data/deferred_data.did @@ -113,7 +113,7 @@ type RestrictedProperty = record { value : GenericValue; access_list : vec RestrictionLevel; }; -type RestrictionLevel = variant { Buyer; Seller; Agent }; +type RestrictionLevel = variant { Buyer; Public; Seller; Agent }; type Result = variant { Ok; Err : DeferredDataError }; type Result_1 = variant { Ok : ContractDocumentData; Err : DeferredDataError }; type Result_2 = variant { Ok : nat64; Err : DeferredDataError }; diff --git a/src/deferred_data/src/app.rs b/src/deferred_data/src/app.rs index 4191e07..75d783a 100644 --- a/src/deferred_data/src/app.rs +++ b/src/deferred_data/src/app.rs @@ -3,7 +3,7 @@ mod inspect; mod memory; mod storage; #[cfg(test)] -mod test_utils; +pub mod test_utils; use candid::{Nat, Principal}; use did::deferred::{ @@ -15,10 +15,10 @@ use ethers_core::abi::ethereum_types::H520; use ic_log::did::Pagination; use ic_log::writer::Logs; use ic_log::{init_log, take_memory_records}; -use storage::ContractStorage; use self::configuration::Configuration; pub use self::inspect::Inspect; +pub use self::storage::ContractStorage; use crate::utils::{caller, cycles}; /// A message used to verify the ownership of a contract (seller or buyer) @@ -182,7 +182,7 @@ impl DeferredData { } else if let Some(signature) = signature { Inspect::inspect_signature(&contract.id, signature.signature, signature.message)? } else { - return Err(DeferredDataError::Unauthorized); + RestrictionLevel::Public }; // check if we have access @@ -212,7 +212,7 @@ impl DeferredData { } else if let Some(signature) = signature { Inspect::inspect_signature(&contract.id, signature.signature, signature.message).ok() } else { - None + Some(RestrictionLevel::Public) }; // if no access level, redact all diff --git a/src/deferred_data/src/app/storage/contracts.rs b/src/deferred_data/src/app/storage/contracts.rs index 26d0425..01eb1b1 100644 --- a/src/deferred_data/src/app/storage/contracts.rs +++ b/src/deferred_data/src/app/storage/contracts.rs @@ -49,6 +49,17 @@ impl ContractStorage { }) } + /// get contracts by filter + pub fn get_contracts_filter(filter: impl Fn(&Contract) -> bool) -> Vec { + with_contracts(|contracts| { + contracts + .iter() + .filter(|(_, contract)| !contract.closed && filter(contract)) + .map(|(key, _)| key.0.clone()) + .collect() + }) + } + /// Update contract property pub fn update_contract_property( contract_id: &ID, @@ -153,6 +164,7 @@ impl ContractStorage { #[cfg(test)] mod test { + use candid::Nat; use did::deferred::{RestrictionLevel, Seller}; use did::H160; use pretty_assertions::assert_eq; @@ -195,6 +207,44 @@ mod test { assert_eq!(ContractStorage::get_contracts(), vec![contract.id]); } + #[test] + fn test_should_filter_contracts() { + let seller = vec![Seller { + address: H160::zero(), + quota: 100, + }]; + + let contract = with_mock_contract(1, 2, |contract| { + contract.sellers = seller.clone(); + contract.buyers = vec![]; + }); + // store + ContractStorage::insert_contract(contract.clone()); + + // other contract + let contract = with_mock_contract(2, 2, |contract| { + contract.sellers = seller; + contract.buyers = vec![]; + + contract.properties.push(( + "contract:cryptomadonne".to_string(), + GenericValue::TextContent("Yes".to_string()), + )); + }); + + // store + ContractStorage::insert_contract(contract.clone()); + + // filter + let contracts = ContractStorage::get_contracts_filter(|contract| { + contract + .properties + .iter() + .any(|(k, _)| k == "contract:cryptomadonne") + }); + assert_eq!(contracts, vec![Nat::from(2u64)]); + } + #[test] fn test_should_update_contract_property() { let contract = with_mock_contract(1, 1, |contract| { diff --git a/src/deferred_data/src/http.rs b/src/deferred_data/src/http.rs index 20f258e..adb3d4e 100644 --- a/src/deferred_data/src/http.rs +++ b/src/deferred_data/src/http.rs @@ -1,3 +1,5 @@ +mod contract_filter; + use std::str::FromStr; use did::{HttpRequest, HttpResponse}; @@ -5,7 +7,8 @@ use ethers_core::abi::ethereum_types::H520; use route_recognizer::Router; use url::Url; -use crate::app::{DeferredData, SignedMessage}; +use self::contract_filter::Filters; +use crate::app::{ContractStorage, DeferredData, SignedMessage}; const ROUTE_CONTRACTS: &str = "Contracts"; const ROUTE_CONTRACT: &str = "Contract"; @@ -41,8 +44,7 @@ impl HttpApi { let handler = **route_match.handler(); let params = route_match.params(); match handler { - ROUTE_CONTRACTS => Self::get_contracts(), - + ROUTE_CONTRACTS => Self::get_contracts(&url), ROUTE_CONTRACT => { let Some(id) = params.find("id") else { return HttpResponse::bad_request("missing contract ID".to_string()); @@ -73,8 +75,12 @@ impl HttpApi { } } - fn get_contracts() -> HttpResponse { - HttpResponse::ok(DeferredData::get_contracts()) + fn get_contracts(url: &Url) -> HttpResponse { + let filters = Filters::from(url); + + HttpResponse::ok(ContractStorage::get_contracts_filter(|contract| { + filters.check(contract) + })) } fn get_contract(url: Url, id: u64) -> HttpResponse { @@ -112,3 +118,236 @@ impl HttpApi { }) } } + +#[cfg(test)] +mod test { + + use std::borrow::Cow; + use std::collections::HashMap; + + use candid::{Nat, Principal}; + use did::deferred::{ContractDocument, GenericValue, RestrictionLevel, Seller}; + use did::H160; + use pretty_assertions::assert_eq; + + use super::*; + use crate::app::test_utils::{store_mock_contract, store_mock_contract_with}; + + #[tokio::test] + async fn test_should_get_contract() { + store_mock_contract_with(1u64, 100u64, |contract| { + contract.restricted_properties = vec![]; + }); + + let url = Url::parse("http://localhost/contract/1").unwrap(); + + let req = HttpRequest { + method: Cow::from("GET".to_string()), + url: url.to_string(), + headers: HashMap::default(), + body: Default::default(), + }; + + let res = HttpApi::handle_http_request(req).await; + assert_eq!(res.status_code, 200); + + let contract: did::deferred::Contract = serde_json::from_slice(&res.body).unwrap(); + + let contract_from_storage = ContractStorage::get_contract(&Nat::from(1u64)).unwrap(); + assert_eq!(contract, contract_from_storage); + } + + #[tokio::test] + async fn test_should_not_get_contract() { + let url = Url::parse("http://localhost/contract/2").unwrap(); + + let req = HttpRequest { + method: Cow::from("GET".to_string()), + url: url.to_string(), + headers: HashMap::default(), + body: Default::default(), + }; + + let res = HttpApi::handle_http_request(req).await; + assert_eq!(res.status_code, 404); + } + + #[tokio::test] + async fn test_should_get_contract_document() { + store_mock_contract(1u64, 100u64); + let document_id = ContractStorage::upload_contract_document( + &Nat::from(1u64), + ContractDocument { + access_list: vec![RestrictionLevel::Public], + mime_type: "application/pdf".to_string(), + }, + vec![0x01, 0x02, 0x03, 0x04], + ) + .expect("Failed to upload document"); + + let url = Url::parse(&format!( + "http://localhost/contract/1/document/{document_id}" + )) + .unwrap(); + + let req = HttpRequest { + method: Cow::from("GET".to_string()), + url: url.to_string(), + headers: HashMap::default(), + body: Default::default(), + }; + + let res = HttpApi::handle_http_request(req).await; + assert_eq!(res.status_code, 200); + + let document: did::deferred::ContractDocumentData = + serde_json::from_slice(&res.body).unwrap(); + + assert_eq!(document.mime_type, "application/pdf".to_string()); + assert_eq!(document.data, vec![0x01, 0x02, 0x03, 0x04]); + } + + #[tokio::test] + async fn test_should_not_get_contract_document() { + store_mock_contract(1u64, 100u64); + + let url = Url::parse(&format!("http://localhost/contract/1/document/2")).unwrap(); + + let req = HttpRequest { + method: Cow::from("GET".to_string()), + url: url.to_string(), + headers: HashMap::default(), + body: Default::default(), + }; + + let res = HttpApi::handle_http_request(req).await; + assert_eq!(res.status_code, 404); + } + + #[tokio::test] + async fn test_should_filter_contract() { + store_mock_contract_with(1u64, 100, |contract| { + // insert all properties + contract.buyers = + vec![H160::from_hex_str("0x0b24F78CF0033FAbf1977D9aA61f583fBF7586D9").unwrap()]; + contract.sellers = vec![Seller { + address: H160::from_hex_str("0x253553366da8546fc250f225fe3d25d0c782303b").unwrap(), + quota: 100, + }]; + contract.agency.as_mut().unwrap().owner = + Principal::from_text("v5vof-zqaaa-aaaal-ai5cq-cai") + .expect("Failed to create principal"); + + // insert properties + contract.properties = vec![ + ( + "contract:name".to_string(), + GenericValue::TextContent("name".to_string()), + ), + ( + "contract:description".to_string(), + GenericValue::TextContent("description".to_string()), + ), + ( + "contract:image".to_string(), + GenericValue::TextContent("image".to_string()), + ), + ( + "contract:address".to_string(), + GenericValue::TextContent("address".to_string()), + ), + ( + "contract:country".to_string(), + GenericValue::TextContent("country".to_string()), + ), + ( + "contract:continent".to_string(), + GenericValue::TextContent("continent".to_string()), + ), + ( + "contract:region".to_string(), + GenericValue::TextContent("region".to_string()), + ), + ( + "contract:zipCode".to_string(), + GenericValue::TextContent("zipCode".to_string()), + ), + ( + "contract:latitude".to_string(), + GenericValue::TextContent("123".to_string()), + ), + ( + "contract:longitude".to_string(), + GenericValue::TextContent("456".to_string()), + ), + ( + "contract:zone".to_string(), + GenericValue::TextContent("zone".to_string()), + ), + ( + "contract:city".to_string(), + GenericValue::TextContent("city".to_string()), + ), + ( + "contract:squareMeters".to_string(), + GenericValue::Nat64Content(123), + ), + ("contract:rooms".to_string(), GenericValue::Nat64Content(4)), + ( + "contract:bathrooms".to_string(), + GenericValue::Nat64Content(8), + ), + ( + "contract:floors".to_string(), + GenericValue::Nat64Content(10), + ), + ( + "contract:balconies".to_string(), + GenericValue::Nat64Content(2), + ), + ( + "contract:garden".to_string(), + GenericValue::BoolContent(true), + ), + ("contract:pool".to_string(), GenericValue::BoolContent(true)), + ( + "contract:garage".to_string(), + GenericValue::BoolContent(true), + ), + ( + "contract:parking".to_string(), + GenericValue::BoolContent(true), + ), + ( + "contract:energyClass".to_string(), + GenericValue::TextContent("A".to_string()), + ), + ( + "contract:youtubeUrl".to_string(), + GenericValue::TextContent( + "https://www.youtube.com/watch?v=IOuTVyaNSrU".to_string(), + ), + ), + ]; + }); + + // build url with filters + let url = Url::parse( + "http://localhost/contracts?latitude=123&longitude=456&zone=zone&city=city&squareMeters=123&rooms=4&bathrooms=8&floors=10&balconies=2&garden=true&pool=true&garage=true&parking=true&energyClass=A&youtubeUrl=https://www.youtube.com/watch?v=IOuTVyaNSrU", + ) + .expect("Failed to parse URL"); + + let req = HttpRequest { + method: Cow::from("GET".to_string()), + url: url.to_string(), + headers: HashMap::default(), + body: Default::default(), + }; + + let res = HttpApi::handle_http_request(req).await; + assert_eq!(res.status_code, 200); + + let contracts: Vec = serde_json::from_slice(&res.body).unwrap(); + assert_eq!(contracts.len(), 1); + } +} diff --git a/src/deferred_data/src/http/contract_filter.rs b/src/deferred_data/src/http/contract_filter.rs new file mode 100644 index 0000000..b8a529c --- /dev/null +++ b/src/deferred_data/src/http/contract_filter.rs @@ -0,0 +1,145 @@ +use candid::Principal; +use did::deferred::Contract; +use did::H160; +use url::Url; + +const FILTER_SELLER: &str = "seller"; +const FILTER_BUYER: &str = "buyer"; +const FILTER_AGENT: &str = "agent"; + +const FILTER_PROPERTY_NAME: &str = "name"; +const FILTER_PROPERTY_DESCRIPTION: &str = "description"; +const FILTER_PROPERTY_IMAGE: &str = "image"; +const FILTER_PROPERTY_ADDRESS: &str = "address"; +const FILTER_PROPERTY_COUNTRY: &str = "country"; +const FILTER_PROPERTY_CONTINENT: &str = "continent"; +const FILTER_PROPERTY_REGION: &str = "region"; +const FILTER_PROPERTY_ZIPCODE: &str = "zipCode"; +const FILTER_PROPERTY_LATITUDE: &str = "latitude"; +const FILTER_PROPERTY_LONGITUDE: &str = "longitude"; +const FILTER_PROPERTY_ZONE: &str = "zone"; +const FILTER_PROPERTY_CITY: &str = "city"; +const FILTER_PROPERTY_SQUAREMETERS: &str = "squareMeters"; +const FILTER_PROPERTY_ROOMS: &str = "rooms"; +const FILTER_PROPERTY_BATHROOMS: &str = "bathrooms"; +const FILTER_PROPERTY_FLOORS: &str = "floors"; +const FILTER_PROPERTY_BALCONIES: &str = "balconies"; +const FILTER_PROPERTY_GARDEN: &str = "garden"; +const FILTER_PROPERTY_POOL: &str = "pool"; +const FILTER_PROPERTY_GARAGE: &str = "garage"; +const FILTER_PROPERTY_PARKING: &str = "parking"; +const FILTER_PROPERTY_ENERGYCLASS: &str = "energyClass"; +const FILTER_PROPERTY_YOUTUBEURL: &str = "youtubeUrl"; + +/// Filter type to filter a contract +enum ContractFilter { + /// Always accept the request. + Always, + /// Has property with the given name and the value is contained in the property value. + HasProperty { name: String, value: String }, + /// Seller + Seller(H160), + /// Buyer + Buyer(H160), + /// Agent + Agent(Principal), +} + +impl ContractFilter { + /// Check if the contract satisfies the filter. + fn check(&self, contract: &Contract) -> bool { + match self { + ContractFilter::Always => true, + ContractFilter::HasProperty { name, value } => contract + .properties + .iter() + .find(|(k, _)| k == name) + .map_or(false, |(_, v)| { + v.to_string().to_lowercase().contains(&value.to_lowercase()) + }), + ContractFilter::Seller(addr) => contract + .sellers + .iter() + .any(|seller| seller.address == *addr), + ContractFilter::Buyer(addr) => contract.buyers.iter().any(|buyer| buyer == addr), + ContractFilter::Agent(agent) => contract + .agency + .as_ref() + .map(|agency| agency.owner == *agent) + .unwrap_or_default(), + } + } +} + +pub struct Filters { + filters: Vec, +} + +impl From<&Url> for Filters { + fn from(url: &Url) -> Self { + let mut filters = vec![ContractFilter::Always]; + + for (name, value) in url.query_pairs() { + match name.as_ref() { + FILTER_AGENT => { + if let Ok(agent) = Principal::from_text(value) { + filters.push(ContractFilter::Agent(agent)); + } + } + FILTER_BUYER => { + if let Ok(addr) = H160::from_hex_str(value.as_ref()) { + filters.push(ContractFilter::Buyer(addr)); + } + } + FILTER_SELLER => { + if let Ok(addr) = H160::from_hex_str(value.as_ref()) { + filters.push(ContractFilter::Seller(addr)); + } + } + FILTER_PROPERTY_NAME + | FILTER_PROPERTY_DESCRIPTION + | FILTER_PROPERTY_IMAGE + | FILTER_PROPERTY_ADDRESS + | FILTER_PROPERTY_COUNTRY + | FILTER_PROPERTY_CONTINENT + | FILTER_PROPERTY_REGION + | FILTER_PROPERTY_ZIPCODE + | FILTER_PROPERTY_LATITUDE + | FILTER_PROPERTY_LONGITUDE + | FILTER_PROPERTY_ZONE + | FILTER_PROPERTY_CITY + | FILTER_PROPERTY_SQUAREMETERS + | FILTER_PROPERTY_ROOMS + | FILTER_PROPERTY_BATHROOMS + | FILTER_PROPERTY_FLOORS + | FILTER_PROPERTY_BALCONIES + | FILTER_PROPERTY_GARDEN + | FILTER_PROPERTY_POOL + | FILTER_PROPERTY_GARAGE + | FILTER_PROPERTY_PARKING + | FILTER_PROPERTY_ENERGYCLASS + | FILTER_PROPERTY_YOUTUBEURL => { + let value = if value.is_empty() { + "true".to_string() + } else { + value.to_string() + }; + filters.push(ContractFilter::HasProperty { + name: format!("contract:{name}"), + value, + }); + } + _ => {} + } + } + + Filters { filters } + } +} + +impl Filters { + /// Check if the contract satisfies the filters. + pub fn check(&self, contract: &Contract) -> bool { + self.filters.iter().all(|filter| filter.check(contract)) + } +} diff --git a/src/deferred_minter/deferred_minter.did b/src/deferred_minter/deferred_minter.did index 0a55d33..daf197d 100644 --- a/src/deferred_minter/deferred_minter.did +++ b/src/deferred_minter/deferred_minter.did @@ -150,7 +150,7 @@ type RestrictedProperty = record { value : GenericValue; access_list : vec RestrictionLevel; }; -type RestrictionLevel = variant { Buyer; Seller; Agent }; +type RestrictionLevel = variant { Buyer; Public; Seller; Agent }; type Result = variant { Ok; Err : DeferredMinterError }; type Result_1 = variant { Ok : nat; Err : DeferredMinterError }; type Result_2 = variant { Ok : text; Err : DeferredMinterError }; diff --git a/src/did/src/deferred/contract.rs b/src/did/src/deferred/contract.rs index 4e33869..ea43fdc 100644 --- a/src/did/src/deferred/contract.rs +++ b/src/did/src/deferred/contract.rs @@ -123,6 +123,8 @@ pub enum RestrictionLevel { Buyer, /// Agent can access the property Agent, + /// Public can access the property + Public, } /// A variant which defines the contract type diff --git a/src/did/src/deferred/contract/generic_value.rs b/src/did/src/deferred/contract/generic_value.rs index b34cca3..e5b91c3 100644 --- a/src/did/src/deferred/contract/generic_value.rs +++ b/src/did/src/deferred/contract/generic_value.rs @@ -1,3 +1,5 @@ +use std::fmt; + use candid::{CandidType, Deserialize, Int, Nat, Principal}; use serde::Serialize; @@ -19,3 +21,91 @@ pub enum GenericValue { IntContent(Int), FloatContent(f64), // motoko only support f64 } + +impl GenericValue { + /// Check if the value equals to the given string + pub fn equals_str(&self, s: &str) -> bool { + self.to_string() == s + } +} + +impl fmt::Display for GenericValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&match self { + GenericValue::BoolContent(v) => v.to_string(), + GenericValue::TextContent(v) => v.clone(), + GenericValue::Principal(v) => v.to_text(), + GenericValue::Nat8Content(v) => v.to_string(), + GenericValue::Nat16Content(v) => v.to_string(), + GenericValue::Nat32Content(v) => v.to_string(), + GenericValue::Nat64Content(v) => v.to_string(), + GenericValue::NatContent(v) => v.to_string(), + GenericValue::Int8Content(v) => v.to_string(), + GenericValue::Int16Content(v) => v.to_string(), + GenericValue::Int32Content(v) => v.to_string(), + GenericValue::Int64Content(v) => v.to_string(), + GenericValue::IntContent(v) => v.to_string(), + GenericValue::FloatContent(v) => v.to_string(), + }) + } +} + +#[cfg(test)] +mod test { + + use super::*; + + #[test] + fn test_generic_value_to_string() { + let v = GenericValue::BoolContent(true); + assert_eq!(v.to_string(), "true"); + + let v = GenericValue::TextContent("hello".to_string()); + assert_eq!(v.to_string(), "hello"); + + let v = GenericValue::Principal( + Principal::from_text("v5vof-zqaaa-aaaal-ai5cq-cai").expect("invalid principal"), + ); + assert_eq!(v.to_string(), "v5vof-zqaaa-aaaal-ai5cq-cai"); + + let v = GenericValue::Nat8Content(8); + assert_eq!(v.to_string(), "8"); + + let v = GenericValue::Nat16Content(16); + assert_eq!(v.to_string(), "16"); + + let v = GenericValue::Nat32Content(32); + assert_eq!(v.to_string(), "32"); + + let v = GenericValue::Nat64Content(64); + assert_eq!(v.to_string(), "64"); + + let v = GenericValue::NatContent(Nat::from(128u64)); + assert_eq!(v.to_string(), "128"); + + let v = GenericValue::Int8Content(-8); + assert_eq!(v.to_string(), "-8"); + + let v = GenericValue::Int16Content(-16); + assert_eq!(v.to_string(), "-16"); + + let v = GenericValue::Int32Content(-32); + assert_eq!(v.to_string(), "-32"); + + let v = GenericValue::Int64Content(-64); + assert_eq!(v.to_string(), "-64"); + + let v = GenericValue::IntContent(Int::from(-128)); + assert_eq!(v.to_string(), "-128"); + + let v = GenericValue::FloatContent(3.14); + assert_eq!(v.to_string(), "3.14"); + } + + #[test] + fn test_eq_str() { + let v = GenericValue::BoolContent(true); + assert_eq!(v.equals_str("true"), true); + assert_eq!(v.equals_str("false"), false); + } +}