From 8310e013f68eea253958a1ac3b7bf5c5eeaa07e5 Mon Sep 17 00:00:00 2001 From: PedroCailleret Date: Tue, 14 Feb 2023 18:40:02 -0300 Subject: [PATCH] Enhanced integration & optimized testing --- .prettierignore | 4 +- README.md | 21 +- .../DataTypes.sol/DataTypes.dbg.json | 2 +- .../EventAndErrors.dbg.json | 2 +- .../Reputation.sol/Reputation.dbg.json | 2 +- .../lib/auth/Owned.sol/Owned.dbg.json | 2 +- .../IReputation.sol/IReputation.dbg.json | 2 +- .../lib/mock/mockToken.sol/MockToken.dbg.json | 2 +- .../lib/tokens/ERC20.sol/ERC20.dbg.json | 2 +- .../MerkleProofLib.dbg.json | 2 +- .../utils/Multicall.sol/Multicall.dbg.json | 4 + .../lib/utils/Multicall.sol/Multicall.json | 116 +++ .../ReentrancyGuard.dbg.json | 2 +- .../SafeTransferLib.dbg.json | 2 +- artifacts/contracts/p2pix.sol/P2PIX.dbg.json | 2 +- artifacts/contracts/p2pix.sol/P2PIX.json | 8 +- contracts/DataTypes.sol | 20 +- contracts/lib/utils/Multicall.sol | 80 ++ contracts/lib/utils/SafeTransferLib.sol | 42 - contracts/p2pix.sol | 380 ++++--- deploys/goerli.json | 2 +- deploys/localhost.json | 2 +- deploys/polygon-mumbai.json | 2 +- hardhat.config.ts | 10 +- package.json | 2 +- scripts/1-deploy-mockToken.ts | 5 +- scripts/2-deploy-p2pix.ts | 12 +- .../factories/lib/utils/Multicall__factory.ts | 174 ++++ src/types/factories/lib/utils/index.ts | 1 + .../factories/p2pix.sol/P2PIX__factory.ts | 6 +- src/types/hardhat.d.ts | 9 + src/types/index.ts | 2 + src/types/lib/utils/Multicall.ts | 155 +++ src/types/lib/utils/index.ts | 1 + src/types/p2pix.sol/P2PIX.ts | 6 +- test/Reputation.test.ts | 74 +- test/p2pix.test.ts | 932 ++++++++++++------ test/utils/errors.ts | 1 + test/utils/fixtures.ts | 61 +- yarn.lock | 11 +- 40 files changed, 1516 insertions(+), 649 deletions(-) create mode 100644 artifacts/contracts/lib/utils/Multicall.sol/Multicall.dbg.json create mode 100644 artifacts/contracts/lib/utils/Multicall.sol/Multicall.json create mode 100644 contracts/lib/utils/Multicall.sol create mode 100644 src/types/factories/lib/utils/Multicall__factory.ts create mode 100644 src/types/lib/utils/Multicall.ts diff --git a/.prettierignore b/.prettierignore index 55e66dd..3cf7293 100644 --- a/.prettierignore +++ b/.prettierignore @@ -18,4 +18,6 @@ coverage.json npm-debug.log* yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log* + +contracts/p2pix.sol \ No newline at end of file diff --git a/README.md b/README.md index 087ca5b..14dc5ed 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,11 @@ ## Current Deployment addresses ### V1 -| Testnet | Token Address | P2pix Address | -|--------- |-------------------------------------------- |-------------------------------------------- | -| Goerli | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | -| Mumbai | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | + +| Testnet | Token Address | P2pix Address | +| ------- | ------------------------------------------ | ------------------------------------------ | +| Goerli | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | +| Mumbai | 0x294003F602c321627152c6b7DED3EAb5bEa853Ee | 0x5f3EFA9A90532914545CEf527C530658af87e196 | @@ -48,10 +49,11 @@ ### V2 -| Testnet | Token Address | P2pix Address | Reputation Address | -|--------- |-------------------------------------------- |-------------------------------------------- |-------------------------------------------- | -| Goerli | 0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00 | 0xefa5cE4351cda51192509cf8De7d8881ADAE95DD | 0x939d3c357dc7017cDbDE681BF8e552b54595318A | -| Mumbai | 0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29 | 0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b | 0x1fd30b94f20d2f73e9630261342ba68f244da92b | + +| Testnet | Token Address | P2pix Address | Reputation Address | +| ------- | ------------------------------------------ | ------------------------------------------ | ------------------------------------------ | +| Goerli | 0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00 | 0xefa5cE4351cda51192509cf8De7d8881ADAE95DD | 0x939d3c357dc7017cDbDE681BF8e552b54595318A | +| Mumbai | 0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29 | 0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b | 0x1fd30b94f20d2f73e9630261342ba68f244da92b | @@ -136,7 +138,6 @@ yarn deploy2:localhost **_NOTE_:** The second script transfers 2M tokens to the first wallet of the node. To use the P2Pix smart contract first transfer some of the tokens to other wallets. - ## Deploying to testnets Deploy to Ethereum's Goerli testnet: @@ -151,4 +152,4 @@ Deploy to Polygon's Mumbai testnet: ```sh yarn deploy1:mumbai yarn deploy2:mumbai -``` \ No newline at end of file +``` diff --git a/artifacts/contracts/DataTypes.sol/DataTypes.dbg.json b/artifacts/contracts/DataTypes.sol/DataTypes.dbg.json index ecd92f8..e4b0eb9 100644 --- a/artifacts/contracts/DataTypes.sol/DataTypes.dbg.json +++ b/artifacts/contracts/DataTypes.sol/DataTypes.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/EventAndErrors.sol/EventAndErrors.dbg.json b/artifacts/contracts/EventAndErrors.sol/EventAndErrors.dbg.json index ecd92f8..e4b0eb9 100644 --- a/artifacts/contracts/EventAndErrors.sol/EventAndErrors.dbg.json +++ b/artifacts/contracts/EventAndErrors.sol/EventAndErrors.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/Reputation.sol/Reputation.dbg.json b/artifacts/contracts/Reputation.sol/Reputation.dbg.json index ecd92f8..e4b0eb9 100644 --- a/artifacts/contracts/Reputation.sol/Reputation.dbg.json +++ b/artifacts/contracts/Reputation.sol/Reputation.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/auth/Owned.sol/Owned.dbg.json b/artifacts/contracts/lib/auth/Owned.sol/Owned.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/auth/Owned.sol/Owned.dbg.json +++ b/artifacts/contracts/lib/auth/Owned.sol/Owned.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/interfaces/IReputation.sol/IReputation.dbg.json b/artifacts/contracts/lib/interfaces/IReputation.sol/IReputation.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/interfaces/IReputation.sol/IReputation.dbg.json +++ b/artifacts/contracts/lib/interfaces/IReputation.sol/IReputation.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/mock/mockToken.sol/MockToken.dbg.json b/artifacts/contracts/lib/mock/mockToken.sol/MockToken.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/mock/mockToken.sol/MockToken.dbg.json +++ b/artifacts/contracts/lib/mock/mockToken.sol/MockToken.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/tokens/ERC20.sol/ERC20.dbg.json b/artifacts/contracts/lib/tokens/ERC20.sol/ERC20.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/tokens/ERC20.sol/ERC20.dbg.json +++ b/artifacts/contracts/lib/tokens/ERC20.sol/ERC20.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/utils/MerkleProofLib.sol/MerkleProofLib.dbg.json b/artifacts/contracts/lib/utils/MerkleProofLib.sol/MerkleProofLib.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/utils/MerkleProofLib.sol/MerkleProofLib.dbg.json +++ b/artifacts/contracts/lib/utils/MerkleProofLib.sol/MerkleProofLib.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/utils/Multicall.sol/Multicall.dbg.json b/artifacts/contracts/lib/utils/Multicall.sol/Multicall.dbg.json new file mode 100644 index 0000000..48e5d52 --- /dev/null +++ b/artifacts/contracts/lib/utils/Multicall.sol/Multicall.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json" +} diff --git a/artifacts/contracts/lib/utils/Multicall.sol/Multicall.json b/artifacts/contracts/lib/utils/Multicall.sol/Multicall.json new file mode 100644 index 0000000..152b46d --- /dev/null +++ b/artifacts/contracts/lib/utils/Multicall.sol/Multicall.json @@ -0,0 +1,116 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Multicall", + "sourceName": "contracts/lib/utils/Multicall.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "payable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "CallFailed", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "mtc1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct Multicall.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "mtc2", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct Multicall.Result[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60806040526108ec806100136000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/artifacts/contracts/lib/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json b/artifacts/contracts/lib/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json index ef0d0ca..1914ecd 100644 --- a/artifacts/contracts/lib/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json +++ b/artifacts/contracts/lib/utils/ReentrancyGuard.sol/ReentrancyGuard.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/b4d8e73fede96cca1403a1884959873e.json" } diff --git a/artifacts/contracts/lib/utils/SafeTransferLib.sol/SafeTransferLib.dbg.json b/artifacts/contracts/lib/utils/SafeTransferLib.sol/SafeTransferLib.dbg.json index ef0d0ca..48e5d52 100644 --- a/artifacts/contracts/lib/utils/SafeTransferLib.sol/SafeTransferLib.dbg.json +++ b/artifacts/contracts/lib/utils/SafeTransferLib.sol/SafeTransferLib.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../../../build-info/e971df088e64e6ab53f252445efd91f4.json" + "buildInfo": "../../../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json" } diff --git a/artifacts/contracts/p2pix.sol/P2PIX.dbg.json b/artifacts/contracts/p2pix.sol/P2PIX.dbg.json index 8855f2e..ea01694 100644 --- a/artifacts/contracts/p2pix.sol/P2PIX.dbg.json +++ b/artifacts/contracts/p2pix.sol/P2PIX.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/4a149f14ea0fec7293fb79d89ccb9fe7.json" + "buildInfo": "../../build-info/666cc6ce6bd689a930692ddaa3c0f679.json" } diff --git a/artifacts/contracts/p2pix.sol/P2PIX.json b/artifacts/contracts/p2pix.sol/P2PIX.json index 7881510..16419cd 100644 --- a/artifacts/contracts/p2pix.sol/P2PIX.json +++ b/artifacts/contracts/p2pix.sol/P2PIX.json @@ -584,9 +584,9 @@ "type": "uint256[]" }, { - "internalType": "bool[]", + "internalType": "enum DataTypes.LockStatus[]", "name": "", - "type": "bool[]" + "type": "uint8[]" } ], "stateMutability": "view", @@ -1089,8 +1089,8 @@ "type": "receive" } ], - "bytecode": "0x6080604052600180556040516200352c3803806200352c8339810160408190526200002a9162000493565b600080546001600160a01b031916339081178255604051909182917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3506200007685620000a3565b620000818362000133565b6200008c84620001bd565b620000988282620002a1565b505050505062000616565b6000546001600160a01b03163314620000f25760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b8511816040516200012891815260200190565b60405180910390a150565b6000546001600160a01b031633146200017e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b60028190556040516001600160a01b03821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f9060200162000128565b6000546001600160a01b03163314620002085760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b80516000905b808210156200026e57600062000246848481518110620002325762000232620005b1565b60200260200101516200038760201b60201c565b6000908152600860205260409020805460ff191660019081179091559290920191506200020e565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051620001289190620005c7565b6000546001600160a01b03163314620002ec5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b815180620003025763df9578836000526004601cfd5b81518114620003195763ff633a386000526004601cfd5b60208301602083018260051b82015b8083146200037f578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a360208301925060208201915062000328565b505050505050565b600c1b90565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620003ce57620003ce6200038d565b604052919050565b60006001600160401b03821115620003f257620003f26200038d565b5060051b60200190565b6001600160a01b03811681146200041257600080fd5b50565b600082601f8301126200042757600080fd5b81516020620004406200043a83620003d6565b620003a3565b82815260059290921b840181019181810190868411156200046057600080fd5b8286015b84811015620004885780516200047a81620003fc565b835291830191830162000464565b509695505050505050565b600080600080600060a08688031215620004ac57600080fd5b8551602080880151919650906001600160401b0380821115620004ce57600080fd5b620004dc8a838b0162000415565b965060408901519150620004f082620003fc565b6060890151919550808211156200050657600080fd5b620005148a838b0162000415565b945060808901519150808211156200052b57600080fd5b508701601f810189136200053e57600080fd5b80516200054f6200043a82620003d6565b81815260059190911b8201830190838101908b8311156200056f57600080fd5b928401925b828410156200059f57835180151581146200058f5760008081fd5b8252928401929084019062000574565b80955050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b818110156200060a5783516001600160a01b031683529284019291840191600101620005e3565b50909695505050505050565b612f0680620006266000396000f3fe6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e366004612608565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e36600461268f565b6107f7565b34801561025f57600080fd5b5061027361026e366004612876565b610ba6565b005b34801561028157600080fd5b506102736102903660046128b3565b610ce0565b3480156102a157600080fd5b506102736102b03660046128ec565b610dd1565b3480156102c157600080fd5b506103426102d0366004612608565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c9366004612608565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e61040936600461295f565b611012565b60405161022a929190612a2b565b34801561042857600080fd5b506102206104373660046128b3565b600c1b90565b34801561044957600080fd5b50610273610458366004612608565b61120c565b34801561046957600080fd5b506102736112c2565b34801561047e57600080fd5b506103de61048d3660046128b3565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612a84565b611384565b3480156104ea57600080fd5b506102736104f9366004612ab9565b61149b565b34801561050a57600080fd5b50610220610519366004612608565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612b1d565b61197a565b34801561055757600080fd5b506103de610566366004612b49565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a6366004612608565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de610645366004612608565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612b82565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612b49565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612ba7565b611a40565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612be9565b611c83565b60405161022a9190612c30565b34801561075857600080fd5b50610220610767366004612b49565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612c43565b611d5d565b3480156107c357600080fd5b506102736107d23660046128b3565b611e6d565b3480156107e357600080fd5b506102736107f2366004612d05565b611f39565b6000610801612035565b61080b8383611a40565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612d90565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612d90565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612079565b610a87848c848489886120d1565b60048054906000610a9783612da8565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886120d1565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612de1565b61222c565b9050610b0d670de0b6b3a764000082612e1c565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6120d1565b60048054906000610b8083612da8565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612e59565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612e88565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612d90565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f25612035565b8415610f3557610f35338661197a565b87878760ff81901b605f83901b610f4c8587612d90565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166122e8565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612760565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612760565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112015743600560008987815181106110ef576110ef612e59565b6020026020010151815260200190815260200160002060040154108061114457506005600088868151811061112657611126612e59565b60200260200101518152602001908152602001600020600301546000145b156111b55786848151811061115b5761115b612e59565b602002602001015181858151811061117557611175612e59565b602002602001018181525050600082858151811061119557611195612e59565b911515602092830291909101909101526111ae84612da8565b93506110d0565b8684815181106111c7576111c7612e59565b60200260200101518185815181106111e1576111e1612e59565b602002602001018181525050600182858151811061119557611195612e59565b969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff163314611343576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b4761134e33826123b2565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091529020548015611463576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a250611495565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6114a3612035565b600086815260056020526040902060038101546114ec576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438160040154101561152a576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016115cd91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff16151560011415611652576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526116ba9060019060a0016020604051602081039080840390855afa1580156116aa573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff16611705576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff9092169160009061173a9083612ee2565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461182657600287015433600c1b600090815260076020526040812080549091906117cc908490612d90565b9091555050600887015482906007906000906117fe9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b8152602001908152602001600020600082825461181b9190612d90565b9091555061185e9050565b8187600201546118369190612d90565b33600c1b60009081526007602052604081208054909190611858908490612d90565b90915550505b600687015461188590849073ffffffffffffffffffffffffffffffffffffffff168361242c565b60028701541561190b57600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146118fc57600787015460028801546118e491859173ffffffffffffffffffffffffffffffffffffffff9091169060011c61242c565b6118f7838d60018a60020154901c61242c565b61190b565b61190b838d896002015461242c565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a25050505050505061197260018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611a0e5780600660006119a785600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611c6d57600060056000868686818110611a6457611a64612e59565b9050602002013581526020019081526020016000209050611a84816124eb565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611ae79083612d90565b1115611b1f576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611b69908490612d90565b90915550506000600383018190556008830154611b9c9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611be057600082815260076020526040902068056bc75e2d631000009055611bf2565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611c4057611c40612e59565b90506020020135604051611c5691815260200190565b60405180910390a285600101955050505050611a44565b808210156114955763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611ca557611ca5612760565b604051908082528060200260200182016040528015611cce578160200160208202803683370190505b5090505b81831015611d54576000611d27878581518110611cf157611cf1612e59565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611d3c57611d3c612e59565b60200260200101818152505083600101935050611cd2565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611df35763df9578836000526004601cfd5b81518114611e095763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611972578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611e18565b60005473ffffffffffffffffffffffffffffffffffffffff163314611eee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b611f41612035565b611f4b8282611a40565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c151560011415611f8157611f81846000611384565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902054611fcf906b3fffffffffffffffffffffff16858784612567565b611fda85338661242c565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061149560018055565b60015460021415612072576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61209b84848473ffffffffffffffffffffffffffffffffffffffff85166125c4565b611495576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556121c086868484612567565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261221c92918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161224a91815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826122df5763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d11600160005114161716915060006060528060405250806123ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612427576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612529576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003810154612564576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8361257a5763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906125b9908490612ee2565b909155505050505050565b60008315612600578360051b8501855b803580851160051b948552602094851852604060002093018181106125f8576125fd565b6125d4565b50505b501492915050565b60006020828403121561261a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461256457600080fd5b60008083601f84011261265557600080fd5b50813567ffffffffffffffff81111561266d57600080fd5b6020830191508360208260051b850101111561268857600080fd5b9250929050565b6000806000806000806000806000806101008b8d0312156126af57600080fd5b8a356126ba81612621565b995060208b01356126ca81612621565b985060408b01356126da81612621565b975060608b01356126ea81612621565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff8082111561271557600080fd5b6127218e838f01612643565b909650945060e08d013591508082111561273a57600080fd5b506127478d828e01612643565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127d6576127d6612760565b604052919050565b600067ffffffffffffffff8211156127f8576127f8612760565b5060051b60200190565b600082601f83011261281357600080fd5b81356020612828612823836127de565b61278f565b82815260059290921b8401810191818101908684111561284757600080fd5b8286015b8481101561286b57803561285e81612621565b835291830191830161284b565b509695505050505050565b60006020828403121561288857600080fd5b813567ffffffffffffffff81111561289f57600080fd5b6128ab84828501612802565b949350505050565b6000602082840312156128c557600080fd5b81356128d081612621565b9392505050565b803580151581146128e757600080fd5b919050565b600080600080600060a0868803121561290457600080fd5b853561290f81612621565b945060208601356bffffffffffffffffffffffff8116811461293057600080fd5b9350604086013561294081612621565b925061294e606087016128d7565b949793965091946080013592915050565b6000602080838503121561297257600080fd5b823567ffffffffffffffff81111561298957600080fd5b8301601f8101851361299a57600080fd5b80356129a8612823826127de565b81815260059190911b820183019083810190878311156129c757600080fd5b928401925b828410156129e5578335825292840192908401906129cc565b979650505050505050565b600081518084526020808501945080840160005b83811015612a2057815187529582019590820190600101612a04565b509495945050505050565b604081526000612a3e60408301856129f0565b82810360208481019190915284518083528582019282019060005b81811015612a77578451151583529383019391830191600101612a59565b5090979650505050505050565b60008060408385031215612a9757600080fd5b8235612aa281612621565b9150612ab0602084016128d7565b90509250929050565b60008060008060008060c08789031215612ad257600080fd5b863595506020870135612ae481612621565b945060408701359350606087013592506080870135915060a087013560ff81168114612b0f57600080fd5b809150509295509295509295565b60008060408385031215612b3057600080fd5b8235612b3b81612621565b946020939093013593505050565b60008060408385031215612b5c57600080fd5b8235612b6781612621565b91506020830135612b7781612621565b809150509250929050565b60008060408385031215612b9557600080fd5b823591506020830135612b7781612621565b60008060208385031215612bba57600080fd5b823567ffffffffffffffff811115612bd157600080fd5b612bdd85828601612643565b90969095509350505050565b60008060408385031215612bfc57600080fd5b823567ffffffffffffffff811115612c1357600080fd5b612c1f85828601612802565b9250506020830135612b7781612621565b6020815260006128d060208301846129f0565b60008060408385031215612c5657600080fd5b823567ffffffffffffffff80821115612c6e57600080fd5b612c7a86838701612802565b9350602091508185013581811115612c9157600080fd5b85019050601f81018613612ca457600080fd5b8035612cb2612823826127de565b81815260059190911b82018301908381019088831115612cd157600080fd5b928401925b82841015612cf657612ce7846128d7565b82529284019290840190612cd6565b80955050505050509250929050565b60008060008060608587031215612d1b57600080fd5b8435612d2681612621565b935060208501359250604085013567ffffffffffffffff811115612d4957600080fd5b612d5587828801612643565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612da357612da3612d61565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612dda57612dda612d61565b5060010190565b600082612e17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612e5457612e54612d61565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015612ed657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612ea4565b50909695505050505050565b600082821015612ef457612ef4612d61565b50039056fea164736f6c6343000809000a", - "deployedBytecode": "0x6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e366004612608565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e36600461268f565b6107f7565b34801561025f57600080fd5b5061027361026e366004612876565b610ba6565b005b34801561028157600080fd5b506102736102903660046128b3565b610ce0565b3480156102a157600080fd5b506102736102b03660046128ec565b610dd1565b3480156102c157600080fd5b506103426102d0366004612608565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c9366004612608565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e61040936600461295f565b611012565b60405161022a929190612a2b565b34801561042857600080fd5b506102206104373660046128b3565b600c1b90565b34801561044957600080fd5b50610273610458366004612608565b61120c565b34801561046957600080fd5b506102736112c2565b34801561047e57600080fd5b506103de61048d3660046128b3565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612a84565b611384565b3480156104ea57600080fd5b506102736104f9366004612ab9565b61149b565b34801561050a57600080fd5b50610220610519366004612608565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612b1d565b61197a565b34801561055757600080fd5b506103de610566366004612b49565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a6366004612608565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de610645366004612608565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612b82565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612b49565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612ba7565b611a40565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612be9565b611c83565b60405161022a9190612c30565b34801561075857600080fd5b50610220610767366004612b49565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612c43565b611d5d565b3480156107c357600080fd5b506102736107d23660046128b3565b611e6d565b3480156107e357600080fd5b506102736107f2366004612d05565b611f39565b6000610801612035565b61080b8383611a40565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612d90565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612d90565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612079565b610a87848c848489886120d1565b60048054906000610a9783612da8565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886120d1565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612de1565b61222c565b9050610b0d670de0b6b3a764000082612e1c565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6120d1565b60048054906000610b8083612da8565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612e59565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612e88565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612d90565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f25612035565b8415610f3557610f35338661197a565b87878760ff81901b605f83901b610f4c8587612d90565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166122e8565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612760565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612760565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112015743600560008987815181106110ef576110ef612e59565b6020026020010151815260200190815260200160002060040154108061114457506005600088868151811061112657611126612e59565b60200260200101518152602001908152602001600020600301546000145b156111b55786848151811061115b5761115b612e59565b602002602001015181858151811061117557611175612e59565b602002602001018181525050600082858151811061119557611195612e59565b911515602092830291909101909101526111ae84612da8565b93506110d0565b8684815181106111c7576111c7612e59565b60200260200101518185815181106111e1576111e1612e59565b602002602001018181525050600182858151811061119557611195612e59565b969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff163314611343576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b4761134e33826123b2565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091529020548015611463576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a250611495565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6114a3612035565b600086815260056020526040902060038101546114ec576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438160040154101561152a576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016115cd91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff16151560011415611652576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526116ba9060019060a0016020604051602081039080840390855afa1580156116aa573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff16611705576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff9092169160009061173a9083612ee2565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461182657600287015433600c1b600090815260076020526040812080549091906117cc908490612d90565b9091555050600887015482906007906000906117fe9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b8152602001908152602001600020600082825461181b9190612d90565b9091555061185e9050565b8187600201546118369190612d90565b33600c1b60009081526007602052604081208054909190611858908490612d90565b90915550505b600687015461188590849073ffffffffffffffffffffffffffffffffffffffff168361242c565b60028701541561190b57600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146118fc57600787015460028801546118e491859173ffffffffffffffffffffffffffffffffffffffff9091169060011c61242c565b6118f7838d60018a60020154901c61242c565b61190b565b61190b838d896002015461242c565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a25050505050505061197260018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611a0e5780600660006119a785600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611c6d57600060056000868686818110611a6457611a64612e59565b9050602002013581526020019081526020016000209050611a84816124eb565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611ae79083612d90565b1115611b1f576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611b69908490612d90565b90915550506000600383018190556008830154611b9c9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611be057600082815260076020526040902068056bc75e2d631000009055611bf2565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611c4057611c40612e59565b90506020020135604051611c5691815260200190565b60405180910390a285600101955050505050611a44565b808210156114955763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611ca557611ca5612760565b604051908082528060200260200182016040528015611cce578160200160208202803683370190505b5090505b81831015611d54576000611d27878581518110611cf157611cf1612e59565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611d3c57611d3c612e59565b60200260200101818152505083600101935050611cd2565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611df35763df9578836000526004601cfd5b81518114611e095763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611972578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611e18565b60005473ffffffffffffffffffffffffffffffffffffffff163314611eee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b611f41612035565b611f4b8282611a40565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c151560011415611f8157611f81846000611384565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902054611fcf906b3fffffffffffffffffffffff16858784612567565b611fda85338661242c565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061149560018055565b60015460021415612072576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61209b84848473ffffffffffffffffffffffffffffffffffffffff85166125c4565b611495576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556121c086868484612567565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261221c92918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161224a91815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826122df5763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d11600160005114161716915060006060528060405250806123ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612427576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612529576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003810154612564576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8361257a5763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906125b9908490612ee2565b909155505050505050565b60008315612600578360051b8501855b803580851160051b948552602094851852604060002093018181106125f8576125fd565b6125d4565b50505b501492915050565b60006020828403121561261a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461256457600080fd5b60008083601f84011261265557600080fd5b50813567ffffffffffffffff81111561266d57600080fd5b6020830191508360208260051b850101111561268857600080fd5b9250929050565b6000806000806000806000806000806101008b8d0312156126af57600080fd5b8a356126ba81612621565b995060208b01356126ca81612621565b985060408b01356126da81612621565b975060608b01356126ea81612621565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff8082111561271557600080fd5b6127218e838f01612643565b909650945060e08d013591508082111561273a57600080fd5b506127478d828e01612643565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127d6576127d6612760565b604052919050565b600067ffffffffffffffff8211156127f8576127f8612760565b5060051b60200190565b600082601f83011261281357600080fd5b81356020612828612823836127de565b61278f565b82815260059290921b8401810191818101908684111561284757600080fd5b8286015b8481101561286b57803561285e81612621565b835291830191830161284b565b509695505050505050565b60006020828403121561288857600080fd5b813567ffffffffffffffff81111561289f57600080fd5b6128ab84828501612802565b949350505050565b6000602082840312156128c557600080fd5b81356128d081612621565b9392505050565b803580151581146128e757600080fd5b919050565b600080600080600060a0868803121561290457600080fd5b853561290f81612621565b945060208601356bffffffffffffffffffffffff8116811461293057600080fd5b9350604086013561294081612621565b925061294e606087016128d7565b949793965091946080013592915050565b6000602080838503121561297257600080fd5b823567ffffffffffffffff81111561298957600080fd5b8301601f8101851361299a57600080fd5b80356129a8612823826127de565b81815260059190911b820183019083810190878311156129c757600080fd5b928401925b828410156129e5578335825292840192908401906129cc565b979650505050505050565b600081518084526020808501945080840160005b83811015612a2057815187529582019590820190600101612a04565b509495945050505050565b604081526000612a3e60408301856129f0565b82810360208481019190915284518083528582019282019060005b81811015612a77578451151583529383019391830191600101612a59565b5090979650505050505050565b60008060408385031215612a9757600080fd5b8235612aa281612621565b9150612ab0602084016128d7565b90509250929050565b60008060008060008060c08789031215612ad257600080fd5b863595506020870135612ae481612621565b945060408701359350606087013592506080870135915060a087013560ff81168114612b0f57600080fd5b809150509295509295509295565b60008060408385031215612b3057600080fd5b8235612b3b81612621565b946020939093013593505050565b60008060408385031215612b5c57600080fd5b8235612b6781612621565b91506020830135612b7781612621565b809150509250929050565b60008060408385031215612b9557600080fd5b823591506020830135612b7781612621565b60008060208385031215612bba57600080fd5b823567ffffffffffffffff811115612bd157600080fd5b612bdd85828601612643565b90969095509350505050565b60008060408385031215612bfc57600080fd5b823567ffffffffffffffff811115612c1357600080fd5b612c1f85828601612802565b9250506020830135612b7781612621565b6020815260006128d060208301846129f0565b60008060408385031215612c5657600080fd5b823567ffffffffffffffff80821115612c6e57600080fd5b612c7a86838701612802565b9350602091508185013581811115612c9157600080fd5b85019050601f81018613612ca457600080fd5b8035612cb2612823826127de565b81815260059190911b82018301908381019088831115612cd157600080fd5b928401925b82841015612cf657612ce7846128d7565b82529284019290840190612cd6565b80955050505050509250929050565b60008060008060608587031215612d1b57600080fd5b8435612d2681612621565b935060208501359250604085013567ffffffffffffffff811115612d4957600080fd5b612d5587828801612643565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612da357612da3612d61565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612dda57612dda612d61565b5060010190565b600082612e17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612e5457612e54612d61565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015612ed657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612ea4565b50909695505050505050565b600082821015612ef457612ef4612d61565b50039056fea164736f6c6343000809000a", + "bytecode": "0x6080604052600180556040516200366e3803806200366e8339810160408190526200002a9162000493565b600080546001600160a01b031916339081178255604051909182917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3506200007685620000a3565b620000818362000133565b6200008c84620001bd565b620000988282620002a1565b505050505062000616565b6000546001600160a01b03163314620000f25760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b8511816040516200012891815260200190565b60405180910390a150565b6000546001600160a01b031633146200017e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b60028190556040516001600160a01b03821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f9060200162000128565b6000546001600160a01b03163314620002085760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b80516000905b808210156200026e57600062000246848481518110620002325762000232620005b1565b60200260200101516200038760201b60201c565b6000908152600860205260409020805460ff191660019081179091559290920191506200020e565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051620001289190620005c7565b6000546001600160a01b03163314620002ec5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b815180620003025763df9578836000526004601cfd5b81518114620003195763ff633a386000526004601cfd5b60208301602083018260051b82015b8083146200037f578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a360208301925060208201915062000328565b505050505050565b600c1b90565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620003ce57620003ce6200038d565b604052919050565b60006001600160401b03821115620003f257620003f26200038d565b5060051b60200190565b6001600160a01b03811681146200041257600080fd5b50565b600082601f8301126200042757600080fd5b81516020620004406200043a83620003d6565b620003a3565b82815260059290921b840181019181810190868411156200046057600080fd5b8286015b84811015620004885780516200047a81620003fc565b835291830191830162000464565b509695505050505050565b600080600080600060a08688031215620004ac57600080fd5b8551602080880151919650906001600160401b0380821115620004ce57600080fd5b620004dc8a838b0162000415565b965060408901519150620004f082620003fc565b6060890151919550808211156200050657600080fd5b620005148a838b0162000415565b945060808901519150808211156200052b57600080fd5b508701601f810189136200053e57600080fd5b80516200054f6200043a82620003d6565b81815260059190911b8201830190838101908b8311156200056f57600080fd5b928401925b828410156200059f57835180151581146200058f5760008081fd5b8252928401929084019062000574565b80955050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b818110156200060a5783516001600160a01b031683529284019291840191600101620005e3565b50909695505050505050565b61304880620006266000396000f3fe6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e3660046126f1565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e366004612778565b6107f7565b34801561025f57600080fd5b5061027361026e36600461295f565b610ba6565b005b34801561028157600080fd5b5061027361029036600461299c565b610ce0565b3480156102a157600080fd5b506102736102b03660046129d5565b610dd1565b3480156102c157600080fd5b506103426102d03660046126f1565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c93660046126f1565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e610409366004612a48565b611012565b60405161022a929190612b43565b34801561042857600080fd5b5061022061043736600461299c565b600c1b90565b34801561044957600080fd5b506102736104583660046126f1565b6112f5565b34801561046957600080fd5b506102736113ab565b34801561047e57600080fd5b506103de61048d36600461299c565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612bd2565b61146d565b3480156104ea57600080fd5b506102736104f9366004612c07565b611584565b34801561050a57600080fd5b506102206105193660046126f1565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612c6b565b611a63565b34801561055757600080fd5b506103de610566366004612c97565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a63660046126f1565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de6106453660046126f1565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612cd0565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612c97565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612cf5565b611b29565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612d2b565b611d6c565b60405161022a9190612d72565b34801561075857600080fd5b50610220610767366004612c97565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612d85565b611e46565b3480156107c357600080fd5b506102736107d236600461299c565b611f56565b3480156107e357600080fd5b506102736107f2366004612e47565b612022565b600061080161211e565b61080b8383611b29565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612ed2565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612ed2565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612162565b610a87848c848489886121ba565b60048054906000610a9783612eea565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886121ba565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612f23565b612315565b9050610b0d670de0b6b3a764000082612f5e565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6121ba565b60048054906000610b8083612eea565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612f9b565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612fca565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612ed2565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f2561211e565b8415610f3557610f353386611a63565b87878760ff81901b605f83901b610f4c8587612ed2565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166123d1565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612849565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612849565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112e957600560008886815181106110ee576110ee612f9b565b6020026020010151815260200190815260200160002060000154600014156111965786848151811061112257611122612f9b565b602002602001015182858151811061113c5761113c612f9b565b602002602001018181525050600081858151811061115c5761115c612f9b565b6020026020010190600381111561117557611175612b14565b9081600381111561118857611188612b14565b9052506001909301926110d0565b600560008886815181106111ac576111ac612f9b565b60200260200101518152602001908152602001600020600301546000141561121a578684815181106111e0576111e0612f9b565b60200260200101518285815181106111fa576111fa612f9b565b602002602001018181525050600381858151811061115c5761115c612f9b565b436005600089878151811061123157611231612f9b565b6020026020010151815260200190815260200160002060040154101561129d5786848151811061126357611263612f9b565b602002602001015182858151811061127d5761127d612f9b565b602002602001018181525050600281858151811061115c5761115c612f9b565b8684815181106112af576112af612f9b565b60200260200101518285815181106112c9576112c9612f9b565b602002602001018181525050600181858151811061115c5761115c612f9b565b90969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b47611437338261249b565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054801561154c576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a25061157e565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b61158c61211e565b600086815260056020526040902060038101546115d5576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4381600401541015611613576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016116b691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff1615156001141561173b576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526117a39060019060a0016020604051602081039080840390855afa158015611793573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff166117ee576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff909216916000906118239083613024565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461190f57600287015433600c1b600090815260076020526040812080549091906118b5908490612ed2565b9091555050600887015482906007906000906118e79073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b815260200190815260200160002060008282546119049190612ed2565b909155506119479050565b81876002015461191f9190612ed2565b33600c1b60009081526007602052604081208054909190611941908490612ed2565b90915550505b600687015461196e90849073ffffffffffffffffffffffffffffffffffffffff1683612515565b6002870154156119f457600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146119e557600787015460028801546119cd91859173ffffffffffffffffffffffffffffffffffffffff9091169060011c612515565b6119e0838d60018a60020154901c612515565b6119f4565b6119f4838d8960020154612515565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a250505050505050611a5b60018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611af7578060066000611a9085600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611d5657600060056000868686818110611b4d57611b4d612f9b565b9050602002013581526020019081526020016000209050611b6d816125d4565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611bd09083612ed2565b1115611c08576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611c52908490612ed2565b90915550506000600383018190556008830154611c859073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611cc957600082815260076020526040902068056bc75e2d631000009055611cdb565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611d2957611d29612f9b565b90506020020135604051611d3f91815260200190565b60405180910390a285600101955050505050611b2d565b8082101561157e5763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611d8e57611d8e612849565b604051908082528060200260200182016040528015611db7578160200160208202803683370190505b5090505b81831015611e3d576000611e10878581518110611dda57611dda612f9b565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611e2557611e25612f9b565b60200260200101818152505083600101935050611dbb565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611edc5763df9578836000526004601cfd5b81518114611ef25763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611a5b578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611f01565b60005473ffffffffffffffffffffffffffffffffffffffff163314611fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b61202a61211e565b6120348282611b29565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c15156001141561206a5761206a84600061146d565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529020546120b8906b3fffffffffffffffffffffff16858784612650565b6120c3853386612515565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061157e60018055565b6001546002141561215b576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61218484848473ffffffffffffffffffffffffffffffffffffffff85166126ad565b61157e576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556122a986868484612650565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261230592918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161233391815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826123c85763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080612494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612510576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d116001600051141617169150600060605280604052508061157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612612576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600381015461264d576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b836126635763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906126a2908490613024565b909155505050505050565b600083156126e9578360051b8501855b803580851160051b948552602094851852604060002093018181106126e1576126e6565b6126bd565b50505b501492915050565b60006020828403121561270357600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461264d57600080fd5b60008083601f84011261273e57600080fd5b50813567ffffffffffffffff81111561275657600080fd5b6020830191508360208260051b850101111561277157600080fd5b9250929050565b6000806000806000806000806000806101008b8d03121561279857600080fd5b8a356127a38161270a565b995060208b01356127b38161270a565b985060408b01356127c38161270a565b975060608b01356127d38161270a565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff808211156127fe57600080fd5b61280a8e838f0161272c565b909650945060e08d013591508082111561282357600080fd5b506128308d828e0161272c565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156128bf576128bf612849565b604052919050565b600067ffffffffffffffff8211156128e1576128e1612849565b5060051b60200190565b600082601f8301126128fc57600080fd5b8135602061291161290c836128c7565b612878565b82815260059290921b8401810191818101908684111561293057600080fd5b8286015b848110156129545780356129478161270a565b8352918301918301612934565b509695505050505050565b60006020828403121561297157600080fd5b813567ffffffffffffffff81111561298857600080fd5b612994848285016128eb565b949350505050565b6000602082840312156129ae57600080fd5b81356129b98161270a565b9392505050565b803580151581146129d057600080fd5b919050565b600080600080600060a086880312156129ed57600080fd5b85356129f88161270a565b945060208601356bffffffffffffffffffffffff81168114612a1957600080fd5b93506040860135612a298161270a565b9250612a37606087016129c0565b949793965091946080013592915050565b60006020808385031215612a5b57600080fd5b823567ffffffffffffffff811115612a7257600080fd5b8301601f81018513612a8357600080fd5b8035612a9161290c826128c7565b81815260059190911b82018301908381019087831115612ab057600080fd5b928401925b82841015612ace57833582529284019290840190612ab5565b979650505050505050565b600081518084526020808501945080840160005b83811015612b0957815187529582019590820190600101612aed565b509495945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604081526000612b566040830185612ad9565b8281036020848101919091528451808352858201928201906000805b82811015612bc45785516004808210612bb1577f4e487b7100000000000000000000000000000000000000000000000000000000845260218152602484fd5b5084529484019492840192600101612b72565b509198975050505050505050565b60008060408385031215612be557600080fd5b8235612bf08161270a565b9150612bfe602084016129c0565b90509250929050565b60008060008060008060c08789031215612c2057600080fd5b863595506020870135612c328161270a565b945060408701359350606087013592506080870135915060a087013560ff81168114612c5d57600080fd5b809150509295509295509295565b60008060408385031215612c7e57600080fd5b8235612c898161270a565b946020939093013593505050565b60008060408385031215612caa57600080fd5b8235612cb58161270a565b91506020830135612cc58161270a565b809150509250929050565b60008060408385031215612ce357600080fd5b823591506020830135612cc58161270a565b60008060208385031215612d0857600080fd5b823567ffffffffffffffff811115612d1f57600080fd5b6112e98582860161272c565b60008060408385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d61858286016128eb565b9250506020830135612cc58161270a565b6020815260006129b96020830184612ad9565b60008060408385031215612d9857600080fd5b823567ffffffffffffffff80821115612db057600080fd5b612dbc868387016128eb565b9350602091508185013581811115612dd357600080fd5b85019050601f81018613612de657600080fd5b8035612df461290c826128c7565b81815260059190911b82018301908381019088831115612e1357600080fd5b928401925b82841015612e3857612e29846129c0565b82529284019290840190612e18565b80955050505050509250929050565b60008060008060608587031215612e5d57600080fd5b8435612e688161270a565b935060208501359250604085013567ffffffffffffffff811115612e8b57600080fd5b612e978782880161272c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612ee557612ee5612ea3565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612f1c57612f1c612ea3565b5060010190565b600082612f59577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612f9657612f96612ea3565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b8181101561301857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fe6565b50909695505050505050565b60008282101561303657613036612ea3565b50039056fea164736f6c6343000809000a", + "deployedBytecode": "0x6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e3660046126f1565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e366004612778565b6107f7565b34801561025f57600080fd5b5061027361026e36600461295f565b610ba6565b005b34801561028157600080fd5b5061027361029036600461299c565b610ce0565b3480156102a157600080fd5b506102736102b03660046129d5565b610dd1565b3480156102c157600080fd5b506103426102d03660046126f1565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c93660046126f1565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e610409366004612a48565b611012565b60405161022a929190612b43565b34801561042857600080fd5b5061022061043736600461299c565b600c1b90565b34801561044957600080fd5b506102736104583660046126f1565b6112f5565b34801561046957600080fd5b506102736113ab565b34801561047e57600080fd5b506103de61048d36600461299c565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612bd2565b61146d565b3480156104ea57600080fd5b506102736104f9366004612c07565b611584565b34801561050a57600080fd5b506102206105193660046126f1565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612c6b565b611a63565b34801561055757600080fd5b506103de610566366004612c97565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a63660046126f1565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de6106453660046126f1565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612cd0565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612c97565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612cf5565b611b29565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612d2b565b611d6c565b60405161022a9190612d72565b34801561075857600080fd5b50610220610767366004612c97565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612d85565b611e46565b3480156107c357600080fd5b506102736107d236600461299c565b611f56565b3480156107e357600080fd5b506102736107f2366004612e47565b612022565b600061080161211e565b61080b8383611b29565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612ed2565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612ed2565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612162565b610a87848c848489886121ba565b60048054906000610a9783612eea565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886121ba565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612f23565b612315565b9050610b0d670de0b6b3a764000082612f5e565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6121ba565b60048054906000610b8083612eea565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612f9b565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612fca565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612ed2565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f2561211e565b8415610f3557610f353386611a63565b87878760ff81901b605f83901b610f4c8587612ed2565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166123d1565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612849565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612849565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112e957600560008886815181106110ee576110ee612f9b565b6020026020010151815260200190815260200160002060000154600014156111965786848151811061112257611122612f9b565b602002602001015182858151811061113c5761113c612f9b565b602002602001018181525050600081858151811061115c5761115c612f9b565b6020026020010190600381111561117557611175612b14565b9081600381111561118857611188612b14565b9052506001909301926110d0565b600560008886815181106111ac576111ac612f9b565b60200260200101518152602001908152602001600020600301546000141561121a578684815181106111e0576111e0612f9b565b60200260200101518285815181106111fa576111fa612f9b565b602002602001018181525050600381858151811061115c5761115c612f9b565b436005600089878151811061123157611231612f9b565b6020026020010151815260200190815260200160002060040154101561129d5786848151811061126357611263612f9b565b602002602001015182858151811061127d5761127d612f9b565b602002602001018181525050600281858151811061115c5761115c612f9b565b8684815181106112af576112af612f9b565b60200260200101518285815181106112c9576112c9612f9b565b602002602001018181525050600181858151811061115c5761115c612f9b565b90969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b47611437338261249b565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054801561154c576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a25061157e565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b61158c61211e565b600086815260056020526040902060038101546115d5576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4381600401541015611613576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016116b691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff1615156001141561173b576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526117a39060019060a0016020604051602081039080840390855afa158015611793573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff166117ee576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff909216916000906118239083613024565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461190f57600287015433600c1b600090815260076020526040812080549091906118b5908490612ed2565b9091555050600887015482906007906000906118e79073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b815260200190815260200160002060008282546119049190612ed2565b909155506119479050565b81876002015461191f9190612ed2565b33600c1b60009081526007602052604081208054909190611941908490612ed2565b90915550505b600687015461196e90849073ffffffffffffffffffffffffffffffffffffffff1683612515565b6002870154156119f457600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146119e557600787015460028801546119cd91859173ffffffffffffffffffffffffffffffffffffffff9091169060011c612515565b6119e0838d60018a60020154901c612515565b6119f4565b6119f4838d8960020154612515565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a250505050505050611a5b60018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611af7578060066000611a9085600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611d5657600060056000868686818110611b4d57611b4d612f9b565b9050602002013581526020019081526020016000209050611b6d816125d4565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611bd09083612ed2565b1115611c08576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611c52908490612ed2565b90915550506000600383018190556008830154611c859073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611cc957600082815260076020526040902068056bc75e2d631000009055611cdb565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611d2957611d29612f9b565b90506020020135604051611d3f91815260200190565b60405180910390a285600101955050505050611b2d565b8082101561157e5763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611d8e57611d8e612849565b604051908082528060200260200182016040528015611db7578160200160208202803683370190505b5090505b81831015611e3d576000611e10878581518110611dda57611dda612f9b565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611e2557611e25612f9b565b60200260200101818152505083600101935050611dbb565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611edc5763df9578836000526004601cfd5b81518114611ef25763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611a5b578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611f01565b60005473ffffffffffffffffffffffffffffffffffffffff163314611fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b61202a61211e565b6120348282611b29565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c15156001141561206a5761206a84600061146d565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529020546120b8906b3fffffffffffffffffffffff16858784612650565b6120c3853386612515565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061157e60018055565b6001546002141561215b576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61218484848473ffffffffffffffffffffffffffffffffffffffff85166126ad565b61157e576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556122a986868484612650565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261230592918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161233391815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826123c85763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080612494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612510576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d116001600051141617169150600060605280604052508061157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612612576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600381015461264d576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b836126635763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906126a2908490613024565b909155505050505050565b600083156126e9578360051b8501855b803580851160051b948552602094851852604060002093018181106126e1576126e6565b6126bd565b50505b501492915050565b60006020828403121561270357600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461264d57600080fd5b60008083601f84011261273e57600080fd5b50813567ffffffffffffffff81111561275657600080fd5b6020830191508360208260051b850101111561277157600080fd5b9250929050565b6000806000806000806000806000806101008b8d03121561279857600080fd5b8a356127a38161270a565b995060208b01356127b38161270a565b985060408b01356127c38161270a565b975060608b01356127d38161270a565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff808211156127fe57600080fd5b61280a8e838f0161272c565b909650945060e08d013591508082111561282357600080fd5b506128308d828e0161272c565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156128bf576128bf612849565b604052919050565b600067ffffffffffffffff8211156128e1576128e1612849565b5060051b60200190565b600082601f8301126128fc57600080fd5b8135602061291161290c836128c7565b612878565b82815260059290921b8401810191818101908684111561293057600080fd5b8286015b848110156129545780356129478161270a565b8352918301918301612934565b509695505050505050565b60006020828403121561297157600080fd5b813567ffffffffffffffff81111561298857600080fd5b612994848285016128eb565b949350505050565b6000602082840312156129ae57600080fd5b81356129b98161270a565b9392505050565b803580151581146129d057600080fd5b919050565b600080600080600060a086880312156129ed57600080fd5b85356129f88161270a565b945060208601356bffffffffffffffffffffffff81168114612a1957600080fd5b93506040860135612a298161270a565b9250612a37606087016129c0565b949793965091946080013592915050565b60006020808385031215612a5b57600080fd5b823567ffffffffffffffff811115612a7257600080fd5b8301601f81018513612a8357600080fd5b8035612a9161290c826128c7565b81815260059190911b82018301908381019087831115612ab057600080fd5b928401925b82841015612ace57833582529284019290840190612ab5565b979650505050505050565b600081518084526020808501945080840160005b83811015612b0957815187529582019590820190600101612aed565b509495945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604081526000612b566040830185612ad9565b8281036020848101919091528451808352858201928201906000805b82811015612bc45785516004808210612bb1577f4e487b7100000000000000000000000000000000000000000000000000000000845260218152602484fd5b5084529484019492840192600101612b72565b509198975050505050505050565b60008060408385031215612be557600080fd5b8235612bf08161270a565b9150612bfe602084016129c0565b90509250929050565b60008060008060008060c08789031215612c2057600080fd5b863595506020870135612c328161270a565b945060408701359350606087013592506080870135915060a087013560ff81168114612c5d57600080fd5b809150509295509295509295565b60008060408385031215612c7e57600080fd5b8235612c898161270a565b946020939093013593505050565b60008060408385031215612caa57600080fd5b8235612cb58161270a565b91506020830135612cc58161270a565b809150509250929050565b60008060408385031215612ce357600080fd5b823591506020830135612cc58161270a565b60008060208385031215612d0857600080fd5b823567ffffffffffffffff811115612d1f57600080fd5b6112e98582860161272c565b60008060408385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d61858286016128eb565b9250506020830135612cc58161270a565b6020815260006129b96020830184612ad9565b60008060408385031215612d9857600080fd5b823567ffffffffffffffff80821115612db057600080fd5b612dbc868387016128eb565b9350602091508185013581811115612dd357600080fd5b85019050601f81018613612de657600080fd5b8035612df461290c826128c7565b81815260059190911b82018301908381019088831115612e1357600080fd5b928401925b82841015612e3857612e29846129c0565b82529284019290840190612e18565b80955050505050509250929050565b60008060008060608587031215612e5d57600080fd5b8435612e688161270a565b935060208501359250604085013567ffffffffffffffff811115612e8b57600080fd5b612e978782880161272c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612ee557612ee5612ea3565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612f1c57612f1c612ea3565b5060010190565b600082612f59577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612f9657612f96612ea3565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b8181101561301857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fe6565b50909695505050505050565b60008282101561303657613036612ea3565b50039056fea164736f6c6343000809000a", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts/DataTypes.sol b/contracts/DataTypes.sol index 4d7a4bd..656094c 100644 --- a/contracts/DataTypes.sol +++ b/contracts/DataTypes.sol @@ -2,18 +2,6 @@ pragma solidity 0.8.9; library DataTypes { - // struct Deposit { - // /// @dev Remaining tokens available. - // uint256 remaining; - // /// @dev The PIX account for the seller receive transactions. - // string pixTarget; - // address seller; - // /// @dev ERC20 stable token address. - // address token; - // /// @dev Could be invalidated by the seller. - // bool valid; - // } - struct Lock { uint256 sellerKey; uint256 counter; @@ -33,4 +21,12 @@ library DataTypes { address relayerAddress; address token; } + + // prettier-ignore + enum LockStatus { + Inexistent, // 0 := Uninitialized Lock. + Active, // 1 := Valid Lock. + Expired, // 2 := Expired Lock. + Released // 3 := Already released Lock. + } } diff --git a/contracts/lib/utils/Multicall.sol b/contracts/lib/utils/Multicall.sol new file mode 100644 index 0000000..2f98220 --- /dev/null +++ b/contracts/lib/utils/Multicall.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.4; + +/// @title Multicall. +/// @notice Contract that batches view function calls and aggregates their results. +/// @author Adapted from Makerdao's Multicall2 (https://github.com/makerdao/multicall/blob/master/src/Multicall2.sol). + +contract Multicall { + /// @dev 0x + error CallFailed(string reason); + + struct Call { + address target; + bytes callData; + } + struct Result { + bool success; + bytes returnData; + } + + //prettier-ignore + constructor(/* */) payable {/* */} + + function mtc1(Call[] calldata calls) + external + returns (uint256, bytes[] memory) + { + uint256 bn = block.number; + uint256 len = calls.length; + bytes[] memory res = new bytes[](len); + uint256 j; + + while (j < len) { + (bool success, bytes memory ret) = calls[j] + .target + .call(calls[j].callData); + if (!success) { + if (ret.length < 0x44) revert CallFailed(""); + assembly { + ret := add(ret, 0x04) + } + revert CallFailed({ + reason: abi.decode(ret, (string)) + }); + } + res[j] = ret; + ++j; + } + return (bn, res); + } + + function mtc2(Call[] calldata calls) + external + returns ( + uint256, + bytes32, + Result[] memory + ) + { + uint256 bn = block.number; + // µ 0 s [0] ≡ P(IHp , µs [0], 0) ∴ P is the hash of a block of a particular number, up to a maximum age. + // 0 is left on the stack if the looked for `block.number` is >= to the current `block.number` or more than 256 + // blocks behind the current block (Yellow Paper, p. 33, https://ethereum.github.io/yellowpaper/paper.pdf). + bytes32 bh = blockhash( + bn /* - 1 */ + ); + uint256 len = calls.length; + Result[] memory res = new Result[](len); + uint256 i; + for (i; i < len; ) { + (bool success, bytes memory ret) = calls[i] + .target + .call(calls[i].callData); + + res[i] = Result(success, ret); + ++i; + } + return (bn, bh, res); + } +} diff --git a/contracts/lib/utils/SafeTransferLib.sol b/contracts/lib/utils/SafeTransferLib.sol index a1f3f5d..7cc0d68 100644 --- a/contracts/lib/utils/SafeTransferLib.sol +++ b/contracts/lib/utils/SafeTransferLib.sol @@ -114,46 +114,4 @@ library SafeTransferLib { require(success, "TRANSFER_FAILED"); } - - function safeApprove( - ERC20 token, - address to, - uint256 amount - ) internal { - bool success; - - assembly { - // We'll write our calldata to this slot below, but restore it later. - let memPointer := mload(0x40) - - // Write the abi-encoded calldata into memory, beginning with the function selector. - mstore( - 0, - 0x095ea7b300000000000000000000000000000000000000000000000000000000 - ) - mstore(4, to) // Append the "to" argument. - mstore(36, amount) // Append the "amount" argument. - - success := and( - // Set success to whether the call reverted, if not we check it either - // returned exactly 1 (can't just be non-zero data), or had no return data. - or( - and( - eq(mload(0), 1), - gt(returndatasize(), 31) - ), - iszero(returndatasize()) - ), - // We use 68 because that's the total length of our calldata (4 + 32 * 2) - // Counterintuitively, this call() must be positioned after the or() in the - // surrounding and() because and() evaluates its arguments from right to left. - call(gas(), token, 0, 0, 68, 0, 32) - ) - - mstore(0x60, 0) // Restore the zero slot to zero. - mstore(0x40, memPointer) // Restore the memPointer. - } - - require(success, "APPROVE_FAILED"); - } } diff --git a/contracts/p2pix.sol b/contracts/p2pix.sol index 990909d..a74d21b 100644 --- a/contracts/p2pix.sol +++ b/contracts/p2pix.sol @@ -26,6 +26,7 @@ contract P2PIX is // solhint-disable no-empty-blocks using DT for DT.Lock; + using DT for DT.LockStatus; /// ███ Constants ██████████████████████████████████████████████████████████ @@ -105,15 +106,11 @@ contract P2PIX is ERC20 t = ERC20(_token); uint256 k = _castAddrToKey(msg.sender); - if (_pixTarget == 0) - revert EmptyPixTarget(); - if (!allowedERC20s[t]) - revert TokenDenied(); - uint256 _sellerBalance = - sellerBalance[k][t]; + if (_pixTarget == 0) revert EmptyPixTarget(); + if (!allowedERC20s[t]) revert TokenDenied(); + uint256 _sellerBalance = sellerBalance[k][t]; - uint256 currBal = - _sellerBalance & BITMASK_SB_ENTRY; + uint256 currBal = _sellerBalance & BITMASK_SB_ENTRY; if ((currBal + _amount) > 1e8 ether) revert MaxBalExceeded(); @@ -130,12 +127,8 @@ contract P2PIX is amountCasted, pixTargetCasted, validCasted - ) = _castToUint( - _amount, - _pixTarget, - _valid - ); - + ) = _castToUint(_amount, _pixTarget, _valid); + sellerBalance[k][t] = (currBal + amountCasted) | (pixTargetCasted << BITPOS_PIXTARGET) | @@ -150,11 +143,7 @@ contract P2PIX is clearReentrancyGuard(); - emit DepositAdded( - msg.sender, - _token, - _amount - ); + emit DepositAdded(msg.sender, _token, _amount); } /// @notice Enables seller to invalidate future @@ -162,29 +151,23 @@ contract P2PIX is /// @dev This function does not affect any ongoing active locks. /// @dev Function sighash: 0x72fada5c. function setValidState(ERC20 token, bool state) public { - uint256 key = - _castAddrToKey(msg.sender); - uint256 _sellerBalance = - sellerBalance[key][token]; - + uint256 key = _castAddrToKey(msg.sender); + uint256 _sellerBalance = sellerBalance[key][token]; + if (_sellerBalance != 0) { uint256 _valid; - assembly { _valid := state } - + assembly { + _valid := state + } + _sellerBalance = (_sellerBalance & BITMASK_VALID) | (_valid << BITPOS_VALID); - - sellerBalance[key][token] = - _sellerBalance; - emit ValidSet( - msg.sender, - address(token), - state - ); - } else - revert NotInitialized(); + sellerBalance[key][token] = _sellerBalance; + + emit ValidSet(msg.sender, address(token), state); + } else revert NotInitialized(); } /// @notice Public method designed to lock an remaining amount of @@ -219,33 +202,26 @@ contract P2PIX is unlockExpired(expiredLocks); ERC20 t = ERC20(_token); - if (!getValid(_seller, t)) - revert InvalidDeposit(); + if (!getValid(_seller, t)) revert InvalidDeposit(); - uint256 bal = - getBalance(_seller, t); - if (bal < _amount) - revert NotEnoughTokens(); + uint256 bal = getBalance(_seller, t); + if (bal < _amount) revert NotEnoughTokens(); - uint256 k = - _castAddrToKey(_seller); + uint256 k = _castAddrToKey(_seller); - uint256 cCounter = - lockCounter + 1; + uint256 cCounter = lockCounter + 1; - if (mapLocks[cCounter].expirationBlock - >= block.number) - revert NotExpired(); + if ( + mapLocks[cCounter].expirationBlock >= block.number + ) revert NotExpired(); DT.Lock memory l = DT.Lock( k, cCounter, _relayerPremium, _amount, - (block.number + - defaultLockBlocks), - uint160(sellerBalance[k][t] - >> BITPOS_PIXTARGET), + (block.number + defaultLockBlocks), + uint160(sellerBalance[k][t] >> BITPOS_PIXTARGET), _buyerAddress, _relayerTarget, msg.sender, @@ -259,58 +235,34 @@ contract P2PIX is msg.sender ); - _addLock( - bal, - _amount, - cCounter, - l, - t, - k - ); + _addLock(bal, _amount, cCounter, l, t, k); lockCounter++; // Halt execution and output `lockID`. return cCounter; - } else { if (l.amount <= 1e2 ether) { - _addLock( - bal, - _amount, - cCounter, - l, - t, - k - ); + _addLock(bal, _amount, cCounter, l, t, k); lockCounter++; // Halt execution and output `lockID`. return cCounter; - } else { uint256 userCredit = userRecord[ _castAddrToKey(msg.sender) ]; uint256 spendLimit; - (spendLimit) = - _limiter(userCredit / WAD); + (spendLimit) = _limiter(userCredit / WAD); if ( l.amount > (spendLimit * WAD) || l.amount > 1e6 ether ) revert AmountNotAllowed(); - _addLock( - bal, - _amount, - cCounter, - l, - t, - k - ); + _addLock(bal, _amount, cCounter, l, t, k); lockCounter++; @@ -374,25 +326,22 @@ contract P2PIX is ERC20 t = ERC20(l.token); // We cache values before zeroing them out. - uint256 lockAmount = - l.amount; - uint256 totalAmount = - (lockAmount - l.relayerPremium); + uint256 lockAmount = l.amount; + uint256 totalAmount = (lockAmount - l.relayerPremium); l.amount = 0; l.expirationBlock = 0; usedTransactions[message] = true; if (msg.sender != l.relayerAddress) { - userRecord[ - _castAddrToKey(msg.sender) - ] += l.relayerPremium; + userRecord[_castAddrToKey(msg.sender)] += l + .relayerPremium; userRecord[ _castAddrToKey(l.relayerAddress) ] += lockAmount; } else { - userRecord[_castAddrToKey(msg.sender)] - += (l.relayerPremium + lockAmount); + userRecord[_castAddrToKey(msg.sender)] += (l + .relayerPremium + lockAmount); } SafeTransferLib.safeTransfer( @@ -423,11 +372,7 @@ contract P2PIX is } } - emit LockReleased( - l.buyerAddress, - lockID, - lockAmount - ); + emit LockReleased(l.buyerAddress, lockID, lockAmount); } /// @notice Unlocks expired locks. @@ -443,42 +388,34 @@ contract P2PIX is uint256 locksSize = lockIDs.length; for (i; i < locksSize; ) { - DT.Lock storage l = - mapLocks[lockIDs[i]]; + DT.Lock storage l = mapLocks[lockIDs[i]]; _notExpired(l); - uint256 _sellerBalance = - sellerBalance[ - l.sellerKey][ERC20(l.token) - ] & BITMASK_SB_ENTRY; - - if ( - (_sellerBalance + l.amount) - > 1e8 ether - ) + uint256 _sellerBalance = sellerBalance[ + l.sellerKey + ][ERC20(l.token)] & BITMASK_SB_ENTRY; + + if ((_sellerBalance + l.amount) > 1e8 ether) revert MaxBalExceeded(); - sellerBalance[ - l.sellerKey][ERC20(l.token) - ] += l.amount; + sellerBalance[l.sellerKey][ERC20(l.token)] += l + .amount; l.amount = 0; - uint256 userKey = - _castAddrToKey(l.relayerAddress); - uint256 _newUserRecord = - (userRecord[userKey] >> 1); + uint256 userKey = _castAddrToKey( + l.relayerAddress + ); + uint256 _newUserRecord = (userRecord[userKey] >> + 1); if (_newUserRecord <= 1e2 ether) { userRecord[userKey] = 1e2 ether; } else { userRecord[userKey] = _newUserRecord; } - emit LockReturned( - l.buyerAddress, - lockIDs[i] - ); + emit LockReturned(l.buyerAddress, lockIDs[i]); unchecked { ++i; @@ -502,23 +439,16 @@ contract P2PIX is ERC20 token, uint256 amount, uint256[] calldata expiredLocks - ) - public - nonReentrant - { + ) public nonReentrant { unlockExpired(expiredLocks); - if (getValid(msg.sender, token) - == true - ) { + if (getValid(msg.sender, token) == true) { setValidState(token, false); } - uint256 key = - _castAddrToKey(msg.sender); + uint256 key = _castAddrToKey(msg.sender); _decBal( - (sellerBalance[key][token] - & BITMASK_SB_ENTRY), + (sellerBalance[key][token] & BITMASK_SB_ENTRY), amount, token, key @@ -784,17 +714,23 @@ contract P2PIX is // sellerBalance[_castAddrToKey(seller)][token] & // BITMASK_SB_ENTRY; assembly { - for {/* */} iszero(0x0) {/* */} { - mstore(0x00, shl(0xC,seller)) - mstore(0x20, sellerBalance.slot) - let sbkslot := keccak256(0x00, 0x40) - mstore(0x00, token) - mstore(0x20, sbkslot) - bal := and( - BITMASK_SB_ENTRY, - sload(keccak256(0x00,0x40) - )) break - }} + for { + /* */ + } iszero(0x0) { + /* */ + } { + mstore(0x00, shl(0xC, seller)) + mstore(0x20, sellerBalance.slot) + let sbkslot := keccak256(0x00, 0x40) + mstore(0x00, token) + mstore(0x20, sbkslot) + bal := and( + BITMASK_SB_ENTRY, + sload(keccak256(0x00, 0x40)) + ) + break + } + } } function getValid(address seller, ERC20 token) @@ -807,19 +743,26 @@ contract P2PIX is // ][token]; // ] >> BITPOS_VALID) & BITMASK_SB_ENTRY; assembly { - for {/* */} iszero(0x0) {/* */} { - mstore(0x00, shl(0xC,seller)) - mstore(0x20, sellerBalance.slot) - let sbkslot := keccak256(0x00, 0x40) - mstore(0x00, token) - mstore(0x20, sbkslot) - valid := and( - BITMASK_SB_ENTRY, - shr( - BITPOS_VALID, - sload(keccak256(0x00,0x40) - ))) break - }} + for { + /* */ + } iszero(0x0) { + /* */ + } { + mstore(0x00, shl(0xC, seller)) + mstore(0x20, sellerBalance.slot) + let sbkslot := keccak256(0x00, 0x40) + mstore(0x00, token) + mstore(0x20, sbkslot) + valid := and( + BITMASK_SB_ENTRY, + shr( + BITPOS_VALID, + sload(keccak256(0x00, 0x40)) + ) + ) + break + } + } } function getPixTarget(address seller, ERC20 token) @@ -832,40 +775,38 @@ contract P2PIX is // BITPOS_PIXTARGET // ); assembly { - for {/* */} iszero(0) {/* */} { - mstore(0,shl(12,seller)) - mstore(32,sellerBalance.slot) - let sbkslot := keccak256(0,64) - mstore(0,token) - mstore(32,sbkslot) - pixTarget := shr( - BITPOS_PIXTARGET, - sload(keccak256(0,64) - )) break - }} + for { + /* */ + } iszero(0) { + /* */ + } { + mstore(0, shl(12, seller)) + mstore(32, sellerBalance.slot) + let sbkslot := keccak256(0, 64) + mstore(0, token) + mstore(32, sbkslot) + pixTarget := shr( + BITPOS_PIXTARGET, + sload(keccak256(0, 64)) + ) + break + } + } } function getBalances( - address[] memory sellers, + address[] memory sellers, ERC20 token - ) - external - view - returns(uint256[] memory) - { + ) external view returns (uint256[] memory) { uint256 j; - uint256 len = - sellers.length; - uint256[] memory balances = - new uint256[](len); + uint256 len = sellers.length; + uint256[] memory balances = new uint256[](len); while (j < len) { - uint256 bal = - getBalance( - sellers[j], - token - ); + uint256 bal = getBalance(sellers[j], token); balances[j] = bal; - unchecked { ++j; } + unchecked { + ++j; + } } return balances; @@ -875,42 +816,51 @@ contract P2PIX is /// @dev Call will not revert if provided with an empty array as parameter. /// @dev Function sighash: 0x49ef8448 function getLocksStatus(uint256[] memory ids) - external - view - returns( - uint256[] memory, - bool[] memory - ) { - if (ids.length == 0) { - uint256[] memory null1 = - new uint256[](0); - bool[] memory null2 = - new bool[](0); - return(null1, null2); } - - uint256 c; - uint256 len = - ids.length; - - bool[] memory status = - new bool[](len); - uint256[] memory sortedIDs = - new uint256[](len); - for(c; c < len;) { - if( - mapLocks[ids[c]].expirationBlock - < block.number || - mapLocks[ids[c]].amount == 0x0) { - sortedIDs[c] = ids[c]; - status[c] = false; ++c; - } else { - sortedIDs[c] = ids[c]; - status[c] = true; ++c; - } - } - return(sortedIDs, status); + external + view + returns (uint256[] memory, DT.LockStatus[] memory) + { + if (ids.length == 0) { + uint256[] memory null1 = new uint256[](0); + DT.LockStatus[] + memory null2 = new DT.LockStatus[](0); + return (null1, null2); } + uint256 c; + uint256 len = ids.length; + + uint256[] memory sortedIDs = new uint256[](len); + DT.LockStatus[] memory status = new DT.LockStatus[]( + len + ); + unchecked { + for (c; c < len; ) { + if (mapLocks[ids[c]].sellerKey == 0x0) { + sortedIDs[c] = ids[c]; + status[c] = type(DT.LockStatus).min; + ++c; + } else if (mapLocks[ids[c]].amount == 0x0) { + sortedIDs[c] = ids[c]; + status[c] = type(DT.LockStatus).max; + ++c; + } else if ( + mapLocks[ids[c]].expirationBlock < + block.number + ) { + sortedIDs[c] = ids[c]; + status[c] = DT.LockStatus.Expired; + ++c; + } else { + sortedIDs[c] = ids[c]; + status[c] = DT.LockStatus.Active; + ++c; + } + } + } + return (sortedIDs, status); + } + /// @notice Public method that handles `address` /// to `uint256` safe type casting. /// @dev Function sighash: 0x4b2ae980. @@ -921,7 +871,7 @@ contract P2PIX is { // _key = uint256(uint160(address(_addr))) << 12; assembly { - _key := shl(12,_addr) + _key := shl(12, _addr) } } @@ -932,7 +882,7 @@ contract P2PIX is { // _addr = address(uint160(uint256(_key >> 12))); assembly { - _addr := shr(12,_key) + _addr := shr(12, _key) } } } diff --git a/deploys/goerli.json b/deploys/goerli.json index 3857f9e..2d422d7 100644 --- a/deploys/goerli.json +++ b/deploys/goerli.json @@ -5,4 +5,4 @@ ], "p2pix": "0xefa5cE4351cda51192509cf8De7d8881ADAE95DD", "token": "0x4A2886EAEc931e04297ed336Cc55c4eb7C75BA00" -} \ No newline at end of file +} diff --git a/deploys/localhost.json b/deploys/localhost.json index 9cd9d57..0b0aeb9 100644 --- a/deploys/localhost.json +++ b/deploys/localhost.json @@ -5,4 +5,4 @@ ], "p2pix": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29", "token": "0xD38D6367f452D097ccBfDe4490b7de570B6A72Db" -} \ No newline at end of file +} diff --git a/deploys/polygon-mumbai.json b/deploys/polygon-mumbai.json index 6ea7d2a..b736331 100644 --- a/deploys/polygon-mumbai.json +++ b/deploys/polygon-mumbai.json @@ -5,4 +5,4 @@ ], "p2pix": "0xA9258eBb157E4cf5e756b77FDD0DF09C2F73240b", "token": "0xC86042E9F2977C62Da8c9dDF7F9c40fde4796A29" -} \ No newline at end of file +} diff --git a/hardhat.config.ts b/hardhat.config.ts index 0c2b4b0..74a1499 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -34,7 +34,7 @@ const chainIds = { hardhat: 31337, mainnet: 1, sepolia: 11155111, - goerli : 5, + goerli: 5, "polygon-mumbai": 80001, }; @@ -44,8 +44,10 @@ function getChainConfig( let jsonRpcUrl: string; switch (chain) { case "polygon-mumbai": - jsonRpcUrl = "https://polygon-mumbai.g.alchemy.com/v2/" + alchemyApiKey; - break; + jsonRpcUrl = + "https://polygon-mumbai.g.alchemy.com/v2/" + + alchemyApiKey; + break; default: jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; @@ -138,4 +140,4 @@ const config: HardhatUserConfig = { }, }; -export default config; \ No newline at end of file +export default config; diff --git a/package.json b/package.json index 8c68673..016ce89 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "fs-extra": "^10.1.0", "hardhat": "^2.12.2", "hardhat-gas-reporter": "^1.0.9", - "hardhat-tracer": "^1.2.0", + "hardhat-tracer": "beta", "husky": "^8.0.1", "keccak256": "^1.0.6", "lint-staged": "^13.0.3", diff --git a/scripts/1-deploy-mockToken.ts b/scripts/1-deploy-mockToken.ts index 7ddfb6d..d2077f2 100644 --- a/scripts/1-deploy-mockToken.ts +++ b/scripts/1-deploy-mockToken.ts @@ -3,11 +3,10 @@ import "@nomiclabs/hardhat-etherscan"; import { BigNumber } from "ethers"; import * as fs from "fs"; import { ethers, network } from "hardhat"; +import hre from "hardhat"; import { Deploys } from "../test/utils/fixtures"; -import hre from "hardhat"; - let deploysJson: Deploys; const supply: BigNumber = ethers.utils.parseEther("20000000"); @@ -54,4 +53,4 @@ main() .catch(error => { console.log(error); process.exit(1); - }); \ No newline at end of file + }); diff --git a/scripts/2-deploy-p2pix.ts b/scripts/2-deploy-p2pix.ts index 0a070f9..dd4def2 100644 --- a/scripts/2-deploy-p2pix.ts +++ b/scripts/2-deploy-p2pix.ts @@ -2,11 +2,10 @@ import "@nomiclabs/hardhat-ethers"; import "@nomiclabs/hardhat-etherscan"; import * as fs from "fs"; import { ethers, network } from "hardhat"; +import hre from "hardhat"; import { Deploys } from "../test/utils/fixtures"; -import hre from "hardhat"; - let deploysJson: Deploys; const main = async () => { @@ -53,10 +52,9 @@ const main = async () => { //verify await hre.run("verify:verify", { address: p2pix.address, - constructorArguments: - [ - 10, - deploysJson.signers, + constructorArguments: [ + 10, + deploysJson.signers, reputation.address, [deploysJson.token], [true], @@ -73,4 +71,4 @@ main() .catch(error => { console.log(error); process.exit(1); - }); \ No newline at end of file + }); diff --git a/src/types/factories/lib/utils/Multicall__factory.ts b/src/types/factories/lib/utils/Multicall__factory.ts new file mode 100644 index 0000000..eb6e5cd --- /dev/null +++ b/src/types/factories/lib/utils/Multicall__factory.ts @@ -0,0 +1,174 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { + Signer, + utils, + Contract, + ContractFactory, + PayableOverrides, +} from "ethers"; +import type { Provider, TransactionRequest } from "@ethersproject/providers"; +import type { PromiseOrValue } from "../../../common"; +import type { + Multicall, + MulticallInterface, +} from "../../../lib/utils/Multicall"; + +const _abi = [ + { + inputs: [], + stateMutability: "payable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "CallFailed", + type: "error", + }, + { + inputs: [ + { + components: [ + { + internalType: "address", + name: "target", + type: "address", + }, + { + internalType: "bytes", + name: "callData", + type: "bytes", + }, + ], + internalType: "struct Multicall.Call[]", + name: "calls", + type: "tuple[]", + }, + ], + name: "mtc1", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + { + internalType: "bytes[]", + name: "", + type: "bytes[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "address", + name: "target", + type: "address", + }, + { + internalType: "bytes", + name: "callData", + type: "bytes", + }, + ], + internalType: "struct Multicall.Call[]", + name: "calls", + type: "tuple[]", + }, + ], + name: "mtc2", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + { + components: [ + { + internalType: "bool", + name: "success", + type: "bool", + }, + { + internalType: "bytes", + name: "returnData", + type: "bytes", + }, + ], + internalType: "struct Multicall.Result[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +]; + +const _bytecode = + "0x60806040526108ec806100136000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631b57b72f1461003b57806386575ee914610066575b600080fd5b61004e610049366004610438565b610087565b60405161005d93929190610527565b60405180910390f35b610079610074366004610438565b610227565b60405161005d9291906105cb565b600080606043804085848167ffffffffffffffff8111156100aa576100aa610653565b6040519080825280602002602001820160405280156100f057816020015b6040805180820190915260008152606060208201528152602001906001900390816100c85790505b50905060005b82811015610217576000808b8b8481811061011357610113610682565b905060200281019061012591906106b1565b6101339060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168c8c8581811061015b5761015b610682565b905060200281019061016d91906106b1565b61017b90602081019061072c565b604051610189929190610791565b6000604051808303816000865af19150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b509150915060405180604001604052808315158152602001828152508484815181106101f9576101f9610682565b60200260200101819052508261020e906107a1565b925050506100f6565b5092989197509195509350505050565b600060604383838167ffffffffffffffff81111561024757610247610653565b60405190808252806020026020018201604052801561027a57816020015b60608152602001906001900390816102655790505b50905060005b828110156104285760008089898481811061029d5761029d610682565b90506020028101906102af91906106b1565b6102bd9060208101906106ef565b73ffffffffffffffffffffffffffffffffffffffff168a8a858181106102e5576102e5610682565b90506020028101906102f791906106b1565b61030590602081019061072c565b604051610313929190610791565b6000604051808303816000865af19150503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b5091509150816103f7576044815110156103aa576040517fb5e1dc2d00000000000000000000000000000000000000000000000000000000815260206004820152600060248201526044015b60405180910390fd5b600481019050808060200190518101906103c49190610801565b6040517fb5e1dc2d0000000000000000000000000000000000000000000000000000000081526004016103a191906108cc565b8084848151811061040a5761040a610682565b60200260200101819052508261041f906107a1565b92505050610280565b50919350909150505b9250929050565b6000806020838503121561044b57600080fd5b823567ffffffffffffffff8082111561046357600080fd5b818501915085601f83011261047757600080fd5b81358181111561048657600080fd5b8660208260051b850101111561049b57600080fd5b60209290920196919550909350505050565b60005b838110156104c85781810151838201526020016104b0565b838111156104d7576000848401525b50505050565b600081518084526104f58160208601602086016104ad565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060820185835260208581850152604060608186015282865180855260808701915060808160051b880101945083880160005b828110156105bb578887037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8001845281518051151588528601518688018690526105a8868901826104dd565b975050928501929085019060010161055c565b50949a9950505050505050505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610645577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526106338683516104dd565b955092840192908401906001016105f9565b509398975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126106e557600080fd5b9190910192915050565b60006020828403121561070157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461072557600080fd5b9392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261076157600080fd5b83018035915067ffffffffffffffff82111561077c57600080fd5b60200191503681900382131561043157600080fd5b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156107fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561081357600080fd5b815167ffffffffffffffff8082111561082b57600080fd5b818401915084601f83011261083f57600080fd5b81518181111561085157610851610653565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561089757610897610653565b816040528281528760208487010111156108b057600080fd5b6108c18360208301602088016104ad565b979650505050505050565b60208152600061072560208301846104dd56fea164736f6c6343000809000a"; + +type MulticallConstructorParams = + | [signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: MulticallConstructorParams +): xs is ConstructorParameters => xs.length > 1; + +export class Multicall__factory extends ContractFactory { + constructor(...args: MulticallConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + } + + override deploy( + overrides?: PayableOverrides & { from?: PromiseOrValue } + ): Promise { + return super.deploy(overrides || {}) as Promise; + } + override getDeployTransaction( + overrides?: PayableOverrides & { from?: PromiseOrValue } + ): TransactionRequest { + return super.getDeployTransaction(overrides || {}); + } + override attach(address: string): Multicall { + return super.attach(address) as Multicall; + } + override connect(signer: Signer): Multicall__factory { + return super.connect(signer) as Multicall__factory; + } + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): MulticallInterface { + return new utils.Interface(_abi) as MulticallInterface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider + ): Multicall { + return new Contract(address, _abi, signerOrProvider) as Multicall; + } +} diff --git a/src/types/factories/lib/utils/index.ts b/src/types/factories/lib/utils/index.ts index 6d82c4c..5fcb977 100644 --- a/src/types/factories/lib/utils/index.ts +++ b/src/types/factories/lib/utils/index.ts @@ -1,4 +1,5 @@ /* Autogenerated file. Do not edit manually. */ /* tslint:disable */ /* eslint-disable */ +export { Multicall__factory } from "./Multicall__factory"; export { ReentrancyGuard__factory } from "./ReentrancyGuard__factory"; diff --git a/src/types/factories/p2pix.sol/P2PIX__factory.ts b/src/types/factories/p2pix.sol/P2PIX__factory.ts index a110a22..1e58e12 100644 --- a/src/types/factories/p2pix.sol/P2PIX__factory.ts +++ b/src/types/factories/p2pix.sol/P2PIX__factory.ts @@ -595,9 +595,9 @@ const _abi = [ type: "uint256[]", }, { - internalType: "bool[]", + internalType: "enum DataTypes.LockStatus[]", name: "", - type: "bool[]", + type: "uint8[]", }, ], stateMutability: "view", @@ -1102,7 +1102,7 @@ const _abi = [ ]; const _bytecode = - "0x6080604052600180556040516200352c3803806200352c8339810160408190526200002a9162000493565b600080546001600160a01b031916339081178255604051909182917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3506200007685620000a3565b620000818362000133565b6200008c84620001bd565b620000988282620002a1565b505050505062000616565b6000546001600160a01b03163314620000f25760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b8511816040516200012891815260200190565b60405180910390a150565b6000546001600160a01b031633146200017e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b60028190556040516001600160a01b03821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f9060200162000128565b6000546001600160a01b03163314620002085760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b80516000905b808210156200026e57600062000246848481518110620002325762000232620005b1565b60200260200101516200038760201b60201c565b6000908152600860205260409020805460ff191660019081179091559290920191506200020e565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051620001289190620005c7565b6000546001600160a01b03163314620002ec5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b815180620003025763df9578836000526004601cfd5b81518114620003195763ff633a386000526004601cfd5b60208301602083018260051b82015b8083146200037f578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a360208301925060208201915062000328565b505050505050565b600c1b90565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620003ce57620003ce6200038d565b604052919050565b60006001600160401b03821115620003f257620003f26200038d565b5060051b60200190565b6001600160a01b03811681146200041257600080fd5b50565b600082601f8301126200042757600080fd5b81516020620004406200043a83620003d6565b620003a3565b82815260059290921b840181019181810190868411156200046057600080fd5b8286015b84811015620004885780516200047a81620003fc565b835291830191830162000464565b509695505050505050565b600080600080600060a08688031215620004ac57600080fd5b8551602080880151919650906001600160401b0380821115620004ce57600080fd5b620004dc8a838b0162000415565b965060408901519150620004f082620003fc565b6060890151919550808211156200050657600080fd5b620005148a838b0162000415565b945060808901519150808211156200052b57600080fd5b508701601f810189136200053e57600080fd5b80516200054f6200043a82620003d6565b81815260059190911b8201830190838101908b8311156200056f57600080fd5b928401925b828410156200059f57835180151581146200058f5760008081fd5b8252928401929084019062000574565b80955050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b818110156200060a5783516001600160a01b031683529284019291840191600101620005e3565b50909695505050505050565b612f0680620006266000396000f3fe6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e366004612608565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e36600461268f565b6107f7565b34801561025f57600080fd5b5061027361026e366004612876565b610ba6565b005b34801561028157600080fd5b506102736102903660046128b3565b610ce0565b3480156102a157600080fd5b506102736102b03660046128ec565b610dd1565b3480156102c157600080fd5b506103426102d0366004612608565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c9366004612608565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e61040936600461295f565b611012565b60405161022a929190612a2b565b34801561042857600080fd5b506102206104373660046128b3565b600c1b90565b34801561044957600080fd5b50610273610458366004612608565b61120c565b34801561046957600080fd5b506102736112c2565b34801561047e57600080fd5b506103de61048d3660046128b3565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612a84565b611384565b3480156104ea57600080fd5b506102736104f9366004612ab9565b61149b565b34801561050a57600080fd5b50610220610519366004612608565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612b1d565b61197a565b34801561055757600080fd5b506103de610566366004612b49565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a6366004612608565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de610645366004612608565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612b82565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612b49565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612ba7565b611a40565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612be9565b611c83565b60405161022a9190612c30565b34801561075857600080fd5b50610220610767366004612b49565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612c43565b611d5d565b3480156107c357600080fd5b506102736107d23660046128b3565b611e6d565b3480156107e357600080fd5b506102736107f2366004612d05565b611f39565b6000610801612035565b61080b8383611a40565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612d90565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612d90565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612079565b610a87848c848489886120d1565b60048054906000610a9783612da8565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886120d1565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612de1565b61222c565b9050610b0d670de0b6b3a764000082612e1c565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6120d1565b60048054906000610b8083612da8565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612e59565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612e88565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612d90565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f25612035565b8415610f3557610f35338661197a565b87878760ff81901b605f83901b610f4c8587612d90565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166122e8565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612760565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612760565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112015743600560008987815181106110ef576110ef612e59565b6020026020010151815260200190815260200160002060040154108061114457506005600088868151811061112657611126612e59565b60200260200101518152602001908152602001600020600301546000145b156111b55786848151811061115b5761115b612e59565b602002602001015181858151811061117557611175612e59565b602002602001018181525050600082858151811061119557611195612e59565b911515602092830291909101909101526111ae84612da8565b93506110d0565b8684815181106111c7576111c7612e59565b60200260200101518185815181106111e1576111e1612e59565b602002602001018181525050600182858151811061119557611195612e59565b969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461128d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff163314611343576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b4761134e33826123b2565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091529020548015611463576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a250611495565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6114a3612035565b600086815260056020526040902060038101546114ec576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b438160040154101561152a576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016115cd91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff16151560011415611652576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526116ba9060019060a0016020604051602081039080840390855afa1580156116aa573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff16611705576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff9092169160009061173a9083612ee2565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461182657600287015433600c1b600090815260076020526040812080549091906117cc908490612d90565b9091555050600887015482906007906000906117fe9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b8152602001908152602001600020600082825461181b9190612d90565b9091555061185e9050565b8187600201546118369190612d90565b33600c1b60009081526007602052604081208054909190611858908490612d90565b90915550505b600687015461188590849073ffffffffffffffffffffffffffffffffffffffff168361242c565b60028701541561190b57600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146118fc57600787015460028801546118e491859173ffffffffffffffffffffffffffffffffffffffff9091169060011c61242c565b6118f7838d60018a60020154901c61242c565b61190b565b61190b838d896002015461242c565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a25050505050505061197260018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611a0e5780600660006119a785600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611c6d57600060056000868686818110611a6457611a64612e59565b9050602002013581526020019081526020016000209050611a84816124eb565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611ae79083612d90565b1115611b1f576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611b69908490612d90565b90915550506000600383018190556008830154611b9c9073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611be057600082815260076020526040902068056bc75e2d631000009055611bf2565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611c4057611c40612e59565b90506020020135604051611c5691815260200190565b60405180910390a285600101955050505050611a44565b808210156114955763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611ca557611ca5612760565b604051908082528060200260200182016040528015611cce578160200160208202803683370190505b5090505b81831015611d54576000611d27878581518110611cf157611cf1612e59565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611d3c57611d3c612e59565b60200260200101818152505083600101935050611cd2565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611df35763df9578836000526004601cfd5b81518114611e095763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611972578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611e18565b60005473ffffffffffffffffffffffffffffffffffffffff163314611eee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b611f41612035565b611f4b8282611a40565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c151560011415611f8157611f81846000611384565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902054611fcf906b3fffffffffffffffffffffff16858784612567565b611fda85338661242c565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061149560018055565b60015460021415612072576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61209b84848473ffffffffffffffffffffffffffffffffffffffff85166125c4565b611495576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556121c086868484612567565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261221c92918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161224a91815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826122df5763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d11600160005114161716915060006060528060405250806123ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612427576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611495576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612529576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003810154612564576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8361257a5763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906125b9908490612ee2565b909155505050505050565b60008315612600578360051b8501855b803580851160051b948552602094851852604060002093018181106125f8576125fd565b6125d4565b50505b501492915050565b60006020828403121561261a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461256457600080fd5b60008083601f84011261265557600080fd5b50813567ffffffffffffffff81111561266d57600080fd5b6020830191508360208260051b850101111561268857600080fd5b9250929050565b6000806000806000806000806000806101008b8d0312156126af57600080fd5b8a356126ba81612621565b995060208b01356126ca81612621565b985060408b01356126da81612621565b975060608b01356126ea81612621565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff8082111561271557600080fd5b6127218e838f01612643565b909650945060e08d013591508082111561273a57600080fd5b506127478d828e01612643565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127d6576127d6612760565b604052919050565b600067ffffffffffffffff8211156127f8576127f8612760565b5060051b60200190565b600082601f83011261281357600080fd5b81356020612828612823836127de565b61278f565b82815260059290921b8401810191818101908684111561284757600080fd5b8286015b8481101561286b57803561285e81612621565b835291830191830161284b565b509695505050505050565b60006020828403121561288857600080fd5b813567ffffffffffffffff81111561289f57600080fd5b6128ab84828501612802565b949350505050565b6000602082840312156128c557600080fd5b81356128d081612621565b9392505050565b803580151581146128e757600080fd5b919050565b600080600080600060a0868803121561290457600080fd5b853561290f81612621565b945060208601356bffffffffffffffffffffffff8116811461293057600080fd5b9350604086013561294081612621565b925061294e606087016128d7565b949793965091946080013592915050565b6000602080838503121561297257600080fd5b823567ffffffffffffffff81111561298957600080fd5b8301601f8101851361299a57600080fd5b80356129a8612823826127de565b81815260059190911b820183019083810190878311156129c757600080fd5b928401925b828410156129e5578335825292840192908401906129cc565b979650505050505050565b600081518084526020808501945080840160005b83811015612a2057815187529582019590820190600101612a04565b509495945050505050565b604081526000612a3e60408301856129f0565b82810360208481019190915284518083528582019282019060005b81811015612a77578451151583529383019391830191600101612a59565b5090979650505050505050565b60008060408385031215612a9757600080fd5b8235612aa281612621565b9150612ab0602084016128d7565b90509250929050565b60008060008060008060c08789031215612ad257600080fd5b863595506020870135612ae481612621565b945060408701359350606087013592506080870135915060a087013560ff81168114612b0f57600080fd5b809150509295509295509295565b60008060408385031215612b3057600080fd5b8235612b3b81612621565b946020939093013593505050565b60008060408385031215612b5c57600080fd5b8235612b6781612621565b91506020830135612b7781612621565b809150509250929050565b60008060408385031215612b9557600080fd5b823591506020830135612b7781612621565b60008060208385031215612bba57600080fd5b823567ffffffffffffffff811115612bd157600080fd5b612bdd85828601612643565b90969095509350505050565b60008060408385031215612bfc57600080fd5b823567ffffffffffffffff811115612c1357600080fd5b612c1f85828601612802565b9250506020830135612b7781612621565b6020815260006128d060208301846129f0565b60008060408385031215612c5657600080fd5b823567ffffffffffffffff80821115612c6e57600080fd5b612c7a86838701612802565b9350602091508185013581811115612c9157600080fd5b85019050601f81018613612ca457600080fd5b8035612cb2612823826127de565b81815260059190911b82018301908381019088831115612cd157600080fd5b928401925b82841015612cf657612ce7846128d7565b82529284019290840190612cd6565b80955050505050509250929050565b60008060008060608587031215612d1b57600080fd5b8435612d2681612621565b935060208501359250604085013567ffffffffffffffff811115612d4957600080fd5b612d5587828801612643565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612da357612da3612d61565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612dda57612dda612d61565b5060010190565b600082612e17577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612e5457612e54612d61565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b81811015612ed657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612ea4565b50909695505050505050565b600082821015612ef457612ef4612d61565b50039056fea164736f6c6343000809000a"; + "0x6080604052600180556040516200366e3803806200366e8339810160408190526200002a9162000493565b600080546001600160a01b031916339081178255604051909182917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3506200007685620000a3565b620000818362000133565b6200008c84620001bd565b620000988282620002a1565b505050505062000616565b6000546001600160a01b03163314620000f25760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b8511816040516200012891815260200190565b60405180910390a150565b6000546001600160a01b031633146200017e5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b60028190556040516001600160a01b03821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f9060200162000128565b6000546001600160a01b03163314620002085760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b80516000905b808210156200026e57600062000246848481518110620002325762000232620005b1565b60200260200101516200038760201b60201c565b6000908152600860205260409020805460ff191660019081179091559290920191506200020e565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051620001289190620005c7565b6000546001600160a01b03163314620002ec5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401620000e9565b815180620003025763df9578836000526004601cfd5b81518114620003195763ff633a386000526004601cfd5b60208301602083018260051b82015b8083146200037f578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a360208301925060208201915062000328565b505050505050565b600c1b90565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715620003ce57620003ce6200038d565b604052919050565b60006001600160401b03821115620003f257620003f26200038d565b5060051b60200190565b6001600160a01b03811681146200041257600080fd5b50565b600082601f8301126200042757600080fd5b81516020620004406200043a83620003d6565b620003a3565b82815260059290921b840181019181810190868411156200046057600080fd5b8286015b84811015620004885780516200047a81620003fc565b835291830191830162000464565b509695505050505050565b600080600080600060a08688031215620004ac57600080fd5b8551602080880151919650906001600160401b0380821115620004ce57600080fd5b620004dc8a838b0162000415565b965060408901519150620004f082620003fc565b6060890151919550808211156200050657600080fd5b620005148a838b0162000415565b945060808901519150808211156200052b57600080fd5b508701601f810189136200053e57600080fd5b80516200054f6200043a82620003d6565b81815260059190911b8201830190838101908b8311156200056f57600080fd5b928401925b828410156200059f57835180151581146200058f5760008081fd5b8252928401929084019062000574565b80955050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b818110156200060a5783516001600160a01b031683529284019291840191600101620005e3565b50909695505050505050565b61304880620006266000396000f3fe6080604052600436106101e75760003560e01c80637f94f65d11610102578063ad8f2eed11610095578063d4fac45d11610064578063d4fac45d1461074c578063d6e8b97314610797578063f7d0e04b146107b7578063fb8c5ef0146107d757600080fd5b8063ad8f2eed14610692578063b0983d39146106d2578063c52164c6146106f2578063d1c070281461071f57600080fd5b80638db564c2116100d15780638db564c2146105fe5780639872dbfe1461061457806398a268711461062a5780639eee8d4b1461065a57600080fd5b80637f94f65d1461052b57806380e1d3021461054b57806384ab1d281461058b5780638da5cb5b146105d157600080fd5b80634b2ae9801161017a5780636a146024116101495780636a146024146104a25780636d82d9e0146104be57806374ba03a0146104de57806377cd38a4146104fe57600080fd5b80634b2ae9801461041c578063574983c81461043d5780635fd8c7101461045d57806369cc6af41461047257600080fd5b8063328a7181116101b6578063328a718114610295578063367821f0146102b5578063461f3120146103ae57806349ef8448146103ee57600080fd5b806304937320146101f35780630a98b9bd146102335780630d2a2d441461025357806313af40351461027557600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b5061022061020e3660046126f1565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561023f57600080fd5b5061022061024e366004612778565b6107f7565b34801561025f57600080fd5b5061027361026e36600461295f565b610ba6565b005b34801561028157600080fd5b5061027361029036600461299c565b610ce0565b3480156102a157600080fd5b506102736102b03660046129d5565b610dd1565b3480156102c157600080fd5b506103426102d03660046126f1565b6005602081905260009182526040909120805460018201546002830154600384015460048501549585015460068601546007870154600888015460099098015496989597949693959473ffffffffffffffffffffffffffffffffffffffff93841694928416939182169290821691168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925273ffffffffffffffffffffffffffffffffffffffff90811660a087015290811660c086015290811660e0850152908116610100840152166101208201526101400161022a565b3480156103ba57600080fd5b506103de6103c93660046126f1565b60096020526000908152604090205460ff1681565b604051901515815260200161022a565b3480156103fa57600080fd5b5061040e610409366004612a48565b611012565b60405161022a929190612b43565b34801561042857600080fd5b5061022061043736600461299c565b600c1b90565b34801561044957600080fd5b506102736104583660046126f1565b6112f5565b34801561046957600080fd5b506102736113ab565b34801561047e57600080fd5b506103de61048d36600461299c565b600a6020526000908152604090205460ff1681565b3480156104ae57600080fd5b50610220670de0b6b3a764000081565b3480156104ca57600080fd5b506102736104d9366004612bd2565b61146d565b3480156104ea57600080fd5b506102736104f9366004612c07565b611584565b34801561050a57600080fd5b506102206105193660046126f1565b60066020526000908152604090205481565b34801561053757600080fd5b50610273610546366004612c6b565b611a63565b34801561055757600080fd5b506103de610566366004612c97565b600c9190911b6000908152600b60209081526040808320938352929052205460ff1c90565b34801561059757600080fd5b506105ac6105a63660046126f1565b600c1c90565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022a565b3480156105dd57600080fd5b506000546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561060a57600080fd5b5061022060045481565b34801561062057600080fd5b5061022060035481565b34801561063657600080fd5b506103de6106453660046126f1565b60086020526000908152604090205460ff1681565b34801561066657600080fd5b50610220610675366004612cd0565b600b60209081526000928352604080842090915290825290205481565b34801561069e57600080fd5b506105ac6106ad366004612c97565b600c9190911b6000908152600b602090815260408083209383529290522054605f1c90565b3480156106de57600080fd5b506102736106ed366004612cf5565b611b29565b3480156106fe57600080fd5b506002546105ac9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561072b57600080fd5b5061073f61073a366004612d2b565b611d6c565b60405161022a9190612d72565b34801561075857600080fd5b50610220610767366004612c97565b600c9190911b6000908152600b6020908152604080832093835292905220546b3fffffffffffffffffffffff1690565b3480156107a357600080fd5b506102736107b2366004612d85565b611e46565b3480156107c357600080fd5b506102736107d236600461299c565b611f56565b3480156107e357600080fd5b506102736107f2366004612e47565b612022565b600061080161211e565b61080b8383611b29565b600c8b901b6000908152600b602090815260408083208d84529091529020548a9060ff1c610865576040517fb2e532de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600c8c901b6000908152600b602090815260408083208484529091529020546b3fffffffffffffffffffffff16878110156108cc576040517f22bbb43c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108d88e600c1b90565b9050600060045460016108eb9190612ed2565b6000818152600560205260409020600401549091504311610938576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052808481526020018381526020018d81526020018c81526020016003544361096c9190612ed2565b8152602001605f600b600087815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054901c73ffffffffffffffffffffffffffffffffffffffff1681526020018f73ffffffffffffffffffffffffffffffffffffffff1681526020018e73ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815250905089899050600014610aa957600083815260066020526040902054610a79908b908b9033612162565b610a87848c848489886121ba565b60048054906000610a9783612eea565b91905055508195505050505050610b8f565b68056bc75e2d63100000816060015111610acb57610a87848c848489886121ba565b33600c1b60009081526007602052604081205490610af9610af4670de0b6b3a764000084612f23565b612315565b9050610b0d670de0b6b3a764000082612f5e565b83606001511180610b2b575069d3c21bcecceda10000008360600151115b15610b62576040517f1c18f84600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b70868e86868b8a6121ba565b60048054906000610b8083612eea565b90915550939750505050505050505b610b9860018055565b9a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b80516000905b80821015610ca4576000610c5f848481518110610c5157610c51612f9b565b6020026020010151600c1b90565b600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155929092019150610c32565b50507f14a422d2412784a5749d03da98921fe468c98577b767851389a9f58ea5a363d781604051610cd59190612fca565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b8433600c1b73ffffffffffffffffffffffffffffffffffffffff8516610e23576040517f6a3bc53e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a602052604090205460ff16610e82576040517f1578328e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546b3fffffffffffffffffffffff81166a52b7d2dcc80cd2e4000000610ee56bffffffffffffffffffffffff8a1683612ed2565b1115610f1d576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f2561211e565b8415610f3557610f353386611a63565b87878760ff81901b605f83901b610f4c8587612ed2565b6000898152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8e16845290915290209117919091179055610f9d8733306bffffffffffffffffffffffff8f166123d1565b610fa660018055565b6040805173ffffffffffffffffffffffffffffffffffffffff8e1681526bffffffffffffffffffffffff8d16602082015233917f63d8d7d5e63e9840ec91a12a160d27b7cfab294f6ba070b7359692acfe6b03bf910160405180910390a2505050505050505050505050565b60608082516000141561103d5750506040805160008082526020820190815281830190925292909150565b8251600090818167ffffffffffffffff81111561105c5761105c612849565b604051908082528060200260200182016040528015611085578160200160208202803683370190505b50905060008267ffffffffffffffff8111156110a3576110a3612849565b6040519080825280602002602001820160405280156110cc578160200160208202803683370190505b5090505b828410156112e957600560008886815181106110ee576110ee612f9b565b6020026020010151815260200190815260200160002060000154600014156111965786848151811061112257611122612f9b565b602002602001015182858151811061113c5761113c612f9b565b602002602001018181525050600081858151811061115c5761115c612f9b565b6020026020010190600381111561117557611175612b14565b9081600381111561118857611188612b14565b9052506001909301926110d0565b600560008886815181106111ac576111ac612f9b565b60200260200101518152602001908152602001600020600301546000141561121a578684815181106111e0576111e0612f9b565b60200260200101518285815181106111fa576111fa612f9b565b602002602001018181525050600381858151811061115c5761115c612f9b565b436005600089878151811061123157611231612f9b565b6020026020010151815260200190815260200160002060040154101561129d5786848151811061126357611263612f9b565b602002602001015182858151811061127d5761127d612f9b565b602002602001018181525050600281858151811061115c5761115c612f9b565b8684815181106112af576112af612f9b565b60200260200101518285815181106112c9576112c9612f9b565b602002602001018181525050600181858151811061115c5761115c612f9b565b90969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b806003557f70fa43ca70216ad905ade86b9e650a691b2ce5a01980d0a81bdd8324141b851181604051610cd591815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff16331461142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b47611437338261249b565b60408051338152602081018390527feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d9101610cd5565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054801561154c576000828152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff8816808552908352928190207f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9490941660ff87901b1793849055805192835285151591830191909152849133917fca585721b6b442dc9183932f7c84dc2880efb67c4da52cc06873e78971105d49910160405180910390a25061157e565b6040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b61158c61211e565b600086815260056020526040902060038101546115d5576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4381600401541015611613576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005810154600382015460405160609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208301526034820152605481018690526000906074016040516020818303038152906040528051906020012090506000816040516020016116b691907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000858152600990935291205490915060ff1615156001141561173b576040517ff490a6ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820180845284905260ff87169282019290925260608101889052608081018790526117a39060019060a0016020604051602081039080840390855afa158015611793573d6000803e3d6000fd5b50505060206040510351600c1b90565b60008181526008602052604090205490915060ff166117ee576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60098401546003850154600286015473ffffffffffffffffffffffffffffffffffffffff909216916000906118239083613024565b6000600389018190556004890181905587815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560088801549091503373ffffffffffffffffffffffffffffffffffffffff9091161461190f57600287015433600c1b600090815260076020526040812080549091906118b5908490612ed2565b9091555050600887015482906007906000906118e79073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b815260200190815260200160002060008282546119049190612ed2565b909155506119479050565b81876002015461191f9190612ed2565b33600c1b60009081526007602052604081208054909190611941908490612ed2565b90915550505b600687015461196e90849073ffffffffffffffffffffffffffffffffffffffff1683612515565b6002870154156119f457600787015473ffffffffffffffffffffffffffffffffffffffff8d81169116146119e557600787015460028801546119cd91859173ffffffffffffffffffffffffffffffffffffffff9091169060011c612515565b6119e0838d60018a60020154901c612515565b6119f4565b6119f4838d8960020154612515565b6006870154604080518f81526020810185905273ffffffffffffffffffffffffffffffffffffffff909216917f364537f14276f2a0ce9905588413f96454cbb8fb2e4f5308389307c1098bede8910160405180910390a250505050505050611a5b60018055565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216331415611af7578060066000611a9085600c1b90565b8152602080820192909252604090810160002092909255815173ffffffffffffffffffffffffffffffffffffffff851681529081018390527f0b294da292f26e55fd442b5c0164fbb9013036ff00c5cfdde0efd01c1baaf632910160405180910390a15050565b6040517f85d1f72600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b80821015611d5657600060056000868686818110611b4d57611b4d612f9b565b9050602002013581526020019081526020016000209050611b6d816125d4565b80546000908152600b60209081526040808320600985015473ffffffffffffffffffffffffffffffffffffffff16845290915290205460038201546b3fffffffffffffffffffffff909116906a52b7d2dcc80cd2e400000090611bd09083612ed2565b1115611c08576040517ff3fb0eb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600382015482546000908152600b60209081526040808320600987015473ffffffffffffffffffffffffffffffffffffffff16845290915281208054909190611c52908490612ed2565b90915550506000600383018190556008830154611c859073ffffffffffffffffffffffffffffffffffffffff16600c1b90565b60008181526007602052604090205490915060011c68056bc75e2d631000008111611cc957600082815260076020526040902068056bc75e2d631000009055611cdb565b60008281526007602052604090208190555b600684015473ffffffffffffffffffffffffffffffffffffffff167f830501e61b8b075e170b22a430e39454bdb12ed3e9620e586430b6ac00079da5898989818110611d2957611d29612f9b565b90506020020135604051611d3f91815260200190565b60405180910390a285600101955050505050611b2d565b8082101561157e5763dfb035c96000526004601cfd5b8151606090600090818167ffffffffffffffff811115611d8e57611d8e612849565b604051908082528060200260200182016040528015611db7578160200160208202803683370190505b5090505b81831015611e3d576000611e10878581518110611dda57611dda612f9b565b602090810291909101810151600c1b6000908152600b825260408082208a835290925220546b3fffffffffffffffffffffff1690565b905080828581518110611e2557611e25612f9b565b60200260200101818152505083600101935050611dbb565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ec7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b815180611edc5763df9578836000526004601cfd5b81518114611ef25763ff633a386000526004601cfd5b60208301602083018260051b82015b808314611a5b578251600052600a60205260406000208251815550815183517f5d6e86e5341d57a92c49934296c51542a25015c9b1782a1c2722a940131c3d9a600080a3602083019250602082019150611f01565b60005473ffffffffffffffffffffffffffffffffffffffff163314611fd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c23565b600281905560405173ffffffffffffffffffffffffffffffffffffffff821681527fe127cf589a3879da0156d4a24f43b44f65cfa3570de594806b0bfa2fcf06884f90602001610cd5565b61202a61211e565b6120348282611b29565b33600c1b6000908152600b6020908152604080832087845290915290205460ff1c15156001141561206a5761206a84600061146d565b33600c1b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529020546120b8906b3fffffffffffffffffffffff16858784612650565b6120c3853386612515565b6040805173ffffffffffffffffffffffffffffffffffffffff871681526020810186905233917f2cd6435b1b961c13f55202979edd0765a809f69a539d8a477436c94c1211e43e910160405180910390a25061157e60018055565b6001546002141561215b576040517fab143c0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b61218484848473ffffffffffffffffffffffffffffffffffffffff85166126ad565b61157e576040517f3b8474be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602081815260409283902086518155908601516001820155918501516002830155606085015160038301556080850151600483015560a085015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560c0860151600684018054831691841691909117905560e08601516007840180548316918416919091179055610100860151600884018054831691841691909117905561012086015160099093018054909116929091169190911790556122a986868484612650565b60c083015183516060850151604051879373ffffffffffffffffffffffffffffffffffffffff16927f8fb3989f70bd172a37d15b41b015e48ea09d59329638377304a4198cd0c4ea659261230592918252602082015260400190565b60405180910390a3505050505050565b600080634d2b179160e01b8360405160240161233391815260200190565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600080600060206000855160208701600254617530fa92503d91506000519050809450826123c85763e10bf1cc6000526004601cfd5b50505050919050565b60006040517f23b872dd000000000000000000000000000000000000000000000000000000006000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080612494576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610c23565b5050505050565b600080600080600085875af1905080612510576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610c23565b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000006000528360045282602452602060006044600080895af13d15601f3d116001600051141617169150600060605280604052508061157e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610c23565b4381600401541115612612576040517fd0404f8500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600381015461264d576040517f63b4904e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b836126635763ce3a3d376000526004601cfd5b6000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812080548592906126a2908490613024565b909155505050505050565b600083156126e9578360051b8501855b803580851160051b948552602094851852604060002093018181106126e1576126e6565b6126bd565b50505b501492915050565b60006020828403121561270357600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461264d57600080fd5b60008083601f84011261273e57600080fd5b50813567ffffffffffffffff81111561275657600080fd5b6020830191508360208260051b850101111561277157600080fd5b9250929050565b6000806000806000806000806000806101008b8d03121561279857600080fd5b8a356127a38161270a565b995060208b01356127b38161270a565b985060408b01356127c38161270a565b975060608b01356127d38161270a565b965060808b0135955060a08b0135945060c08b013567ffffffffffffffff808211156127fe57600080fd5b61280a8e838f0161272c565b909650945060e08d013591508082111561282357600080fd5b506128308d828e0161272c565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156128bf576128bf612849565b604052919050565b600067ffffffffffffffff8211156128e1576128e1612849565b5060051b60200190565b600082601f8301126128fc57600080fd5b8135602061291161290c836128c7565b612878565b82815260059290921b8401810191818101908684111561293057600080fd5b8286015b848110156129545780356129478161270a565b8352918301918301612934565b509695505050505050565b60006020828403121561297157600080fd5b813567ffffffffffffffff81111561298857600080fd5b612994848285016128eb565b949350505050565b6000602082840312156129ae57600080fd5b81356129b98161270a565b9392505050565b803580151581146129d057600080fd5b919050565b600080600080600060a086880312156129ed57600080fd5b85356129f88161270a565b945060208601356bffffffffffffffffffffffff81168114612a1957600080fd5b93506040860135612a298161270a565b9250612a37606087016129c0565b949793965091946080013592915050565b60006020808385031215612a5b57600080fd5b823567ffffffffffffffff811115612a7257600080fd5b8301601f81018513612a8357600080fd5b8035612a9161290c826128c7565b81815260059190911b82018301908381019087831115612ab057600080fd5b928401925b82841015612ace57833582529284019290840190612ab5565b979650505050505050565b600081518084526020808501945080840160005b83811015612b0957815187529582019590820190600101612aed565b509495945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604081526000612b566040830185612ad9565b8281036020848101919091528451808352858201928201906000805b82811015612bc45785516004808210612bb1577f4e487b7100000000000000000000000000000000000000000000000000000000845260218152602484fd5b5084529484019492840192600101612b72565b509198975050505050505050565b60008060408385031215612be557600080fd5b8235612bf08161270a565b9150612bfe602084016129c0565b90509250929050565b60008060008060008060c08789031215612c2057600080fd5b863595506020870135612c328161270a565b945060408701359350606087013592506080870135915060a087013560ff81168114612c5d57600080fd5b809150509295509295509295565b60008060408385031215612c7e57600080fd5b8235612c898161270a565b946020939093013593505050565b60008060408385031215612caa57600080fd5b8235612cb58161270a565b91506020830135612cc58161270a565b809150509250929050565b60008060408385031215612ce357600080fd5b823591506020830135612cc58161270a565b60008060208385031215612d0857600080fd5b823567ffffffffffffffff811115612d1f57600080fd5b6112e98582860161272c565b60008060408385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d61858286016128eb565b9250506020830135612cc58161270a565b6020815260006129b96020830184612ad9565b60008060408385031215612d9857600080fd5b823567ffffffffffffffff80821115612db057600080fd5b612dbc868387016128eb565b9350602091508185013581811115612dd357600080fd5b85019050601f81018613612de657600080fd5b8035612df461290c826128c7565b81815260059190911b82018301908381019088831115612e1357600080fd5b928401925b82841015612e3857612e29846129c0565b82529284019290840190612e18565b80955050505050509250929050565b60008060008060608587031215612e5d57600080fd5b8435612e688161270a565b935060208501359250604085013567ffffffffffffffff811115612e8b57600080fd5b612e978782880161272c565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115612ee557612ee5612ea3565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612f1c57612f1c612ea3565b5060010190565b600082612f59577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612f9657612f96612ea3565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020808252825182820181905260009190848201906040850190845b8181101561301857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fe6565b50909695505050505050565b60008282101561303657613036612ea3565b50039056fea164736f6c6343000809000a"; type P2PIXConstructorParams = | [signer?: Signer] diff --git a/src/types/hardhat.d.ts b/src/types/hardhat.d.ts index d3747a0..5a9fb88 100644 --- a/src/types/hardhat.d.ts +++ b/src/types/hardhat.d.ts @@ -32,6 +32,10 @@ declare module "hardhat/types/runtime" { name: "ERC20", signerOrOptions?: ethers.Signer | FactoryOptions ): Promise; + getContractFactory( + name: "Multicall", + signerOrOptions?: ethers.Signer | FactoryOptions + ): Promise; getContractFactory( name: "ReentrancyGuard", signerOrOptions?: ethers.Signer | FactoryOptions @@ -70,6 +74,11 @@ declare module "hardhat/types/runtime" { address: string, signer?: ethers.Signer ): Promise; + getContractAt( + name: "Multicall", + address: string, + signer?: ethers.Signer + ): Promise; getContractAt( name: "ReentrancyGuard", address: string, diff --git a/src/types/index.ts b/src/types/index.ts index 60e8d58..7742b5a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -17,6 +17,8 @@ export type { MockToken } from "./lib/mock/mockToken.sol/MockToken"; export { MockToken__factory } from "./factories/lib/mock/mockToken.sol/MockToken__factory"; export type { ERC20 } from "./lib/tokens/ERC20"; export { ERC20__factory } from "./factories/lib/tokens/ERC20__factory"; +export type { Multicall } from "./lib/utils/Multicall"; +export { Multicall__factory } from "./factories/lib/utils/Multicall__factory"; export type { ReentrancyGuard } from "./lib/utils/ReentrancyGuard"; export { ReentrancyGuard__factory } from "./factories/lib/utils/ReentrancyGuard__factory"; export type { P2PIX } from "./p2pix.sol/P2PIX"; diff --git a/src/types/lib/utils/Multicall.ts b/src/types/lib/utils/Multicall.ts new file mode 100644 index 0000000..a4936d5 --- /dev/null +++ b/src/types/lib/utils/Multicall.ts @@ -0,0 +1,155 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumber, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PopulatedTransaction, + Signer, + utils, +} from "ethers"; +import type { FunctionFragment, Result } from "@ethersproject/abi"; +import type { Listener, Provider } from "@ethersproject/providers"; +import type { + TypedEventFilter, + TypedEvent, + TypedListener, + OnEvent, + PromiseOrValue, +} from "../../common"; + +export declare namespace Multicall { + export type CallStruct = { + target: PromiseOrValue; + callData: PromiseOrValue; + }; + + export type CallStructOutput = [string, string] & { + target: string; + callData: string; + }; + + export type ResultStruct = { + success: PromiseOrValue; + returnData: PromiseOrValue; + }; + + export type ResultStructOutput = [boolean, string] & { + success: boolean; + returnData: string; + }; +} + +export interface MulticallInterface extends utils.Interface { + functions: { + "mtc1((address,bytes)[])": FunctionFragment; + "mtc2((address,bytes)[])": FunctionFragment; + }; + + getFunction(nameOrSignatureOrTopic: "mtc1" | "mtc2"): FunctionFragment; + + encodeFunctionData( + functionFragment: "mtc1", + values: [Multicall.CallStruct[]] + ): string; + encodeFunctionData( + functionFragment: "mtc2", + values: [Multicall.CallStruct[]] + ): string; + + decodeFunctionResult(functionFragment: "mtc1", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "mtc2", data: BytesLike): Result; + + events: {}; +} + +export interface Multicall extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: MulticallInterface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + mtc1( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + + mtc2( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + }; + + mtc1( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + + mtc2( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + + callStatic: { + mtc1( + calls: Multicall.CallStruct[], + overrides?: CallOverrides + ): Promise<[BigNumber, string[]]>; + + mtc2( + calls: Multicall.CallStruct[], + overrides?: CallOverrides + ): Promise<[BigNumber, string, Multicall.ResultStructOutput[]]>; + }; + + filters: {}; + + estimateGas: { + mtc1( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + + mtc2( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + }; + + populateTransaction: { + mtc1( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + + mtc2( + calls: Multicall.CallStruct[], + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise; + }; +} diff --git a/src/types/lib/utils/index.ts b/src/types/lib/utils/index.ts index 447e059..40d13ce 100644 --- a/src/types/lib/utils/index.ts +++ b/src/types/lib/utils/index.ts @@ -1,4 +1,5 @@ /* Autogenerated file. Do not edit manually. */ /* tslint:disable */ /* eslint-disable */ +export type { Multicall } from "./Multicall"; export type { ReentrancyGuard } from "./ReentrancyGuard"; diff --git a/src/types/p2pix.sol/P2PIX.ts b/src/types/p2pix.sol/P2PIX.ts index 403e46e..5d9e230 100644 --- a/src/types/p2pix.sol/P2PIX.ts +++ b/src/types/p2pix.sol/P2PIX.ts @@ -590,7 +590,7 @@ export interface P2PIX extends BaseContract { getLocksStatus( ids: PromiseOrValue[], overrides?: CallOverrides - ): Promise<[BigNumber[], boolean[]]>; + ): Promise<[BigNumber[], number[]]>; getPixTarget( seller: PromiseOrValue, @@ -785,7 +785,7 @@ export interface P2PIX extends BaseContract { getLocksStatus( ids: PromiseOrValue[], overrides?: CallOverrides - ): Promise<[BigNumber[], boolean[]]>; + ): Promise<[BigNumber[], number[]]>; getPixTarget( seller: PromiseOrValue, @@ -980,7 +980,7 @@ export interface P2PIX extends BaseContract { getLocksStatus( ids: PromiseOrValue[], overrides?: CallOverrides - ): Promise<[BigNumber[], boolean[]]>; + ): Promise<[BigNumber[], number[]]>; getPixTarget( seller: PromiseOrValue, diff --git a/test/Reputation.test.ts b/test/Reputation.test.ts index 395ca5c..6f7c435 100644 --- a/test/Reputation.test.ts +++ b/test/Reputation.test.ts @@ -23,19 +23,73 @@ describe("Reputation", () => { ({ reputation } = await loadFixture(repFixture)); }); + // describe("Limiter", async () => { + // it("Curve reliability", async () => { + // const tx1 = await reputation.connect(owner).limiter(0); + // const tx2 = await reputation.limiter(500); + // const tx3 = await reputation + // .connect(owner) + // .limiter(444444); + // const tx4 = await reputation.limiter(988700); + + // expect(tx1).to.eq(curve(0)); + // expect(tx2).to.eq(curve(500)); + // expect(tx3).to.eq(curve(444444)); + // expect(tx4).to.eq(curve(988700)); + // }); + // }); + describe("Limiter", async () => { it("Curve reliability", async () => { - const tx1 = await reputation.connect(owner).limiter(0); - const tx2 = await reputation.limiter(500); - const tx3 = await reputation - .connect(owner) - .limiter(444444); - const tx4 = await reputation.limiter(988700); + const testCases = [ + { + x: 0, + expected: curve(0), + }, + { + x: 500, + expected: curve(500), + }, + { + x: 444444, + expected: curve(444444), + }, + { + x: 988700, + expected: curve(988700), + }, + { + x: Number.MAX_SAFE_INTEGER, + shouldRevert: "overflow", + }, + { + x: Number.POSITIVE_INFINITY, + shouldRevert: "overflow", + }, + { + x: Number.NEGATIVE_INFINITY, + shouldRevert: "overflow", + }, + { + x: -1, + shouldRevert: "value out-of-bounds", + }, + { + x: Number.NaN, + shouldRevert: "invalid BigNumber string", + }, + ]; - expect(tx1).to.eq(curve(0)); - expect(tx2).to.eq(curve(500)); - expect(tx3).to.eq(curve(444444)); - expect(tx4).to.eq(curve(988700)); + for (const testCase of testCases) { + if (testCase.shouldRevert != undefined) { + await expect(reputation.limiter(testCase.x)).to.be + .rejected; + } else { + const result = await reputation.limiter(testCase.x); + expect(result).to.eq(testCase.expected).and.to.be + .ok; + } + } }); }); }); diff --git a/test/p2pix.test.ts b/test/p2pix.test.ts index 183515c..4e51ee4 100644 --- a/test/p2pix.test.ts +++ b/test/p2pix.test.ts @@ -7,6 +7,8 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; import { BigNumber, + Bytes, + BytesLike, ContractReceipt, ContractTransaction, Wallet, @@ -17,12 +19,19 @@ import { /* tracer */ } from "hardhat"; -// import keccak256 from "keccak256"; -import { MockToken, P2PIX, Reputation } from "../src/types"; +import { + MockToken, + Multicall, + P2PIX, + Reputation, +} from "../src/types"; import { P2PixErrors } from "./utils/errors"; import { - // Deposit, + Call, Lock, + Result, + getBnFrom, + getLockData, getSignerAddrs, p2pixFixture, randomSigners, @@ -45,6 +54,7 @@ describe("P2PIX", () => { let p2pix: P2PIX; // Contract instance let erc20: MockToken; // Token instance let reputation: Reputation; // Reputation Interface instance + let multicall: Multicall; // Multicall contract instance let merkleRoot: string; // MerkleRoot from seller's allowlist let proof: string[]; // Owner's proof as whitelisted address @@ -62,8 +72,14 @@ describe("P2PIX", () => { await network.provider.send("hardhat_reset"); }); beforeEach("Load deployment fixtures", async () => { - ({ erc20, p2pix, reputation, merkleRoot, proof } = - await loadFixture(p2pixFixture)); + ({ + erc20, + p2pix, + reputation, + multicall, + merkleRoot, + proof, + } = await loadFixture(p2pixFixture)); }); describe("Init", async () => { @@ -234,11 +250,22 @@ describe("P2PIX", () => { await p2pix.callStatic.allowedERC20s(erc20.address); const newTokenState2 = await p2pix.callStatic.allowedERC20s(owner.address); + const funcSig = "0xd6e8b973"; + const args = ethers.utils.defaultAbiCoder.encode( + ["address[]", "bool[]"], + [[acc01.address], [false]], + ); + const cd = funcSig + args.substring(2); + const callStruct: Call = { + target: p2pix.address, + callData: cd, + }; const fail = p2pix .connect(acc01) .tokenSettings([acc01.address], [false]); const fail2 = p2pix.tokenSettings([], [true, false]); const fail3 = p2pix.tokenSettings([zero], [true, true]); + const mtcFail = multicall.mtc1([callStruct]); expect(tx).to.be.ok; await expect(tx) @@ -262,6 +289,12 @@ describe("P2PIX", () => { p2pix, P2PixErrors.LengthMismatch, ); + await expect(mtcFail) + .to.be.revertedWithCustomError( + multicall, + P2PixErrors.CallFailed, + ) + .withArgs(P2PixErrors.UNAUTHORIZED); }); }); describe("Deposit", async () => { @@ -330,9 +363,18 @@ describe("P2PIX", () => { true, root, ); - const storage = await p2pix.callStatic.getBalance(owner.address, erc20.address); - const pixTarget = await p2pix.callStatic.getPixTarget(owner.address,erc20.address); - const valid = await p2pix.callStatic.getValid(owner.address,erc20.address); + const storage = await p2pix.callStatic.getBalance( + owner.address, + erc20.address, + ); + const pixTarget = await p2pix.callStatic.getPixTarget( + owner.address, + erc20.address, + ); + const valid = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); const ownerKey = await p2pix.callStatic._castAddrToKey( owner.address, ); @@ -340,7 +382,7 @@ describe("P2PIX", () => { const balances = await p2pix.callStatic.getBalances( [owner.address, acc01.address], erc20.address, - ); + ); expect(tx).to.be.ok; await expect(tx) @@ -385,7 +427,12 @@ describe("P2PIX", () => { const price2 = price.mul(ethers.BigNumber.from(2)); const price3 = price.mul(ethers.BigNumber.from(3)); const price4 = price.mul(ethers.BigNumber.from(4)); - const prices:BigNumber[] = [price, price2, price3, price4]; + const prices: BigNumber[] = [ + price, + price2, + price3, + price4, + ]; await erc20.mint( getSignerAddrs(4, await ethers.getSigners()), price4, @@ -408,31 +455,86 @@ describe("P2PIX", () => { .deposit(erc20.address, price, pTarget, true, root); const tx2 = await p2pix .connect(acc01) - .deposit(erc20.address, price2, pTarget2, false, nullRoot); + .deposit( + erc20.address, + price2, + pTarget2, + false, + nullRoot, + ); const tx3 = await p2pix .connect(acc02) .deposit(erc20.address, price3, pTarget3, true, root); const tx4 = await p2pix .connect(acc03) - .deposit(erc20.address, price4, pTarget, false, nullRoot); + .deposit( + erc20.address, + price4, + pTarget, + false, + nullRoot, + ); const balances = await p2pix.callStatic.getBalances( - [owner.address, acc01.address, acc02.address, acc03.address], erc20.address); + [ + owner.address, + acc01.address, + acc02.address, + acc03.address, + ], + erc20.address, + ); - const storage1 = await p2pix.callStatic.getBalance(owner.address, erc20.address); - const storage2 = await p2pix.callStatic.getBalance(acc01.address, erc20.address); - const storage3 = await p2pix.callStatic.getBalance(acc02.address, erc20.address); - const storage4 = await p2pix.callStatic.getBalance(acc03.address, erc20.address); + const storage1 = await p2pix.callStatic.getBalance( + owner.address, + erc20.address, + ); + const storage2 = await p2pix.callStatic.getBalance( + acc01.address, + erc20.address, + ); + const storage3 = await p2pix.callStatic.getBalance( + acc02.address, + erc20.address, + ); + const storage4 = await p2pix.callStatic.getBalance( + acc03.address, + erc20.address, + ); - const pixTarget1 = await p2pix.callStatic.getPixTarget(owner.address, erc20.address); - const pixTarget2 = await p2pix.callStatic.getPixTarget(acc01.address, erc20.address); - const pixTarget3 = await p2pix.callStatic.getPixTarget(acc02.address, erc20.address); - const pixTarget4 = await p2pix.callStatic.getPixTarget(acc03.address, erc20.address); + const pixTarget1 = await p2pix.callStatic.getPixTarget( + owner.address, + erc20.address, + ); + const pixTarget2 = await p2pix.callStatic.getPixTarget( + acc01.address, + erc20.address, + ); + const pixTarget3 = await p2pix.callStatic.getPixTarget( + acc02.address, + erc20.address, + ); + const pixTarget4 = await p2pix.callStatic.getPixTarget( + acc03.address, + erc20.address, + ); - const valid1 = await p2pix.callStatic.getValid(owner.address, erc20.address); - const valid2 = await p2pix.callStatic.getValid(acc01.address, erc20.address); - const valid3 = await p2pix.callStatic.getValid(acc02.address, erc20.address); - const valid4 = await p2pix.callStatic.getValid(acc03.address, erc20.address); + const valid1 = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); + const valid2 = await p2pix.callStatic.getValid( + acc01.address, + erc20.address, + ); + const valid3 = await p2pix.callStatic.getValid( + acc02.address, + erc20.address, + ); + const valid4 = await p2pix.callStatic.getValid( + acc03.address, + erc20.address, + ); const allowList1 = await p2pix.sellerAllowList( ownerKey, @@ -452,42 +554,67 @@ describe("P2PIX", () => { expect(tx3).to.be.ok; expect(tx4).to.be.ok; - await expect(tx) - .to.emit(p2pix, "DepositAdded") - .withArgs(owner.address, erc20.address, price); - await expect(tx).to.changeTokenBalances( - erc20, - [owner.address, p2pix.address], - ["-100000000000000000000", price], - ); + // await expect(tx) + // .to.emit(p2pix, "DepositAdded") + // .withArgs(owner.address, erc20.address, price); + // await expect(tx).to.changeTokenBalances( + // erc20, + // [owner.address, p2pix.address], + // ["-100000000000000000000", price], + // ); - await expect(tx2) - .to.emit(p2pix, "DepositAdded") - .withArgs(acc01.address, erc20.address, price2); - await expect(tx2).to.changeTokenBalances( - erc20, - [acc01.address, p2pix.address], - ["-200000000000000000000", price2], - ); + // await expect(tx2) + // .to.emit(p2pix, "DepositAdded") + // .withArgs(acc01.address, erc20.address, price2); + // await expect(tx2).to.changeTokenBalances( + // erc20, + // [acc01.address, p2pix.address], + // ["-200000000000000000000", price2], + // ); - await expect(tx3) - .to.emit(p2pix, "DepositAdded") - .withArgs(acc02.address, erc20.address, price3); - await expect(tx3).to.changeTokenBalances( - erc20, - [acc02.address, p2pix.address], - ["-300000000000000000000", price3], - ); + // await expect(tx3) + // .to.emit(p2pix, "DepositAdded") + // .withArgs(acc02.address, erc20.address, price3); + // await expect(tx3).to.changeTokenBalances( + // erc20, + // [acc02.address, p2pix.address], + // ["-300000000000000000000", price3], + // ); + + // await expect(tx4) + // .to.emit(p2pix, "DepositAdded") + // .withArgs(acc03.address, erc20.address, price4); + // await expect(tx4).to.changeTokenBalances( + // erc20, + // [acc03.address, p2pix.address], + // ["-400000000000000000000", price4], + // ); + + const transactions = [tx, tx2, tx3, tx4]; + const addresses = [ + owner.address, + acc01.address, + acc02.address, + acc03.address, + ]; + const depositPrices = [price, price2, price3, price4]; + + for (let i = 0; i < transactions.length; i++) { + const tx = transactions[i]; + const addr = addresses[i]; + const depositPrice = depositPrices[i]; + const amount = `-${(i + 1) * 100000000000000000000}`; + + await expect(tx) + .to.emit(p2pix, "DepositAdded") + .withArgs(addr, erc20.address, depositPrice); + await expect(tx).to.changeTokenBalances( + erc20, + [addr, p2pix.address], + [amount, depositPrice], + ); + } - await expect(tx4) - .to.emit(p2pix, "DepositAdded") - .withArgs(acc03.address, erc20.address, price4); - await expect(tx4).to.changeTokenBalances( - erc20, - [acc03.address, p2pix.address], - ["-400000000000000000000", price4], - ); - expect(prices[0]).to.eq(balances[0]); expect(prices[1]).to.eq(balances[1]); expect(prices[2]).to.eq(balances[2]); @@ -525,7 +652,7 @@ describe("P2PIX", () => { true, ethers.constants.HashZero, ); - await p2pix.setValidState(erc20.address,false); + await p2pix.setValidState(erc20.address, false); const fail = p2pix .connect(acc03) .lock( @@ -586,7 +713,7 @@ describe("P2PIX", () => { P2PixErrors.NotEnoughTokens, ); }); - // test invalid since lockID has been replaced by a counter. + // test invalid since lockID has been replaced by a counter. // it.only("should revert if a non expired lock has the same ID encoded", async () => { // const pTarget = ethers.BigNumber.from(1337); // await erc20.approve(p2pix.address, price); @@ -600,21 +727,21 @@ describe("P2PIX", () => { // await p2pix // .connect(acc03) // .lock( - // owner.address, + // owner.address, // erc20.address, - // acc02.address, - // acc03.address, + // acc02.address, + // acc03.address, // 0, 1, [], []); - // console.log(await p2pix.callStatic.getValid(owner.address,erc20.address)) - // const fail = p2pix - // .connect(acc03) - // .lock(owner.address, erc20.address, acc02.address, acc03.address, 0, 1, [], []); + // console.log(await p2pix.callStatic.getValid(owner.address,erc20.address)) + // const fail = p2pix + // .connect(acc03) + // .lock(owner.address, erc20.address, acc02.address, acc03.address, 0, 1, [], []); - // await expect(fail).to.be.revertedWithCustomError( - // p2pix, - // P2PixErrors.NotExpired, - // ); + // await expect(fail).to.be.revertedWithCustomError( + // p2pix, + // P2PixErrors.NotExpired, + // ); // }); it("should revert if an invalid allowlist merkleproof is provided", async () => { await erc20.approve(p2pix.address, price); @@ -699,12 +826,16 @@ describe("P2PIX", () => { proof, [], ); - const storage: Lock = await p2pix.callStatic.mapLocks(1); + const storage: Lock = await p2pix.callStatic.mapLocks( + 1, + ); const rc: ContractReceipt = await tx.wait(); const expiration = rc.blockNumber + 10; - const key = await p2pix.callStatic._castAddrToKey(owner.address); - + const key = await p2pix.callStatic._castAddrToKey( + owner.address, + ); + await expect(tx) .to.emit(p2pix, "LockAdded") .withArgs( @@ -750,12 +881,18 @@ describe("P2PIX", () => { [], [], ); - const storage: Lock = await p2pix.callStatic.mapLocks(1); + const storage: Lock = await p2pix.callStatic.mapLocks( + 1, + ); const rc: ContractReceipt = await tx.wait(); const expiration = rc.blockNumber + 10; - const key = await p2pix.callStatic._castAddrToKey(owner.address); - const castBack = await p2pix.callStatic._castKeyToAddr(key); + const key = await p2pix.callStatic._castAddrToKey( + owner.address, + ); + const castBack = await p2pix.callStatic._castKeyToAddr( + key, + ); expect(tx).to.be.ok; expect(castBack).to.eq(owner.address); @@ -771,19 +908,16 @@ describe("P2PIX", () => { expect(storage.relayerTarget).to.eq(acc03.address); expect(storage.relayerAddress).to.eq(acc01.address); expect(storage.token).to.eq(erc20.address); - + await expect(tx) .to.emit(p2pix, "LockAdded") - .withArgs( - acc02.address, - 1, - key, - storage.amount, - ); + .withArgs(acc02.address, 1, key, storage.amount); }); it("should create a lock, update storage and emit events via the reputation path 2", async () => { const root = ethers.constants.HashZero; - const newPrice = price.mul(ethers.constants.Two).add(ethers.constants.One); + const newPrice = price + .mul(ethers.constants.Two) + .add(ethers.constants.One); const endtoendID = ethers.constants.HashZero; const target = ethers.BigNumber.from(101); const messageToSign = ethers.utils.solidityKeccak256( @@ -816,34 +950,40 @@ describe("P2PIX", () => { [], [], ); - await p2pix - .connect(acc01) - .release( - 1, - acc02.address, - endtoendID, - sig.r, - sig.s, - sig.v, - ); + await p2pix + .connect(acc01) + .release( + 1, + acc02.address, + endtoendID, + sig.r, + sig.s, + sig.v, + ); const tx = await p2pix - .connect(acc01) - .lock( - owner.address, - erc20.address, - acc02.address, - acc03.address, - 0, - price.add(ethers.constants.One), - [], - [], + .connect(acc01) + .lock( + owner.address, + erc20.address, + acc02.address, + acc03.address, + 0, + price.add(ethers.constants.One), + [], + [], + ); + const storage: Lock = await p2pix.callStatic.mapLocks( + 2, ); - const storage: Lock = await p2pix.callStatic.mapLocks(2); const rc: ContractReceipt = await tx.wait(); const expiration = rc.blockNumber + 10; - const key = await p2pix.callStatic._castAddrToKey(owner.address); - const castBack = await p2pix.callStatic._castKeyToAddr(key); + const key = await p2pix.callStatic._castAddrToKey( + owner.address, + ); + const castBack = await p2pix.callStatic._castKeyToAddr( + key, + ); expect(tx).to.be.ok; expect(castBack).to.eq(owner.address); @@ -852,22 +992,19 @@ describe("P2PIX", () => { expect(storage.relayerPremium).to.eq( ethers.constants.Zero, ); - expect(storage.amount).to.eq(price.add(ethers.constants.One)); + expect(storage.amount).to.eq( + price.add(ethers.constants.One), + ); expect(storage.expirationBlock).to.eq(expiration); expect(storage.pixTarget).to.eq(target); expect(storage.buyerAddress).to.eq(acc02.address); expect(storage.relayerTarget).to.eq(acc03.address); expect(storage.relayerAddress).to.eq(acc01.address); expect(storage.token).to.eq(erc20.address); - + await expect(tx) .to.emit(p2pix, "LockAdded") - .withArgs( - acc02.address, - 2, - key, - storage.amount, - ); + .withArgs(acc02.address, 2, key, storage.amount); }); // edge case test it("should create multiple locks", async () => { @@ -912,7 +1049,9 @@ describe("P2PIX", () => { [], [], ); - const storage2: Lock = await p2pix.callStatic.mapLocks(2); + const storage2: Lock = await p2pix.callStatic.mapLocks( + 2, + ); const rc2: ContractReceipt = await tx2.wait(); const expiration2 = rc2.blockNumber + 10; @@ -929,70 +1068,80 @@ describe("P2PIX", () => { [], [], ); - const storage3: Lock = await p2pix.callStatic.mapLocks(3); + const storage3: Lock = await p2pix.callStatic.mapLocks( + 3, + ); const rc3: ContractReceipt = await tx3.wait(); const expiration3 = rc3.blockNumber + 10; - const key = await p2pix.callStatic._castAddrToKey(owner.address); + const key = await p2pix.callStatic._castAddrToKey( + owner.address, + ); - const lockStatus1 = await p2pix.callStatic.getLocksStatus([1,7,7,2,3,4,5,5,2,3]); - const lockStatus2 = await p2pix.callStatic.getLocksStatus([0,1,2,3]); - const lockStatus3 = await p2pix.callStatic.getLocksStatus([7,7,333,14,777]); - const lockStatus4 = await p2pix.callStatic.getLocksStatus([]); + // const lockStatus1 = await p2pix.callStatic.getLocksStatus([1,7,7,2,3,4,5,5,2,3]); + // const lockStatus2 = await p2pix.callStatic.getLocksStatus([0,1,2,3]); + // const lockStatus3 = await p2pix.callStatic.getLocksStatus([7,7,333,14,777]); + // const lockStatus4 = await p2pix.callStatic.getLocksStatus([]); - const ls1: [BigNumber[], boolean[]] = [ - [ - ethers.constants.One, - ethers.BigNumber.from(7), - ethers.BigNumber.from(7), - ethers.constants.Two, - ethers.BigNumber.from(3), - ethers.BigNumber.from(4), - ethers.BigNumber.from(5), - ethers.BigNumber.from(5), - ethers.constants.Two, - ethers.BigNumber.from(3), - ], - [ - true, false, - false, true, - true, false, - false, false, - true, true, - ]]; + // All getLocksStatus calls were batched via the Multicall contract. + const ls1: [BigNumber[], BigNumber[]] = [ + getBnFrom([1, 7, 7, 2, 3, 4, 5, 5, 2, 3]), + getBnFrom([1, 0, 0, 1, 1, 0, 0, 0, 1, 1]), + ]; - const ls2: [BigNumber[], boolean[]] = [ - [ - ethers.constants.Zero, - ethers.constants.One, - ethers.constants.Two, - ethers.BigNumber.from(3), - ], [false, true, true, true] ]; - - const ls3: [BigNumber[], boolean[]] = [ - [ - ethers.BigNumber.from(7), - ethers.BigNumber.from(7), - ethers.BigNumber.from(333), - ethers.BigNumber.from(14), - ethers.BigNumber.from(777), - ], [false, false, false, false, false] ]; + const ls2: [BigNumber[], BigNumber[]] = [ + getBnFrom([0, 1, 2, 3]), + getBnFrom([0, 1, 1, 1]), + ]; - const ls4 = [[],[]]; + const ls3: [BigNumber[], BigNumber[]] = [ + getBnFrom([7, 7, 333, 14, 777]), + getBnFrom([0, 0, 0, 0, 0]), + ]; + + const ls4 = [[], []]; + + const batchedLocks: Array = [ + ls1, + ls2, + ls3, + ls4, + ].map(arr => arr[0]); + + const cData: Call[] = getLockData( + p2pix.address, + batchedLocks, + ); + + const batchCall = await multicall.callStatic.mtc1( + cData, + ); + const blockNumber = batchCall[0]; + + const result: Array = batchCall[1].slice( + 0, + 4, + ); + + const decodedData = result.map(r => + ethers.utils.defaultAbiCoder.decode( + ["uint256[]", "uint8[]"], + r, + ), + ); + + const [ls1Res, ls2Res, ls3Res, ls4Res] = decodedData; expect(tx1).to.be.ok; expect(tx2).to.be.ok; expect(tx3).to.be.ok; - - expect(lockStatus1[0].toString()).to.equal(ls1[0].toString()); - expect(lockStatus1[1].toString()).to.equal(ls1[1].toString()); - expect(lockStatus2[0].toString()).to.equal(ls2[0].toString()); - expect(lockStatus2[1].toString()).to.equal(ls2[1].toString()); - expect(lockStatus3[0].toString()).to.equal(ls3[0].toString()); - expect(lockStatus3[1].toString()).to.equal(ls3[1].toString()); - expect(lockStatus4[0].toString()).to.equal(ls4[0].toString()); - expect(lockStatus4[1].toString()).to.equal(ls4[1].toString()); + + expect(blockNumber).to.eq(9); + expect(ls1Res).to.deep.equal(ls1); + expect(ls2Res).to.deep.equal(ls2); + expect(ls3Res).to.deep.equal(ls3); + expect(ls4Res).to.deep.equal(ls4); expect(key) .to.eq(storage1.sellerKey) @@ -1018,9 +1167,9 @@ describe("P2PIX", () => { expect(storage3.expirationBlock).to.eq(expiration3); expect(target) - .to.eq(storage1.pixTarget) - .and.to.eq(storage2.pixTarget) - .and.to.eq(storage3.pixTarget); + .to.eq(storage1.pixTarget) + .and.to.eq(storage2.pixTarget) + .and.to.eq(storage3.pixTarget); expect(acc02.address) .to.eq(storage1.buyerAddress) @@ -1038,40 +1187,25 @@ describe("P2PIX", () => { expect(storage3.relayerAddress).to.eq(acc03.address); expect(erc20.address) - .to.eq(storage1.token) - .and.to.eq(storage2.token) - .and.to.eq(storage3.token); + .to.eq(storage1.token) + .and.to.eq(storage2.token) + .and.to.eq(storage3.token); await expect(tx1) .to.emit(p2pix, "LockAdded") - .withArgs( - acc02.address, - 1, - key, - storage1.amount, - ); + .withArgs(acc02.address, 1, key, storage1.amount); await expect(tx2) .to.emit(p2pix, "LockAdded") - .withArgs( - acc02.address, - 2, - key, - storage2.amount, - ); + .withArgs(acc02.address, 2, key, storage2.amount); await expect(tx3) .to.emit(p2pix, "LockAdded") - .withArgs( - acc03.address, - 3, - key, - storage3.amount, - ); + .withArgs(acc03.address, 3, key, storage3.amount); }); }); describe("Set sellerBalance Valid State", async () => { it("should revert if sellerBalance hasn't been initialized", async () => { - const fail = p2pix.setValidState(erc20.address,false); - + const fail = p2pix.setValidState(erc20.address, false); + await expect(fail).to.be.revertedWithCustomError( p2pix, P2PixErrors.NotInitialized, @@ -1086,11 +1220,18 @@ describe("P2PIX", () => { true, merkleRoot, ); - const state1 = - await p2pix.callStatic.getValid(owner.address,erc20.address); - const tx = await p2pix.setValidState(erc20.address,false); - const state2 = - await p2pix.callStatic.getValid(owner.address,erc20.address); + const state1 = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); + const tx = await p2pix.setValidState( + erc20.address, + false, + ); + const state2 = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); expect(tx).to.be.ok; await expect(tx) @@ -1101,7 +1242,7 @@ describe("P2PIX", () => { }); it("should cancel multiple balances", async () => { const hashZero = ethers.constants.HashZero; - await erc20.mint([acc01.address,acc02.address],price); + await erc20.mint([acc01.address, acc02.address], price); const target = ethers.BigNumber.from("1"); await erc20.approve(p2pix.address, price); await p2pix.deposit( @@ -1111,50 +1252,77 @@ describe("P2PIX", () => { true, hashZero, ); - await erc20.connect(acc01).approve(p2pix.address, price); - await p2pix.connect(acc01).deposit( + await erc20 + .connect(acc01) + .approve(p2pix.address, price); + await p2pix + .connect(acc01) + .deposit( + erc20.address, + price, + target, + false, + hashZero, + ); + await erc20 + .connect(acc02) + .approve(p2pix.address, price); + await p2pix + .connect(acc02) + .deposit( + erc20.address, + price, + target, + true, + hashZero, + ); + const oldState1 = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); + const oldState2 = await p2pix.callStatic.getValid( + acc01.address, + erc20.address, + ); + const oldState3 = await p2pix.callStatic.getValid( + acc02.address, + erc20.address, + ); + const tx1 = await p2pix.setValidState( erc20.address, - price, - target, false, - hashZero, ); - await erc20.connect(acc02).approve(p2pix.address, price); - await p2pix.connect(acc02).deposit( + const tx2 = await p2pix + .connect(acc01) + .setValidState(erc20.address, true); + const tx3 = await p2pix + .connect(acc02) + .setValidState(erc20.address, true); + const newState1 = await p2pix.callStatic.getValid( + owner.address, + erc20.address, + ); + const newState2 = await p2pix.callStatic.getValid( + acc01.address, + erc20.address, + ); + const newState3 = await p2pix.callStatic.getValid( + acc02.address, erc20.address, - price, - target, - true, - hashZero, ); - const oldState1 = - await p2pix.callStatic.getValid(owner.address,erc20.address); - const oldState2 = - await p2pix.callStatic.getValid(acc01.address,erc20.address); - const oldState3 = - await p2pix.callStatic.getValid(acc02.address,erc20.address); - const tx1 = await p2pix.setValidState(erc20.address,false); - const tx2 = await p2pix.connect(acc01).setValidState(erc20.address,true); - const tx3 = await p2pix.connect(acc02).setValidState(erc20.address,true); - const newState1 = - await p2pix.callStatic.getValid(owner.address,erc20.address); - const newState2 = - await p2pix.callStatic.getValid(acc01.address,erc20.address); - const newState3 = - await p2pix.callStatic.getValid(acc02.address,erc20.address); expect(tx1).to.be.ok; expect(tx2).to.be.ok; expect(tx3).to.be.ok; await expect(tx1) .to.emit(p2pix, "ValidSet") - .withArgs(owner.address, erc20.address,false); + .withArgs(owner.address, erc20.address, false); await expect(tx2) .to.emit(p2pix, "ValidSet") - .withArgs(acc01.address, erc20.address,true); + .withArgs(acc01.address, erc20.address, true); await expect(tx3) .to.emit(p2pix, "ValidSet") - .withArgs(acc02.address, erc20.address,true); + .withArgs(acc02.address, erc20.address, true); expect(oldState1).to.be.true; expect(oldState2).to.be.false; expect(oldState3).to.be.true; @@ -1294,7 +1462,7 @@ describe("P2PIX", () => { [], [], ); - + await p2pix .connect(acc01) .release( @@ -1438,7 +1606,9 @@ describe("P2PIX", () => { const userRecord1 = await p2pix.callStatic.userRecord( acc03Key, ); - const storage1: Lock = await p2pix.callStatic.mapLocks(1); + const storage1: Lock = await p2pix.callStatic.mapLocks( + 1, + ); const tx = await p2pix .connect(acc01) .release( @@ -1449,7 +1619,41 @@ describe("P2PIX", () => { sig.s, sig.v, ); - const storage2: Lock = await p2pix.callStatic.mapLocks(1); + + const lockStatus1 = + await p2pix.callStatic.getLocksStatus([1]); + const ls1: [BigNumber[], number[]] = [ + [ethers.constants.One], + [3], + ]; + const funcSig = "0xd6e8b973"; + const args = ethers.utils.defaultAbiCoder.encode( + ["address[]", "bool[]"], + [[acc01.address], [false]], + ); + const cd1 = funcSig + args.substring(2); + const cd2: Call[] = getLockData(p2pix.address, [ + ls1[0], + ]); + const mtcCalls = [ + { target: p2pix.address, callData: cd1 }, + ]; + mtcCalls.push(cd2[0]); + const mtc2 = await multicall.callStatic.mtc2(mtcCalls); + const blockNumber: BigNumber = mtc2[0]; + const blockhash: BytesLike = mtc2[1]; + const result = mtc2.slice(2).flat(1) as Result[]; + const res1: BytesLike[] = [result[1].returnData]; + const decodedLockData = res1.map(r => + ethers.utils.defaultAbiCoder.decode( + ["uint256[]", "uint8[]"], + r, + ), + ); + + const storage2: Lock = await p2pix.callStatic.mapLocks( + 1, + ); const userRecordB = await p2pix.callStatic.userRecord( acc01Key, ); @@ -1462,13 +1666,30 @@ describe("P2PIX", () => { expect(tx).to.be.ok; await expect(tx) .to.emit(p2pix, "LockReleased") - .withArgs(acc02.address, ethers.constants.One, storage1.amount); + .withArgs( + acc02.address, + ethers.constants.One, + storage1.amount, + ); expect(storage1.expirationBlock).to.eq( - ethers.BigNumber.from(16), + ethers.BigNumber.from(17), ); expect(storage1.amount).to.eq( ethers.BigNumber.from(100), ); + expect(lockStatus1[0].toString()).to.equal( + ls1[0].toString(), + ); + expect(lockStatus1[1].toString()).to.equal( + ls1[1].toString(), + ); + expect(blockNumber).to.eq(8); + expect(blockhash).to.deep.equal( + ethers.constants.HashZero, + ); + expect(result[0].success).to.eq(false); + expect(result[1].success).to.eq(true); + expect(decodedLockData.flat(1)).to.deep.eq(ls1); expect(storage2.expirationBlock).to.eq(zero); expect(storage2.amount).to.eq(zero); expect(used).to.eq(true); @@ -1550,13 +1771,13 @@ describe("P2PIX", () => { .lock( owner.address, erc20.address, - acc02.address, - acc03.address, - 6, - 50, - [], - [] - ); + acc02.address, + acc03.address, + 6, + 50, + [], + [], + ); await p2pix .connect(acc03) .lock( @@ -1569,12 +1790,31 @@ describe("P2PIX", () => { [], [], ); + + const lockStatus1 = + await p2pix.callStatic.getLocksStatus([1, 2, 3, 44]); + const ls1: [BigNumber[], BigNumber[]] = [ + [ + ethers.constants.One, + ethers.constants.Two, + ethers.BigNumber.from(3), + ethers.BigNumber.from(44), + ], + getBnFrom([1, 1, 1, 0]), + ]; + const lockID = ethers.constants.One; const lockID2 = ethers.constants.Two; const lockID3 = ethers.BigNumber.from(3); - const storage1: Lock = await p2pix.callStatic.mapLocks(lockID); - const storage2: Lock = await p2pix.callStatic.mapLocks(lockID2); - const storage3: Lock = await p2pix.callStatic.mapLocks(lockID3); + const storage1: Lock = await p2pix.callStatic.mapLocks( + lockID, + ); + const storage2: Lock = await p2pix.callStatic.mapLocks( + lockID2, + ); + const storage3: Lock = await p2pix.callStatic.mapLocks( + lockID3, + ); // relayerPremium == 0 const tx = await p2pix .connect(acc01) @@ -1626,6 +1866,27 @@ describe("P2PIX", () => { acc03Key, ); + const lockStatus2 = + await p2pix.callStatic.getLocksStatus([1, 2, 3, 44]); + const ls2: [BigNumber[], BigNumber[]] = [ + [ + ethers.constants.One, + ethers.constants.Two, + ethers.BigNumber.from(3), + ethers.BigNumber.from(44), + ], + getBnFrom([3, 3, 3, 0]), + ]; + + const batchedLocks: Array = [ + ls1.slice(0, 1)[0], + ls2.slice(0, 1)[0], + ]; + const cData: Call[] = getLockData( + erc20.address, + batchedLocks, + ); + expect(tx).to.be.ok; expect(tx1).to.be.ok; expect(tx2).to.be.ok; @@ -1644,35 +1905,77 @@ describe("P2PIX", () => { expect(0).to.eq(acc01Record1).and.to.eq(acc03Record1); expect(acc01Record2).to.eq(6); // 0 + 6 expect(acc03Record2).to.eq(185); // 100 + 50 + 25 + 10 - await expect(tx).to.changeTokenBalances( - erc20, - [ - acc01.address, - acc02.address, - acc03.address, - p2pix.address, - ], + + // await expect(tx).to.changeTokenBalances( + // erc20, + // [ + // acc01.address, + // acc02.address, + // acc03.address, + // p2pix.address, + // ], + // [0, 100, 0, "-100"], + // ); + // await expect(tx1).to.changeTokenBalances( + // erc20, + // [ + // acc01.address, + // acc02.address, + // acc03.address, + // p2pix.address, + // ], + // [0, 47, 3, "-50"], + // ); + // await expect(tx2).to.changeTokenBalances( + // erc20, + // [ + // acc01.address, + // acc02.address, + // acc03.address, + // p2pix.address, + // ], + // [0, 20, 5, "-25"], + // ); + + const addresses = [ + acc01.address, + acc02.address, + acc03.address, + p2pix.address, + ]; + + const balances = [ [0, 100, 0, "-100"], - ); - await expect(tx1).to.changeTokenBalances( - erc20, - [ - acc01.address, - acc02.address, - acc03.address, - p2pix.address, - ], [0, 47, 3, "-50"], - ); - await expect(tx2).to.changeTokenBalances( - erc20, - [ - acc01.address, - acc02.address, - acc03.address, - p2pix.address, - ], [0, 20, 5, "-25"], + ]; + + for (let i = 0; i < 3; i++) { + const txs = [tx, tx1, tx2][i]; + await expect(txs).to.changeTokenBalances( + erc20, + addresses, + balances[i], + ); + } + + expect(lockStatus1[0].toString()).to.equal( + ls1[0].toString(), + ); + expect(lockStatus1[1].toString()).to.equal( + ls1[1].toString(), + ); + expect(lockStatus2[0].toString()).to.equal( + ls2[0].toString(), + ); + expect(lockStatus2[1].toString()).to.equal( + ls2[1].toString(), + ); + await expect( + multicall.callStatic.mtc1(cData), + ).to.be.revertedWithCustomError( + multicall, + P2PixErrors.CallFailed, ); }); }); @@ -1692,12 +1995,12 @@ describe("P2PIX", () => { .lock( owner.address, erc20.address, - acc02.address, - acc03.address, - 0, - 1, - [], - [] + acc02.address, + acc03.address, + 0, + 1, + [], + [], ); const lockID = ethers.constants.One; const fail = p2pix.unlockExpired([lockID]); @@ -1732,13 +2035,13 @@ describe("P2PIX", () => { .connect(acc02) .lock( owner.address, - erc20.address, - acc02.address, - acc03.address, - 0, - 1, - [], - [] + erc20.address, + acc02.address, + acc03.address, + 0, + 1, + [], + [], ); const lockID = ethers.constants.One; // await mine(10); @@ -1770,17 +2073,29 @@ describe("P2PIX", () => { await p2pix .connect(acc02) .lock( - owner.address, - erc20.address, - acc02.address, - acc03.address, - 0, - 1, - [], - [] + owner.address, + erc20.address, + acc02.address, + acc03.address, + 0, + 1, + [], + [], ); const lockID = ethers.constants.One; await mine(11); + + const lockStatus1 = + await p2pix.callStatic.getLocksStatus([11, 1, 777]); + const ls1: [BigNumber[], BigNumber[]] = [ + [ + ethers.BigNumber.from(11), + ethers.constants.One, + ethers.BigNumber.from(777), + ], + getBnFrom([0, 2, 0]), + ]; + const storage: Lock = await p2pix.callStatic.mapLocks( lockID, ); @@ -1806,6 +2121,9 @@ describe("P2PIX", () => { expect(storage2.amount).to.eq(ethers.constants.Zero); expect(record1).to.eq(0); expect(record2).to.eq(price); + expect(lockStatus1[0].toString()).to.equal( + ls1[0].toString(), + ); }); it("should unlock expired through lock function", async () => { const target = ethers.BigNumber.from(101); @@ -1872,7 +2190,10 @@ describe("P2PIX", () => { [], [lockID], ); - const remaining = await p2pix.callStatic.getBalance(owner.address,erc20.address); + const remaining = await p2pix.callStatic.getBalance( + owner.address, + erc20.address, + ); expect(tx1).to.be.ok; await expect(tx1) @@ -1908,8 +2229,13 @@ describe("P2PIX", () => { const lockID = ethers.constants.One; // mine blocks to expire lock await mine(11); - const tx = await p2pix.withdraw(erc20.address, price, [lockID]); - const remaining = await p2pix.callStatic.getBalance(owner.address, erc20.address); + const tx = await p2pix.withdraw(erc20.address, price, [ + lockID, + ]); + const remaining = await p2pix.callStatic.getBalance( + owner.address, + erc20.address, + ); expect(tx).to.be.ok; await expect(tx) @@ -1930,13 +2256,18 @@ describe("P2PIX", () => { true, merkleRoot, ); - const fail = p2pix.connect(acc02).withdraw(erc20.address, price.mul(ethers.constants.Two),[]); + const fail = p2pix + .connect(acc02) + .withdraw( + erc20.address, + price.mul(ethers.constants.Two), + [], + ); await expect(fail).to.be.revertedWithCustomError( p2pix, P2PixErrors.DecOverflow, ); - }); it("should withdraw remaining funds from deposit, update storage and emit event", async () => { const newPrice = price.div(ethers.constants.Two); @@ -1949,9 +2280,9 @@ describe("P2PIX", () => { merkleRoot, ); const tx = await p2pix.withdraw( - erc20.address, - price.div(ethers.constants.Two), - [] + erc20.address, + price.div(ethers.constants.Two), + [], ); expect(tx).to.be.ok; @@ -1979,6 +2310,7 @@ describe("P2PIX", () => { .withArgs(owner.address, erc20.address, newPrice); }); }); + describe("Allowlist Settings", async () => { it("should revert if the msg.sender differs from deposit's seller", async () => { const root = ethers.utils.keccak256( diff --git a/test/utils/errors.ts b/test/utils/errors.ts index 5bf5595..c2e3e98 100644 --- a/test/utils/errors.ts +++ b/test/utils/errors.ts @@ -19,4 +19,5 @@ export enum P2PixErrors { MaxBalExceeded = "MaxBalExceeded", NotInitialized = "NotInitialized", DecOverflow = "DecOverflow", + CallFailed = "CallFailed", } diff --git a/test/utils/fixtures.ts b/test/utils/fixtures.ts index fd9baca..f4b19a5 100644 --- a/test/utils/fixtures.ts +++ b/test/utils/fixtures.ts @@ -6,7 +6,9 @@ import { MerkleTree } from "merkletreejs"; import { MockToken, + Multicall, P2PIX, + P2PIX__factory, Reputation, } from "../../src/types"; @@ -17,14 +19,6 @@ export interface Deploys { token: string; } -// export interface Deposit { -// remaining: BigNumber; -// pixTarget: string; -// seller: string; -// token: string; -// valid: boolean; -// } - export interface Lock { sellerKey: BigNumber; counter: BigNumber; @@ -38,6 +32,16 @@ export interface Lock { token: string; } +export interface Call { + target: string; + callData: string; +} + +export interface Result { + success: boolean; + returnData: string; +} + export interface P2pixFixture { p2pix: P2PIX; erc20: MockToken; @@ -49,19 +53,40 @@ export interface RepFixture { reputation: Reputation; } -type P2PixAndReputation = P2pixFixture & RepFixture; +export interface MtcFixture { + multicall: Multicall; +} + +type P2PixAndReputation = P2pixFixture & + RepFixture & + MtcFixture; // exported constants export const getSignerAddrs = ( amount: number, addrs: SignerWithAddress[], ): string[] => { - const signers: string[] = []; - const buffr = addrs.slice(0, amount); - for (let i = 0; i < amount; i++) { - signers.push(buffr[i].address); - } - return signers; + return addrs.slice(0, amount).map(({ address }) => address); +}; + +export const getBnFrom = (nums: number[]): BigNumber[] => { + const bns = nums.map(num => ethers.BigNumber.from(num)); + return bns; +}; + +export const getLockData = ( + addr: string, + locks: BigNumber[][], +): Call[] => { + const iface = new ethers.utils.Interface( + P2PIX__factory.abi, + ); + return locks.map(lock => ({ + target: addr, + callData: iface.encodeFunctionData("getLocksStatus", [ + lock, + ]), + })); }; export const randomSigners = (amount: number): Signer[] => { @@ -128,6 +153,11 @@ export async function p2pixFixture(): Promise { [true], )) as P2PIX; + const Multicall = await ethers.getContractFactory( + "Multicall", + ); + const multicall = (await Multicall.deploy()) as Multicall; + const signers = await ethers.getSigners(); const whitelisted = signers.slice(0, 2); const leaves = whitelisted.map(account => @@ -142,6 +172,7 @@ export async function p2pixFixture(): Promise { ); return { + multicall, reputation, erc20, p2pix, diff --git a/yarn.lock b/yarn.lock index dcdf33f..aa58fdb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6049,16 +6049,17 @@ fsevents@~2.1.1: languageName: node linkType: hard -"hardhat-tracer@npm:^1.2.0": - version: 1.2.0 - resolution: "hardhat-tracer@npm:1.2.0" +"hardhat-tracer@npm:beta": + version: 2.0.0-beta.6 + resolution: "hardhat-tracer@npm:2.0.0-beta.6" dependencies: ethers: ^5.6.1 peerDependencies: + chai: 4.x chalk: 4.x ethers: 5.x hardhat: 2.x - checksum: 1d348fb3ed60cbde2287329730ccd37c73af80cc2cf4ccfb045f26af26c7efebd4a6fdf611035f34ca7fb75d0eb95985e8f5ed4f0537d2615fb6e126d1d035f0 + checksum: b14795adf3eecd487b874ef06799ab43c342a4908bcf58bbd0bc7274caa7976456a0c75a702aaf3a937fe7c8afbfe2e2a9f263b6a0c7e2fc56e6a54144288369 languageName: node linkType: hard @@ -8459,7 +8460,7 @@ fsevents@~2.1.1: fs-extra: ^10.1.0 hardhat: ^2.12.2 hardhat-gas-reporter: ^1.0.9 - hardhat-tracer: ^1.2.0 + hardhat-tracer: beta husky: ^8.0.1 keccak256: ^1.0.6 lint-staged: ^13.0.3