From 7f309f7703beb072d4d984a5396a72d125762788 Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Thu, 5 Jan 2023 17:01:00 +0300 Subject: [PATCH 01/11] add watcherSpend and watcherRefund functions for watchers --- contracts/EtomicSwap.sol | 72 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 3a1ccec..8e9b52c 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.0; +pragma solidity ^0.8.0; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; contract EtomicSwap { @@ -21,7 +21,7 @@ contract EtomicSwap { event ReceiverSpent(bytes32 id, bytes32 secret); event SenderRefunded(bytes32 id); - constructor() public { } + constructor() { } function ethPayment( bytes32 _id, @@ -97,7 +97,7 @@ contract EtomicSwap { require(paymentHash == payments[_id].paymentHash); payments[_id].state = PaymentState.ReceivedSpent; if (_tokenAddress == address(0)) { - msg.sender.transfer(_amount); + payable(msg.sender).transfer(_amount); } else { IERC20 token = IERC20(_tokenAddress); require(token.transfer(msg.sender, _amount)); @@ -106,6 +106,36 @@ contract EtomicSwap { emit ReceiverSpent(_id, _secret); } + function watcherSpend( + bytes32 _id, + uint256 _amount, + bytes32 _secret, + address _tokenAddress, + address _sender, + address _receiver + ) external { + require(payments[_id].state == PaymentState.PaymentSent); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + _receiver, + _sender, + ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), + _tokenAddress, + _amount + )); + + require(paymentHash == payments[_id].paymentHash); + payments[_id].state = PaymentState.ReceivedSpent; + if (_tokenAddress == address(0)) { + payable(_receiver).transfer(_amount); + } else { + IERC20 token = IERC20(_tokenAddress); + require(token.transfer(_receiver, _amount)); + } + + emit ReceiverSpent(_id, _secret); + } + function senderRefund( bytes32 _id, uint256 _amount, @@ -123,12 +153,12 @@ contract EtomicSwap { _amount )); - require(paymentHash == payments[_id].paymentHash && now >= payments[_id].lockTime); + require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); payments[_id].state = PaymentState.SenderRefunded; if (_tokenAddress == address(0)) { - msg.sender.transfer(_amount); + payable(msg.sender).transfer(_amount); } else { IERC20 token = IERC20(_tokenAddress); require(token.transfer(msg.sender, _amount)); @@ -136,4 +166,36 @@ contract EtomicSwap { emit SenderRefunded(_id); } + + function watcherRefund( + bytes32 _id, + uint256 _amount, + bytes20 _paymentHash, + address _tokenAddress, + address _sender, + address _receiver + ) external { + require(payments[_id].state == PaymentState.PaymentSent); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + _receiver, + _sender, + _paymentHash, + _tokenAddress, + _amount + )); + + require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); + + payments[_id].state = PaymentState.SenderRefunded; + + if (_tokenAddress == address(0)) { + payable(_sender).transfer(_amount); + } else { + IERC20 token = IERC20(_tokenAddress); + require(token.transfer(_sender, _amount)); + } + + emit SenderRefunded(_id); + } } From bd134f2c9e4078230f92534856580514adba9f17 Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Fri, 20 Jan 2023 15:09:41 +0300 Subject: [PATCH 02/11] fix docker build problems --- contracts/EtomicSwap.sol | 4 +- contracts/Migrations.sol | 6 +- contracts/Token.sol | 8 +- package.json | 5 +- rpc.Dockerfile | 8 +- truffle.js | 5 + workspace.Dockerfile | 10 +- yarn.lock | 3482 ++++++++++++++++++++++---------------- 8 files changed, 2084 insertions(+), 1444 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 8e9b52c..f9a5233 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -1,5 +1,5 @@ -pragma solidity ^0.8.0; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; +pragma solidity ^0.8.9; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract EtomicSwap { enum PaymentState { diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 17b44d8..29d8d74 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.5.0; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +pragma solidity ^0.8.9; +import "@openzeppelin/contracts/access/Ownable.sol"; contract Migrations is Ownable { uint public last_completed_migration; - constructor() public { } + constructor() { } function setCompleted(uint completed) public onlyOwner { last_completed_migration = completed; diff --git a/contracts/Token.sol b/contracts/Token.sol index 7f8d977..38e6c76 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -1,7 +1,7 @@ -pragma solidity ^0.5.0; +pragma solidity ^0.8.9; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; /** * @title Standard ERC20 token @@ -29,7 +29,7 @@ contract Token is IERC20 { uint8 public constant decimals = 18; - constructor() public { + constructor() { _balances[msg.sender] = 1000 ether; _totalSupply = 1000 ether; } diff --git a/package.json b/package.json index 0a4cab1..79355b4 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "rpc": "node startRPC.js", "test": "truffle test", + "clean": "rm -rf merge", "merge": "node node_modules/sol-merger/bin/sol-merger.js './contracts/*.sol' ./merge" }, "author": "ortgma@gmail.com", @@ -13,8 +14,8 @@ "dependencies": { "chai": "^4.1.2", "chai-as-promised": "^7.1.1", - "ganache-cli": "^6.2.5", - "openzeppelin-solidity": "https://github.com/OpenZeppelin/openzeppelin-solidity.git#release-v2.1.0-solc-0.5", + "ganache-cli": "^6.7.0", + "@openzeppelin/contracts": "^4.8.1", "request": "^2.83.0", "request-promise-native": "^1.0.5", "ripemd160": "^2.0.1", diff --git a/rpc.Dockerfile b/rpc.Dockerfile index 91a344f..b7dca10 100644 --- a/rpc.Dockerfile +++ b/rpc.Dockerfile @@ -1,6 +1,10 @@ -FROM mhart/alpine-node:11 +FROM node:19-bullseye-slim -RUN apk update && apk upgrade && apk add git && apk add python && apk add make && apk add g++ +RUN apt-get update && apt-get install -y \ + git \ + python3 \ + make \ + g++ ADD . /usr/src/rpc diff --git a/truffle.js b/truffle.js index 8e18127..721d064 100644 --- a/truffle.js +++ b/truffle.js @@ -6,4 +6,9 @@ module.exports = { network_id: "*" // Match any network id } }, + compilers: { + solc: { + version: "0.8.17", + } + }, }; diff --git a/workspace.Dockerfile b/workspace.Dockerfile index d1878b7..23f45f2 100644 --- a/workspace.Dockerfile +++ b/workspace.Dockerfile @@ -1,7 +1,11 @@ -FROM mhart/alpine-node:11 +FROM node:19-bullseye-slim -RUN apk update && apk upgrade && apk add git && apk add python && apk add make && apk add g++ +RUN apt-get update && apt-get install -y \ + git \ + python3 \ + make \ + g++ -RUN npm i -g truffle@5.0.0 +RUN npm i -g truffle@5.7.3 VOLUME /usr/src/workspace WORKDIR /usr/src/workspace diff --git a/yarn.lock b/yarn.lock index 7a82def..e242dad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,165 +2,466 @@ # yarn lockfile v1 -"@types/node@^10.3.2": - version "10.11.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.2.tgz#59508b88ce90fe2742f7b8414c6f5db3e359570d" +"@ethereumjs/common@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" + integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.1" -accepts@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" +"@ethereumjs/common@^2.5.0": + version "2.6.5" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" + integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" + crc-32 "^1.2.0" + ethereumjs-util "^7.1.5" -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" +"@ethereumjs/tx@3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" + integrity sha512-6AaJhwg4ucmwTvw/1qLaZUX5miWrwZ4nLOUsKyb/HtzS3BMw/CasKhdi1ims9mBKeK9sOJCH4qGKOBGyJCeeog== + dependencies: + "@ethereumjs/common" "^2.5.0" + ethereumjs-util "^7.1.2" + +"@ethersproject/abi@^5.6.3": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + +"@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + +"@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + bn.js "^5.2.1" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + dependencies: + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + +"@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + dependencies: + "@ethersproject/base64" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@openzeppelin/contracts@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.1.tgz#709cfc4bbb3ca9f4460d60101f15dac6b7a2d5e4" + integrity sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ== + +"@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + +"@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== + +"@types/node@^12.12.6": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +abortcontroller-polyfill@^1.7.3: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" -ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" -ansi-regex@^2.0.0, ansi-regex@^2.1.1: +ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== -any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" +ansi-styles@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" -base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== -bluebird@^2.9.34: - version "2.11.0" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" +blakejs@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" + integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@^3.5.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" +bluebird@^3.5.0, bluebird@^3.5.3: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" +body-parser@1.20.1, body-parser@^1.16.0: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: - bytes "3.0.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.1" - http-errors "~1.6.2" - iconv-lite "0.4.19" - on-finished "~2.3.0" - qs "6.5.1" - raw-body "2.3.2" - type-is "~1.6.15" - -body-parser@^1.16.0: - version "1.18.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "~1.6.3" - iconv-lite "0.4.23" - on-finished "~2.3.0" - qs "6.5.2" - raw-body "2.3.3" - type-is "~1.6.16" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" brace-expansion@^1.1.7: version "1.1.11" @@ -170,13 +471,15 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -188,6 +491,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" browserify-des "^1.0.0" @@ -196,127 +500,186 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" des.js "^1.0.0" inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: - bn.js "^4.1.0" + bn.js "^5.0.0" randombytes "^2.0.1" -browserify-sha3@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - dependencies: - js-sha3 "^0.3.1" - browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + base-x "^3.0.2" -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-to-arraybuffer@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ== buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - -buffer@^3.0.1: - version "3.6.0" - resolved "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - dependencies: - base64-js "0.0.8" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^5.0.5: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== + dependencies: + node-gyp-build "^4.3.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-lookup@^6.0.4: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz#0330a543471c61faa4e9035db583aad753b36385" + integrity sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww== + +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" + function-bind "^1.1.1" + get-intrinsic "^1.0.2" -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== chai-as-promised@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: check-error "^1.0.2" chai@^4.1.2: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" - deep-eql "^3.0.1" + deep-eql "^4.1.2" get-func-name "^2.0.0" - pathval "^1.1.0" + loupe "^2.3.1" + pathval "^1.1.1" type-detect "^4.0.5" check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -cli-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +cli-color@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f" + integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w== dependencies: ansi-regex "^2.1.1" d "1" @@ -325,92 +688,112 @@ cli-color@^1.2.0: memoizee "^0.4.14" timers-ext "^0.1.5" -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: - delayed-stream "~1.0.0" + mimic-response "^1.0.0" -combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: - delayed-stream "~1.0.0" + color-name "1.1.3" -commander@^2.11.0, commander@^2.8.1: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: - graceful-readlink ">= 1.0.0" + delayed-stream "~1.0.0" + +commander@^2.19.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== cors@^2.8.1: - version "2.8.4" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== dependencies: object-assign "^4" vary "^1" +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" - elliptic "^6.0.0" + elliptic "^6.5.3" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" inherits "^2.0.1" @@ -418,9 +801,10 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" create-hash "^1.1.0" @@ -429,18 +813,28 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= +cross-fetch@^3.1.4: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== dependencies: - lru-cache "^4.0.1" + node-fetch "2.6.7" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" shebang-command "^1.2.0" which "^1.2.9" crypto-browserify@3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -454,141 +848,112 @@ crypto-browserify@3.12.0: randombytes "^2.0.0" randomfill "^1.0.3" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== dependencies: - es5-ext "^0.10.9" + es5-ext "^0.10.50" + type "^1.0.1" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^3.0.1: - version "3.2.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407" +debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" -decamelize@^1.1.1: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -decompress-response@^3.2.0, decompress-response@^3.3.0: +decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" + mimic-response "^3.1.0" -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" +defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -depd@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - -depd@~1.1.1, depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" randombytes "^2.0.0" dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" @@ -596,152 +961,214 @@ ecc-jsbn@~0.1.1: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - inherits "^2.0.1" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" -elliptic@^6.0.0, elliptic@^6.4.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: - version "0.10.46" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572" +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: +es6-iterator@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== dependencies: d "1" es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" +es6-promise@^4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== dependencies: - d "1" - es5-ext "~0.10.14" + d "^1.0.1" + ext "^1.1.2" -es6-weak-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== dependencies: d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" es6-symbol "^3.1.1" escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== eth-ens-namehash@2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== dependencies: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-lib@0.1.27, eth-lib@^0.1.26: - version "0.1.27" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" - keccakjs "^0.2.1" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" xhr-request-promise "^0.1.2" -eth-lib@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== dependencies: bn.js "^4.11.6" elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" xhr-request-promise "^0.1.2" -ethers@4.0.0-beta.1: - version "4.0.0-beta.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.1.tgz#0648268b83e0e91a961b1af971c662cdf8cbab6d" - dependencies: - "@types/node" "^10.3.2" - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.3.3" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereumjs-util@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.5: + version "7.1.5" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" + integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw== dependencies: bn.js "4.11.6" number-to-bn "1.7.0" +ethjs-util@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + event-emitter@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== dependencies: d "1" es5-ext "~0.10.14" -eventemitter3@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" + cross-spawn "^6.0.0" + get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" @@ -749,719 +1176,881 @@ execa@^0.7.0: strip-eof "^1.0.0" express@^4.14.0: - version "4.16.3" - resolved "https://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.5" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" + body-parser "1.20.1" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.3.1" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.1.1" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" + on-finished "2.4.1" + parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.3" - qs "6.5.1" - range-parser "~1.2.0" - safe-buffer "5.1.1" - send "0.16.2" - serve-static "1.13.2" - setprototypeof "1.1.0" - statuses "~1.4.0" - type-is "~1.6.16" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - dependencies: - pend "~1.2.0" - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -finalhandler@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.4.0" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" unpipe "~1.0.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: - locate-path "^2.0.0" + locate-path "^3.0.0" -for-each@^0.3.2: +for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data-encoder@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== dependencies: asynckit "^0.4.0" - combined-stream "1.0.6" + combined-stream "^1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - -fs-extra@^2.0.0, fs-extra@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" universalify "^0.1.0" -fs-promise@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: - any-promise "^1.3.0" - fs-extra "^2.0.0" - mz "^2.6.0" - thenify-all "^1.6.0" + minipass "^2.6.0" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fstream@^1.0.12, fstream@^1.0.8: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -ganache-cli@^6.2.5: - version "6.2.5" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.5.tgz#efda5115fa3a0c62d7f5729fdd78da70ca55b1ad" - integrity sha512-E4SP8QNeuc2N/ojFoCK+08OYHX8yrtGeFtipZmJPPTQ6U8Hmq3JcbXZDxQfChPQUY5mtbRSwptJa4EtiQyJjAQ== +ganache-cli@^6.7.0: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.12.2.tgz#c0920f7db0d4ac062ffe2375cb004089806f627a" + integrity sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw== dependencies: - bn.js "4.11.8" - source-map-support "0.5.9" - yargs "11.1.0" + ethereumjs-util "6.2.1" + source-map-support "0.5.12" + yargs "13.2.4" -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" +get-intrinsic@^1.0.2, get-intrinsic@^1.1.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" glob@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3: - version "7.1.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0" - integrity sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global@~4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== dependencies: min-document "^2.19.0" - process "~0.5.1" - -got@7.1.0, got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + process "^0.11.10" -"graceful-readlink@>= 1.0.0": +gopd@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-12.1.0.tgz#099f3815305c682be4fd6b0ee0726d8e4c6b0af4" + integrity sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig== + dependencies: + "@sindresorhus/is" "^4.6.0" + "@szmarczak/http-timer" "^5.0.1" + "@types/cacheable-request" "^6.0.2" + "@types/responselike" "^1.0.0" + cacheable-lookup "^6.0.4" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + form-data-encoder "1.7.1" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^2.0.0" + +got@^11.8.5: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== -har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^5.3.0" + ajv "^6.12.3" har-schema "^2.0.0" -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== dependencies: - has-symbol-support-x "^1.4.1" + has-symbols "^1.0.2" -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + function-bind "^1.1.1" -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-errors@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== -http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: - version "1.6.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -iconv-lite@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +http2-wrapper@^2.1.10: + version "2.2.0" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" + integrity sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" -iconv-lite@0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" idna-uts46-hx@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== dependencies: punycode "2.1.0" -ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipaddr.js@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" is-callable@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - -is-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - -is-promise@^2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-stream@^1.0.0, is-stream@^1.1.0: +is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-typed-array@^1.1.10, is-typed-array@^1.1.3: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-sha3@0.5.7, js-sha3@^0.5.7: +js-sha3@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - -js-sha3@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" + integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - optionalDependencies: - graceful-fs "^4.1.6" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" extsprintf "1.3.0" - json-schema "0.2.3" + json-schema "0.4.0" verror "1.10.0" -keccakjs@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" +keccak@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== dependencies: - browserify-sha3 "^0.0.1" - sha3 "^1.1.0" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== dependencies: - invert-kv "^1.0.0" + json-buffer "3.0.1" -locate-path@^2.0.0: +lcid@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" + invert-kv "^2.0.0" -lodash@^4.13.1: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" +lodash@^4.17.19: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + get-func-name "^2.0.0" + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-queue@0.1: +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + +lru-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== dependencies: es5-ext "~0.10.2" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== dependencies: - pify "^3.0.0" + p-defer "^1.0.0" md5.js@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" inherits "^2.0.1" + safe-buffer "^5.1.2" media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== dependencies: - mimic-fn "^1.0.0" + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" memoizee@^0.4.14: - version "0.4.14" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== dependencies: - d "1" - es5-ext "^0.10.45" - es6-weak-map "^2.0.2" + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" event-emitter "^0.3.5" - is-promise "^2.1" - lru-queue "0.1" - next-tick "1" - timers-ext "^0.1.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "~1.36.0" + mime-db "1.52.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== min-document@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== dependencies: dom-walk "^0.1.0" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= +minimist@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w== dependencies: mkdirp "*" -mkdirp@*, "mkdirp@>=0.5 0": - version "0.5.1" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" +mkdirp@*: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.3.tgz#b083ff37be046fd3d6552468c1f0ff44c1545d1f" + integrity sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw== + +mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - minimist "0.0.8" + minimist "^1.2.6" mock-fs@^4.1.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - -mout@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mz@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" + base-x "^3.0.8" + buffer "^5.5.0" -nan@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" -nan@^2.0.8, nan@^2.3.3: - version "2.11.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew== -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" +next-tick@1, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== dependencies: path-key "^2.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig== dependencies: bn.js "4.11.6" strip-hex-prefix "1.0.0" @@ -1469,123 +2058,142 @@ number-to-bn@1.7.0: oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -oboe@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA== dependencies: http-https "^1.0.0" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -"openzeppelin-solidity@https://github.com/OpenZeppelin/openzeppelin-solidity.git#release-v2.1.0-solc-0.5": - version "2.1.0-rc.1" - resolved "https://github.com/OpenZeppelin/openzeppelin-solidity.git#4b8fcbcee16437d8a29bc0e5bb328b2a1547f996" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: - p-limit "^1.1.0" + p-try "^2.0.0" -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: - p-finally "^1.0.0" + p-limit "^2.0.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" parse-headers@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - dependencies: - for-each "^0.3.2" - trim "0.0.1" + version "2.0.5" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" + integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.0: +path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" +pbkdf2@^3.0.17, pbkdf2@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -1593,162 +2201,144 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - -proxy-addr@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: - forwarded "~0.1.2" - ipaddr.js "1.8.0" + forwarded "0.2.0" + ipaddr.js "1.9.1" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== public-encrypt@^4.0.0: - version "4.0.2" - resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" browserify-rsa "^4.0.0" create-hash "^1.1.0" parse-asn1 "^5.0.0" randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" punycode@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -qs@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" -qs@6.5.2, qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" object-assign "^4.1.0" strict-uri-encode "^1.0.0" -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" -randomhex@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" unpipe "1.0.0" -readable-stream@^2.3.0, readable-stream@^2.3.5: - version "2.3.6" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" -request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: - lodash "^4.13.1" + lodash "^4.17.19" request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" request@^2.79.0, request@^2.83.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -1757,7 +2347,7 @@ request@^2.79.0, request@^2.83.0: extend "~3.0.2" forever-agent "~0.6.1" form-data "~2.3.2" - har-validator "~5.1.0" + har-validator "~5.1.3" http-signature "~1.2.0" is-typedarray "~1.0.0" isstream "~0.1.2" @@ -1767,105 +2357,114 @@ request@^2.79.0, request@^2.83.0: performance-now "^2.1.0" qs "~6.5.2" safe-buffer "^5.1.2" - tough-cookie "~2.4.3" + tough-cookie "~2.5.0" tunnel-agent "^0.6.0" uuid "^3.3.2" require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== -rimraf@2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== dependencies: - glob "^7.1.3" + lowercase-keys "^2.0.0" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" -safe-buffer@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +rlp@^2.2.3, rlp@^2.2.4: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - -scrypt.js@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - -scrypt@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - dependencies: - nan "^2.0.8" +scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: - pbkdf2 "^3.0.3" + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - dependencies: - commander "~2.8.1" +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -serve-static@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" + parseurl "~1.3.3" + send "0.18.0" servify@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== dependencies: body-parser "^1.16.0" cors "^2.8.1" @@ -1876,81 +2475,82 @@ servify@^0.1.12: set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - dependencies: - nan "2.10.0" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + version "2.8.2" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.2.tgz#5708fb0919d440657326cd5fe7d2599d07705019" + integrity sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw== dependencies: decompress-response "^3.3.0" once "^1.3.1" simple-concat "^1.0.0" sol-merger@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.2.tgz#1f12500f42d427dc0ec8e4c113392acd8a6f62d9" - dependencies: - bluebird "^3.5.0" - cli-color "^1.2.0" - commander "^2.11.0" - debug "^3.0.1" - fs-extra "^4.0.2" + version "0.1.4" + resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-0.1.4.tgz#f19df03d9b24cf24c78a5ea57dd7d9d093236139" + integrity sha512-IhwwwFpbKUT+FJkJ0cEdqRJLXBh9hDPhWjKQyS4xwlTuYu4z5Sq4XfYN8qa107hiYk2ZERHYjsOvZnfnDsBwbw== + dependencies: + bluebird "^3.5.3" + cli-color "^1.4.0" + commander "^2.19.0" + debug "^3.2.6" + fs-extra "^7.0.1" glob "^7.1.2" -source-map-support@0.5.9: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -1958,500 +2558,536 @@ source-map-support@0.5.9: source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" ecc-jsbn "~0.1.1" + getpass "^0.1.1" jsbn "~0.1.0" + safer-buffer "^2.0.2" tweetnacl "~0.14.0" -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stealthy-require@^1.1.0: +stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: + emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" + strip-ansi "^5.1.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - ansi-regex "^3.0.0" + safe-buffer "~5.2.0" -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: - is-natural-number "^4.0.1" + ansi-regex "^4.1.0" strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: is-hex-prefixed "1.0.0" -swarm-js@0.1.37: - version "0.1.37" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" +swarm-js@^0.1.40: + version "0.1.42" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" + integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== dependencies: bluebird "^3.5.0" buffer "^5.0.5" - decompress "^4.0.0" eth-lib "^0.1.26" - fs-extra "^2.1.2" - fs-promise "^2.0.0" - got "^7.1.0" + fs-extra "^4.0.2" + got "^11.8.5" mime-types "^2.1.16" mkdirp-promise "^5.0.1" mock-fs "^4.1.0" setimmediate "^1.0.5" - tar.gz "^1.0.5" - xhr-request-promise "^0.1.2" - -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar.gz@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - dependencies: - bluebird "^2.9.34" - commander "^2.8.1" - fstream "^1.0.8" - mout "^0.11.0" - tar "^2.1.1" - -tar@^2.1.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - -thenify-all@^1.0.0, thenify-all@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" - dependencies: - thenify ">= 3.1.0 < 4" + tar "^4.0.2" + xhr-request "^1.0.1" -"thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== dependencies: - any-promise "^1.0.0" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" -timed-out@^4.0.0, timed-out@^4.0.1: +timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -timers-ext@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.5.tgz#77147dd4e76b660c2abb8785db96574cbbd12922" +timers-ext@^0.1.5, timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== dependencies: - es5-ext "~0.10.14" + es5-ext "~0.10.46" next-tick "1" -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -tough-cookie@>=2.3.3, tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: - psl "^1.1.24" - punycode "^1.4.1" + psl "^1.1.28" + punycode "^2.1.1" -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-is@~1.6.15, type-is@~1.6.16: - version "1.6.16" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" - mime-types "~2.1.18" + mime-types "~2.1.24" -typedarray-to-buffer@^3.1.2: +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== dependencies: is-typedarray "^1.0.0" ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - -unbzip2-stream@^1.0.9: - version "1.3.0" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.0.tgz#745ad5745bc4d8f1ac2eb6fc707cfa51d52ab215" - dependencies: - buffer "^3.0.1" - through "^2.3.6" - -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: - prepend-http "^1.0.1" + punycode "^2.1.0" url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" -utf8@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.0: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" -web3-bzz@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz#adb3fe7a70053eb7843e32b106792b01b482ef41" - dependencies: - got "7.1.0" - swarm-js "0.1.37" - underscore "1.8.3" - -web3-core-helpers@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz#6f618e80f1a6588d846efbfdc28f92ae0477f8d2" +web3-bzz@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.8.1.tgz#81397be5ce262d03d82b92e9d8acc11f8a609ea1" + integrity sha512-dJJHS84nvpoxv6ijTMkdUSlRr5beCXNtx4UZcrFLHBva8dT63QEtKdLyDt2AyMJJdVzTCk78uir/6XtVWrdS6w== dependencies: - underscore "1.8.3" - web3-eth-iban "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + "@types/node" "^12.12.6" + got "12.1.0" + swarm-js "^0.1.40" -web3-core-method@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz#855c0365ae7d0ead394d973ea9e28828602900e0" +web3-core-helpers@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.8.1.tgz#7904747b23fd0afa4f2c86ed98ea9418ccad7672" + integrity sha512-ClzNO6T1S1gifC+BThw0+GTfcsjLEY8T1qUp6Ly2+w4PntAdNtKahxWKApWJ0l9idqot/fFIDXwO3Euu7I0Xqw== dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + web3-eth-iban "1.8.1" + web3-utils "1.8.1" -web3-core-promievent@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz#3a5127787fff751be6de272722cbc77dc9523fd5" +web3-core-method@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.8.1.tgz#0fc5a433a9fc784c447522f141c0a8e0163c7790" + integrity sha512-oYGRodktfs86NrnFwaWTbv2S38JnpPslFwSSARwFv4W9cjbGUW3LDeA5MKD/dRY+ssZ5OaekeMsUCLoGhX68yA== dependencies: - any-promise "1.3.0" - eventemitter3 "1.1.1" + "@ethersproject/transactions" "^5.6.2" + web3-core-helpers "1.8.1" + web3-core-promievent "1.8.1" + web3-core-subscriptions "1.8.1" + web3-utils "1.8.1" -web3-core-requestmanager@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz#70c8eead84da9ed1cf258e6dde3f137116d0691b" +web3-core-promievent@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.8.1.tgz#f334c8b2ceac6c2228f06d2a515f6d103157f036" + integrity sha512-9mxqHlgB0MrZI4oUIRFkuoJMNj3E7btjrMv3sMer/Z9rYR1PfoSc1aAokw4rxKIcAh+ylVtd/acaB2HKB7aRPg== dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-providers-http "1.0.0-beta.36" - web3-providers-ipc "1.0.0-beta.36" - web3-providers-ws "1.0.0-beta.36" + eventemitter3 "4.0.4" -web3-core-subscriptions@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz#20f1f20c85d5b40f1e5a49b070ba977a142621f3" +web3-core-requestmanager@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.8.1.tgz#272ffa55b7b568ecbc8e4a257ca080355c31c60e" + integrity sha512-x+VC2YPPwZ1khvqA6TA69LvfFCOZXsoUVOxmTx/vIN22PrY9KzKhxcE7pBSiGhmab1jtmRYXUbcQSVpAXqL8cw== dependencies: - eventemitter3 "1.1.1" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" + util "^0.12.0" + web3-core-helpers "1.8.1" + web3-providers-http "1.8.1" + web3-providers-ipc "1.8.1" + web3-providers-ws "1.8.1" -web3-core@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.36.tgz#86182f2456c2cf1cd6e7654d314e195eac211917" +web3-core-subscriptions@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.8.1.tgz#f5ae1380e92746eadfab6475b8a70ef5a1be6bbf" + integrity sha512-bmCMq5OeA3E2vZUh8Js1HcJbhwtsE+yeMqGC4oIZB3XsL5SLqyKLB/pU+qUYqQ9o4GdcrFTDPhPg1bgvf7p1Pw== dependencies: - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-requestmanager "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + eventemitter3 "4.0.4" + web3-core-helpers "1.8.1" -web3-eth-abi@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz#21c0f222701db827a8a269accb9cd18bbd8f70f9" +web3-core@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.8.1.tgz#050b1c408d1f9b7ae539e90f7f7d1b7a7d10578b" + integrity sha512-LbRZlJH2N6nS3n3Eo9Y++25IvzMY7WvYnp4NM/Ajhh97dAdglYs6rToQ2DbL2RLvTYmTew4O/y9WmOk4nq9COw== + dependencies: + "@types/bn.js" "^5.1.0" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.8.1" + web3-core-method "1.8.1" + web3-core-requestmanager "1.8.1" + web3-utils "1.8.1" + +web3-eth-abi@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.8.1.tgz#47455d6513217c4b0866fea6f97b1c4afa0b6535" + integrity sha512-0mZvCRTIG0UhDhJwNQJgJxu4b4DyIpuMA0GTfqxqeuqzX4Q/ZvmoNurw0ExTfXaGPP82UUmmdkRi6FdZOx+C6w== dependencies: - ethers "4.0.0-beta.1" - underscore "1.8.3" - web3-utils "1.0.0-beta.36" + "@ethersproject/abi" "^5.6.3" + web3-utils "1.8.1" -web3-eth-accounts@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.36.tgz#8aea37df9b038ef2c6cda608856ffd861b39eeef" +web3-eth-accounts@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.8.1.tgz#1ce7387721f118aeb0376291e4d8bbe2ac323406" + integrity sha512-mgzxSYgN54/NsOFBO1Fq1KkXp1S5KlBvI/DlgvajU72rupoFMq6Cu6Yp9GUaZ/w2ij9PzEJuFJk174XwtfMCmg== dependencies: - any-promise "1.3.0" + "@ethereumjs/common" "2.5.0" + "@ethereumjs/tx" "3.3.2" crypto-browserify "3.12.0" - eth-lib "0.2.7" - scrypt.js "0.2.0" - underscore "1.8.3" - uuid "2.0.1" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-contract@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.36.tgz#c0c366c4e4016896142208cee758a2ff2a31be2a" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-ens@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.36.tgz#c7440b42b597fd74f64bc402f03ad2e832f423d8" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + uuid "^9.0.0" + web3-core "1.8.1" + web3-core-helpers "1.8.1" + web3-core-method "1.8.1" + web3-utils "1.8.1" + +web3-eth-contract@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.8.1.tgz#bdf3e33bbcb79a1b6144dffd6a0deefd2e459272" + integrity sha512-1wphnl+/xwCE2io44JKnN+ti3oa47BKRiVzvWd42icwRbcpFfRxH9QH+aQX3u8VZIISNH7dAkTWpGIIJgGFTmg== + dependencies: + "@types/bn.js" "^5.1.0" + web3-core "1.8.1" + web3-core-helpers "1.8.1" + web3-core-method "1.8.1" + web3-core-promievent "1.8.1" + web3-core-subscriptions "1.8.1" + web3-eth-abi "1.8.1" + web3-utils "1.8.1" + +web3-eth-ens@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.8.1.tgz#e78a9651fea8282abe8565b001819e2d645e5929" + integrity sha512-FT8xTI9uN8RxeBQa/W8pLa2aoFh4+EE34w7W2271LICKzla1dtLyb6XSdn48vsUcPmhWsTVk9mO9RTU0l4LGQQ== dependencies: + content-hash "^2.5.2" eth-ens-namehash "2.0.8" - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-iban@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz#00cb3aba7a5aeb15d02b07421042e263d7b2e01b" + web3-core "1.8.1" + web3-core-helpers "1.8.1" + web3-core-promievent "1.8.1" + web3-eth-abi "1.8.1" + web3-eth-contract "1.8.1" + web3-utils "1.8.1" + +web3-eth-iban@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.8.1.tgz#c6484e5d68ca644aa78431301e7acd5df24598d1" + integrity sha512-DomoQBfvIdtM08RyMGkMVBOH0vpOIxSSQ+jukWk/EkMLGMWJtXw/K2c2uHAeq3L/VPWNB7zXV2DUEGV/lNE2Dg== dependencies: - bn.js "4.11.6" - web3-utils "1.0.0-beta.36" - -web3-eth-personal@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.36.tgz#95545998a8ee377e3bb71e27c8d1a5dc1d7d5a21" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.36.tgz#04a8c748d344c1accaa26d7d5d0eac0da7127f14" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-accounts "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-eth-ens "1.0.0-beta.36" - web3-eth-iban "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-net@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.36.tgz#396cd35cb40934ed022a1f44a8a642d3908c41eb" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-providers-http@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz#c1937a2e64f8db7cd30f166794e37cf0fcca1131" - dependencies: - web3-core-helpers "1.0.0-beta.36" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz#0c78efb4ed6b0305ec830e1e0b785e61217ee605" - dependencies: - oboe "2.1.3" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - -web3-providers-ws@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz#27b74082c7adfa0cb5a65535eb312e49008c97c3" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" - -web3-shh@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.36.tgz#6ff297594480edefc710d9d287765a0c4a5d5af1" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - -web3-utils@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.36.tgz#dc19c9aeec009b1816cc91ef64d7fe9f8ee344c9" + bn.js "^5.2.1" + web3-utils "1.8.1" + +web3-eth-personal@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.8.1.tgz#00b5ff1898b62044d25ed5fddd8486168d4827cf" + integrity sha512-myIYMvj7SDIoV9vE5BkVdon3pya1WinaXItugoii2VoTcQNPOtBxmYVH+XS5ErzCJlnxzphpQrkywyY64bbbCA== dependencies: - bn.js "4.11.6" - eth-lib "0.1.27" + "@types/node" "^12.12.6" + web3-core "1.8.1" + web3-core-helpers "1.8.1" + web3-core-method "1.8.1" + web3-net "1.8.1" + web3-utils "1.8.1" + +web3-eth@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.8.1.tgz#395f6cd56edaac5dbb23e8cec9886c3fd32c430e" + integrity sha512-LgyzbhFqiFRd8M8sBXoFN4ztzOnkeckl3H/9lH5ek7AdoRMhBg7tYpYRP3E5qkhd/q+yiZmcUgy1AF6NHrC1wg== + dependencies: + web3-core "1.8.1" + web3-core-helpers "1.8.1" + web3-core-method "1.8.1" + web3-core-subscriptions "1.8.1" + web3-eth-abi "1.8.1" + web3-eth-accounts "1.8.1" + web3-eth-contract "1.8.1" + web3-eth-ens "1.8.1" + web3-eth-iban "1.8.1" + web3-eth-personal "1.8.1" + web3-net "1.8.1" + web3-utils "1.8.1" + +web3-net@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.8.1.tgz#2bed4d4b93166724129ec33d0e5dea98880285f4" + integrity sha512-LyEJAwogdFo0UAXZqoSJGFjopdt+kLw0P00FSZn2yszbgcoI7EwC+nXiOsEe12xz4LqpYLOtbR7+gxgiTVjjHQ== + dependencies: + web3-core "1.8.1" + web3-core-method "1.8.1" + web3-utils "1.8.1" + +web3-providers-http@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.8.1.tgz#8aa89c11a9272f11ddb74b871273c92225faa28d" + integrity sha512-1Zyts4O9W/UNEPkp+jyL19Jc3D15S4yp8xuLTjVhcUEAlHo24NDWEKxtZGUuHk4HrKL2gp8OlsDbJ7MM+ESDgg== + dependencies: + abortcontroller-polyfill "^1.7.3" + cross-fetch "^3.1.4" + es6-promise "^4.2.8" + web3-core-helpers "1.8.1" + +web3-providers-ipc@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.8.1.tgz#6128a3a3a824d06bf0efcfe86325401f8691a5ca" + integrity sha512-nw/W5nclvi+P2z2dYkLWReKLnocStflWqFl+qjtv0xn3MrUTyXMzSF0+61i77+16xFsTgzo4wS/NWIOVkR0EFA== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.8.1" + +web3-providers-ws@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.8.1.tgz#5e5370e07eb8c615ed298ebc8602b283c7b7d649" + integrity sha512-TNefIDAMpdx57+YdWpYZ/xdofS0P+FfKaDYXhn24ie/tH9G+AB+UBSOKnjN0KSadcRSCMBwGPRiEmNHPavZdsA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.8.1" + websocket "^1.0.32" + +web3-shh@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.8.1.tgz#028a95cf9d3a36020380938b9a127610efbb9be7" + integrity sha512-sqHgarnfcY2Qt3PYS4R6YveHrDy7hmL09yeLLHHCI+RKirmjLVqV0rc5LJWUtlbYI+kDoa5gbgde489M9ZAC0g== + dependencies: + web3-core "1.8.1" + web3-core-method "1.8.1" + web3-core-subscriptions "1.8.1" + web3-net "1.8.1" + +web3-utils@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" + integrity sha512-LgnM9p6V7rHHUGfpMZod+NST8cRfGzJ1BTXAyNo7A9cJX9LczBfSRxJp+U/GInYe9mby40t3v22AJdlELibnsQ== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" ethjs-unit "0.1.6" number-to-bn "1.7.0" - randomhex "0.1.5" - underscore "1.8.3" - utf8 "2.1.1" + randombytes "^2.1.0" + utf8 "3.0.0" web3@^1.0.0-beta.27: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.36.tgz#2954da9e431124c88396025510d840ba731c8373" - dependencies: - web3-bzz "1.0.0-beta.36" - web3-core "1.0.0-beta.36" - web3-eth "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-shh "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" + version "1.8.1" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.8.1.tgz#8ea67215ef5f3a6f6d3381800b527242ea22885a" + integrity sha512-tAqFsQhGv340C9OgRJIuoScN7f7wa1tUvsnnDUMt9YE6J4gcm7TV2Uwv+KERnzvV+xgdeuULYpsioRRNKrUvoQ== + dependencies: + web3-bzz "1.8.1" + web3-core "1.8.1" + web3-eth "1.8.1" + web3-eth-personal "1.8.1" + web3-net "1.8.1" + web3-shh "1.8.1" + web3-utils "1.8.1" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": - version "1.0.26" - resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" +websocket@^1.0.32: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== dependencies: + bufferutil "^4.0.1" debug "^2.2.0" - nan "^2.3.3" - typedarray-to-buffer "^3.1.2" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" yaeti "^0.0.6" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +which-typed-array@^1.1.2: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" which@^1.2.9: version "1.3.1" @@ -2460,36 +3096,40 @@ which@^1.2.9: dependencies: isexe "^2.0.0" -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" ultron "~1.1.0" xhr-request-promise@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== dependencies: - xhr-request "^1.0.1" + xhr-request "^1.1.0" -xhr-request@^1.0.1: +xhr-request@^1.0.1, xhr-request@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== dependencies: buffer-to-arraybuffer "^0.0.5" object-assign "^4.1.1" @@ -2499,71 +3139,57 @@ xhr-request@^1.0.1: url-set-query "^1.0.0" xhr "^2.0.4" -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - dependencies: - cookiejar "^2.1.1" - xhr@^2.0.4, xhr@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== dependencies: - global "~4.3.0" + global "~4.4.0" is-function "^1.0.1" parse-headers "^2.0.0" xtend "^4.0.0" -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= - dependencies: - camelcase "^4.1.0" - -yargs@11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" +yallist@^3.0.0, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^13.1.0: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^2.0.0" + string-width "^3.0.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" From 66893b9ae523573dd7e560eca638c1a0f640c9ff Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Tue, 24 Jan 2023 19:45:26 +0300 Subject: [PATCH 03/11] add unit tests for EtomicSwap contract watcher functions --- test/EtomicSwap.js | 187 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 620c41e..03d2029 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -308,7 +308,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver to spend ERC20 payment by revealing a secret even after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -342,4 +342,189 @@ contract('EtomicSwap', function(accounts) { // should not allow to spend again await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); + + it('should allow a watcher to refund ETH payment on behalf of the sender after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime + ]; + + // not allow to refund if payment was not sent + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.watcherRefund(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong sender address + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong receiver address + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success refund + const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + const tx = await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + // check sender balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to refund ERC20 payment on behalf of the sender after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + web3.utils.toWei('1'), + this.token.address, + accounts[1], + secretHash, + lockTime + ]; + + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20Payment(...params).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.watcherRefund(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong sender address + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong receiver address + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success refund + const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.fulfilled; + + const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + + // check sender balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to spend ETH payment on behalf of the receiver by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime + ]; + + // should not allow to spend uninitialized payment + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.watcherSpend(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.watcherSpend(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success spend + const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + const tx = await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + + const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + // check receiver balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + web3.utils.toWei('1'), + this.token.address, + accounts[1], + secretHash, + lockTime + ]; + + // should not allow to spend uninitialized payment + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20Payment(...params).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.watcherSpend(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.watcherSpend(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success spend + const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + // check receiver balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + }); }); From aa2597f34d4f57bb3fbdc7f6590cad4106a4baf8 Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Mon, 30 Jan 2023 18:35:28 +0300 Subject: [PATCH 04/11] refactor code to remove duplication --- contracts/EtomicSwap.sol | 52 +++++-------------------------------- test/EtomicSwap.js | 56 ++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index f9a5233..9478a74 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -84,36 +84,17 @@ contract EtomicSwap { address _tokenAddress, address _sender ) external { - require(payments[_id].state == PaymentState.PaymentSent); - - bytes20 paymentHash = ripemd160(abi.encodePacked( - msg.sender, - _sender, - ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), - _tokenAddress, - _amount - )); - - require(paymentHash == payments[_id].paymentHash); - payments[_id].state = PaymentState.ReceivedSpent; - if (_tokenAddress == address(0)) { - payable(msg.sender).transfer(_amount); - } else { - IERC20 token = IERC20(_tokenAddress); - require(token.transfer(msg.sender, _amount)); - } - - emit ReceiverSpent(_id, _secret); + receiverSpendV2(_id, _amount, _secret, _tokenAddress, _sender, msg.sender); } - function watcherSpend( + function receiverSpendV2( bytes32 _id, uint256 _amount, bytes32 _secret, address _tokenAddress, address _sender, address _receiver - ) external { + ) public { require(payments[_id].state == PaymentState.PaymentSent); bytes20 paymentHash = ripemd160(abi.encodePacked( @@ -143,38 +124,17 @@ contract EtomicSwap { address _tokenAddress, address _receiver ) external { - require(payments[_id].state == PaymentState.PaymentSent); - - bytes20 paymentHash = ripemd160(abi.encodePacked( - _receiver, - msg.sender, - _paymentHash, - _tokenAddress, - _amount - )); - - require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); - - payments[_id].state = PaymentState.SenderRefunded; - - if (_tokenAddress == address(0)) { - payable(msg.sender).transfer(_amount); - } else { - IERC20 token = IERC20(_tokenAddress); - require(token.transfer(msg.sender, _amount)); - } - - emit SenderRefunded(_id); + senderRefundV2(_id, _amount, _paymentHash, _tokenAddress, msg.sender, _receiver); } - function watcherRefund( + function senderRefundV2( bytes32 _id, uint256 _amount, bytes20 _paymentHash, address _tokenAddress, address _sender, address _receiver - ) external { + ) public { require(payments[_id].state == PaymentState.PaymentSent); bytes20 paymentHash = ripemd160(abi.encodePacked( diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 03d2029..a485451 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -353,29 +353,29 @@ contract('EtomicSwap', function(accounts) { ]; // not allow to refund if payment was not sent - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.watcherRefund(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); // check sender balance @@ -385,7 +385,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to refund ERC20 payment on behalf of the sender after locktime', async function () { @@ -403,26 +403,26 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20Payment(...params).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.watcherRefund(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.fulfilled; + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -433,7 +433,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.watcherRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ETH payment on behalf of the receiver by revealing a secret', async function () { @@ -446,26 +446,26 @@ contract('EtomicSwap', function(accounts) { ]; // should not allow to spend uninitialized payment - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.watcherSpend(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.watcherSpend(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -478,7 +478,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { @@ -493,27 +493,27 @@ contract('EtomicSwap', function(accounts) { ]; // should not allow to spend uninitialized payment - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, web3.utils.toWei('1')); await this.swap.erc20Payment(...params).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.watcherSpend(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.watcherSpend(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); // check receiver balance @@ -525,6 +525,6 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.watcherSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); }); From 8d54825315a96d6012e29308a8cdd54ecbd561ce Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Mon, 30 Jan 2023 18:37:38 +0300 Subject: [PATCH 05/11] fix a typo --- contracts/EtomicSwap.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 9478a74..1ca4dc5 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -5,7 +5,7 @@ contract EtomicSwap { enum PaymentState { Uninitialized, PaymentSent, - ReceivedSpent, + ReceiverSpent, SenderRefunded } @@ -106,7 +106,7 @@ contract EtomicSwap { )); require(paymentHash == payments[_id].paymentHash); - payments[_id].state = PaymentState.ReceivedSpent; + payments[_id].state = PaymentState.ReceiverSpent; if (_tokenAddress == address(0)) { payable(_receiver).transfer(_amount); } else { From 6b9b73219d1ac631133a0901d78601fe0b7b7d9c Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Wed, 15 Feb 2023 16:15:43 +0300 Subject: [PATCH 06/11] add watcher reward functionality and unit tests --- contracts/EtomicSwap.sol | 130 ++++++++++++++-- test/EtomicSwap.js | 323 ++++++++++++++++++++++++++++++++------- 2 files changed, 389 insertions(+), 64 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 1ca4dc5..822a54e 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -48,6 +48,33 @@ contract EtomicSwap { emit PaymentSent(_id); } + function ethPaymentReward( + bytes32 _id, + address _receiver, + bytes20 _secretHash, + uint64 _lockTime, + uint256 _watcherReward + ) external payable { + require(_receiver != address(0) && msg.value > 0 && payments[_id].state == PaymentState.Uninitialized); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + _receiver, + msg.sender, + _secretHash, + address(0), + msg.value, + _watcherReward + )); + + payments[_id] = Payment( + paymentHash, + _lockTime, + PaymentState.PaymentSent + ); + + emit PaymentSent(_id); + } + function erc20Payment( bytes32 _id, uint256 _amount, @@ -55,7 +82,7 @@ contract EtomicSwap { address _receiver, bytes20 _secretHash, uint64 _lockTime - ) external payable { + ) external { require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); bytes20 paymentHash = ripemd160(abi.encodePacked( @@ -77,6 +104,36 @@ contract EtomicSwap { emit PaymentSent(_id); } + function erc20PaymentReward( + bytes32 _id, + uint256 _amount, + address _tokenAddress, + address _receiver, + bytes20 _secretHash, + uint64 _lockTime + ) external payable { + require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + _receiver, + msg.sender, + _secretHash, + _tokenAddress, + _amount, + msg.value + )); + + payments[_id] = Payment( + paymentHash, + _lockTime, + PaymentState.PaymentSent + ); + + IERC20 token = IERC20(_tokenAddress); + require(token.transferFrom(msg.sender, address(this), _amount)); + emit PaymentSent(_id); + } + function receiverSpend( bytes32 _id, uint256 _amount, @@ -84,17 +141,37 @@ contract EtomicSwap { address _tokenAddress, address _sender ) external { - receiverSpendV2(_id, _amount, _secret, _tokenAddress, _sender, msg.sender); + require(payments[_id].state == PaymentState.PaymentSent); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + msg.sender, + _sender, + ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), + _tokenAddress, + _amount + )); + + require(paymentHash == payments[_id].paymentHash); + payments[_id].state = PaymentState.ReceiverSpent; + if (_tokenAddress == address(0)) { + payable(msg.sender).transfer(_amount); + } else { + IERC20 token = IERC20(_tokenAddress); + require(token.transfer(msg.sender, _amount)); + } + + emit ReceiverSpent(_id, _secret); } - function receiverSpendV2( + function receiverSpendReward( bytes32 _id, uint256 _amount, bytes32 _secret, address _tokenAddress, address _sender, - address _receiver - ) public { + address _receiver, + uint256 _watcherReward + ) external { require(payments[_id].state == PaymentState.PaymentSent); bytes20 paymentHash = ripemd160(abi.encodePacked( @@ -102,17 +179,20 @@ contract EtomicSwap { _sender, ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), _tokenAddress, - _amount + _amount, + _watcherReward )); require(paymentHash == payments[_id].paymentHash); payments[_id].state = PaymentState.ReceiverSpent; + if (_tokenAddress == address(0)) { - payable(_receiver).transfer(_amount); + payable(_receiver).transfer(_amount - _watcherReward); } else { IERC20 token = IERC20(_tokenAddress); require(token.transfer(_receiver, _amount)); } + payable(msg.sender).transfer(_watcherReward); emit ReceiverSpent(_id, _secret); } @@ -124,17 +204,39 @@ contract EtomicSwap { address _tokenAddress, address _receiver ) external { - senderRefundV2(_id, _amount, _paymentHash, _tokenAddress, msg.sender, _receiver); + require(payments[_id].state == PaymentState.PaymentSent); + + bytes20 paymentHash = ripemd160(abi.encodePacked( + _receiver, + msg.sender, + _paymentHash, + _tokenAddress, + _amount + )); + + require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); + + payments[_id].state = PaymentState.SenderRefunded; + + if (_tokenAddress == address(0)) { + payable(msg.sender).transfer(_amount); + } else { + IERC20 token = IERC20(_tokenAddress); + require(token.transfer(msg.sender, _amount)); + } + + emit SenderRefunded(_id); } - function senderRefundV2( + function senderRefundReward( bytes32 _id, uint256 _amount, bytes20 _paymentHash, address _tokenAddress, address _sender, - address _receiver - ) public { + address _receiver, + uint256 _watcherReward + ) external { require(payments[_id].state == PaymentState.PaymentSent); bytes20 paymentHash = ripemd160(abi.encodePacked( @@ -142,7 +244,8 @@ contract EtomicSwap { _sender, _paymentHash, _tokenAddress, - _amount + _amount, + _watcherReward )); require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); @@ -150,11 +253,12 @@ contract EtomicSwap { payments[_id].state = PaymentState.SenderRefunded; if (_tokenAddress == address(0)) { - payable(_sender).transfer(_amount); + payable(_sender).transfer(_amount - _watcherReward); } else { IERC20 token = IERC20(_tokenAddress); require(token.transfer(_sender, _amount)); } + payable(msg.sender).transfer(_watcherReward); emit SenderRefunded(_id); } diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index a485451..12d712e 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -36,6 +36,8 @@ const secretHex = '0x' + secret.toString('hex'); const zeroAddr = '0x0000000000000000000000000000000000000000'; +const watcherReward = web3.utils.toBN(100000); + contract('EtomicSwap', function(accounts) { beforeEach(async function () { @@ -59,6 +61,7 @@ contract('EtomicSwap', function(accounts) { ]; await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + const payment = await this.swap.payments(id); // locktime @@ -99,7 +102,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20Payment(...params).should.be.rejectedWith(EVMThrow); }); - it('should allow sender to refund ETH payment after locktime', async function () { + it('should allow sender without watcher support to refund ETH payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -142,7 +145,53 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); }); - it('should allow sender to refund ERC20 payment after locktime', async function () { + it('should allow sender with watcher support to refund ETH payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + watcherReward + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + //not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); + + // success refund + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; + + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + // check sender balance + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender without watcher support to refund ERC20 payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -187,7 +236,57 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver to spend ETH payment by revealing a secret', async function () { + it('should allow sender with watcher support to refund ERC20 payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + web3.utils.toWei('1'), + this.token.address, + accounts[1], + secretHash, + lockTime + ]; + + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcherReward amount + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], web3.utils.toWei('2')).should.be.rejectedWith(EVMThrow); + + // success refund + const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + let tx = await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + // check sender balance + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore.add(watcherReward)); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver without watcher support to spend ETH payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -230,7 +329,51 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver with watcher support to spend ETH payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + watcherReward + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // success spend + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + // check receiver balance + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver without watcher support to spend ERC20 payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -274,6 +417,56 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); + it('should allow receiver with watcher support to spend ERC20 payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + web3.utils.toWei('1'), + this.token.address, + accounts[1], + secretHash, + lockTime + ]; + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid watcher reward amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], web3.utils.toWei('5'), { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // success spend + const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + let tx = await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + // check receiver balance + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore.add(watcherReward)); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + it('should allow receiver to spend ETH payment by revealing a secret even after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ @@ -349,43 +542,53 @@ contract('EtomicSwap', function(accounts) { id, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // not allow to refund if payment was not sent - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundV2(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const tx = await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); - // check sender balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + // check watcher balance + assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).toString(), watcherReward.sub(txFee)); + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to refund ERC20 payment on behalf of the sender after locktime', async function () { @@ -400,40 +603,45 @@ contract('EtomicSwap', function(accounts) { ]; await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward} ).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundV2(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.fulfilled; + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check sender balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee)); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundV2(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ETH payment on behalf of the receiver by revealing a secret', async function () { @@ -442,35 +650,42 @@ contract('EtomicSwap', function(accounts) { id, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount - await this.swap.receiverSpendV2(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const tx = await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; - - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).add(txFee).toString(), watcherReward); const payment = await this.swap.payments(id); @@ -478,7 +693,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { @@ -493,31 +708,37 @@ contract('EtomicSwap', function(accounts) { ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendV2(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const takerBalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const takerBalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).add(txFee).toString(), watcherReward); const payment = await this.swap.payments(id); @@ -525,6 +746,6 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendV2(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); }); From 00a759b04350b8a7407317736fa0c480dbdc9d29 Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Wed, 22 Mar 2023 19:02:09 +0300 Subject: [PATCH 07/11] use ERC20 tokens as watcher reward --- contracts/EtomicSwap.sol | 18 ++++--- test/EtomicSwap.js | 108 ++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 54 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 822a54e..8bce6e3 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -110,7 +110,8 @@ contract EtomicSwap { address _tokenAddress, address _receiver, bytes20 _secretHash, - uint64 _lockTime + uint64 _lockTime, + uint256 _watcherReward ) external payable { require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); @@ -120,7 +121,7 @@ contract EtomicSwap { _secretHash, _tokenAddress, _amount, - msg.value + _watcherReward )); payments[_id] = Payment( @@ -172,6 +173,7 @@ contract EtomicSwap { address _receiver, uint256 _watcherReward ) external { + payments[0].state = PaymentState.ReceiverSpent; require(payments[_id].state == PaymentState.PaymentSent); bytes20 paymentHash = ripemd160(abi.encodePacked( @@ -188,12 +190,13 @@ contract EtomicSwap { if (_tokenAddress == address(0)) { payable(_receiver).transfer(_amount - _watcherReward); + payable(msg.sender).transfer(_watcherReward); } else { IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_receiver, _amount)); + require(token.transfer(_receiver, _amount - _watcherReward)); + require(token.transfer(msg.sender, _watcherReward)); } - payable(msg.sender).transfer(_watcherReward); - + emit ReceiverSpent(_id, _secret); } @@ -254,11 +257,12 @@ contract EtomicSwap { if (_tokenAddress == address(0)) { payable(_sender).transfer(_amount - _watcherReward); + payable(msg.sender).transfer(_watcherReward); } else { IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_sender, _amount)); + require(token.transfer(_sender, _amount - _watcherReward)); + require(token.transfer(msg.sender, _watcherReward)); } - payable(msg.sender).transfer(_watcherReward); emit SenderRefunded(_id); } diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 12d712e..e131c07 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -61,7 +61,6 @@ contract('EtomicSwap', function(accounts) { ]; await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; - const payment = await this.swap.payments(id); // locktime @@ -238,23 +237,25 @@ contract('EtomicSwap', function(accounts) { it('should allow sender with watcher support to refund ERC20 payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); await increaseTime(1000); @@ -262,22 +263,22 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcherReward amount - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], web3.utils.toWei('2')).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount).should.be.rejectedWith(EVMThrow); // success refund const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); // check sender balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore.add(watcherReward)); + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); @@ -419,44 +420,46 @@ contract('EtomicSwap', function(accounts) { it('should allow receiver with watcher support to spend ERC20 payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid watcher reward amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], web3.utils.toWei('5'), { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); // check receiver balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore.add(watcherReward)); + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore); const payment = await this.swap.payments(id); @@ -593,23 +596,25 @@ contract('EtomicSwap', function(accounts) { it('should allow a watcher to refund ERC20 payment on behalf of the sender after locktime', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20PaymentReward(...params, {value: watcherReward} ).should.be.fulfilled; + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); @@ -617,25 +622,29 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + ////web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward) // check sender balance assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee)); + assert.equal(watcherETHBalanceBefore.sub(watcherETHBalanceAfter).toString(), txFee.toString()); + assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); @@ -698,47 +707,52 @@ contract('EtomicSwap', function(accounts) { it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + watcherReward ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend - const takerBalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const takerBalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); // check receiver balance - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).add(txFee).toString(), watcherReward); + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherETHBalanceBefore.sub(watcherETHBalanceAfter).toString(), txFee.toString()); + assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -746,6 +760,6 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); }); From 7ff37ca147a12dde3619d63019e87c662e3ce7bc Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Thu, 23 Mar 2023 00:03:30 +0300 Subject: [PATCH 08/11] add refund-only watcher rewards --- contracts/EtomicSwap.sol | 36 ++- test/EtomicSwap.js | 469 +++++++++++++++++++++++++++++++++------ 2 files changed, 428 insertions(+), 77 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 8bce6e3..3510408 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -53,7 +53,8 @@ contract EtomicSwap { address _receiver, bytes20 _secretHash, uint64 _lockTime, - uint256 _watcherReward + uint256 _watcherReward, + bool _refundOnlyReward ) external payable { require(_receiver != address(0) && msg.value > 0 && payments[_id].state == PaymentState.Uninitialized); @@ -63,7 +64,8 @@ contract EtomicSwap { _secretHash, address(0), msg.value, - _watcherReward + _watcherReward, + _refundOnlyReward )); payments[_id] = Payment( @@ -111,7 +113,8 @@ contract EtomicSwap { address _receiver, bytes20 _secretHash, uint64 _lockTime, - uint256 _watcherReward + uint256 _watcherReward, + bool _refundOnlyReward ) external payable { require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); @@ -121,7 +124,8 @@ contract EtomicSwap { _secretHash, _tokenAddress, _amount, - _watcherReward + _watcherReward, + _refundOnlyReward )); payments[_id] = Payment( @@ -171,7 +175,8 @@ contract EtomicSwap { address _tokenAddress, address _sender, address _receiver, - uint256 _watcherReward + uint256 _watcherReward, + bool _refundOnlyReward ) external { payments[0].state = PaymentState.ReceiverSpent; require(payments[_id].state == PaymentState.PaymentSent); @@ -182,7 +187,8 @@ contract EtomicSwap { ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), _tokenAddress, _amount, - _watcherReward + _watcherReward, + _refundOnlyReward )); require(paymentHash == payments[_id].paymentHash); @@ -190,11 +196,19 @@ contract EtomicSwap { if (_tokenAddress == address(0)) { payable(_receiver).transfer(_amount - _watcherReward); - payable(msg.sender).transfer(_watcherReward); + if (_refundOnlyReward) { + payable(_sender).transfer(_watcherReward); + } else { + payable(msg.sender).transfer(_watcherReward); + } } else { IERC20 token = IERC20(_tokenAddress); require(token.transfer(_receiver, _amount - _watcherReward)); - require(token.transfer(msg.sender, _watcherReward)); + if (_refundOnlyReward) { + require(token.transfer(_sender, _watcherReward)); + } else { + require(token.transfer(msg.sender, _watcherReward)); + } } emit ReceiverSpent(_id, _secret); @@ -238,7 +252,8 @@ contract EtomicSwap { address _tokenAddress, address _sender, address _receiver, - uint256 _watcherReward + uint256 _watcherReward, + bool _refundOnlyReward ) external { require(payments[_id].state == PaymentState.PaymentSent); @@ -248,7 +263,8 @@ contract EtomicSwap { _paymentHash, _tokenAddress, _amount, - _watcherReward + _watcherReward, + _refundOnlyReward )); require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index e131c07..b85a2f3 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -61,6 +61,7 @@ contract('EtomicSwap', function(accounts) { ]; await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + const payment = await this.swap.payments(id); // locktime @@ -144,38 +145,39 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with watcher support to refund ETH payment after locktime', async function () { + it('should allow sender with regular watcher reward to refund ETH payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); //not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), false).should.be.rejectedWith(EVMThrow); // success refund const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.fulfilled; const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); @@ -187,7 +189,56 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender with refund-only watcher reward to refund ETH payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + //not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), true).should.be.rejectedWith(EVMThrow); + + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // not allow to refund with regular watcher reward parameter + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.rejectedWith(EVMThrow); + + // success refund + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { gasPrice }).should.be.fulfilled; + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + // check sender balance + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).add(watcherReward).toString()); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); }); it('should allow sender without watcher support to refund ERC20 payment after locktime', async function () { @@ -235,7 +286,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with watcher support to refund ERC20 payment after locktime', async function () { + it('should allow sender with regular watcher reward to refund ERC20 payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ @@ -245,32 +296,33 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcherReward amount - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount, false).should.be.rejectedWith(EVMThrow); // success refund const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { gasPrice }).should.be.fulfilled; + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -284,7 +336,61 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender with refund-only watcher reward to refund ERC20 payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + const params = [ + id, + amount, + this.token.address, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcherReward amount + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount, true).should.be.rejectedWith(EVMThrow); + + + const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // not allow to refund with regular watcher reward parameter + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.rejectedWith(EVMThrow); + + // success refund + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + + // check sender balance + assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); }); it('should allow receiver without watcher support to spend ETH payment by revealing a secret', async function () { @@ -330,33 +436,34 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with watcher support to spend ETH payment by revealing a secret', async function () { + it('should allow receiver with regular watcher reward to spend ETH payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); @@ -371,7 +478,57 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver with refund-only watcher reward to spend ETH payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // now allow to spend with regular watcher reward parameter + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + + // success spend + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.fulfilled; + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + // check receiver balance + assert.equal(receiverBalanceAfter.sub(receiverBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).toString()); + assert.equal(senderBalanceAfter.sub(senderBalanceBefore).toString(), watcherReward); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow receiver without watcher support to spend ERC20 payment by revealing a secret', async function () { @@ -418,7 +575,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with watcher support to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver with regular watcher reward to spend ERC20 payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ @@ -428,30 +585,31 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid watcher reward amount - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); @@ -467,7 +625,63 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver with refund-only watcher reward to spend ERC20 payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + const params = [ + id, + amount, + this.token.address, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid watcher reward amount + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // now allow to spend with regular watcher reward parameter + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + + // success spend + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + // check receiver balance + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), watcherReward); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow receiver to spend ETH payment by revealing a secret even after locktime', async function () { @@ -539,45 +753,46 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ETH payment on behalf of the sender after locktime', async function () { + it('should allow a watcher to refund ETH payment with regular reward on behalf of the sender after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); @@ -591,10 +806,69 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to refund ETH payment with refund-only reward on behalf of the sender after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong sender address + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong receiver address + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // now allow to refund with regular watcher reward parameter + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + + // success refund + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + // check watcher balance + assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).toString(), watcherReward.sub(txFee)); + assert.equal(senderBalanceAfter.sub(senderBalanceBefore).toString(), web3.utils.toWei('1')); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ERC20 payment on behalf of the sender after locktime', async function () { + it('should allow a watcher to refund ERC20 payment with regular reward on behalf of the sender after locktime', async function () { const lockTime = await currentEvmTime() + 1000; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ @@ -604,28 +878,29 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -633,14 +908,13 @@ contract('EtomicSwap', function(accounts) { const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - ////web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward) // check sender balance assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); assert.equal(watcherETHBalanceBefore.sub(watcherETHBalanceAfter).toString(), txFee.toString()); @@ -650,7 +924,66 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to refund ERC20 payment with refund-only reward on behalf of the sender after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + const params = [ + id, + amount, + this.token.address, + accounts[1], + secretHash, + lockTime, + watcherReward, + true + ]; + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong sender address + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong receiver address + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success refund + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // now allow to refund with regular watcher reward parameter + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + + // check sender balance + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ETH payment on behalf of the receiver by revealing a secret', async function () { @@ -660,33 +993,34 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -702,7 +1036,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { @@ -715,25 +1049,26 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - watcherReward + watcherReward, + false ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); @@ -741,7 +1076,7 @@ contract('EtomicSwap', function(accounts) { const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); @@ -760,6 +1095,6 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); }); From 244d269577eeaedcd0f9320190cfc4c3cfc7a9eb Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Sat, 1 Apr 2023 22:32:28 +0300 Subject: [PATCH 09/11] improve the reward functionality --- contracts/EtomicSwap.sol | 96 ++-- test/EtomicSwap.js | 1120 ++++++++++++++++++++++++-------------- 2 files changed, 785 insertions(+), 431 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 3510408..8fe4938 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -9,6 +9,13 @@ contract EtomicSwap { SenderRefunded } + enum RewardTargetOnSpend { + None, + Contract, + RewardSender, + PaymentSpender + } + struct Payment { bytes20 paymentHash; uint64 lockTime; @@ -53,8 +60,9 @@ contract EtomicSwap { address _receiver, bytes20 _secretHash, uint64 _lockTime, - uint256 _watcherReward, - bool _refundOnlyReward + RewardTargetOnSpend _rewardTarget, + bool _sendsReward, + uint256 _rewardAmount ) external payable { require(_receiver != address(0) && msg.value > 0 && payments[_id].state == PaymentState.Uninitialized); @@ -64,8 +72,9 @@ contract EtomicSwap { _secretHash, address(0), msg.value, - _watcherReward, - _refundOnlyReward + _rewardTarget, + _sendsReward, + _rewardAmount )); payments[_id] = Payment( @@ -113,19 +122,25 @@ contract EtomicSwap { address _receiver, bytes20 _secretHash, uint64 _lockTime, - uint256 _watcherReward, - bool _refundOnlyReward + RewardTargetOnSpend _rewardTarget, + bool _sendsReward, + uint256 _rewardAmount ) external payable { require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); + if (_rewardTarget != RewardTargetOnSpend.None) { + require(msg.value == _rewardAmount); + } + bytes20 paymentHash = ripemd160(abi.encodePacked( _receiver, msg.sender, _secretHash, _tokenAddress, _amount, - _watcherReward, - _refundOnlyReward + _rewardTarget, + _sendsReward, + _rewardAmount )); payments[_id] = Payment( @@ -136,6 +151,7 @@ contract EtomicSwap { IERC20 token = IERC20(_tokenAddress); require(token.transferFrom(msg.sender, address(this), _amount)); + emit PaymentSent(_id); } @@ -175,11 +191,11 @@ contract EtomicSwap { address _tokenAddress, address _sender, address _receiver, - uint256 _watcherReward, - bool _refundOnlyReward + RewardTargetOnSpend _rewardTarget, + bool _sendsReward, + uint256 _rewardAmount ) external { - payments[0].state = PaymentState.ReceiverSpent; - require(payments[_id].state == PaymentState.PaymentSent); + require(payments[_id].state == PaymentState.PaymentSent, "Payment was not sent"); bytes20 paymentHash = ripemd160(abi.encodePacked( _receiver, @@ -187,28 +203,30 @@ contract EtomicSwap { ripemd160(abi.encodePacked(sha256(abi.encodePacked(_secret)))), _tokenAddress, _amount, - _watcherReward, - _refundOnlyReward + _rewardTarget, + _sendsReward, + _rewardAmount )); - require(paymentHash == payments[_id].paymentHash); + require(paymentHash == payments[_id].paymentHash, "Invalid payment hash"); payments[_id].state = PaymentState.ReceiverSpent; if (_tokenAddress == address(0)) { - payable(_receiver).transfer(_amount - _watcherReward); - if (_refundOnlyReward) { - payable(_sender).transfer(_watcherReward); - } else { - payable(msg.sender).transfer(_watcherReward); - } + uint256 transferAmount = _rewardTarget == RewardTargetOnSpend.None ? _amount : _amount - _rewardAmount; + payable(_receiver).transfer(transferAmount); } else { IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_receiver, _amount - _watcherReward)); - if (_refundOnlyReward) { - require(token.transfer(_sender, _watcherReward)); - } else { - require(token.transfer(msg.sender, _watcherReward)); - } + require(token.transfer(_receiver, _amount), "Token transfer failed"); + } + + if (_rewardTarget == RewardTargetOnSpend.RewardSender) { + payable(_sender).transfer(_rewardAmount); + } else if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { + payable(msg.sender).transfer(_rewardAmount); + } + + if (_sendsReward) { + payable(msg.sender).transfer(_rewardAmount); } emit ReceiverSpent(_id, _secret); @@ -252,8 +270,9 @@ contract EtomicSwap { address _tokenAddress, address _sender, address _receiver, - uint256 _watcherReward, - bool _refundOnlyReward + RewardTargetOnSpend _rewardTarget, + bool _sendsReward, + uint256 _rewardAmount ) external { require(payments[_id].state == PaymentState.PaymentSent); @@ -263,8 +282,9 @@ contract EtomicSwap { _paymentHash, _tokenAddress, _amount, - _watcherReward, - _refundOnlyReward + _rewardTarget, + _sendsReward, + _rewardAmount )); require(paymentHash == payments[_id].paymentHash && block.timestamp >= payments[_id].lockTime); @@ -272,12 +292,18 @@ contract EtomicSwap { payments[_id].state = PaymentState.SenderRefunded; if (_tokenAddress == address(0)) { - payable(_sender).transfer(_amount - _watcherReward); - payable(msg.sender).transfer(_watcherReward); + if (_rewardTarget == RewardTargetOnSpend.None){ + payable(_sender).transfer(_amount); + } else { + payable(_sender).transfer(_amount - _rewardAmount); + } } else { IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_sender, _amount - _watcherReward)); - require(token.transfer(msg.sender, _watcherReward)); + require(token.transfer(_sender, _amount)); + } + + if (_rewardTarget != RewardTargetOnSpend.None) { + payable(msg.sender).transfer(_rewardAmount); } emit SenderRefunded(_id); diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index b85a2f3..6cf8e75 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -28,7 +28,10 @@ async function currentEvmTime() { } const id = '0x' + crypto.randomBytes(32).toString('hex'); +const id_2 = '0x' + crypto.randomBytes(32).toString('hex'); + const [PAYMENT_UNINITIALIZED, PAYMENT_SENT, RECEIVER_SPENT, SENDER_REFUNDED] = [0, 1, 2, 3]; +const [NONE, CONTRACT, REWARD_SENDER, PAYMENT_SPENDER] = [0, 1, 2, 3]; const secret = crypto.randomBytes(32); const secretHash = '0x' + new RIPEMD160().update(crypto.createHash('sha256').update(secret).digest()).digest('hex'); @@ -102,7 +105,10 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20Payment(...params).should.be.rejectedWith(EVMThrow); }); - it('should allow sender without watcher support to refund ETH payment after locktime', async function () { + //********************************* */ + // PAYMENTS WITHOUT WATCHER SUPPORT + //********************************* */ + it('should allow receiver without watcher support to spend ETH payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, @@ -111,134 +117,125 @@ contract('EtomicSwap', function(accounts) { lockTime ]; - // not allow to refund if payment was not sent - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + // should not allow to spend uninitialized payment + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; - // not allow to refund before locktime - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); - - await increaseTime(1000); - - // not allow to call refund from non-sender address - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend with invalid secret + await this.swap.receiverSpend(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.receiverSpend(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // not allow to refund invalid amount - await this.swap.senderRefund(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + // should not allow to claim from non-receiver address even with valid secret + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); - // success refund - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + // success spend + const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1], { gasPrice }).should.be.fulfilled; - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); - + const tx = await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - // check sender balance + + const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + + // check receiver balance assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); - // not allow to refund again - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with regular watcher reward to refund ETH payment after locktime', async function () { + it('should allow receiver without watcher support to spend ERC20 payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, + web3.utils.toWei('1'), + this.token.address, accounts[1], secretHash, - lockTime, - watcherReward, - false + lockTime ]; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); - - //not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); - await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; - - // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + // should not allow to spend uninitialized payment + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - await increaseTime(1000); + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20Payment(...params).should.be.fulfilled; - // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + // should not allow to spend with invalid secret + await this.swap.receiverSpend(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.receiverSpend(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), false).should.be.rejectedWith(EVMThrow); + // should not allow to claim from non-receiver address even with valid secret + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); - // success refund - const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + // success spend + const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.fulfilled; - - const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; + const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - // check sender balance - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + // check receiver balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); - // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with refund-only watcher reward to refund ETH payment after locktime', async function () { + it('should allow sender without watcher support to refund ETH payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, - lockTime, - watcherReward, - true + lockTime ]; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); - - //not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); - await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + // not allow to refund if payment was not sent + await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); await increaseTime(1000); - // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + // not allow to call refund from non-sender address + await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), true).should.be.rejectedWith(EVMThrow); + // not allow to refund invalid amount + await this.swap.senderRefund(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); - const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + // success refund + const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - // not allow to refund with regular watcher reward parameter - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.rejectedWith(EVMThrow); - - // success refund - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { gasPrice }).should.be.fulfilled; - const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const tx = await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1], { gasPrice }).should.be.fulfilled; + const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); // check sender balance - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).add(watcherReward).toString()); + assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); }); it('should allow sender without watcher support to refund ERC20 payment after locktime', async function () { @@ -286,146 +283,117 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with regular watcher reward to refund ERC20 payment after locktime', async function () { + it('should allow receiver to spend ETH payment by revealing a secret even after locktime', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - amount, - this.token.address, accounts[1], secretHash, - lockTime, - watcherReward, - false + lockTime ]; - await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; - - // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); - - // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; await increaseTime(1000); - // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); - - // not allow to refund invalid watcherReward amount - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount, false).should.be.rejectedWith(EVMThrow); - - // success refund - const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); - + // success spend + const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.fulfilled; + + const tx = await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - // check sender balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); - assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore); + // check receiver balance + assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); - // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false).should.be.rejectedWith(EVMThrow); + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow sender with refund-only watcher reward to refund ERC20 payment after locktime', async function () { + it('should allow receiver to spend ERC20 payment by revealing a secret even after locktime', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, - amount, + web3.utils.toWei('1'), this.token.address, accounts[1], secretHash, - lockTime, - watcherReward, - true + lockTime ]; - await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; - - // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); - - // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + await this.token.approve(this.swap.address, web3.utils.toWei('1')); + await this.swap.erc20Payment(...params).should.be.fulfilled; await increaseTime(1000); - // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); - - // not allow to refund invalid watcherReward amount - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], amount, true).should.be.rejectedWith(EVMThrow); + // success spend + const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - - const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; + const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - // not allow to refund with regular watcher reward parameter - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { gasPrice }).should.be.rejectedWith(EVMThrow); - - // success refund - let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { gasPrice }).should.be.fulfilled; - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - - const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - - // check sender balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + // check receiver balance + assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); - // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true).should.be.rejectedWith(EVMThrow); + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver without watcher support to spend ETH payment by revealing a secret', async function () { + //*********************************************** */ + // PAYMENT SPENT BY RECEIVER WITH WATCHER SUPPORT + //*********************************************** */ + it('should allow receiver to spend ETH payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, - lockTime + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), id, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount - await this.swap.receiverSpend(id, web3.utils.toWei('2'), secretHex, zeroAddr, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // should not allow to claim from non-receiver address even with valid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend with wrong rewardTarget parameter + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); + assert.equal(takerBalanceAfter.sub(takerBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); const payment = await this.swap.payments(id); @@ -433,44 +401,50 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with regular watcher reward to spend ETH payment by revealing a secret', async function () { + it('should allow receiver to spend ETH payment, rewardTarget = RewardSender', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, + REWARD_SENDER, + false, watcherReward, - false ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // success spend - const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.fulfilled; + // not allow to spend with wrong rewardTarget parameter + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + + // success spend + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - - const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); // check receiver balance - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + assert.equal(receiverBalanceAfter.sub(receiverBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).toString()); + assert.equal(senderBalanceAfter.sub(senderBalanceBefore).toString(), watcherReward); const payment = await this.swap.payments(id); @@ -478,49 +452,53 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with refund-only watcher reward to spend ETH payment by revealing a secret', async function () { + it('should allow receiver to spend ETH payment, rewardTarget = Contract', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, + CONTRACT, + false, watcherReward, - true ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + const contractBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(this.swap.address)); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - // now allow to spend with regular watcher reward parameter - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + // not allow to spend with wrong rewardTarget parameter + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); // success spend - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const contractBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(this.swap.address)); // check receiver balance assert.equal(receiverBalanceAfter.sub(receiverBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).toString()); - assert.equal(senderBalanceAfter.sub(senderBalanceBefore).toString(), watcherReward); + assert.equal(senderBalanceAfter.toString(), senderBalanceBefore.toString()); + assert.equal(contractBalanceAfter.sub(contractBalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -528,43 +506,57 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver without watcher support to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver to spend ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; - // should not allow to spend with invalid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), id, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + //should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount - await this.swap.receiverSpend(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - // should not allow to claim from non-receiver address even with valid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid watcher reward amount + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const receiverETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; - const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const receiverETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); + assert.equal(receiverETHBalanceAfter.sub(receiverETHBalanceBefore).toString(), watcherReward.sub(txFee)); const payment = await this.swap.payments(id); @@ -572,12 +564,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with regular watcher reward to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver to spend ERC20 payment, rewardTarget = RewardSender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, amount, @@ -585,39 +577,43 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, + REWARD_SENDER, + false, watcherReward, - false ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward,{ from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid watcher reward amount - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, false, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - - // success spend - const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.fulfilled; - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - - const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - // check receiver balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); - assert.equal(takerETHBalanceAfter.add(txFee).toString(), takerETHBalanceBefore); + // not allow to spend with wrong reward target parameter + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + + // success spend + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + // check receiver balance + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1).toString())); + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -625,12 +621,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver with refund-only watcher reward to spend ERC20 payment by revealing a secret', async function () { + it('should allow receiver to spend ERC20 payment, rewardTarget = Contract', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, amount, @@ -638,42 +634,47 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, + CONTRACT, + false, watcherReward, - true ]; + const contractBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(this.swap.address)); + // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], CONTRACT, false, watcherReward,{ from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid watcher reward amount - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], amount, true, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], CONTRACT, false, amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); - const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - // now allow to spend with regular watcher reward parameter - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + // not allow to spend with wrong reward target parameter + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); // success spend - let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[1], gasPrice }).should.be.fulfilled; + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const contractBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(this.swap.address)); // check receiver balance - assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); - assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), watcherReward); + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1).toString())); + assert.equal(senderETHBalanceAfter.toString(), senderETHBalanceBefore.toString()); + assert.equal(contractBalanceAfter.sub(contractBalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -681,33 +682,334 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], CONTRACT, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver to spend ETH payment by revealing a secret even after locktime', async function () { + //********************************************************* */ + // PAYMENT REFUND BY SENDER WITH WATCHER SUPPORT + //********************************************************* */ + + it('should allow sender to refund ETH payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, - lockTime + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + //not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); + + // success refund + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + // check sender balance + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).add(txFee).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender to refund ETH payment, rewardTarget = RewardSender', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + REWARD_SENDER, + false, + watcherReward, + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + //not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcher reward amount + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); + + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // not allow to refund with wrong reward target parameter + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.rejectedWith(EVMThrow); + + // success refund + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + // check sender balance + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).sub(txFee).add(watcherReward).toString()); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender to refund ERC20 payment, rewardTarget = PaymentSpender', async function () { + const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)); + const params = [ + id, + amount, + this.token.address, + accounts[1], + secretHash, + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, + ]; + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); await increaseTime(1000); + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcherReward amount + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, amount).should.be.rejectedWith(EVMThrow); + + // not allow to refund with wrong reward target parameter + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount).should.be.rejectedWith(EVMThrow); + + // success refund + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + // check sender balance + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender to refund ERC20 payment, rewardTarget = RewardSender', async function () { + const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)); + const params = [ + id, + amount, + this.token.address, + accounts[1], + secretHash, + lockTime, + REWARD_SENDER, + false, + watcherReward, + ]; + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // not allow to refund if payment was not sent + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund before locktime + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + await increaseTime(1000); + + // not allow to refund invalid amount + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + + // not allow to refund invalid watcherReward amount + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount).should.be.rejectedWith(EVMThrow); + + + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + + // not allow to refund with wrong reward target parameter + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.rejectedWith(EVMThrow); + + // success refund + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + // check sender balance + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); + + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // not allow to refund again + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + }); + + //**************************************************** */ + // PAYMENT SPENT BY WATCHER + //**************************************************** */ + + it('should allow a watcher to spend ETH payment, rewardTarget = PaymentSpender', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong reward target + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // success spend - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const receiverETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const tx = await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; + const receiverETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + + // check receiver balance + assert.equal(receiverETHBalanceAfter.sub(receiverETHBalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).add(txFee).toString(), watcherReward); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow a watcher to spend ETH payment, rewardTarget = RewardSender', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + REWARD_SENDER, + false, + watcherReward, + ]; + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong reward target + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success spend + const receiverETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const receiverETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); + assert.equal(receiverETHBalanceAfter.sub(receiverETHBalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -715,34 +1017,56 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow receiver to spend ERC20 payment by revealing a secret even after locktime', async function () { + it('should allow a watcher to spend ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, - web3.utils.toWei('1'), + amount, this.token.address, accounts[1], secretHash, - lockTime + lockTime, + PAYMENT_SPENDER, + false, + watcherReward, ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - await increaseTime(1000); + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); + + const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), amount); + assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); const payment = await this.swap.payments(id); @@ -750,108 +1074,169 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpend(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ETH payment with regular reward on behalf of the sender after locktime', async function () { + it('should allow a watcher to spend ERC20 payment, rewardTarget = RewardSender', async function () { const lockTime = await currentEvmTime() + 1000; + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, + amount, + this.token.address, accounts[1], secretHash, lockTime, + REWARD_SENDER, + false, watcherReward, - false + ]; + + // should not allow to spend uninitialized payment + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + await this.token.approve(this.swap.address, amount); + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + + // should not allow to spend with invalid secret + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + // should not allow to spend invalid amount + await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong sender address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // should not allow to spend with wrong receiver address + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + + // success spend + const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + const gasPrice = web3.utils.toWei('100', 'gwei'); + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + + const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + + // check receiver balance + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), amount); + assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.toString()); + + const payment = await this.swap.payments(id); + + // status + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // should not allow to spend again + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + }); + + //**************************************************** */ + // PAYMENT REFUND BY WATCHER + //**************************************************** */ + + it('should allow a watcher to refund ETH payment, rewardTarget = PaymentSpender', async function () { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + accounts[1], + secretHash, + lockTime, + PAYMENT_SPENDER, + false, + watcherReward ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); + const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); // check watcher balance assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).toString(), watcherReward.sub(txFee)); - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(senderBalanceAfter.sub(senderBalanceBefore).toString(), web3.utils.toWei('1')); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ETH payment with refund-only reward on behalf of the sender after locktime', async function () { + it('should allow a watcher to refund ETH payment, rewardTarget = RewardSender', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ id, accounts[1], secretHash, lockTime, + REWARD_SENDER, + false, watcherReward, - true ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], web3.utils.toWei('5'), true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - // now allow to refund with regular watcher reward parameter - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + // now allow to refund with wrong reward target + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); // success refund - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); @@ -865,12 +1250,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ERC20 payment with regular reward on behalf of the sender after locktime', async function () { + it('should allow a watcher to refund ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, amount, @@ -878,58 +1263,56 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, + PAYMENT_SPENDER, + false, watcherReward, - false ]; await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund - const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check sender balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherETHBalanceBefore.sub(watcherETHBalanceAfter).toString(), txFee.toString()); - assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei('1')); + assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to refund ERC20 payment with refund-only reward on behalf of the sender after locktime', async function () { + it('should allow a watcher to refund ERC20 payment, rewardTarget = RewardSender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + let amount = web3.utils.toWei(web3.utils.toBN(1)); const params = [ id, amount, @@ -937,164 +1320,109 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, + REWARD_SENDER, + false, watcherReward, - true ]; await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], watcherReward, true, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); - // now allow to refund with regular watcher reward parameter - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + // now allow to refund with wrong reward target + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); // check sender balance assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); + assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], watcherReward, true, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); - it('should allow a watcher to spend ETH payment on behalf of the receiver by revealing a secret', async function () { + //******************************************** */ + // SWAP SCENARIOS + //******************************************** */ + + it('Taker spends maker payment, taker: ERC20, maker: ETH', async function () { const lockTime = await currentEvmTime() + 1000; - const params = [ + + const takerAddress = accounts[0]; + const makerAddress = accounts[1]; + + let makerAmount = web3.utils.toWei(web3.utils.toBN(1)); + const makerParams = [ id, - accounts[1], + takerAddress, secretHash, lockTime, + NONE, + true, watcherReward, - false ]; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); + await this.swap.ethPaymentReward(...makerParams, { from: makerAddress, value: makerAmount }).should.be.fulfilled; - // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; - - // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // success spend - const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - - const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - - const takerBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - - // check receiver balance - assert.equal(takerBalanceAfter.sub(takerBalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherBalanceAfter.sub(watcherBalanceBefore).add(txFee).toString(), watcherReward); - - const payment = await this.swap.payments(id); - - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); - - // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); - }); - - it('should allow a watcher to spend ERC20 payment on behalf of the receiver by revealing a secret', async function () { - const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); - const params = [ - id, - amount, + let takerAmount = web3.utils.toWei(web3.utils.toBN(1)); + const takerParams = [ + id_2, + takerAmount, this.token.address, - accounts[1], + makerAddress, secretHash, lockTime, + CONTRACT, + false, watcherReward, - false ]; - - // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params).should.be.fulfilled; - - // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); - - // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], watcherReward, false, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.token.approve(this.swap.address, takerAmount); + await this.swap.erc20PaymentReward(...takerParams, {value: watcherReward}).should.be.fulfilled; // success spend - const takerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const takerETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(takerAddress)); + const makerERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(makerAddress)); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.fulfilled; - const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - const takerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); - const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); + const takerPaymentSpendTx = await this.swap.receiverSpendReward(id_2, takerAmount, secretHex, this.token.address, takerAddress, makerAddress, CONTRACT, false, watcherReward, { from: makerAddress, gasPrice }).should.be.fulfilled; - // check receiver balance - assert.equal(takerERC20BalanceAfter.sub(takerERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherETHBalanceBefore.sub(watcherETHBalanceAfter).toString(), txFee.toString()); - assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore), watcherReward.toString()); + const makerPaymentSpendTx = await this.swap.receiverSpendReward(id, makerAmount, secretHex, zeroAddr, makerAddress, takerAddress, NONE, true, watcherReward, { gasPrice }).should.be.fulfilled; + const makerPaymentSpendTxFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(makerPaymentSpendTx.receipt.gasUsed)); - const payment = await this.swap.payments(id); + const takerETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(takerAddress)); + const makerERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(makerAddress)); - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); - - // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], watcherReward, false, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + assert.equal(makerERC20BalanceAfter.sub(makerERC20BalanceBefore).toString(), takerAmount); + assert.equal(takerETHBalanceAfter.sub(takerETHBalanceBefore).toString(), makerAmount.add(watcherReward).sub(makerPaymentSpendTxFee).toString()); + }); }); From 2f76702a94af9c4f71bfe25e1a815c722bd0ecd6 Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Sun, 9 Apr 2023 01:50:50 +0300 Subject: [PATCH 10/11] fix bugs in the contract and adjust the unit tests --- contracts/EtomicSwap.sol | 56 ++++++++------ test/EtomicSwap.js | 159 +++++++++++++++++++-------------------- 2 files changed, 112 insertions(+), 103 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 8fe4938..da4c206 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -12,7 +12,7 @@ contract EtomicSwap { enum RewardTargetOnSpend { None, Contract, - RewardSender, + PaymentSender, PaymentSpender } @@ -61,7 +61,7 @@ contract EtomicSwap { bytes20 _secretHash, uint64 _lockTime, RewardTargetOnSpend _rewardTarget, - bool _sendsReward, + bool _sendsContractRewardOnSpend, uint256 _rewardAmount ) external payable { require(_receiver != address(0) && msg.value > 0 && payments[_id].state == PaymentState.Uninitialized); @@ -73,7 +73,7 @@ contract EtomicSwap { address(0), msg.value, _rewardTarget, - _sendsReward, + _sendsContractRewardOnSpend, _rewardAmount )); @@ -123,12 +123,12 @@ contract EtomicSwap { bytes20 _secretHash, uint64 _lockTime, RewardTargetOnSpend _rewardTarget, - bool _sendsReward, + bool _sendsContractRewardOnSpend, uint256 _rewardAmount ) external payable { require(_receiver != address(0) && _amount > 0 && payments[_id].state == PaymentState.Uninitialized); - if (_rewardTarget != RewardTargetOnSpend.None) { + if (_rewardTarget != RewardTargetOnSpend.None && _rewardTarget != RewardTargetOnSpend.PaymentSpender) { require(msg.value == _rewardAmount); } @@ -139,7 +139,7 @@ contract EtomicSwap { _tokenAddress, _amount, _rewardTarget, - _sendsReward, + _sendsContractRewardOnSpend, _rewardAmount )); @@ -151,7 +151,6 @@ contract EtomicSwap { IERC20 token = IERC20(_tokenAddress); require(token.transferFrom(msg.sender, address(this), _amount)); - emit PaymentSent(_id); } @@ -192,7 +191,7 @@ contract EtomicSwap { address _sender, address _receiver, RewardTargetOnSpend _rewardTarget, - bool _sendsReward, + bool _sendsContractRewardOnSpend, uint256 _rewardAmount ) external { require(payments[_id].state == PaymentState.PaymentSent, "Payment was not sent"); @@ -204,7 +203,7 @@ contract EtomicSwap { _tokenAddress, _amount, _rewardTarget, - _sendsReward, + _sendsContractRewardOnSpend, _rewardAmount )); @@ -214,18 +213,25 @@ contract EtomicSwap { if (_tokenAddress == address(0)) { uint256 transferAmount = _rewardTarget == RewardTargetOnSpend.None ? _amount : _amount - _rewardAmount; payable(_receiver).transfer(transferAmount); + + if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { + payable(msg.sender).transfer(_rewardAmount); + } } else { + uint256 transferAmount = _rewardTarget == RewardTargetOnSpend.PaymentSpender ? _amount - _rewardAmount : _amount; IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_receiver, _amount), "Token transfer failed"); + require(token.transfer(_receiver, transferAmount), "Token transfer failed"); + + if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { + require(token.transfer(msg.sender, _rewardAmount), "Token transfer failed"); + } } - if (_rewardTarget == RewardTargetOnSpend.RewardSender) { + if (_rewardTarget == RewardTargetOnSpend.PaymentSender) { payable(_sender).transfer(_rewardAmount); - } else if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { - payable(msg.sender).transfer(_rewardAmount); - } + } - if (_sendsReward) { + if (_sendsContractRewardOnSpend) { payable(msg.sender).transfer(_rewardAmount); } @@ -292,18 +298,22 @@ contract EtomicSwap { payments[_id].state = PaymentState.SenderRefunded; if (_tokenAddress == address(0)) { - if (_rewardTarget == RewardTargetOnSpend.None){ - payable(_sender).transfer(_amount); - } else { - payable(_sender).transfer(_amount - _rewardAmount); + uint256 transferAmount = _rewardTarget == RewardTargetOnSpend.None ? _amount : _amount - _rewardAmount; + payable(_sender).transfer(transferAmount); + + if (_rewardTarget != RewardTargetOnSpend.None) { + payable(msg.sender).transfer(_rewardAmount); } } else { + uint256 transferAmount = _rewardTarget == RewardTargetOnSpend.PaymentSpender ? _amount - _rewardAmount : _amount; IERC20 token = IERC20(_tokenAddress); - require(token.transfer(_sender, _amount)); - } + require(token.transfer(_sender, transferAmount)); - if (_rewardTarget != RewardTargetOnSpend.None) { - payable(msg.sender).transfer(_rewardAmount); + if (_rewardTarget == RewardTargetOnSpend.PaymentSender) { + payable(msg.sender).transfer(_rewardAmount); + } else if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { + require(token.transfer(msg.sender, _rewardAmount)); + } } emit SenderRefunded(_id); diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 6cf8e75..7bae6b0 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -31,7 +31,7 @@ const id = '0x' + crypto.randomBytes(32).toString('hex'); const id_2 = '0x' + crypto.randomBytes(32).toString('hex'); const [PAYMENT_UNINITIALIZED, PAYMENT_SENT, RECEIVER_SPENT, SENDER_REFUNDED] = [0, 1, 2, 3]; -const [NONE, CONTRACT, REWARD_SENDER, PAYMENT_SPENDER] = [0, 1, 2, 3]; +const [NONE, CONTRACT, PAYMENT_SENDER, PAYMENT_SPENDER] = [0, 1, 2, 3]; const secret = crypto.randomBytes(32); const secretHash = '0x' + new RIPEMD160().update(crypto.createHash('sha256').update(secret).digest()).digest('hex'); @@ -380,7 +380,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong rewardTarget parameter - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // success spend const takerBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -411,22 +411,22 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -436,7 +436,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); // success spend - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); @@ -452,7 +452,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow receiver to spend ETH payment, rewardTarget = Contract', async function () { @@ -511,7 +511,7 @@ contract('EtomicSwap', function(accounts) { it('should allow receiver to spend ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)); + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, amount, @@ -528,7 +528,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); - await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; + await this.swap.erc20PaymentReward(...params).should.be.fulfilled; //should not allow to spend with invalid secret await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); @@ -555,8 +555,8 @@ contract('EtomicSwap', function(accounts) { const receiverETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); // check receiver balance - assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); - assert.equal(receiverETHBalanceAfter.sub(receiverETHBalanceBefore).toString(), watcherReward.sub(txFee)); + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); + assert.equal(receiverETHBalanceBefore.sub(receiverETHBalanceAfter).toString(), txFee.toString()); const payment = await this.swap.payments(id); @@ -577,25 +577,25 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward,{ from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward,{ from: accounts[1] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid watcher reward amount - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, amount, { from: accounts[1] }).should.be.rejectedWith(EVMThrow); const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); @@ -605,7 +605,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); // success spend - let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; + let tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); @@ -621,7 +621,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('1'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[1], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow receiver to spend ERC20 payment, rewardTarget = Contract', async function () { @@ -744,27 +744,27 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); //not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, web3.utils.toWei('5')).should.be.rejectedWith(EVMThrow); const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); @@ -773,7 +773,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.rejectedWith(EVMThrow); // success refund - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); @@ -784,12 +784,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); }); it('should allow sender to refund ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)); + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, amount, @@ -820,7 +820,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, amount).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong reward target parameter - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, amount).should.be.rejectedWith(EVMThrow); // success refund const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -834,8 +834,7 @@ contract('EtomicSwap', function(accounts) { const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); // check sender balance - assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); - assert.equal(senderETHBalanceAfter.sub(senderETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); + assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward)); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); @@ -854,7 +853,7 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; @@ -863,18 +862,18 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcherReward amount - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, amount).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, amount).should.be.rejectedWith(EVMThrow); const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -885,7 +884,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { gasPrice }).should.be.rejectedWith(EVMThrow); // success refund - let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; + let tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -899,7 +898,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward).should.be.rejectedWith(EVMThrow); }); //**************************************************** */ @@ -937,7 +936,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong reward target - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const receiverETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -970,28 +969,28 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('5'), secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong reward target await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); @@ -1001,7 +1000,7 @@ contract('EtomicSwap', function(accounts) { const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const receiverETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -1017,12 +1016,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to spend ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)); + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, amount, @@ -1054,7 +1053,7 @@ contract('EtomicSwap', function(accounts) { // success spend const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; @@ -1062,11 +1061,11 @@ contract('EtomicSwap', function(accounts) { const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); - const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); // check receiver balance - assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), amount); - assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); + assert.equal(receiverERC20BalanceAfter.sub(receiverERC20BalanceBefore).toString(), web3.utils.toWei(web3.utils.toBN(1))); + assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); @@ -1087,34 +1086,34 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; // should not allow to spend uninitialized payment - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.token.approve(this.swap.address, amount); await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // should not allow to spend with invalid secret - await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, id, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend invalid amount - await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, web3.utils.toWei('2'), secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong sender address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[2], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // should not allow to spend with wrong receiver address - await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, zeroAddr, accounts[0], accounts[2], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success spend const senderETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); const gasPrice = web3.utils.toWei('100', 'gwei'); - const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const senderETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); const receiverERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[1])); @@ -1129,7 +1128,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), RECEIVER_SPENT); // should not allow to spend again - await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); + await this.swap.receiverSpendReward(id, amount, secretHex, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); }); //**************************************************** */ @@ -1200,33 +1199,33 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await this.swap.ethPaymentReward(...params, { value: amount }).should.be.fulfilled; // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('5'), secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund invalid watcher reward amount - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, web3.utils.toWei('5'), { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); const watcherBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); const senderBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); @@ -1236,7 +1235,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); // success refund - const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const watcherBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); @@ -1250,12 +1249,12 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); it('should allow a watcher to refund ERC20 payment, rewardTarget = PaymentSpender', async function () { const lockTime = await currentEvmTime() + 1000; - let amount = web3.utils.toWei(web3.utils.toBN(1)); + let amount = web3.utils.toWei(web3.utils.toBN(1)).add(watcherReward); const params = [ id, amount, @@ -1290,18 +1289,18 @@ contract('EtomicSwap', function(accounts) { // success refund const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherETHBalanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[2])); const gasPrice = web3.utils.toWei('100', 'gwei'); const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); - const watcherETHBalanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[2])); + const watcherERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[2])); // check sender balance assert.equal(senderERC20BalanceAfter.sub(senderERC20BalanceBefore).toString(), web3.utils.toWei('1')); - assert.equal(watcherETHBalanceAfter.sub(watcherETHBalanceBefore).toString(), watcherReward.sub(txFee).toString()); + assert.equal(watcherERC20BalanceAfter.sub(watcherERC20BalanceBefore).toString(), watcherReward.toString()); const payment = await this.swap.payments(id); assert.equal(payment[2].valueOf(), SENDER_REFUNDED); @@ -1320,7 +1319,7 @@ contract('EtomicSwap', function(accounts) { accounts[1], secretHash, lockTime, - REWARD_SENDER, + PAYMENT_SENDER, false, watcherReward, ]; @@ -1329,21 +1328,21 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20PaymentReward(...params, {value: watcherReward}).should.be.fulfilled; // not allow to refund if payment was not sent - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund before locktime - await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); await increaseTime(1000); // not allow to refund invalid amount - await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong sender address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[2], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // not allow to refund with wrong receiver address - await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], REWARD_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, amount, secretHash, zeroAddr, accounts[0], accounts[2], PAYMENT_SENDER, false, watcherReward, { from: accounts[2] }).should.be.rejectedWith(EVMThrow); // success refund const senderERC20BalanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -1353,7 +1352,7 @@ contract('EtomicSwap', function(accounts) { // now allow to refund with wrong reward target await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SPENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.rejectedWith(EVMThrow); - const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; + const tx = await this.swap.senderRefundReward(id, amount, secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, { from: accounts[2], gasPrice }).should.be.fulfilled; const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); const senderERC20BalanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); @@ -1367,7 +1366,7 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), SENDER_REFUNDED); // not allow to refund again - await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], REWARD_SENDER, false, watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); + await this.swap.senderRefundReward(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[0], accounts[1], PAYMENT_SENDER, false, watcherReward, {from: accounts[2] }).should.be.rejectedWith(EVMThrow); }); //******************************************** */ From b4879c0c047eb95570d7bbd06d87723779ce4b6f Mon Sep 17 00:00:00 2001 From: Caglar Kaya Date: Sun, 9 Apr 2023 13:54:22 +0300 Subject: [PATCH 11/11] fix a bug in senderRefundReward --- contracts/EtomicSwap.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index da4c206..66fdca1 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -309,10 +309,10 @@ contract EtomicSwap { IERC20 token = IERC20(_tokenAddress); require(token.transfer(_sender, transferAmount)); - if (_rewardTarget == RewardTargetOnSpend.PaymentSender) { - payable(msg.sender).transfer(_rewardAmount); - } else if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { + if (_rewardTarget == RewardTargetOnSpend.PaymentSpender) { require(token.transfer(msg.sender, _rewardAmount)); + } else if (_rewardTarget != RewardTargetOnSpend.None) { + payable(msg.sender).transfer(_rewardAmount); } }