From 1892e0bd9b0204388d0b0971fa89561fcbd4fa03 Mon Sep 17 00:00:00 2001 From: Filipe Soccol Date: Tue, 8 Nov 2022 16:06:25 -0300 Subject: [PATCH] Add lock and Release tests. Add instructions to run contracts locally. --- README.md | 23 +++ artifacts/contracts/p2pix.sol/P2PIX.dbg.json | 2 +- artifacts/contracts/p2pix.sol/P2PIX.json | 23 ++- contracts/p2pix.sol | 35 ++-- test/2-lock-release.test.js | 174 ++++++++++++++++++- 5 files changed, 234 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 7e8ec4a..087dfd2 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,29 @@ Then use a Contract instance to interact directly with it: const p2pixContract = new ethers.Contract(address, P2PIXArtifact.abi, signer); ``` +## Deploying local environment + +Clone the repo and install dependencies: +``` +git clone https://github.com/doiim/p2pix-smart-contracts.git +cd p2pix-smart-contract +npm install +``` + +On the first teminal use the following command and import some wallets to your Metamask and connect to the network pointed: +``` +npx hardhat node +``` + +On the second teminal run following commands: +``` +npx hardhat run --network localhost scripts/1-deploy-p2pix.js +npx hardhat run --network localhost scripts/2-deploy-mockToken.js +``` + +The second script transfer 2M tokens to the firrs wallet of the node. +To use the P2Pix smart contract first transfer some of the tokens to other wallets. + ## Testing To run tests, clone this repo, install dependencies and run Hardhat tests. diff --git a/artifacts/contracts/p2pix.sol/P2PIX.dbg.json b/artifacts/contracts/p2pix.sol/P2PIX.dbg.json index 51c5d14..81db4d7 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/5ce31c4ec8418c4fef71a52ed732efd0.json" + "buildInfo": "../../build-info/7e909668316aeda4fb9591ef4393e389.json" } diff --git a/artifacts/contracts/p2pix.sol/P2PIX.json b/artifacts/contracts/p2pix.sol/P2PIX.json index ef5cf9d..5511e73 100644 --- a/artifacts/contracts/p2pix.sol/P2PIX.json +++ b/artifacts/contracts/p2pix.sol/P2PIX.json @@ -145,6 +145,12 @@ "internalType": "uint256", "name": "amount", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "locked", + "type": "uint256" } ], "name": "LockAdded", @@ -343,6 +349,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "lockIDs", + "type": "bytes32[]" + } + ], + "name": "unlockExpired", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -381,8 +400,8 @@ "type": "function" } ], - "bytecode": "0x60806040523480156200001157600080fd5b50604051620026cf380380620026cf83398181016040528101906200003791906200030d565b8160008190555060005b81518160ff161015620000db576001806000848460ff16815181106200006c576200006b62000373565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080620000d290620003de565b91505062000041565b5050506200040c565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6200010d81620000f8565b81146200011957600080fd5b50565b6000815190506200012d8162000102565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620001838262000138565b810181811067ffffffffffffffff82111715620001a557620001a462000149565b5b80604052505050565b6000620001ba620000e4565b9050620001c8828262000178565b919050565b600067ffffffffffffffff821115620001eb57620001ea62000149565b5b602082029050602081019050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022e8262000201565b9050919050565b620002408162000221565b81146200024c57600080fd5b50565b600081519050620002608162000235565b92915050565b60006200027d6200027784620001cd565b620001ae565b90508083825260208201905060208402830185811115620002a357620002a2620001fc565b5b835b81811015620002d05780620002bb88826200024f565b845260208401935050602081019050620002a5565b5050509392505050565b600082601f830112620002f257620002f162000133565b5b81516200030484826020860162000266565b91505092915050565b60008060408385031215620003275762000326620000ee565b5b600062000337858286016200011c565b925050602083015167ffffffffffffffff8111156200035b576200035a620000f3565b5b6200036985828601620002da565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff82169050919050565b6000620003eb82620003d1565b915060ff8203620004015762000400620003a2565b5b600182019050919050565b6122b3806200041c6000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063708ace651161005b578063708ace65146101115780639872dbfe14610141578063b93bd7d41461015f578063e33f72911461018f57610088565b8063314044841461008d5780633a8cbc38146100a95780634b83a7be146100d95780634e1389ed146100f5575b600080fd5b6100a760048036038101906100a291906111a4565b6101ab565b005b6100c360048036038101906100be91906112ca565b610307565b6040516100d09190611361565b60405180910390f35b6100f360048036038101906100ee91906113d2565b610612565b005b61010f600480360381019061010a919061146b565b610835565b005b61012b600480360381019061012691906114e6565b610c3b565b6040516101389190611361565b60405180910390f35b610149610f58565b60405161015691906115a4565b60405180910390f35b610179600480360381019061017491906115bf565b610f5e565b6040516101869190611607565b60405180910390f35b6101a960048036038101906101a49190611622565b610f7e565b005b803373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610250576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610247906116e5565b60405180910390fd5b60006002600084815260200190815260200160002060040160006101000a81548160ff0219169083151502179055506002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f81a84d666c6a692c1cf93ca3b3648cc7bf23d34a1c6afa2e15e346f424baa06c836040516102fb9190611361565b60405180910390a25050565b600082828660405160200161031e93929190611765565b6040516020818303038152906040528051906020012090506002600082815260200190815260200160002060040160009054906101000a900460ff161561039a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039190611801565b60405180910390fd5b60008690508073ffffffffffffffffffffffffffffffffffffffff166323b872dd3330896040518463ffffffff1660e01b81526004016103dc93929190611830565b6020604051808303816000875af11580156103fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041f9190611893565b5060006040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff16815260200188815260200187815260200160011515815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050806002600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050190816105af9190611b06565b509050503373ffffffffffffffffffffffffffffffffffffffff167fb2d817df1a92003b7e8b40681145547601989b987e206c6f7d0bc46369652913848a898b6040516105ff9493929190611bd8565b60405180910390a2505095945050505050565b823373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ae906116e5565b60405180910390fd5b6106c18383610fdb565b60006002600086815260200190815260200160002090508060040160009054906101000a900460ff16156106f9576106f8856101ab565b5b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600201546040518363ffffffff1660e01b8152600401610785929190611c1d565b6020604051808303816000875af11580156107a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c89190611893565b50600082600201549050600083600201819055503373ffffffffffffffffffffffffffffffffffffffff167fbc44d79619424e05dd4e8ea6a3e67823f43e45cf0c9b52463ec7a8806146991d8883604051610824929190611c46565b60405180910390a250505050505050565b60006003600087815260200190815260200160002090506000600260008360000154815260200190815260200160002090506000600260008460000154815260200190815260200160002060050183600401548860405160200161089b93929190611cf2565b6040516020818303038152906040528051906020012090506004600082815260200190815260200160002060009054906101000a900460ff1615610914576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090b90611d9d565b60405180910390fd5b6000600182868989604051600081526020016040526040516109399493929190611dcc565b6020604051602081039080840390855afa15801561095b573d6000803e3d6000fd5b505050602060405103519050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166109f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ea90611e5d565b60405180910390fd5b60008360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8660010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687600301548860050154610a719190611eac565b6040518363ffffffff1660e01b8152600401610a8e929190611c1d565b6020604051808303816000875af1158015610aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad19190611893565b50600085600301541115610b87578073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8660020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687600301546040518363ffffffff1660e01b8152600401610b42929190611c1d565b6020604051808303816000875af1158015610b61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b859190611893565b505b6000856004018190555060016004600085815260200190815260200160002060006101000a81548160ff0219169083151502179055508460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5e420822d2f7281fdc4b763c62c8b7874bf22108a35efe93144d79296aacc67d8b604051610c279190611361565b60405180910390a250505050505050505050565b6000610c478383610fdb565b6000600260008a815260200190815260200160002090508060040160009054906101000a900460ff16610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca690611f2c565b60405180910390fd5b806003015485610cbf9190611f7b565b816002015411610d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfb90611ff8565b60405180910390fd5b888589604051602001610d1993929190612081565b60405160208183030381529060405280519060200120915043600360008481526020019081526020016000206006015410610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8090612130565b60405180910390fd5b60006040518060e001604052808b81526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff168152602001888152602001878152602001836003015488610df09190611f7b565b815260200160005443610e039190612150565b815250905080600360008581526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505085826002016000828254610ef39190611eac565b92505081905550828973ffffffffffffffffffffffffffffffffffffffff167f51a2e0610065407cec419b292d4e03c1149e2336f34bc3bdab24dba9fe7edbff8c89604051610f43929190611c46565b60405180910390a35050979650505050505050565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6000600260008481526020019081526020016000209050818160030181905550827f42dfc0c297064717f06aefc162216c94dc59f9a1af9ff6ed92f00cadbe9ba80383604051610fce91906115a4565b60405180910390a2505050565b600082829050905060005b818161ffff16101561115e5760006003600086868561ffff1681811061100f5761100e612184565b5b905060200201358152602001908152602001600020905043816006015410801561103d575060008160040154115b61107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107390612225565b60405180910390fd5b8060040154600260008360000154815260200190815260200160002060020160008282546110aa9190612150565b92505081905550600081600401819055508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f67e089478e21dd12c98e69331c4152f6c9b2038b91e0f28268ffa01558c0b4ff86868561ffff1681811061112e5761112d612184565b5b905060200201356040516111429190611361565b60405180910390a250808061115690612253565b915050610fe6565b50505050565b600080fd5b600080fd5b6000819050919050565b6111818161116e565b811461118c57600080fd5b50565b60008135905061119e81611178565b92915050565b6000602082840312156111ba576111b9611164565b5b60006111c88482850161118f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006111fc826111d1565b9050919050565b61120c816111f1565b811461121757600080fd5b50565b60008135905061122981611203565b92915050565b6000819050919050565b6112428161122f565b811461124d57600080fd5b50565b60008135905061125f81611239565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261128a57611289611265565b5b8235905067ffffffffffffffff8111156112a7576112a661126a565b5b6020830191508360018202830111156112c3576112c261126f565b5b9250929050565b6000806000806000608086880312156112e6576112e5611164565b5b60006112f48882890161121a565b955050602061130588828901611250565b945050604061131688828901611250565b935050606086013567ffffffffffffffff81111561133757611336611169565b5b61134388828901611274565b92509250509295509295909350565b61135b8161116e565b82525050565b60006020820190506113766000830184611352565b92915050565b60008083601f84011261139257611391611265565b5b8235905067ffffffffffffffff8111156113af576113ae61126a565b5b6020830191508360208202830111156113cb576113ca61126f565b5b9250929050565b6000806000604084860312156113eb576113ea611164565b5b60006113f98682870161118f565b935050602084013567ffffffffffffffff81111561141a57611419611169565b5b6114268682870161137c565b92509250509250925092565b600060ff82169050919050565b61144881611432565b811461145357600080fd5b50565b6000813590506114658161143f565b92915050565b600080600080600060a0868803121561148757611486611164565b5b60006114958882890161118f565b95505060206114a688828901611250565b94505060406114b78882890161118f565b93505060606114c88882890161118f565b92505060806114d988828901611456565b9150509295509295909350565b600080600080600080600060c0888a03121561150557611504611164565b5b60006115138a828b0161118f565b97505060206115248a828b0161121a565b96505060406115358a828b0161121a565b95505060606115468a828b01611250565b94505060806115578a828b01611250565b93505060a088013567ffffffffffffffff81111561157857611577611169565b5b6115848a828b0161137c565b925092505092959891949750929550565b61159e8161122f565b82525050565b60006020820190506115b96000830184611595565b92915050565b6000602082840312156115d5576115d4611164565b5b60006115e38482850161121a565b91505092915050565b60008115159050919050565b611601816115ec565b82525050565b600060208201905061161c60008301846115f8565b92915050565b6000806040838503121561163957611638611164565b5b60006116478582860161118f565b925050602061165885828601611250565b9150509250929050565b600082825260208201905092915050565b7f50325049583a204f6e6c792073656c6c657220636f756c642063616c6c20746860008201527f69732066756e6374696f6e2e0000000000000000000000000000000000000000602082015250565b60006116cf602c83611662565b91506116da82611673565b604082019050919050565b600060208201905081810360008301526116fe816116c2565b9050919050565b600081905092915050565b82818337600083830152505050565b600061172b8385611705565b9350611738838584611710565b82840190509392505050565b6000819050919050565b61175f61175a8261122f565b611744565b82525050565b600061177282858761171f565b915061177e828461174e565b602082019150819050949350505050565b7f50325049583a204465706f73697420616c726561647920657869737420616e6460008201527f206974206973207374696c6c2076616c69640000000000000000000000000000602082015250565b60006117eb603283611662565b91506117f68261178f565b604082019050919050565b6000602082019050818103600083015261181a816117de565b9050919050565b61182a816111f1565b82525050565b60006060820190506118456000830186611821565b6118526020830185611821565b61185f6040830184611595565b949350505050565b611870816115ec565b811461187b57600080fd5b50565b60008151905061188d81611867565b92915050565b6000602082840312156118a9576118a8611164565b5b60006118b78482850161187e565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061194157607f821691505b602082108103611954576119536118fa565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119bc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261197f565b6119c6868361197f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a036119fe6119f98461122f565b6119de565b61122f565b9050919050565b6000819050919050565b611a1d836119e8565b611a31611a2982611a0a565b84845461198c565b825550505050565b600090565b611a46611a39565b611a51818484611a14565b505050565b5b81811015611a7557611a6a600082611a3e565b600181019050611a57565b5050565b601f821115611aba57611a8b8161195a565b611a948461196f565b81016020851015611aa3578190505b611ab7611aaf8561196f565b830182611a56565b50505b505050565b600082821c905092915050565b6000611add60001984600802611abf565b1980831691505092915050565b6000611af68383611acc565b9150826002028217905092915050565b611b0f826118c0565b67ffffffffffffffff811115611b2857611b276118cb565b5b611b328254611929565b611b3d828285611a79565b600060209050601f831160018114611b705760008415611b5e578287015190505b611b688582611aea565b865550611bd0565b601f198416611b7e8661195a565b60005b82811015611ba657848901518255600182019150602085019450602081019050611b81565b86831015611bc35784890151611bbf601f891682611acc565b8355505b6001600288020188555050505b505050505050565b6000608082019050611bed6000830187611352565b611bfa6020830186611821565b611c076040830185611595565b611c146060830184611595565b95945050505050565b6000604082019050611c326000830185611821565b611c3f6020830184611595565b9392505050565b6000604082019050611c5b6000830185611352565b611c686020830184611595565b9392505050565b60008154611c7c81611929565b611c868186611705565b94506001821660008114611ca15760018114611cb657611ce9565b60ff1983168652811515820286019350611ce9565b611cbf8561195a565b60005b83811015611ce157815481890152600182019150602081019050611cc2565b838801955050505b50505092915050565b6000611cfe8286611c6f565b9150611d0a828561174e565b602082019150611d1a828461174e565b602082019150819050949350505050565b7f5472616e73616374696f6e20616c7265616479207573656420746f20756e6c6f60008201527f636b207061796d656e742e000000000000000000000000000000000000000000602082015250565b6000611d87602b83611662565b9150611d9282611d2b565b604082019050919050565b60006020820190508181036000830152611db681611d7a565b9050919050565b611dc681611432565b82525050565b6000608082019050611de16000830187611352565b611dee6020830186611dbd565b611dfb6040830185611352565b611e086060830184611352565b95945050505050565b7f5369676e6572206973206e6f7420612076616c6964207369676e65722e000000600082015250565b6000611e47601d83611662565b9150611e5282611e11565b602082019050919050565b60006020820190508181036000830152611e7681611e3a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611eb78261122f565b9150611ec28361122f565b9250828203905081811115611eda57611ed9611e7d565b5b92915050565b7f50325049583a204465706f736974206e6f742076616c696420616e796d6f7265600082015250565b6000611f16602083611662565b9150611f2182611ee0565b602082019050919050565b60006020820190508181036000830152611f4581611f09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f868261122f565b9150611f918361122f565b925082611fa157611fa0611f4c565b5b828204905092915050565b7f50325049583a204e6f7420656e6f7567682072656d61696e696e670000000000600082015250565b6000611fe2601b83611662565b9150611fed82611fac565b602082019050919050565b6000602082019050818103600083015261201181611fd5565b9050919050565b6000819050919050565b61203361202e8261116e565b612018565b82525050565b60008160601b9050919050565b600061205182612039565b9050919050565b600061206382612046565b9050919050565b61207b612076826111f1565b612058565b82525050565b600061208d8286612022565b60208201915061209d828561174e565b6020820191506120ad828461206a565b601482019150819050949350505050565b7f50325049583a20416e6f74686572206c6f636b20776974682073616d6520494460008201527f206973206e6f7420657870697265642079657400000000000000000000000000602082015250565b600061211a603383611662565b9150612125826120be565b604082019050919050565b600060208201905081810360008301526121498161210d565b9050919050565b600061215b8261122f565b91506121668361122f565b925082820190508082111561217e5761217d611e7d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50325049583a204c6f636b206e6f742065787069726564206f7220616c72656160008201527f6479207061696400000000000000000000000000000000000000000000000000602082015250565b600061220f602783611662565b915061221a826121b3565b604082019050919050565b6000602082019050818103600083015261223e81612202565b9050919050565b600061ffff82169050919050565b600061225e82612245565b915061ffff820361227257612271611e7d565b5b60018201905091905056fea2646970667358221220c53996c989fa22a5161ea19229cf4a37bd9ddd0c602f2269f8b7baaaf7c9ff5a64736f6c63430008110033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063708ace651161005b578063708ace65146101115780639872dbfe14610141578063b93bd7d41461015f578063e33f72911461018f57610088565b8063314044841461008d5780633a8cbc38146100a95780634b83a7be146100d95780634e1389ed146100f5575b600080fd5b6100a760048036038101906100a291906111a4565b6101ab565b005b6100c360048036038101906100be91906112ca565b610307565b6040516100d09190611361565b60405180910390f35b6100f360048036038101906100ee91906113d2565b610612565b005b61010f600480360381019061010a919061146b565b610835565b005b61012b600480360381019061012691906114e6565b610c3b565b6040516101389190611361565b60405180910390f35b610149610f58565b60405161015691906115a4565b60405180910390f35b610179600480360381019061017491906115bf565b610f5e565b6040516101869190611607565b60405180910390f35b6101a960048036038101906101a49190611622565b610f7e565b005b803373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610250576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610247906116e5565b60405180910390fd5b60006002600084815260200190815260200160002060040160006101000a81548160ff0219169083151502179055506002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f81a84d666c6a692c1cf93ca3b3648cc7bf23d34a1c6afa2e15e346f424baa06c836040516102fb9190611361565b60405180910390a25050565b600082828660405160200161031e93929190611765565b6040516020818303038152906040528051906020012090506002600082815260200190815260200160002060040160009054906101000a900460ff161561039a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039190611801565b60405180910390fd5b60008690508073ffffffffffffffffffffffffffffffffffffffff166323b872dd3330896040518463ffffffff1660e01b81526004016103dc93929190611830565b6020604051808303816000875af11580156103fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041f9190611893565b5060006040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff16815260200188815260200187815260200160011515815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050806002600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050190816105af9190611b06565b509050503373ffffffffffffffffffffffffffffffffffffffff167fb2d817df1a92003b7e8b40681145547601989b987e206c6f7d0bc46369652913848a898b6040516105ff9493929190611bd8565b60405180910390a2505095945050505050565b823373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106ae906116e5565b60405180910390fd5b6106c18383610fdb565b60006002600086815260200190815260200160002090508060040160009054906101000a900460ff16156106f9576106f8856101ab565b5b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600201546040518363ffffffff1660e01b8152600401610785929190611c1d565b6020604051808303816000875af11580156107a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c89190611893565b50600082600201549050600083600201819055503373ffffffffffffffffffffffffffffffffffffffff167fbc44d79619424e05dd4e8ea6a3e67823f43e45cf0c9b52463ec7a8806146991d8883604051610824929190611c46565b60405180910390a250505050505050565b60006003600087815260200190815260200160002090506000600260008360000154815260200190815260200160002090506000600260008460000154815260200190815260200160002060050183600401548860405160200161089b93929190611cf2565b6040516020818303038152906040528051906020012090506004600082815260200190815260200160002060009054906101000a900460ff1615610914576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090b90611d9d565b60405180910390fd5b6000600182868989604051600081526020016040526040516109399493929190611dcc565b6020604051602081039080840390855afa15801561095b573d6000803e3d6000fd5b505050602060405103519050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166109f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ea90611e5d565b60405180910390fd5b60008360010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8660010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687600301548860050154610a719190611eac565b6040518363ffffffff1660e01b8152600401610a8e929190611c1d565b6020604051808303816000875af1158015610aad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ad19190611893565b50600085600301541115610b87578073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8660020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687600301546040518363ffffffff1660e01b8152600401610b42929190611c1d565b6020604051808303816000875af1158015610b61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b859190611893565b505b6000856004018190555060016004600085815260200190815260200160002060006101000a81548160ff0219169083151502179055508460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5e420822d2f7281fdc4b763c62c8b7874bf22108a35efe93144d79296aacc67d8b604051610c279190611361565b60405180910390a250505050505050505050565b6000610c478383610fdb565b6000600260008a815260200190815260200160002090508060040160009054906101000a900460ff16610caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ca690611f2c565b60405180910390fd5b806003015485610cbf9190611f7b565b816002015411610d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cfb90611ff8565b60405180910390fd5b888589604051602001610d1993929190612081565b60405160208183030381529060405280519060200120915043600360008481526020019081526020016000206006015410610d89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8090612130565b60405180910390fd5b60006040518060e001604052808b81526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff168152602001888152602001878152602001836003015488610df09190611f7b565b815260200160005443610e039190612150565b815250905080600360008581526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505085826002016000828254610ef39190611eac565b92505081905550828973ffffffffffffffffffffffffffffffffffffffff167f51a2e0610065407cec419b292d4e03c1149e2336f34bc3bdab24dba9fe7edbff8c89604051610f43929190611c46565b60405180910390a35050979650505050505050565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6000600260008481526020019081526020016000209050818160030181905550827f42dfc0c297064717f06aefc162216c94dc59f9a1af9ff6ed92f00cadbe9ba80383604051610fce91906115a4565b60405180910390a2505050565b600082829050905060005b818161ffff16101561115e5760006003600086868561ffff1681811061100f5761100e612184565b5b905060200201358152602001908152602001600020905043816006015410801561103d575060008160040154115b61107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107390612225565b60405180910390fd5b8060040154600260008360000154815260200190815260200160002060020160008282546110aa9190612150565b92505081905550600081600401819055508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f67e089478e21dd12c98e69331c4152f6c9b2038b91e0f28268ffa01558c0b4ff86868561ffff1681811061112e5761112d612184565b5b905060200201356040516111429190611361565b60405180910390a250808061115690612253565b915050610fe6565b50505050565b600080fd5b600080fd5b6000819050919050565b6111818161116e565b811461118c57600080fd5b50565b60008135905061119e81611178565b92915050565b6000602082840312156111ba576111b9611164565b5b60006111c88482850161118f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006111fc826111d1565b9050919050565b61120c816111f1565b811461121757600080fd5b50565b60008135905061122981611203565b92915050565b6000819050919050565b6112428161122f565b811461124d57600080fd5b50565b60008135905061125f81611239565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261128a57611289611265565b5b8235905067ffffffffffffffff8111156112a7576112a661126a565b5b6020830191508360018202830111156112c3576112c261126f565b5b9250929050565b6000806000806000608086880312156112e6576112e5611164565b5b60006112f48882890161121a565b955050602061130588828901611250565b945050604061131688828901611250565b935050606086013567ffffffffffffffff81111561133757611336611169565b5b61134388828901611274565b92509250509295509295909350565b61135b8161116e565b82525050565b60006020820190506113766000830184611352565b92915050565b60008083601f84011261139257611391611265565b5b8235905067ffffffffffffffff8111156113af576113ae61126a565b5b6020830191508360208202830111156113cb576113ca61126f565b5b9250929050565b6000806000604084860312156113eb576113ea611164565b5b60006113f98682870161118f565b935050602084013567ffffffffffffffff81111561141a57611419611169565b5b6114268682870161137c565b92509250509250925092565b600060ff82169050919050565b61144881611432565b811461145357600080fd5b50565b6000813590506114658161143f565b92915050565b600080600080600060a0868803121561148757611486611164565b5b60006114958882890161118f565b95505060206114a688828901611250565b94505060406114b78882890161118f565b93505060606114c88882890161118f565b92505060806114d988828901611456565b9150509295509295909350565b600080600080600080600060c0888a03121561150557611504611164565b5b60006115138a828b0161118f565b97505060206115248a828b0161121a565b96505060406115358a828b0161121a565b95505060606115468a828b01611250565b94505060806115578a828b01611250565b93505060a088013567ffffffffffffffff81111561157857611577611169565b5b6115848a828b0161137c565b925092505092959891949750929550565b61159e8161122f565b82525050565b60006020820190506115b96000830184611595565b92915050565b6000602082840312156115d5576115d4611164565b5b60006115e38482850161121a565b91505092915050565b60008115159050919050565b611601816115ec565b82525050565b600060208201905061161c60008301846115f8565b92915050565b6000806040838503121561163957611638611164565b5b60006116478582860161118f565b925050602061165885828601611250565b9150509250929050565b600082825260208201905092915050565b7f50325049583a204f6e6c792073656c6c657220636f756c642063616c6c20746860008201527f69732066756e6374696f6e2e0000000000000000000000000000000000000000602082015250565b60006116cf602c83611662565b91506116da82611673565b604082019050919050565b600060208201905081810360008301526116fe816116c2565b9050919050565b600081905092915050565b82818337600083830152505050565b600061172b8385611705565b9350611738838584611710565b82840190509392505050565b6000819050919050565b61175f61175a8261122f565b611744565b82525050565b600061177282858761171f565b915061177e828461174e565b602082019150819050949350505050565b7f50325049583a204465706f73697420616c726561647920657869737420616e6460008201527f206974206973207374696c6c2076616c69640000000000000000000000000000602082015250565b60006117eb603283611662565b91506117f68261178f565b604082019050919050565b6000602082019050818103600083015261181a816117de565b9050919050565b61182a816111f1565b82525050565b60006060820190506118456000830186611821565b6118526020830185611821565b61185f6040830184611595565b949350505050565b611870816115ec565b811461187b57600080fd5b50565b60008151905061188d81611867565b92915050565b6000602082840312156118a9576118a8611164565b5b60006118b78482850161187e565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061194157607f821691505b602082108103611954576119536118fa565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119bc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261197f565b6119c6868361197f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a036119fe6119f98461122f565b6119de565b61122f565b9050919050565b6000819050919050565b611a1d836119e8565b611a31611a2982611a0a565b84845461198c565b825550505050565b600090565b611a46611a39565b611a51818484611a14565b505050565b5b81811015611a7557611a6a600082611a3e565b600181019050611a57565b5050565b601f821115611aba57611a8b8161195a565b611a948461196f565b81016020851015611aa3578190505b611ab7611aaf8561196f565b830182611a56565b50505b505050565b600082821c905092915050565b6000611add60001984600802611abf565b1980831691505092915050565b6000611af68383611acc565b9150826002028217905092915050565b611b0f826118c0565b67ffffffffffffffff811115611b2857611b276118cb565b5b611b328254611929565b611b3d828285611a79565b600060209050601f831160018114611b705760008415611b5e578287015190505b611b688582611aea565b865550611bd0565b601f198416611b7e8661195a565b60005b82811015611ba657848901518255600182019150602085019450602081019050611b81565b86831015611bc35784890151611bbf601f891682611acc565b8355505b6001600288020188555050505b505050505050565b6000608082019050611bed6000830187611352565b611bfa6020830186611821565b611c076040830185611595565b611c146060830184611595565b95945050505050565b6000604082019050611c326000830185611821565b611c3f6020830184611595565b9392505050565b6000604082019050611c5b6000830185611352565b611c686020830184611595565b9392505050565b60008154611c7c81611929565b611c868186611705565b94506001821660008114611ca15760018114611cb657611ce9565b60ff1983168652811515820286019350611ce9565b611cbf8561195a565b60005b83811015611ce157815481890152600182019150602081019050611cc2565b838801955050505b50505092915050565b6000611cfe8286611c6f565b9150611d0a828561174e565b602082019150611d1a828461174e565b602082019150819050949350505050565b7f5472616e73616374696f6e20616c7265616479207573656420746f20756e6c6f60008201527f636b207061796d656e742e000000000000000000000000000000000000000000602082015250565b6000611d87602b83611662565b9150611d9282611d2b565b604082019050919050565b60006020820190508181036000830152611db681611d7a565b9050919050565b611dc681611432565b82525050565b6000608082019050611de16000830187611352565b611dee6020830186611dbd565b611dfb6040830185611352565b611e086060830184611352565b95945050505050565b7f5369676e6572206973206e6f7420612076616c6964207369676e65722e000000600082015250565b6000611e47601d83611662565b9150611e5282611e11565b602082019050919050565b60006020820190508181036000830152611e7681611e3a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611eb78261122f565b9150611ec28361122f565b9250828203905081811115611eda57611ed9611e7d565b5b92915050565b7f50325049583a204465706f736974206e6f742076616c696420616e796d6f7265600082015250565b6000611f16602083611662565b9150611f2182611ee0565b602082019050919050565b60006020820190508181036000830152611f4581611f09565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611f868261122f565b9150611f918361122f565b925082611fa157611fa0611f4c565b5b828204905092915050565b7f50325049583a204e6f7420656e6f7567682072656d61696e696e670000000000600082015250565b6000611fe2601b83611662565b9150611fed82611fac565b602082019050919050565b6000602082019050818103600083015261201181611fd5565b9050919050565b6000819050919050565b61203361202e8261116e565b612018565b82525050565b60008160601b9050919050565b600061205182612039565b9050919050565b600061206382612046565b9050919050565b61207b612076826111f1565b612058565b82525050565b600061208d8286612022565b60208201915061209d828561174e565b6020820191506120ad828461206a565b601482019150819050949350505050565b7f50325049583a20416e6f74686572206c6f636b20776974682073616d6520494460008201527f206973206e6f7420657870697265642079657400000000000000000000000000602082015250565b600061211a603383611662565b9150612125826120be565b604082019050919050565b600060208201905081810360008301526121498161210d565b9050919050565b600061215b8261122f565b91506121668361122f565b925082820190508082111561217e5761217d611e7d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50325049583a204c6f636b206e6f742065787069726564206f7220616c72656160008201527f6479207061696400000000000000000000000000000000000000000000000000602082015250565b600061220f602783611662565b915061221a826121b3565b604082019050919050565b6000602082019050818103600083015261223e81612202565b9050919050565b600061ffff82169050919050565b600061225e82612245565b915061ffff820361227257612271611e7d565b5b60018201905091905056fea2646970667358221220c53996c989fa22a5161ea19229cf4a37bd9ddd0c602f2269f8b7baaaf7c9ff5a64736f6c63430008110033", + "bytecode": "0x60806040523480156200001157600080fd5b50604051620029a5380380620029a583398181016040528101906200003791906200030d565b8160008190555060005b81518160ff161015620000db576001806000848460ff16815181106200006c576200006b62000373565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508080620000d290620003de565b91505062000041565b5050506200040c565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6200010d81620000f8565b81146200011957600080fd5b50565b6000815190506200012d8162000102565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620001838262000138565b810181811067ffffffffffffffff82111715620001a557620001a462000149565b5b80604052505050565b6000620001ba620000e4565b9050620001c8828262000178565b919050565b600067ffffffffffffffff821115620001eb57620001ea62000149565b5b602082029050602081019050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200022e8262000201565b9050919050565b620002408162000221565b81146200024c57600080fd5b50565b600081519050620002608162000235565b92915050565b60006200027d6200027784620001cd565b620001ae565b90508083825260208201905060208402830185811115620002a357620002a2620001fc565b5b835b81811015620002d05780620002bb88826200024f565b845260208401935050602081019050620002a5565b5050509392505050565b600082601f830112620002f257620002f162000133565b5b81516200030484826020860162000266565b91505092915050565b60008060408385031215620003275762000326620000ee565b5b600062000337858286016200011c565b925050602083015167ffffffffffffffff8111156200035b576200035a620000f3565b5b6200036985828601620002da565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff82169050919050565b6000620003eb82620003d1565b915060ff8203620004015762000400620003a2565b5b600182019050919050565b612589806200041c6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063708ace6511610066578063708ace651461011c5780638e2749d61461014c5780639872dbfe14610168578063b93bd7d414610186578063e33f7291146101b657610093565b806331404484146100985780633a8cbc38146100b45780634b83a7be146100e45780634e1389ed14610100575b600080fd5b6100b260048036038101906100ad9190611264565b6101d2565b005b6100ce60048036038101906100c9919061138a565b61032e565b6040516100db9190611421565b60405180910390f35b6100fe60048036038101906100f99190611492565b610639565b005b61011a6004803603810190610115919061152b565b61085c565b005b610136600480360381019061013191906115a6565b610cee565b6040516101439190611421565b60405180910390f35b61016660048036038101906101619190611655565b611018565b005b6101706111a1565b60405161017d91906116b1565b60405180910390f35b6101a0600480360381019061019b91906116cc565b6111a7565b6040516101ad9190611714565b60405180910390f35b6101d060048036038101906101cb919061172f565b6111c7565b005b803373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161026e906117f2565b60405180910390fd5b60006002600084815260200190815260200160002060040160006101000a81548160ff0219169083151502179055506002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f81a84d666c6a692c1cf93ca3b3648cc7bf23d34a1c6afa2e15e346f424baa06c836040516103229190611421565b60405180910390a25050565b600082828660405160200161034593929190611872565b6040516020818303038152906040528051906020012090506002600082815260200190815260200160002060040160009054906101000a900460ff16156103c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103b89061190e565b60405180910390fd5b60008690508073ffffffffffffffffffffffffffffffffffffffff166323b872dd3330896040518463ffffffff1660e01b81526004016104039392919061193d565b6020604051808303816000875af1158015610422573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044691906119a0565b5060006040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff16815260200188815260200187815260200160011515815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050806002600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050190816105d69190611c13565b509050503373ffffffffffffffffffffffffffffffffffffffff167fb2d817df1a92003b7e8b40681145547601989b987e206c6f7d0bc46369652913848a898b6040516106269493929190611ce5565b60405180910390a2505095945050505050565b823373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106d5906117f2565b60405180910390fd5b6106e88383611018565b60006002600086815260200190815260200160002090508060040160009054906101000a900460ff16156107205761071f856101d2565b5b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600201546040518363ffffffff1660e01b81526004016107ac929190611d2a565b6020604051808303816000875af11580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef91906119a0565b50600082600201549050600083600201819055503373ffffffffffffffffffffffffffffffffffffffff167fbc44d79619424e05dd4e8ea6a3e67823f43e45cf0c9b52463ec7a8806146991d888360405161084b929190611d53565b60405180910390a250505050505050565b600060036000878152602001908152602001600020905043816006015411801561088a575060008160050154115b6108c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c090611dee565b60405180910390fd5b6000600260008360000154815260200190815260200160002090506000600260008460000154815260200190815260200160002060050183600401548860405160200161091893929190611e91565b6040516020818303038152906040528051906020012090506000816040516020016109439190611f37565b6040516020818303038152906040528051906020012090506004600083815260200190815260200160002060009054906101000a900460ff16156109bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b390611fcf565b60405180910390fd5b6000600182878a8a604051600081526020016040526040516109e19493929190611ffe565b6020604051602081039080840390855afa158015610a03573d6000803e3d6000fd5b505050602060405103519050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a92906120b5565b60405180910390fd5b60008460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8760010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688600301548960050154610b199190612104565b6040518363ffffffff1660e01b8152600401610b36929190611d2a565b6020604051808303816000875af1158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7991906119a0565b50600086600301541115610c2f578073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688600301546040518363ffffffff1660e01b8152600401610bea929190611d2a565b6020604051808303816000875af1158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906119a0565b505b600086600501819055506000866006018190555060016004600086815260200190815260200160002060006101000a81548160ff0219169083151502179055508560010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5e420822d2f7281fdc4b763c62c8b7874bf22108a35efe93144d79296aacc67d8c604051610cd99190611421565b60405180910390a25050505050505050505050565b6000610cfa8383611018565b6000600260008a815260200190815260200160002090508060040160009054906101000a900460ff16610d62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5990612184565b60405180910390fd5b60008160030154670de0b6b3a764000087610d7d91906121a4565b610d879190612215565b90508082600201541015610dd0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc7906122b8565b60405180910390fd5b89868a604051602001610de593929190612320565b60405160208183030381529060405280519060200120925043600360008581526020019081526020016000206006015410610e55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e4c906123cf565b60405180910390fd5b60006040518060e001604052808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff16815260200189815260200188815260200183815260200160005443610ec091906123ef565b815250905080600360008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081836002016000828254610fb09190612104565b92505081905550838a73ffffffffffffffffffffffffffffffffffffffff167fd122043a71eaa13e3a89d5660c858559e90861de4a8afcb4a9795e855539d6438d8a8660405161100293929190612423565b60405180910390a3505050979650505050505050565b600082829050905060005b818161ffff16101561119b5760006003600086868561ffff1681811061104c5761104b61245a565b5b905060200201358152602001908152602001600020905043816006015410801561107a575060008160050154115b6110b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b0906124fb565b60405180910390fd5b8060050154600260008360000154815260200190815260200160002060020160008282546110e791906123ef565b92505081905550600081600501819055508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f67e089478e21dd12c98e69331c4152f6c9b2038b91e0f28268ffa01558c0b4ff86868561ffff1681811061116b5761116a61245a565b5b9050602002013560405161117f9190611421565b60405180910390a250808061119390612529565b915050611023565b50505050565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6000600260008481526020019081526020016000209050818160030181905550827f42dfc0c297064717f06aefc162216c94dc59f9a1af9ff6ed92f00cadbe9ba8038360405161121791906116b1565b60405180910390a2505050565b600080fd5b600080fd5b6000819050919050565b6112418161122e565b811461124c57600080fd5b50565b60008135905061125e81611238565b92915050565b60006020828403121561127a57611279611224565b5b60006112888482850161124f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006112bc82611291565b9050919050565b6112cc816112b1565b81146112d757600080fd5b50565b6000813590506112e9816112c3565b92915050565b6000819050919050565b611302816112ef565b811461130d57600080fd5b50565b60008135905061131f816112f9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261134a57611349611325565b5b8235905067ffffffffffffffff8111156113675761136661132a565b5b6020830191508360018202830111156113835761138261132f565b5b9250929050565b6000806000806000608086880312156113a6576113a5611224565b5b60006113b4888289016112da565b95505060206113c588828901611310565b94505060406113d688828901611310565b935050606086013567ffffffffffffffff8111156113f7576113f6611229565b5b61140388828901611334565b92509250509295509295909350565b61141b8161122e565b82525050565b60006020820190506114366000830184611412565b92915050565b60008083601f84011261145257611451611325565b5b8235905067ffffffffffffffff81111561146f5761146e61132a565b5b60208301915083602082028301111561148b5761148a61132f565b5b9250929050565b6000806000604084860312156114ab576114aa611224565b5b60006114b98682870161124f565b935050602084013567ffffffffffffffff8111156114da576114d9611229565b5b6114e68682870161143c565b92509250509250925092565b600060ff82169050919050565b611508816114f2565b811461151357600080fd5b50565b600081359050611525816114ff565b92915050565b600080600080600060a0868803121561154757611546611224565b5b60006115558882890161124f565b955050602061156688828901611310565b94505060406115778882890161124f565b93505060606115888882890161124f565b925050608061159988828901611516565b9150509295509295909350565b600080600080600080600060c0888a0312156115c5576115c4611224565b5b60006115d38a828b0161124f565b97505060206115e48a828b016112da565b96505060406115f58a828b016112da565b95505060606116068a828b01611310565b94505060806116178a828b01611310565b93505060a088013567ffffffffffffffff81111561163857611637611229565b5b6116448a828b0161143c565b925092505092959891949750929550565b6000806020838503121561166c5761166b611224565b5b600083013567ffffffffffffffff81111561168a57611689611229565b5b6116968582860161143c565b92509250509250929050565b6116ab816112ef565b82525050565b60006020820190506116c660008301846116a2565b92915050565b6000602082840312156116e2576116e1611224565b5b60006116f0848285016112da565b91505092915050565b60008115159050919050565b61170e816116f9565b82525050565b60006020820190506117296000830184611705565b92915050565b6000806040838503121561174657611745611224565b5b60006117548582860161124f565b925050602061176585828601611310565b9150509250929050565b600082825260208201905092915050565b7f50325049583a204f6e6c792073656c6c657220636f756c642063616c6c20746860008201527f69732066756e6374696f6e2e0000000000000000000000000000000000000000602082015250565b60006117dc602c8361176f565b91506117e782611780565b604082019050919050565b6000602082019050818103600083015261180b816117cf565b9050919050565b600081905092915050565b82818337600083830152505050565b60006118388385611812565b935061184583858461181d565b82840190509392505050565b6000819050919050565b61186c611867826112ef565b611851565b82525050565b600061187f82858761182c565b915061188b828461185b565b602082019150819050949350505050565b7f50325049583a204465706f73697420616c726561647920657869737420616e6460008201527f206974206973207374696c6c2076616c69640000000000000000000000000000602082015250565b60006118f860328361176f565b91506119038261189c565b604082019050919050565b60006020820190508181036000830152611927816118eb565b9050919050565b611937816112b1565b82525050565b6000606082019050611952600083018661192e565b61195f602083018561192e565b61196c60408301846116a2565b949350505050565b61197d816116f9565b811461198857600080fd5b50565b60008151905061199a81611974565b92915050565b6000602082840312156119b6576119b5611224565b5b60006119c48482850161198b565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611a4e57607f821691505b602082108103611a6157611a60611a07565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ac97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611a8c565b611ad38683611a8c565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611b10611b0b611b06846112ef565b611aeb565b6112ef565b9050919050565b6000819050919050565b611b2a83611af5565b611b3e611b3682611b17565b848454611a99565b825550505050565b600090565b611b53611b46565b611b5e818484611b21565b505050565b5b81811015611b8257611b77600082611b4b565b600181019050611b64565b5050565b601f821115611bc757611b9881611a67565b611ba184611a7c565b81016020851015611bb0578190505b611bc4611bbc85611a7c565b830182611b63565b50505b505050565b600082821c905092915050565b6000611bea60001984600802611bcc565b1980831691505092915050565b6000611c038383611bd9565b9150826002028217905092915050565b611c1c826119cd565b67ffffffffffffffff811115611c3557611c346119d8565b5b611c3f8254611a36565b611c4a828285611b86565b600060209050601f831160018114611c7d5760008415611c6b578287015190505b611c758582611bf7565b865550611cdd565b601f198416611c8b86611a67565b60005b82811015611cb357848901518255600182019150602085019450602081019050611c8e565b86831015611cd05784890151611ccc601f891682611bd9565b8355505b6001600288020188555050505b505050505050565b6000608082019050611cfa6000830187611412565b611d07602083018661192e565b611d1460408301856116a2565b611d2160608301846116a2565b95945050505050565b6000604082019050611d3f600083018561192e565b611d4c60208301846116a2565b9392505050565b6000604082019050611d686000830185611412565b611d7560208301846116a2565b9392505050565b7f50325049583a204c6f636b20616c72656164792072656c6561736564206f722060008201527f72657475726e6564000000000000000000000000000000000000000000000000602082015250565b6000611dd860288361176f565b9150611de382611d7c565b604082019050919050565b60006020820190508181036000830152611e0781611dcb565b9050919050565b60008154611e1b81611a36565b611e258186611812565b94506001821660008114611e405760018114611e5557611e88565b60ff1983168652811515820286019350611e88565b611e5e85611a67565b60005b83811015611e8057815481890152600182019150602081019050611e61565b838801955050505b50505092915050565b6000611e9d8286611e0e565b9150611ea9828561185b565b602082019150611eb9828461185b565b602082019150819050949350505050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000611f00601c83611812565b9150611f0b82611eca565b601c82019050919050565b6000819050919050565b611f31611f2c8261122e565b611f16565b82525050565b6000611f4282611ef3565b9150611f4e8284611f20565b60208201915081905092915050565b7f50325049583a205472616e73616374696f6e20616c726561647920757365642060008201527f746f20756e6c6f636b207061796d656e74000000000000000000000000000000602082015250565b6000611fb960318361176f565b9150611fc482611f5d565b604082019050919050565b60006020820190508181036000830152611fe881611fac565b9050919050565b611ff8816114f2565b82525050565b60006080820190506120136000830187611412565b6120206020830186611fef565b61202d6040830185611412565b61203a6060830184611412565b95945050505050565b7f50325049583a205369676e6572206973206e6f7420612076616c69642073696760008201527f6e65720000000000000000000000000000000000000000000000000000000000602082015250565b600061209f60238361176f565b91506120aa82612043565b604082019050919050565b600060208201905081810360008301526120ce81612092565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061210f826112ef565b915061211a836112ef565b9250828203905081811115612132576121316120d5565b5b92915050565b7f50325049583a204465706f736974206e6f742076616c696420616e796d6f7265600082015250565b600061216e60208361176f565b915061217982612138565b602082019050919050565b6000602082019050818103600083015261219d81612161565b9050919050565b60006121af826112ef565b91506121ba836112ef565b92508282026121c8816112ef565b915082820484148315176121df576121de6120d5565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612220826112ef565b915061222b836112ef565b92508261223b5761223a6121e6565b5b828204905092915050565b7f50325049583a204e6f7420656e6f75676820746f6b656e2072656d61696e696e60008201527f67206f6e206465706f7369740000000000000000000000000000000000000000602082015250565b60006122a2602c8361176f565b91506122ad82612246565b604082019050919050565b600060208201905081810360008301526122d181612295565b9050919050565b60008160601b9050919050565b60006122f0826122d8565b9050919050565b6000612302826122e5565b9050919050565b61231a612315826112b1565b6122f7565b82525050565b600061232c8286611f20565b60208201915061233c828561185b565b60208201915061234c8284612309565b601482019150819050949350505050565b7f50325049583a20416e6f74686572206c6f636b20776974682073616d6520494460008201527f206973206e6f7420657870697265642079657400000000000000000000000000602082015250565b60006123b960338361176f565b91506123c48261235d565b604082019050919050565b600060208201905081810360008301526123e8816123ac565b9050919050565b60006123fa826112ef565b9150612405836112ef565b925082820190508082111561241d5761241c6120d5565b5b92915050565b60006060820190506124386000830186611412565b61244560208301856116a2565b61245260408301846116a2565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50325049583a204c6f636b206e6f742065787069726564206f7220616c72656160008201527f64792072656c6561736564000000000000000000000000000000000000000000602082015250565b60006124e5602b8361176f565b91506124f082612489565b604082019050919050565b60006020820190508181036000830152612514816124d8565b9050919050565b600061ffff82169050919050565b60006125348261251b565b915061ffff8203612548576125476120d5565b5b60018201905091905056fea2646970667358221220b2c46c7bf94e90ea83c1fcb04e9d8c8e81d1f22325b65ab6850361de1bdba86e64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063708ace6511610066578063708ace651461011c5780638e2749d61461014c5780639872dbfe14610168578063b93bd7d414610186578063e33f7291146101b657610093565b806331404484146100985780633a8cbc38146100b45780634b83a7be146100e45780634e1389ed14610100575b600080fd5b6100b260048036038101906100ad9190611264565b6101d2565b005b6100ce60048036038101906100c9919061138a565b61032e565b6040516100db9190611421565b60405180910390f35b6100fe60048036038101906100f99190611492565b610639565b005b61011a6004803603810190610115919061152b565b61085c565b005b610136600480360381019061013191906115a6565b610cee565b6040516101439190611421565b60405180910390f35b61016660048036038101906101619190611655565b611018565b005b6101706111a1565b60405161017d91906116b1565b60405180910390f35b6101a0600480360381019061019b91906116cc565b6111a7565b6040516101ad9190611714565b60405180910390f35b6101d060048036038101906101cb919061172f565b6111c7565b005b803373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161026e906117f2565b60405180910390fd5b60006002600084815260200190815260200160002060040160006101000a81548160ff0219169083151502179055506002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f81a84d666c6a692c1cf93ca3b3648cc7bf23d34a1c6afa2e15e346f424baa06c836040516103229190611421565b60405180910390a25050565b600082828660405160200161034593929190611872565b6040516020818303038152906040528051906020012090506002600082815260200190815260200160002060040160009054906101000a900460ff16156103c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103b89061190e565b60405180910390fd5b60008690508073ffffffffffffffffffffffffffffffffffffffff166323b872dd3330896040518463ffffffff1660e01b81526004016104039392919061193d565b6020604051808303816000875af1158015610422573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044691906119a0565b5060006040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff16815260200188815260200187815260200160011515815260200186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152509050806002600085815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160050190816105d69190611c13565b509050503373ffffffffffffffffffffffffffffffffffffffff167fb2d817df1a92003b7e8b40681145547601989b987e206c6f7d0bc46369652913848a898b6040516106269493929190611ce5565b60405180910390a2505095945050505050565b823373ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106d5906117f2565b60405180910390fd5b6106e88383611018565b60006002600086815260200190815260200160002090508060040160009054906101000a900460ff16156107205761071f856101d2565b5b60008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600201546040518363ffffffff1660e01b81526004016107ac929190611d2a565b6020604051808303816000875af11580156107cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ef91906119a0565b50600082600201549050600083600201819055503373ffffffffffffffffffffffffffffffffffffffff167fbc44d79619424e05dd4e8ea6a3e67823f43e45cf0c9b52463ec7a8806146991d888360405161084b929190611d53565b60405180910390a250505050505050565b600060036000878152602001908152602001600020905043816006015411801561088a575060008160050154115b6108c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c090611dee565b60405180910390fd5b6000600260008360000154815260200190815260200160002090506000600260008460000154815260200190815260200160002060050183600401548860405160200161091893929190611e91565b6040516020818303038152906040528051906020012090506000816040516020016109439190611f37565b6040516020818303038152906040528051906020012090506004600083815260200190815260200160002060009054906101000a900460ff16156109bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b390611fcf565b60405180910390fd5b6000600182878a8a604051600081526020016040526040516109e19493929190611ffe565b6020604051602081039080840390855afa158015610a03573d6000803e3d6000fd5b505050602060405103519050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610a9b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a92906120b5565b60405180910390fd5b60008460010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8760010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688600301548960050154610b199190612104565b6040518363ffffffff1660e01b8152600401610b36929190611d2a565b6020604051808303816000875af1158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7991906119a0565b50600086600301541115610c2f578073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688600301546040518363ffffffff1660e01b8152600401610bea929190611d2a565b6020604051808303816000875af1158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906119a0565b505b600086600501819055506000866006018190555060016004600086815260200190815260200160002060006101000a81548160ff0219169083151502179055508560010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f5e420822d2f7281fdc4b763c62c8b7874bf22108a35efe93144d79296aacc67d8c604051610cd99190611421565b60405180910390a25050505050505050505050565b6000610cfa8383611018565b6000600260008a815260200190815260200160002090508060040160009054906101000a900460ff16610d62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5990612184565b60405180910390fd5b60008160030154670de0b6b3a764000087610d7d91906121a4565b610d879190612215565b90508082600201541015610dd0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc7906122b8565b60405180910390fd5b89868a604051602001610de593929190612320565b60405160208183030381529060405280519060200120925043600360008581526020019081526020016000206006015410610e55576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e4c906123cf565b60405180910390fd5b60006040518060e001604052808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff16815260200189815260200188815260200183815260200160005443610ec091906123ef565b815250905080600360008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081836002016000828254610fb09190612104565b92505081905550838a73ffffffffffffffffffffffffffffffffffffffff167fd122043a71eaa13e3a89d5660c858559e90861de4a8afcb4a9795e855539d6438d8a8660405161100293929190612423565b60405180910390a3505050979650505050505050565b600082829050905060005b818161ffff16101561119b5760006003600086868561ffff1681811061104c5761104b61245a565b5b905060200201358152602001908152602001600020905043816006015410801561107a575060008160050154115b6110b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110b0906124fb565b60405180910390fd5b8060050154600260008360000154815260200190815260200160002060020160008282546110e791906123ef565b92505081905550600081600501819055508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f67e089478e21dd12c98e69331c4152f6c9b2038b91e0f28268ffa01558c0b4ff86868561ffff1681811061116b5761116a61245a565b5b9050602002013560405161117f9190611421565b60405180910390a250808061119390612529565b915050611023565b50505050565b60005481565b60016020528060005260406000206000915054906101000a900460ff1681565b6000600260008481526020019081526020016000209050818160030181905550827f42dfc0c297064717f06aefc162216c94dc59f9a1af9ff6ed92f00cadbe9ba8038360405161121791906116b1565b60405180910390a2505050565b600080fd5b600080fd5b6000819050919050565b6112418161122e565b811461124c57600080fd5b50565b60008135905061125e81611238565b92915050565b60006020828403121561127a57611279611224565b5b60006112888482850161124f565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006112bc82611291565b9050919050565b6112cc816112b1565b81146112d757600080fd5b50565b6000813590506112e9816112c3565b92915050565b6000819050919050565b611302816112ef565b811461130d57600080fd5b50565b60008135905061131f816112f9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261134a57611349611325565b5b8235905067ffffffffffffffff8111156113675761136661132a565b5b6020830191508360018202830111156113835761138261132f565b5b9250929050565b6000806000806000608086880312156113a6576113a5611224565b5b60006113b4888289016112da565b95505060206113c588828901611310565b94505060406113d688828901611310565b935050606086013567ffffffffffffffff8111156113f7576113f6611229565b5b61140388828901611334565b92509250509295509295909350565b61141b8161122e565b82525050565b60006020820190506114366000830184611412565b92915050565b60008083601f84011261145257611451611325565b5b8235905067ffffffffffffffff81111561146f5761146e61132a565b5b60208301915083602082028301111561148b5761148a61132f565b5b9250929050565b6000806000604084860312156114ab576114aa611224565b5b60006114b98682870161124f565b935050602084013567ffffffffffffffff8111156114da576114d9611229565b5b6114e68682870161143c565b92509250509250925092565b600060ff82169050919050565b611508816114f2565b811461151357600080fd5b50565b600081359050611525816114ff565b92915050565b600080600080600060a0868803121561154757611546611224565b5b60006115558882890161124f565b955050602061156688828901611310565b94505060406115778882890161124f565b93505060606115888882890161124f565b925050608061159988828901611516565b9150509295509295909350565b600080600080600080600060c0888a0312156115c5576115c4611224565b5b60006115d38a828b0161124f565b97505060206115e48a828b016112da565b96505060406115f58a828b016112da565b95505060606116068a828b01611310565b94505060806116178a828b01611310565b93505060a088013567ffffffffffffffff81111561163857611637611229565b5b6116448a828b0161143c565b925092505092959891949750929550565b6000806020838503121561166c5761166b611224565b5b600083013567ffffffffffffffff81111561168a57611689611229565b5b6116968582860161143c565b92509250509250929050565b6116ab816112ef565b82525050565b60006020820190506116c660008301846116a2565b92915050565b6000602082840312156116e2576116e1611224565b5b60006116f0848285016112da565b91505092915050565b60008115159050919050565b61170e816116f9565b82525050565b60006020820190506117296000830184611705565b92915050565b6000806040838503121561174657611745611224565b5b60006117548582860161124f565b925050602061176585828601611310565b9150509250929050565b600082825260208201905092915050565b7f50325049583a204f6e6c792073656c6c657220636f756c642063616c6c20746860008201527f69732066756e6374696f6e2e0000000000000000000000000000000000000000602082015250565b60006117dc602c8361176f565b91506117e782611780565b604082019050919050565b6000602082019050818103600083015261180b816117cf565b9050919050565b600081905092915050565b82818337600083830152505050565b60006118388385611812565b935061184583858461181d565b82840190509392505050565b6000819050919050565b61186c611867826112ef565b611851565b82525050565b600061187f82858761182c565b915061188b828461185b565b602082019150819050949350505050565b7f50325049583a204465706f73697420616c726561647920657869737420616e6460008201527f206974206973207374696c6c2076616c69640000000000000000000000000000602082015250565b60006118f860328361176f565b91506119038261189c565b604082019050919050565b60006020820190508181036000830152611927816118eb565b9050919050565b611937816112b1565b82525050565b6000606082019050611952600083018661192e565b61195f602083018561192e565b61196c60408301846116a2565b949350505050565b61197d816116f9565b811461198857600080fd5b50565b60008151905061199a81611974565b92915050565b6000602082840312156119b6576119b5611224565b5b60006119c48482850161198b565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611a4e57607f821691505b602082108103611a6157611a60611a07565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ac97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611a8c565b611ad38683611a8c565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611b10611b0b611b06846112ef565b611aeb565b6112ef565b9050919050565b6000819050919050565b611b2a83611af5565b611b3e611b3682611b17565b848454611a99565b825550505050565b600090565b611b53611b46565b611b5e818484611b21565b505050565b5b81811015611b8257611b77600082611b4b565b600181019050611b64565b5050565b601f821115611bc757611b9881611a67565b611ba184611a7c565b81016020851015611bb0578190505b611bc4611bbc85611a7c565b830182611b63565b50505b505050565b600082821c905092915050565b6000611bea60001984600802611bcc565b1980831691505092915050565b6000611c038383611bd9565b9150826002028217905092915050565b611c1c826119cd565b67ffffffffffffffff811115611c3557611c346119d8565b5b611c3f8254611a36565b611c4a828285611b86565b600060209050601f831160018114611c7d5760008415611c6b578287015190505b611c758582611bf7565b865550611cdd565b601f198416611c8b86611a67565b60005b82811015611cb357848901518255600182019150602085019450602081019050611c8e565b86831015611cd05784890151611ccc601f891682611bd9565b8355505b6001600288020188555050505b505050505050565b6000608082019050611cfa6000830187611412565b611d07602083018661192e565b611d1460408301856116a2565b611d2160608301846116a2565b95945050505050565b6000604082019050611d3f600083018561192e565b611d4c60208301846116a2565b9392505050565b6000604082019050611d686000830185611412565b611d7560208301846116a2565b9392505050565b7f50325049583a204c6f636b20616c72656164792072656c6561736564206f722060008201527f72657475726e6564000000000000000000000000000000000000000000000000602082015250565b6000611dd860288361176f565b9150611de382611d7c565b604082019050919050565b60006020820190508181036000830152611e0781611dcb565b9050919050565b60008154611e1b81611a36565b611e258186611812565b94506001821660008114611e405760018114611e5557611e88565b60ff1983168652811515820286019350611e88565b611e5e85611a67565b60005b83811015611e8057815481890152600182019150602081019050611e61565b838801955050505b50505092915050565b6000611e9d8286611e0e565b9150611ea9828561185b565b602082019150611eb9828461185b565b602082019150819050949350505050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000611f00601c83611812565b9150611f0b82611eca565b601c82019050919050565b6000819050919050565b611f31611f2c8261122e565b611f16565b82525050565b6000611f4282611ef3565b9150611f4e8284611f20565b60208201915081905092915050565b7f50325049583a205472616e73616374696f6e20616c726561647920757365642060008201527f746f20756e6c6f636b207061796d656e74000000000000000000000000000000602082015250565b6000611fb960318361176f565b9150611fc482611f5d565b604082019050919050565b60006020820190508181036000830152611fe881611fac565b9050919050565b611ff8816114f2565b82525050565b60006080820190506120136000830187611412565b6120206020830186611fef565b61202d6040830185611412565b61203a6060830184611412565b95945050505050565b7f50325049583a205369676e6572206973206e6f7420612076616c69642073696760008201527f6e65720000000000000000000000000000000000000000000000000000000000602082015250565b600061209f60238361176f565b91506120aa82612043565b604082019050919050565b600060208201905081810360008301526120ce81612092565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061210f826112ef565b915061211a836112ef565b9250828203905081811115612132576121316120d5565b5b92915050565b7f50325049583a204465706f736974206e6f742076616c696420616e796d6f7265600082015250565b600061216e60208361176f565b915061217982612138565b602082019050919050565b6000602082019050818103600083015261219d81612161565b9050919050565b60006121af826112ef565b91506121ba836112ef565b92508282026121c8816112ef565b915082820484148315176121df576121de6120d5565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612220826112ef565b915061222b836112ef565b92508261223b5761223a6121e6565b5b828204905092915050565b7f50325049583a204e6f7420656e6f75676820746f6b656e2072656d61696e696e60008201527f67206f6e206465706f7369740000000000000000000000000000000000000000602082015250565b60006122a2602c8361176f565b91506122ad82612246565b604082019050919050565b600060208201905081810360008301526122d181612295565b9050919050565b60008160601b9050919050565b60006122f0826122d8565b9050919050565b6000612302826122e5565b9050919050565b61231a612315826112b1565b6122f7565b82525050565b600061232c8286611f20565b60208201915061233c828561185b565b60208201915061234c8284612309565b601482019150819050949350505050565b7f50325049583a20416e6f74686572206c6f636b20776974682073616d6520494460008201527f206973206e6f7420657870697265642079657400000000000000000000000000602082015250565b60006123b960338361176f565b91506123c48261235d565b604082019050919050565b600060208201905081810360008301526123e8816123ac565b9050919050565b60006123fa826112ef565b9150612405836112ef565b925082820190508082111561241d5761241c6120d5565b5b92915050565b60006060820190506124386000830186611412565b61244560208301856116a2565b61245260408301846116a2565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50325049583a204c6f636b206e6f742065787069726564206f7220616c72656160008201527f64792072656c6561736564000000000000000000000000000000000000000000602082015250565b60006124e5602b8361176f565b91506124f082612489565b604082019050919050565b60006020820190508181036000830152612514816124d8565b9050919050565b600061ffff82169050919050565b60006125348261251b565b915061ffff8203612548576125476120d5565b5b60018201905091905056fea2646970667358221220b2c46c7bf94e90ea83c1fcb04e9d8c8e81d1f22325b65ab6850361de1bdba86e64736f6c63430008110033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts/p2pix.sol b/contracts/p2pix.sol index cc27a0f..58e095e 100644 --- a/contracts/p2pix.sol +++ b/contracts/p2pix.sol @@ -9,7 +9,7 @@ contract P2PIX { event DepositClosed(address indexed seller, bytes32 depositID); event DepositWithdrawn(address indexed seller, bytes32 depositID, uint256 amount); event DepositPriceChanged(bytes32 indexed depositID, uint256 price); - event LockAdded(address indexed buyer, bytes32 indexed lockID, bytes32 depositID, uint256 amount); + event LockAdded(address indexed buyer, bytes32 indexed lockID, bytes32 depositID, uint256 amount, uint256 locked); event LockReleased(address indexed buyer, bytes32 lockId); event LockReturned(address indexed buyer, bytes32 lockId); @@ -95,7 +95,8 @@ contract P2PIX { unlockExpired(expiredLocks); Deposit storage d = mapDeposits[depositID]; require(d.valid, "P2PIX: Deposit not valid anymore"); - require(d.remaining > amount/d.price, "P2PIX: Not enough remaining"); + uint256 toLock = (amount * 1 ether) / d.price; + require(d.remaining >= toLock, "P2PIX: Not enough token remaining on deposit"); lockID = keccak256(abi.encodePacked(depositID, amount, targetAddress)); require( mapLocks[lockID].expirationBlock < block.number, @@ -107,12 +108,12 @@ contract P2PIX { relayerAddress, relayerPremium, amount, - amount/d.price, + toLock, block.number+defaultLockBlocks ); mapLocks[lockID] = l; - d.remaining -= amount; - emit LockAdded(targetAddress, lockID, depositID, amount); + d.remaining -= toLock; + emit LockAdded(targetAddress, lockID, depositID, amount, toLock); } // Relayer interage com o smart contract, colocando no calldata o comprovante do PIX realizado. @@ -124,41 +125,43 @@ contract P2PIX { bytes32 s, uint8 v ) public { - // TODO Check if lockID exists and is enabled // TODO **Prevenir que um Pix não relacionado ao APP seja usado pois tem o mesmo destino Lock storage l = mapLocks[lockID]; + require(l.expirationBlock > block.number && l.locked > 0, "P2PIX: Lock already released or returned"); Deposit storage d = mapDeposits[l.depositID]; bytes32 message = keccak256(abi.encodePacked( mapDeposits[l.depositID].pixTarget, l.amount, pixTimestamp )); - require(!usedTransactions[message], "Transaction already used to unlock payment."); - address signer = ecrecover(message, v, r, s); - require(validBacenSigners[signer], "Signer is not a valid signer."); + bytes32 messageDigest = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + require(!usedTransactions[message], "P2PIX: Transaction already used to unlock payment"); + address signer = ecrecover(messageDigest, v, r, s); + require(validBacenSigners[signer], "P2PIX: Signer is not a valid signer"); IERC20 t = IERC20(d.token); t.transfer(l.targetAddress, l.locked-l.relayerPremium); if (l.relayerPremium > 0) t.transfer(l.relayerAddress, l.relayerPremium); - l.amount = 0; + l.locked = 0; + l.expirationBlock = 0; usedTransactions[message] = true; emit LockReleased(l.targetAddress, lockID); } // Change price for deposit amount - function changeDepositPrice(bytes32 depositID, uint256 price) public { + function changeDepositPrice(bytes32 depositID, uint256 price) public onlySeller(depositID) { Deposit storage d = mapDeposits[depositID]; d.price = price; emit DepositPriceChanged(depositID, price); } // Unlock expired locks - function unlockExpired(bytes32[] calldata lockIDs) internal { + function unlockExpired(bytes32[] calldata lockIDs) public { uint256 locksSize = lockIDs.length; for (uint16 i = 0; i < locksSize; i++){ Lock storage l = mapLocks[lockIDs[i]]; - require(l.expirationBlock < block.number && l.amount > 0, "P2PIX: Lock not expired or already paid"); - mapDeposits[l.depositID].remaining += l.amount; - l.amount = 0; + require(l.expirationBlock < block.number && l.locked > 0, "P2PIX: Lock not expired or already released"); + mapDeposits[l.depositID].remaining += l.locked; + l.locked = 0; emit LockReturned(l.targetAddress, lockIDs[i]); } } @@ -172,8 +175,8 @@ contract P2PIX { Deposit storage d = mapDeposits[depositID]; if (d.valid) cancelDeposit(depositID); IERC20 token = IERC20(d.token); - token.transfer(d.seller, d.remaining); // Withdraw remaining tokens from mapDeposit[depositID] + token.transfer(d.seller, d.remaining); uint256 amount = d.remaining; d.remaining = 0; emit DepositWithdrawn(msg.sender, depositID, amount); diff --git a/test/2-lock-release.test.js b/test/2-lock-release.test.js index 1649cee..c6cd66c 100644 --- a/test/2-lock-release.test.js +++ b/test/2-lock-release.test.js @@ -6,7 +6,7 @@ describe("P2PIX lock/release test", function () { let owner, wallet2, wallet3, wallet4; let p2pix; // Contract instance let erc20; // Token instance - let depositID; + let depositID, lockID; it("Will deploy contracts", async function () { @@ -20,12 +20,13 @@ describe("P2PIX lock/release test", function () { expect(await erc20.balanceOf(owner.address)).to.equal(ethers.utils.parseEther('20000000', 'wei')); const P2PIX = await ethers.getContractFactory("P2PIX"); - p2pix = await P2PIX.deploy(2, [owner.address, wallet2.address]); + p2pix = await P2PIX.deploy(3, [owner.address, wallet2.address]); await p2pix.deployed(); // Verify values at deployment expect(await p2pix.validBacenSigners(owner.address)).to.equal(true); expect(await p2pix.validBacenSigners(wallet2.address)).to.equal(true); + expect(await p2pix.validBacenSigners(wallet3.address)).to.equal(false); }); it("Should allow create a deposit", async function () { @@ -51,6 +52,7 @@ describe("P2PIX lock/release test", function () { ethers.utils.parseEther('0.99'), ethers.utils.parseEther('1000') ) + console.log('GAS USED:', (await transaction.wait()).cumulativeGasUsed.toString()) }) it("Should allow create a new lock", async function () { @@ -62,7 +64,7 @@ describe("P2PIX lock/release test", function () { ethers.utils.parseEther('100'), [] ) - const lockID = ethers.utils.solidityKeccak256(['bytes32', 'uint256', 'address'], [ + lockID = ethers.utils.solidityKeccak256(['bytes32', 'uint256', 'address'], [ depositID, ethers.utils.parseEther('100'), wallet3.address @@ -71,8 +73,172 @@ describe("P2PIX lock/release test", function () { wallet3.address, lockID, depositID, - ethers.utils.parseEther('100') + ethers.utils.parseEther('100'), + "101010101010101010101" + ) + console.log('GAS USED:', (await transaction.wait()).cumulativeGasUsed.toString()) + }) + + it("Should release the locked amount to the buyer", async function () { + const endtoendID = '123'; + const messageToSign = ethers.utils.solidityKeccak256(['string', 'uint256', 'uint256'], [ + 'SELLER PIX KEY', + ethers.utils.parseEther('100'), + endtoendID + ]) + // Note: messageToSign is a string, that is 66-bytes long, to sign the + // binary value, we must convert it to the 32 byte Array that + // the string represents + // + // i.e. + // // 66-byte string + // "0x592fa743889fc7f92ac2a37bb1f5ba1daf2a5c84741ca0e0061d243a2e6707ba" + // ... vs ... + // // 32 entry Uint8Array + // [ 89, 47, 167, 67, 136, 159, ... 103, 7, 186] + const messageHashBytes = ethers.utils.arrayify(messageToSign) + // Sign the string message + const flatSig = await owner.signMessage(messageHashBytes); + // For Solidity, we need the expanded-format of a signature + const sig = ethers.utils.splitSignature(flatSig); + transaction = await p2pix.connect(wallet3).release( + lockID, + endtoendID, + sig.r, + sig.s, + sig.v + ) + await expect(transaction).to.emit(p2pix, 'LockReleased').withArgs( + wallet3.address, + lockID + ) + console.log('GAS USED:', (await transaction.wait()).cumulativeGasUsed.toString()) + expect(await erc20.balanceOf(wallet3.address)).to.equal("101010101010101010101"); + }) + + it("Should allow recreate same lock", async function () { + transaction = await p2pix.connect(wallet3).lock( + depositID, + wallet3.address, + ethers.constants.AddressZero, + '0', + ethers.utils.parseEther('100'), + [] + ) + lockID = ethers.utils.solidityKeccak256(['bytes32', 'uint256', 'address'], [ + depositID, + ethers.utils.parseEther('100'), + wallet3.address + ]) + await expect(transaction).to.emit(p2pix, 'LockAdded').withArgs( + wallet3.address, + lockID, + depositID, + ethers.utils.parseEther('100'), + "101010101010101010101" ) }) + it("Should prevent create again same lock", async function () { + await expect(p2pix.connect(wallet3).lock( + depositID, + wallet3.address, + ethers.constants.AddressZero, + '0', + ethers.utils.parseEther('100'), + [] + )).to.be.revertedWith('P2PIX: Another lock with same ID is not expired yet'); + }) + + it("Should release the locked amount to the buyer", async function () { + const endtoendID = '124'; + const messageToSign = ethers.utils.solidityKeccak256(['string', 'uint256', 'uint256'], [ + 'SELLER PIX KEY', + ethers.utils.parseEther('100'), + endtoendID + ]) + const messageHashBytes = ethers.utils.arrayify(messageToSign) + const flatSig = await owner.signMessage(messageHashBytes); + const sig = ethers.utils.splitSignature(flatSig); + transaction = await p2pix.connect(wallet3).release( + lockID, + endtoendID, + sig.r, + sig.s, + sig.v + ) + expect(await erc20.balanceOf(wallet3.address)).to.equal("202020202020202020202"); + }) + + it("Should prevent release again the lock", async function () { + const endtoendID = '125'; + const messageToSign = ethers.utils.solidityKeccak256(['string', 'uint256', 'uint256'], [ + 'SELLER PIX KEY', + ethers.utils.parseEther('100'), + endtoendID + ]) + const messageHashBytes = ethers.utils.arrayify(messageToSign) + const flatSig = await owner.signMessage(messageHashBytes); + const sig = ethers.utils.splitSignature(flatSig); + await expect(p2pix.connect(wallet3).release( + lockID, + endtoendID, + sig.r, + sig.s, + sig.v + )).to.be.revertedWith('P2PIX: Lock already released or returned'); + }) + + it("Should prevent create a 800 lock", async function () { + await expect(p2pix.connect(wallet3).lock( + depositID, + wallet3.address, + ethers.constants.AddressZero, + '0', + ethers.utils.parseEther('800'), + [] + )).to.be.revertedWith('P2PIX: Not enough token remaining on deposit'); + }) + + it("Should allow recreate same lock again", async function () { + transaction = await p2pix.connect(wallet3).lock( + depositID, + wallet3.address, + ethers.constants.AddressZero, + '0', + ethers.utils.parseEther('100'), + [] + ) + lockID = ethers.utils.solidityKeccak256(['bytes32', 'uint256', 'address'], [ + depositID, + ethers.utils.parseEther('100'), + wallet3.address + ]) + await expect(transaction).to.emit(p2pix, 'LockAdded').withArgs( + wallet3.address, + lockID, + depositID, + ethers.utils.parseEther('100'), + "101010101010101010101" + ) + }) + + it("Should allow unlock expired lock", async function () { + await expect(p2pix.unlockExpired([lockID])) + .to.be.revertedWith('P2PIX: Lock not expired or already released'); + await network.provider.send("evm_mine"); + await network.provider.send("evm_mine"); + await network.provider.send("evm_mine"); + transaction = await p2pix.unlockExpired([lockID]) + await expect(transaction).to.emit(p2pix, 'LockReturned').withArgs( + wallet3.address, + lockID + ) + }) + + it("Should prevent unlock again", async function () { + await expect(p2pix.unlockExpired([lockID])) + .to.be.revertedWith('P2PIX: Lock not expired or already released'); + }) + }) \ No newline at end of file