From 3242f0c2d23c3df54bd92627057d3ee7b15f32df Mon Sep 17 00:00:00 2001 From: Alina Sharon <52405288+laruh@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:42:38 +0700 Subject: [PATCH 1/4] feat(nft): update deps and solc version, add ERC721 and ERC1155 support (#2) This commit does the following: * updates deps * updates solidity version from ^0.5.0 to ^0.8.20 * implements ERC721 functions for EtomicSwap contract * adds ERC721 tests * implements ERC1155 functions for EtomicSwap contract * adds ERC1155 tests --- README.md | 27 +- contracts/Erc1155Token.sol | 12 + contracts/Erc721Token.sol | 13 + contracts/EtomicSwap.sol | 429 ++++-- contracts/Migrations.sol | 22 +- contracts/Token.sol | 385 ++--- package.json | 11 +- rpc.Dockerfile | 11 +- startRPC.js | 2 +- test/EtomicSwap.js | 328 ++++- truffle.js | 5 + workspace.Dockerfile | 10 +- yarn.lock | 2849 +++++++++++------------------------- 13 files changed, 1826 insertions(+), 2278 deletions(-) create mode 100644 contracts/Erc1155Token.sol create mode 100644 contracts/Erc721Token.sol diff --git a/README.md b/README.md index 72516ed..31c0c68 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Etomic Swap Smart Contracts for BarterDex platform. +# Etomic Swap Smart Contracts for Komodo SDK. [![Build Status](https://travis-ci.org/artemii235/etomic-swap.svg?branch=master)](https://travis-ci.org/artemii235/etomic-swap) -Etomic swap Smart Contract is implemented to support ETH and ERC20 atomic swaps on BarterDex platform. +Etomic swap Smart Contract is implemented to support ETH and ERC20 atomic swaps on Komodo SDK. Please note that this project is not production ready yet! ## Swap workflow @@ -17,13 +17,14 @@ Despite example shows swap of ETH/ERC20 this approach will work also for ETH/ERC ## Project structure 1. `contracts` - Smart Contracts source code. +1. `migrations` - Deployment scripts. 1. `test` - Smart contracts unit tests. ## How to setup dev environment? 1. Install docker. -1. Run `docker-compose build`. 1. `cp .env.empty .env`. +1. Run `docker-compose build`. 1. Start containers `docker-compose up -d`. 1. Install project dependencies: `docker-compose exec workspace yarn`. 1. To run tests: `docker-compose exec workspace truffle test`. @@ -35,5 +36,21 @@ Despite example shows swap of ETH/ERC20 this approach will work also for ETH/ERC ## Useful links for smart contracts development 1. Truffle suite - https://github.com/trufflesuite/truffle -1. Ganache-cli (EthereumJS Testrpc) - https://github.com/trufflesuite/ganache-cli -1. Zeppelin Solidity - https://github.com/OpenZeppelin/zeppelin-solidity +1. Ganache (EthereumJS Testrpc) - https://github.com/trufflesuite/ganache +1. OpenZeppelin Contracts - https://github.com/OpenZeppelin/openzeppelin-contracts + +## Contribution Guide + +- Run Docker tests to ensure that the project is set up successfully. +- Write tests for new contracts and functionalities. +- Run tests to confirm that new implementations work correctly. +- Format Solidity code before opening a pull request (PR). For formatting, you can use Remix Online IDE - https://remix.ethereum.org/ + +## Where Can I Write Solidity Code? + +### Notes for Those Without an IDE: +Using Remix Online IDE is sufficient. There's no need to install anything locally. + +### Notes for JetBrains or Visual Studio Code (VSCode) Users: +- These IDEs offer Solidity plugins, which can simplify your workflow. However, Remix Online IDE is also a viable option. +- To index JavaScript code, execute the Docker commands as mentioned. Necessary dependencies will be downloaded, enabling the IDE to index the rest of the code. \ No newline at end of file diff --git a/contracts/Erc1155Token.sol b/contracts/Erc1155Token.sol new file mode 100644 index 0000000..62c2980 --- /dev/null +++ b/contracts/Erc1155Token.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; + +contract Erc1155Token is ERC1155 { + constructor(string memory tokenUri) ERC1155(tokenUri) { + uint256 tokenId = 1; + uint256 amount = 3; + _mint(msg.sender, tokenId, amount, ""); + } +} diff --git a/contracts/Erc721Token.sol b/contracts/Erc721Token.sol new file mode 100644 index 0000000..c764076 --- /dev/null +++ b/contracts/Erc721Token.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract Erc721Token is ERC721 { + constructor(string memory tokenName, string memory tokenSymbol) + ERC721(tokenName, tokenSymbol) + { + uint256 tokenId = 1; + _mint(msg.sender, tokenId); + } +} diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index 3a1ccec..c40f99c 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -1,11 +1,18 @@ -pragma solidity ^0.5.0; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; +// SPDX-License-Identifier: MIT -contract EtomicSwap { +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { enum PaymentState { Uninitialized, PaymentSent, - ReceivedSpent, + ReceiverSpent, SenderRefunded } @@ -15,125 +22,381 @@ contract EtomicSwap { PaymentState state; } - mapping (bytes32 => Payment) public payments; + mapping(bytes32 => Payment) public payments; event PaymentSent(bytes32 id); event ReceiverSpent(bytes32 id, bytes32 secret); event SenderRefunded(bytes32 id); - constructor() public { } + constructor() {} function ethPayment( - bytes32 _id, - address _receiver, - bytes20 _secretHash, - uint64 _lockTime + bytes32 id, + address receiver, + bytes20 secretHash, + uint64 lockTime ) external payable { - require(_receiver != address(0) && msg.value > 0 && payments[_id].state == PaymentState.Uninitialized); + require( + receiver != address(0) && + msg.value > 0 && + payments[id].state == PaymentState.Uninitialized + ); - bytes20 paymentHash = ripemd160(abi.encodePacked( - _receiver, + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, msg.sender, - _secretHash, + secretHash, address(0), msg.value - )); - - payments[_id] = Payment( - paymentHash, - _lockTime, - PaymentState.PaymentSent + ) ); - emit PaymentSent(_id); + payments[id] = Payment(paymentHash, lockTime, PaymentState.PaymentSent); + + emit PaymentSent(id); } function erc20Payment( - bytes32 _id, - uint256 _amount, - address _tokenAddress, - address _receiver, - bytes20 _secretHash, - uint64 _lockTime + 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); + require( + receiver != address(0) && + amount > 0 && + payments[id].state == PaymentState.Uninitialized + ); - bytes20 paymentHash = ripemd160(abi.encodePacked( - _receiver, + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, msg.sender, - _secretHash, - _tokenAddress, - _amount - )); - - payments[_id] = Payment( - paymentHash, - _lockTime, - PaymentState.PaymentSent + secretHash, + tokenAddress, + amount + ) ); - IERC20 token = IERC20(_tokenAddress); - require(token.transferFrom(msg.sender, address(this), _amount)); - emit PaymentSent(_id); + payments[id] = Payment(paymentHash, lockTime, PaymentState.PaymentSent); + + // Emitting the event before making the external call + emit PaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + require(token.transferFrom(msg.sender, address(this), amount)); } function receiverSpend( - bytes32 _id, - uint256 _amount, - bytes32 _secret, - address _tokenAddress, - address _sender + bytes32 id, + uint256 amount, + bytes32 secret, + address tokenAddress, + address sender ) external { - require(payments[_id].state == PaymentState.PaymentSent); - - bytes20 paymentHash = ripemd160(abi.encodePacked( + // Checks + 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)) { - msg.sender.transfer(_amount); + sender, + ripemd160(abi.encodePacked(sha256(abi.encodePacked(secret)))), + tokenAddress, + amount + ) + ); + require(paymentHash == payments[id].paymentHash); + + // Effects + payments[id].state = PaymentState.ReceiverSpent; + + // Event Emission + emit ReceiverSpent(id, secret); + + // Interactions + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); } else { - IERC20 token = IERC20(_tokenAddress); - require(token.transfer(msg.sender, _amount)); + IERC20 token = IERC20(tokenAddress); + require(token.transfer(msg.sender, amount)); } + } + + function receiverSpendErc721( + bytes32 id, + bytes32 secret, + address tokenAddress, + uint256 tokenId, + address sender + ) external { + // Checks + require( + payments[id].state == PaymentState.PaymentSent && + msg.sender == tx.origin + ); + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + sender, + ripemd160(abi.encodePacked(sha256(abi.encodePacked(secret)))), + tokenAddress, + tokenId + ) + ); + require(paymentHash == payments[id].paymentHash); - emit ReceiverSpent(_id, _secret); + // Effects + payments[id].state = PaymentState.ReceiverSpent; + + // Event Emission + emit ReceiverSpent(id, secret); + + // Interactions + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); } - function senderRefund( - bytes32 _id, - uint256 _amount, - bytes20 _paymentHash, - address _tokenAddress, - address _receiver + function receiverSpendErc1155( + bytes32 id, + uint256 amount, + bytes32 secret, + address tokenAddress, + uint256 tokenId, + address sender ) external { - require(payments[_id].state == PaymentState.PaymentSent); + // Checks + require( + payments[id].state == PaymentState.PaymentSent && + msg.sender == tx.origin + ); + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + sender, + ripemd160(abi.encodePacked(sha256(abi.encodePacked(secret)))), + tokenAddress, + tokenId, + amount + ) + ); + require(paymentHash == payments[id].paymentHash); + + // Effects + payments[id].state = PaymentState.ReceiverSpent; + + // Event Emission + emit ReceiverSpent(id, secret); + + // Interactions + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } - bytes20 paymentHash = ripemd160(abi.encodePacked( - _receiver, + function senderRefund( + bytes32 id, + uint256 amount, + bytes20 secretHash, + address tokenAddress, + address receiver + ) external { + require(payments[id].state == PaymentState.PaymentSent); + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, msg.sender, - _paymentHash, - _tokenAddress, - _amount - )); + secretHash, + tokenAddress, + amount + ) + ); + require( + paymentHash == payments[id].paymentHash && + block.timestamp >= payments[id].lockTime + ); - require(paymentHash == payments[_id].paymentHash && now >= payments[_id].lockTime); + payments[id].state = PaymentState.SenderRefunded; - payments[_id].state = PaymentState.SenderRefunded; + emit SenderRefunded(id); - if (_tokenAddress == address(0)) { - msg.sender.transfer(_amount); + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); } else { - IERC20 token = IERC20(_tokenAddress); - require(token.transfer(msg.sender, _amount)); + IERC20 token = IERC20(tokenAddress); + require(token.transfer(msg.sender, amount)); } + } - emit SenderRefunded(_id); + function senderRefundErc721( + bytes32 id, + bytes20 secretHash, + address tokenAddress, + uint256 tokenId, + address receiver + ) external { + require(payments[id].state == PaymentState.PaymentSent); + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, + msg.sender, + secretHash, + tokenAddress, + tokenId + ) + ); + require( + paymentHash == payments[id].paymentHash && + block.timestamp >= payments[id].lockTime + ); + + payments[id].state = PaymentState.SenderRefunded; + + emit SenderRefunded(id); + + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function senderRefundErc1155( + bytes32 id, + uint256 amount, + bytes20 secretHash, + address tokenAddress, + uint256 tokenId, + address receiver + ) external { + require(payments[id].state == PaymentState.PaymentSent); + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, + msg.sender, + secretHash, + tokenAddress, + tokenId, + amount + ) + ); + require( + paymentHash == payments[id].paymentHash && + block.timestamp >= payments[id].lockTime + ); + + payments[id].state = PaymentState.SenderRefunded; + + emit SenderRefunded(id); + + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function onERC1155Received( + address operator, + address from, + uint256 tokenId, + uint256 value, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + ( + bytes32 id, + address receiver, + address tokenAddress, + bytes20 secretHash, + uint64 lockTime + ) = abi.decode(data, (bytes32, address, address, bytes20, uint64)); + + require( + receiver != address(0) && + tokenAddress != address(0) && + msg.sender == tokenAddress && + operator == from && + value > 0 && + payments[id].state == PaymentState.Uninitialized && + !isContract(receiver) + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + receiver, + from, + secretHash, + tokenAddress, + tokenId, + value + ) + ); + + payments[id] = Payment(paymentHash, lockTime, PaymentState.PaymentSent); + emit PaymentSent(id); + + // Return this magic value to confirm receipt of ERC1155 token + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, /* operator */ + address, /* from */ + uint256[] calldata, /* ids */ + uint256[] calldata, /* values */ + bytes calldata /* data */ + ) external pure override returns (bytes4) { + revert("Batch transfers not supported"); + } + + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC165, IERC165) + returns (bool) + { + return + interfaceId == type(IERC1155Receiver).interfaceId || + super.supportsInterface(interfaceId); + } + + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + ( + bytes32 id, + address receiver, + address tokenAddress, + bytes20 secretHash, + uint64 lockTime + ) = abi.decode(data, (bytes32, address, address, bytes20, uint64)); + + require( + receiver != address(0) && + tokenAddress != address(0) && + msg.sender == tokenAddress && + operator == from && + payments[id].state == PaymentState.Uninitialized && + !isContract(receiver) + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked(receiver, from, secretHash, tokenAddress, tokenId) + ); + + payments[id] = Payment(paymentHash, lockTime, PaymentState.PaymentSent); + emit PaymentSent(id); + + // Return this magic value to confirm receipt of ERC721 token + return this.onERC721Received.selector; + } + + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; } } diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 17b44d8..054fbe0 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,17 +1,19 @@ -pragma solidity ^0.5.0; -import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/access/Ownable.sol"; contract Migrations is Ownable { - uint public last_completed_migration; + uint256 public lastCompletedMigration; - constructor() public { } + constructor() Ownable(msg.sender) {} - function setCompleted(uint completed) public onlyOwner { - last_completed_migration = completed; + function setCompleted(uint256 completed) public onlyOwner { + lastCompletedMigration = completed; } - function upgrade(address new_address) public onlyOwner { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); + function upgrade(address newAddress) public onlyOwner { + Migrations upgraded = Migrations(newAddress); + upgraded.setCompleted(lastCompletedMigration); } -} +} \ No newline at end of file diff --git a/contracts/Token.sol b/contracts/Token.sol index 7f8d977..1b2f286 100644 --- a/contracts/Token.sol +++ b/contracts/Token.sol @@ -1,7 +1,8 @@ -pragma solidity ^0.5.0; +// SPDX-License-Identifier: MIT -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title Standard ERC20 token @@ -15,183 +16,203 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; * compliant implementations may not do it. */ contract Token is IERC20 { - using SafeMath for uint256; - - mapping (address => uint256) private _balances; - - mapping (address => mapping (address => uint256)) private _allowed; - - uint256 private _totalSupply; - - string public constant name = "Just Token"; - - string public constant symbol = "JST"; - - uint8 public constant decimals = 18; - - constructor() public { - _balances[msg.sender] = 1000 ether; - _totalSupply = 1000 ether; - } - - /** - * @dev Total number of tokens in existence - */ - function totalSupply() public view returns (uint256) { - return _totalSupply; - } - - /** - * @dev Gets the balance of the specified address. - * @param owner The address to query the balance of. - * @return An uint256 representing the amount owned by the passed address. - */ - function balanceOf(address owner) public view returns (uint256) { - return _balances[owner]; - } - - /** - * @dev Function to check the amount of tokens that an owner allowed to a spender. - * @param owner address The address which owns the funds. - * @param spender address The address which will spend the funds. - * @return A uint256 specifying the amount of tokens still available for the spender. - */ - function allowance(address owner, address spender) public view returns (uint256) { - return _allowed[owner][spender]; - } - - /** - * @dev Transfer token for a specified address - * @param to The address to transfer to. - * @param value The amount to be transferred. - */ - function transfer(address to, uint256 value) public returns (bool) { - _transfer(msg.sender, to, value); - return true; - } - - /** - * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. - * Beware that changing an allowance with this method brings the risk that someone may use both the old - * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this - * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * @param spender The address which will spend the funds. - * @param value The amount of tokens to be spent. - */ - function approve(address spender, uint256 value) public returns (bool) { - require(spender != address(0)); - - _allowed[msg.sender][spender] = value; - emit Approval(msg.sender, spender, value); - return true; - } - - /** - * @dev Transfer tokens from one address to another. - * Note that while this function emits an Approval event, this is not required as per the specification, - * and other compliant implementations may not emit the event. - * @param from address The address which you want to send tokens from - * @param to address The address which you want to transfer to - * @param value uint256 the amount of tokens to be transferred - */ - function transferFrom(address from, address to, uint256 value) public returns (bool) { - _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); - _transfer(from, to, value); - emit Approval(from, msg.sender, _allowed[from][msg.sender]); - return true; - } - - /** - * @dev Increase the amount of tokens that an owner allowed to a spender. - * approve should be called when allowed_[_spender] == 0. To increment - * allowed value is better to use this function to avoid 2 calls (and wait until - * the first transaction is mined) - * From MonolithDAO Token.sol - * Emits an Approval event. - * @param spender The address which will spend the funds. - * @param addedValue The amount of tokens to increase the allowance by. - */ - function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { - require(spender != address(0)); - - _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue); - emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); - return true; - } - - /** - * @dev Decrease the amount of tokens that an owner allowed to a spender. - * approve should be called when allowed_[_spender] == 0. To decrement - * allowed value is better to use this function to avoid 2 calls (and wait until - * the first transaction is mined) - * From MonolithDAO Token.sol - * Emits an Approval event. - * @param spender The address which will spend the funds. - * @param subtractedValue The amount of tokens to decrease the allowance by. - */ - function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { - require(spender != address(0)); - - _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue); - emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); - return true; - } - - /** - * @dev Transfer token for a specified addresses - * @param from The address to transfer from. - * @param to The address to transfer to. - * @param value The amount to be transferred. - */ - function _transfer(address from, address to, uint256 value) internal { - require(to != address(0)); - - _balances[from] = _balances[from].sub(value); - _balances[to] = _balances[to].add(value); - emit Transfer(from, to, value); - } - - /** - * @dev Internal function that mints an amount of the token and assigns it to - * an account. This encapsulates the modification of balances such that the - * proper events are emitted. - * @param account The account that will receive the created tokens. - * @param value The amount that will be created. - */ - function _mint(address account, uint256 value) internal { - require(account != address(0)); - - _totalSupply = _totalSupply.add(value); - _balances[account] = _balances[account].add(value); - emit Transfer(address(0), account, value); - } - - /** - * @dev Internal function that burns an amount of the token of a given - * account. - * @param account The account whose tokens will be burnt. - * @param value The amount that will be burnt. - */ - function _burn(address account, uint256 value) internal { - require(account != address(0)); - - _totalSupply = _totalSupply.sub(value); - _balances[account] = _balances[account].sub(value); - emit Transfer(account, address(0), value); - } - - /** - * @dev Internal function that burns an amount of the token of a given - * account, deducting from the sender's allowance for said account. Uses the - * internal burn function. - * Emits an Approval event (reflecting the reduced allowance). - * @param account The account whose tokens will be burnt. - * @param value The amount that will be burnt. - */ - function _burnFrom(address account, uint256 value) internal { - _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value); - _burn(account, value); - emit Approval(account, msg.sender, _allowed[account][msg.sender]); - } + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowed; + + uint256 private _totalSupply; + + string public constant name = "Just Token"; + + string public constant symbol = "JST"; + + uint8 public constant decimals = 18; + + constructor() { + _balances[msg.sender] = 1000 ether; + _totalSupply = 1000 ether; + } + + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return _totalSupply; + } + + /** + * @dev Gets the balance of the specified address. + * @param owner The address to query the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address owner) public view returns (uint256) { + return _balances[owner]; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param owner address The address which owns the funds. + * @param spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance(address owner, address spender) + public + view + returns (uint256) + { + return _allowed[owner][spender]; + } + + /** + * @dev Transfer token for a specified address + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function transfer(address to, uint256 value) public returns (bool) { + _transfer(msg.sender, to, value); + return true; + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param spender The address which will spend the funds. + * @param value The amount of tokens to be spent. + */ + function approve(address spender, uint256 value) public returns (bool) { + require(spender != address(0)); + + _allowed[msg.sender][spender] = value; + emit Approval(msg.sender, spender, value); + return true; + } + + /** + * @dev Transfer tokens from one address to another. + * Note that while this function emits an Approval event, this is not required as per the specification, + * and other compliant implementations may not emit the event. + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address from, + address to, + uint256 value + ) public returns (bool) { + _allowed[from][msg.sender] = _allowed[from][msg.sender] - value; + _transfer(from, to, value); + emit Approval(from, msg.sender, _allowed[from][msg.sender]); + return true; + } + + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed_[_spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * Emits an Approval event. + * @param spender The address which will spend the funds. + * @param addedValue The amount of tokens to increase the allowance by. + */ + function increaseAllowance(address spender, uint256 addedValue) + public + returns (bool) + { + require(spender != address(0)); + + _allowed[msg.sender][spender] = + _allowed[msg.sender][spender] + + addedValue; + emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); + return true; + } + + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed_[_spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * Emits an Approval event. + * @param spender The address which will spend the funds. + * @param subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) + public + returns (bool) + { + require(spender != address(0)); + + _allowed[msg.sender][spender] = + _allowed[msg.sender][spender] - + subtractedValue; + emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); + return true; + } + + /** + * @dev Transfer token for a specified addresses + * @param from The address to transfer from. + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function _transfer( + address from, + address to, + uint256 value + ) internal { + require(to != address(0)); + + _balances[from] = _balances[from] - value; + _balances[to] = _balances[to] + value; + emit Transfer(from, to, value); + } + + /** + * @dev Internal function that mints an amount of the token and assigns it to + * an account. This encapsulates the modification of balances such that the + * proper events are emitted. + * @param account The account that will receive the created tokens. + * @param value The amount that will be created. + */ + function _mint(address account, uint256 value) internal { + require(account != address(0)); + + _totalSupply = _totalSupply + value; + _balances[account] = _balances[account] + value; + emit Transfer(address(0), account, value); + } + + /** + * @dev Internal function that burns an amount of the token of a given + * account. + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burn(address account, uint256 value) internal { + require(account != address(0)); + + _totalSupply = _totalSupply + value; + _balances[account] = _balances[account] - value; + emit Transfer(account, address(0), value); + } + + /** + * @dev Internal function that burns an amount of the token of a given + * account, deducting from the sender's allowance for said account. Uses the + * internal burn function. + * Emits an Approval event (reflecting the reduced allowance). + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burnFrom(address account, uint256 value) internal { + _allowed[account][msg.sender] = _allowed[account][msg.sender] - value; + _burn(account, value); + emit Approval(account, msg.sender, _allowed[account][msg.sender]); + } } diff --git a/package.json b/package.json index 0a4cab1..8506dea 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,20 @@ "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", "license": "ISC", "dependencies": { - "chai": "^4.1.2", + "chai": "^4.3.10", "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": "^7.9.1", + "@openzeppelin/contracts": "^5.0.0", "request": "^2.83.0", "request-promise-native": "^1.0.5", "ripemd160": "^2.0.1", - "sol-merger": "^0.1.0", - "web3": "^1.0.0-beta.27" + "sol-merger": "^4.4.0", + "web3": "^4.2.2" } } diff --git a/rpc.Dockerfile b/rpc.Dockerfile index 91a344f..c48276b 100644 --- a/rpc.Dockerfile +++ b/rpc.Dockerfile @@ -1,10 +1,15 @@ -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 WORKDIR /usr/src/rpc -RUN yarn +RUN git config --global url."https://".insteadOf git:// +RUN yarn install CMD yarn rpc \ No newline at end of file diff --git a/startRPC.js b/startRPC.js index 1992e9f..b4c9f82 100644 --- a/startRPC.js +++ b/startRPC.js @@ -1,4 +1,4 @@ -const TestRPC = require("ganache-cli"); +const TestRPC = require("ganache"); //create 10 accounts with 1000000 ETH Balance const server = TestRPC.server({ diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 620c41e..3b8dfc7 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -1,5 +1,7 @@ const Swap = artifacts.require('EtomicSwap'); const Token = artifacts.require('Token'); +const Erc721Token = artifacts.require('Erc721Token'); +const Erc1155Token = artifacts.require('Erc1155Token'); const crypto = require('crypto'); const RIPEMD160 = require('ripemd160'); @@ -9,17 +11,23 @@ require('chai') .use(require('chai-as-promised')) .should(); -function increaseTime (increaseAmount) { - return new Promise((resolve, reject) => { - web3.currentProvider.send({ - jsonrpc: '2.0', - method: 'evm_increaseTime', - id: Date.now(), - params: [increaseAmount] - }, (err, res) => { - return err ? reject(err) : resolve(res); - }); +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await web3.currentProvider.request({ + method: 'evm_increaseTime', + params: [increaseAmount], }); + await web3.currentProvider.request({ method: 'evm_mine' }); } async function currentEvmTime() { @@ -34,6 +42,9 @@ const secret = crypto.randomBytes(32); const secretHash = '0x' + new RIPEMD160().update(crypto.createHash('sha256').update(secret).digest()).digest('hex'); const secretHex = '0x' + secret.toString('hex'); +const invalidSecret = crypto.randomBytes(32); +const invalidSecretHex = '0x' + invalidSecret.toString('hex'); + const zeroAddr = '0x0000000000000000000000000000000000000000'; contract('EtomicSwap', function(accounts) { @@ -41,6 +52,8 @@ contract('EtomicSwap', function(accounts) { beforeEach(async function () { this.swap = await Swap.new(); this.token = await Token.new(); + this.erc721token = await Erc721Token.new("MyNFT", "MNFT"); + this.erc1155token = await Erc1155Token.new("uri"); await this.token.transfer(accounts[1], web3.utils.toWei('100')); }); @@ -49,6 +62,13 @@ contract('EtomicSwap', function(accounts) { assert.equal(payment[2].valueOf(), PAYMENT_UNINITIALIZED); }); + it('should have correct ERC1155 token balance', async function() { + const amount = 3; + const tokenId = 1; + const balance = await this.erc1155token.balanceOf(accounts[0], tokenId); + assert.equal(balance.toNumber(), amount, "Balance of ERC1155 tokens in EtomicSwap contract is incorrect"); + }); + it('should allow to send ETH payment', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ @@ -99,6 +119,71 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20Payment(...params).should.be.rejectedWith(EVMThrow); }); + it('should allow to send ERC721 payment', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] in Erc721Token contract + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc721token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract + await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + + // Check the payment lockTime and state + const payment = await this.swap.payments(id); + assert.equal(payment[1].valueOf(), lockTime); + assert.equal(payment[2].valueOf(), PAYMENT_SENT); + + // Check the ownership of the token + const tokenOwner = await this.erc721token.ownerOf(tokenId); + assert.equal(tokenOwner, this.swap.address); + + // should not allow to send again + await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.rejectedWith(EVMThrow); + }); + + it('should allow to send ERC1155 payment', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + + // Check the payment lockTime and state + const payment = await this.swap.payments(id); + assert.equal(payment[1].valueOf(), lockTime); + assert.equal(payment[2].valueOf(), PAYMENT_SENT); + + // Check the balance of the token in the swap contract + const tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); + assert.equal(tokenBalance.toNumber(), amountToSend); + + // should not allow to send same params again + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.rejectedWith(EVMThrow); + + // sender should be capable to send more tokens, if they have it + const id1 = '0x' + crypto.randomBytes(32).toString('hex'); + const data1 = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id1, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, 1, data1).should.be.fulfilled; + + // Check sending more tokens than the sender owns - should fail + const id2 = '0x' + crypto.randomBytes(32).toString('hex'); + const data2 = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id2, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, 1, data2).should.be.rejectedWith(EVMThrow); + }); + it('should allow sender to refund ETH payment after locktime', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ @@ -116,7 +201,7 @@ contract('EtomicSwap', function(accounts) { // 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); + await advanceTimeAndMine(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); @@ -162,7 +247,7 @@ contract('EtomicSwap', function(accounts) { // not allow to refund before locktime await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); - await increaseTime(1000); + await advanceTimeAndMine(1000); // not allow to call refund from non-sender address await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); @@ -187,6 +272,77 @@ 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 to refund ERC721 payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc721token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract + await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + + // Attempt refund before locktime - should fail + await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + + // Advance time past locktime + await advanceTimeAndMine(1000); + + // Attempt refund from non-sender address - should fail + await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // Successful refund by sender after locktime + await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // Check the ownership of the token - should be back to the sender (accounts[0]) + const tokenOwner = await this.erc721token.ownerOf(tokenId); + assert.equal(tokenOwner, accounts[0]); + + // Attempting refund again - should fail + await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow sender to refund ERC1155 payment after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 3; // Amount of tokens to send + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + + // Attempt refund before locktime - should fail + await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + + // Advance time past locktime + await advanceTimeAndMine(1000); + + // Attempt refund from non-sender address - should fail + await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // Successful refund by sender after locktime + await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + + // Check the balance of the token - should be back to the sender (accounts[0]) + const tokenBalance = await this.erc1155token.balanceOf(accounts[0], tokenId); + assert.equal(tokenBalance.toNumber(), amountToSend); + + // Attempting refund again - should fail + await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + }); + it('should allow receiver to spend ETH payment by revealing a secret', async function () { const lockTime = await currentEvmTime() + 1000; const params = [ @@ -202,7 +358,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).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.receiverSpend(id, web3.utils.toWei('1'), invalidSecretHex, 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); @@ -248,7 +404,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.erc20Payment(...params).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); + await this.swap.receiverSpend(id, web3.utils.toWei('1'), invalidSecretHex, 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); @@ -274,6 +430,83 @@ 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 to spend ERC721 payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc721token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract + await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + + // Check the ownership of the token before receiver spend payment - should be owned by swap contract + const tokenOwnerBeforeReceiverSpend = await this.erc721token.ownerOf(tokenId); + assert.equal(tokenOwnerBeforeReceiverSpend, this.swap.address); + + // Attempt to spend with invalid secret - should fail + await this.swap.receiverSpendErc721(id, invalidSecretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // Attempt to claim from non-receiver address even with valid secret - should fail + await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + + // Successful spend by receiver with valid secret + await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // Check the ownership of the token - should be transferred to the receiver (accounts[1]) + const tokenOwner = await this.erc721token.ownerOf(tokenId); + assert.equal(tokenOwner, accounts[1]); + + // Attempting to spend again - should fail + await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver to spend ERC1155 payment by revealing a secret', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + + // Check the balance of the token before receiver spend payment - should be in swap contract + let tokenBalanceBeforeReceiverSpend = await this.erc1155token.balanceOf(this.swap.address, tokenId); + assert.equal(tokenBalanceBeforeReceiverSpend.toNumber(), amountToSend); + + // Attempt to spend with invalid secret - should fail + await this.swap.receiverSpendErc1155(id, amountToSend, invalidSecretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + + // Attempt to claim from non-receiver address even with valid secret - should fail + await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + + // Successful spend by receiver with valid secret + await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // Check the balance of the token - should be transferred to the receiver (accounts[1]) + let tokenBalance = await this.erc1155token.balanceOf(accounts[1], tokenId); + assert.equal(tokenBalance.toNumber(), amountToSend); + + // Check that the swap contract no longer holds the tokens + tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); + assert.equal(tokenBalance.toNumber(), 0); + + // Attempting to spend again - should fail + await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).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 = [ @@ -285,7 +518,7 @@ contract('EtomicSwap', function(accounts) { await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; - await increaseTime(1000); + await advanceTimeAndMine(1000); // success spend const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); @@ -308,7 +541,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, @@ -322,7 +555,7 @@ contract('EtomicSwap', function(accounts) { await this.token.approve(this.swap.address, web3.utils.toWei('1')); await this.swap.erc20Payment(...params).should.be.fulfilled; - await increaseTime(1000); + await advanceTimeAndMine(1000); // success spend const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); @@ -342,4 +575,65 @@ 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 receiver to spend ERC721 payment by revealing a secret even after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc721token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract + await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + + await advanceTimeAndMine(1000); + + // Successful spend by receiver with valid secret even after locktime + await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // Check the ownership of the token - should be transferred to the receiver (accounts[1]) + const tokenOwner = await this.erc721token.ownerOf(tokenId); + assert.equal(tokenOwner, accounts[1]); + + // Attempting to spend again - should fail + await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + }); + + it('should allow receiver to spend ERC1155 payment by revealing a secret even after locktime', async function () { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const data = web3.eth.abi.encodeParameters( + ['bytes32', 'address', 'address', 'bytes20', 'uint64'], + [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + ); + // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract + await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + + await advanceTimeAndMine(1000); + + // Successful spend by receiver with valid secret even after locktime + await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + + // Check the state of the payment + const payment = await this.swap.payments(id); + assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + + // Check the balance of the token - should be transferred to the receiver (accounts[1]) + let tokenBalance = await this.erc1155token.balanceOf(accounts[1], tokenId); + assert.equal(tokenBalance.toNumber(), amountToSend); + + // Check that the swap contract no longer holds the tokens + tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); + assert.equal(tokenBalance.toNumber(), 0); + + // Attempting to spend again - should fail + await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + }); }); diff --git a/truffle.js b/truffle.js index 8e18127..fb3f280 100644 --- a/truffle.js +++ b/truffle.js @@ -6,4 +6,9 @@ module.exports = { network_id: "*" // Match any network id } }, + compilers: { + solc: { + version: "0.8.20", + } + }, }; diff --git a/workspace.Dockerfile b/workspace.Dockerfile index d1878b7..8e5913a 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.11.5 VOLUME /usr/src/workspace WORKDIR /usr/src/workspace diff --git a/yarn.lock b/yarn.lock index 7a82def..a1c90b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,20 +2,137 @@ # 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" +"@adraffy/ens-normalize@^1.8.8": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" + +"@noble/hashes@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@openzeppelin/contracts@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c" + integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw== + +"@scure/base@~1.1.0": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" + integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== + +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@trufflesuite/bigint-buffer@1.1.10": + version "1.1.10" + resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz#a1d9ca22d3cad1a138b78baaf15543637a3e1692" + integrity sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw== + dependencies: + node-gyp-build "4.4.0" + +"@trufflesuite/uws-js-unofficial@20.30.0-unofficial.0": + version "20.30.0-unofficial.0" + resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.30.0-unofficial.0.tgz#2fbc2f8ef7e82fbeea6abaf7e8a9d42a02b479d3" + integrity sha512-r5X0aOQcuT6pLwTRLD+mPnAM/nlKtvIK4Z+My++A8tTOR0qTjNRx8UB8jzRj3D+p9PMAp5LnpCUUGmz7/TppwA== + dependencies: + ws "8.13.0" + optionalDependencies: + bufferutil "4.0.7" + utf-8-validate "6.0.3" + +"@types/bn.js@^5.1.0": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + +"@types/lru-cache@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/node@*": + version "20.9.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298" + integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw== + dependencies: + undici-types "~5.26.4" + +"@types/seedrandom@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.1.tgz#1254750a4fec4aff2ebec088ccd0bb02e91fedb4" + integrity sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw== -accepts@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" +"@types/ws@8.5.3": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" + "@types/node" "*" -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" +abitype@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.7.1.tgz#16db20abe67de80f6183cf75f3de1ff86453b745" + integrity sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ== + +abstract-level@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + +abstract-leveldown@7.2.0, abstract-leveldown@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" + integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== + dependencies: + buffer "^6.0.3" + catering "^2.0.0" + is-buffer "^2.0.5" + level-concat-iterator "^3.0.0" + level-supports "^2.0.1" + queue-microtask "^1.2.3" ajv@^5.3.0: version "5.5.2" @@ -26,31 +143,10 @@ ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ansi-regex@^2.0.0, 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= - -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= - -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" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== asn1@~0.2.3: version "0.2.4" @@ -66,14 +162,29 @@ assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" +async-eventemitter@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async@^2.4.0: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +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" @@ -87,13 +198,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - -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" @@ -101,66 +209,10 @@ bcrypt-pbkdf@^1.0.0: 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" - -bluebird@^2.9.34: - version "2.11.0" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - -bluebird@^3.5.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - -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== - -body-parser@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - dependencies: - bytes "3.0.0" - 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" +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== brace-expansion@^1.1.7: version "1.1.11" @@ -170,179 +222,96 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.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: - version "1.2.0" - resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^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" - 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" - dependencies: - bn.js "^4.1.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" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 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" + base64-js "^1.3.1" + ieee754 "^1.2.1" -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" +bufferutil@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" + integrity sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A== 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" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - -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" + node-gyp-build "^4.3.0" -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" +bufferutil@4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== dependencies: - base64-js "0.0.8" - ieee754 "^1.1.4" - isarray "^1.0.0" + node-gyp-build "^4.3.0" -buffer@^5.0.5: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" +call-bind@^1.0.2, call-bind@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -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= + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" +catering@^2.0.0, catering@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + 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" 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" +chai@^4.3.10: + version "4.3.10" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" + integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== dependencies: assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" -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" +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + get-func-name "^2.0.2" -cli-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.3.0.tgz#cd2ec212efbd1a0eeb5b017f17d4e2d15e91420f" +cli-color@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" + integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== dependencies: - ansi-regex "^2.1.1" - d "1" - es5-ext "^0.10.46" + d "^1.0.1" + es5-ext "^0.10.61" es6-iterator "^2.0.3" - 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== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" + memoizee "^0.4.15" + timers-ext "^0.1.7" 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" @@ -355,104 +324,31 @@ combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.8.1: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - dependencies: - graceful-readlink ">= 1.0.0" +commander@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== 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= -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - -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" -cors@^2.8.1: - version "2.8.4" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" - dependencies: - object-assign "^4" - vary "^1" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" +crc-32@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" +cross-fetch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - 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= - dependencies: - lru-cache "^4.0.1" - 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" - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" + node-fetch "^2.6.12" d@1: version "1.0.0" @@ -460,132 +356,47 @@ d@1: dependencies: es5-ext "^0.10.9" +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.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" 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" - 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" - dependencies: - ms "^2.1.1" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -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" - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - 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" +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 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" + ms "2.1.2" -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" +deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" + type-detect "^4.0.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" +define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== dependencies: - type-detect "^4.0.0" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" -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" - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - 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" - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - 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" - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -593,42 +404,25 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.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" +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" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" -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" - dependencies: - once "^1.4.0" +emittery@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026" + integrity sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ== -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: +es5-ext@^0.10.35, 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" dependencies: @@ -636,7 +430,16 @@ es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@ es6-symbol "~3.1.1" next-tick "1" -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: +es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, 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.3" + next-tick "^1.1.0" + +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" dependencies: @@ -651,71 +454,33 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.1: d "1" es5-ext "~0.10.14" -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-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.0.1" + ext "^1.1.2" + +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" - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - -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" - 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" - 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" - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.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" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" +ethereum-cryptography@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" + integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + dependencies: + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" event-emitter@^0.3.5: version "0.3.5" @@ -724,64 +489,12 @@ event-emitter@^0.3.5: 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" - -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" +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: - 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= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.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" - dependencies: - accepts "~1.3.5" - array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.1" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - 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" - utils-merge "1.0.1" - vary "~1.1.2" + type "^2.7.2" extend@~3.0.2: version "3.0.2" @@ -803,46 +516,10 @@ 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" - -finalhandler@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - 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" - 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= - dependencies: - locate-path "^2.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" @@ -858,85 +535,60 @@ form-data@~2.3.2: 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" - -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" - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - 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@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: - any-promise "^1.3.0" - fs-extra "^2.0.0" - mz "^2.6.0" - thenify-all "^1.6.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.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= -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" - -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== - dependencies: - bn.js "4.11.8" - source-map-support "0.5.9" - yargs "11.1.0" - -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== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +ganache@^7.9.1: + version "7.9.1" + resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.9.1.tgz#94f8518215c7989ff5fd542db80bd47d7c7da786" + integrity sha512-Tqhd4J3cpiLeYTD6ek/zlchSB107IVPMIm4ypyg+xz1sdkeALUnYYZnmY4Bdjqj3i6QwtlZPCu7U4qKy7HlWTA== + dependencies: + "@trufflesuite/bigint-buffer" "1.1.10" + "@trufflesuite/uws-js-unofficial" "20.30.0-unofficial.0" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "5.1.1" + "@types/seedrandom" "3.0.1" + abstract-level "1.0.3" + abstract-leveldown "7.2.0" + async-eventemitter "0.2.4" + emittery "0.10.0" + keccak "3.0.2" + leveldown "6.1.0" + secp256k1 "4.0.3" + optionalDependencies: + bufferutil "4.0.5" + utf-8-validate "5.0.7" -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" +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -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.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" getpass@^0.1.1: version "0.1.7" @@ -944,63 +596,34 @@ getpass@^0.1.1: 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" +glob@^7.1.7: + 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== +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 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" - 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" + get-intrinsic "^1.1.3" -graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +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== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== har-schema@^2.0.0: version "2.0.0" @@ -1013,15 +636,29 @@ har-validator@~5.1.0: ajv "^5.3.0" 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-property-descriptors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" -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-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +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-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" @@ -1030,13 +667,6 @@ hash-base@^3.0.0: inherits "^2.0.1" safe-buffer "^5.0.1" -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.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" @@ -1044,36 +674,22 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hmac-drbg@^1.0.0: +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +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-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" - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -1082,25 +698,10 @@ http-signature@~1.2.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" - -iconv-lite@0.4.23: - version "0.4.23" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" - 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" - 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.2.1: + 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" @@ -1110,104 +711,60 @@ inflight@^1.0.4: 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.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" +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" -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.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== 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= +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: - number-is-nan "^1.0.0" - -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= - -is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - -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" - -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" + has-tostringtag "^1.0.0" -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: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-typed-array@^1.1.3: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" -is-typedarray@^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" - -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= +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -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.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" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -1224,15 +781,12 @@ 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" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" @@ -1245,492 +799,208 @@ jsprim@^1.2.2: json-schema "0.2.3" 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.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== 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= +level-concat-iterator@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" + integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== dependencies: - invert-kv "^1.0.0" + catering "^2.1.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= +level-supports@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" + integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== + +level-supports@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" + integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== + +level-transcoder@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" + integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== + dependencies: + buffer "^6.0.3" + module-error "^1.0.1" + +leveldown@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" + integrity sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w== dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" + abstract-leveldown "^7.2.0" + napi-macros "~2.0.0" + node-gyp-build "^4.3.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== -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.14: + 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.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + get-func-name "^2.0.1" -lru-queue@0.1: +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" - dependencies: - pify "^3.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" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - -memoizee@^0.4.14: - version "0.4.14" - resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" +memoizee@^0.4.15: + 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" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: +mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.20" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" dependencies: mime-db "~1.36.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - -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-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - 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" -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" -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= - -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - dependencies: - mkdirp "*" - -mkdirp@*, "mkdirp@>=0.5 0": - version "0.5.1" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mock-fs@^4.1.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" +module-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" + integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== -mout@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.0.0: +napi-macros@~2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - -mz@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" - dependencies: - any-promise "^1.0.0" - object-assign "^4.0.1" - thenify-all "^1.0.0" - -nan@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - -nan@^2.0.8, nan@^2.3.3: - version "2.11.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" - -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" - -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== next-tick@1: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" -npm-run-path@^2.0.0: +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== + +node-addon-api@^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= + 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.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: - path-key "^2.0.0" + whatwg-url "^5.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= +node-gyp-build@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" + integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== -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" - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" + integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" -object-assign@^4, object-assign@^4.0.1, 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" - -oboe@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - 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" - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 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== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.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-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - -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-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= - dependencies: - p-limit "^1.1.0" - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - dependencies: - p-finally "^1.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= - -parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - -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" - -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - -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= - 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= -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -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" - -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - 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" +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" -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.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" - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.8.0" - -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" -public-encrypt@^4.0.0: - version "4.0.2" - resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" - 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" - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -qs@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - -qs@6.5.2, qs@~6.5.2: +qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - 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" - dependencies: - safe-buffer "^5.1.0" +queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== 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" - -raw-body@2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" - dependencies: - bytes "3.0.0" - http-errors "1.6.3" - iconv-lite "0.4.23" - 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" - 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" @@ -1746,7 +1016,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@^2.79.0, request@^2.83.0: +request@^2.83.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" dependencies: @@ -1771,193 +1041,61 @@ request@^2.79.0, request@^2.83.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= - -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= - -rimraf@2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: +ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" 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" - -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.0.1, safe-buffer@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +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== + +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" -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" +secp256k1@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: - nan "^2.0.8" + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== dependencies: - pbkdf2 "^3.0.3" - -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" - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - 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" - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - -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" + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" -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" - -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" - 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= - 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= - -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= - -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - -simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - 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" - 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== +sol-merger@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-4.4.0.tgz#d637cb50d1553dde1f9fb19833bf6ea01ba2da11" + integrity sha512-eYlgsVAeTPiIpLwRCnu8vdhAI40mt8I9BAnwdHazF+8ggWd0EuucQYxs4v+GyjC/5cmCfPMJ55T37tgk/zXqSg== dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + antlr4ts "^0.5.0-alpha.4" + cli-color "^2.0.3" + commander "^4.0.1" + debug "^4.3.4" + fs-extra "^10.0.0" + glob "^7.1.7" + strip-json-comments "^3.0.1" sshpk@^1.7.0: version "1.14.2" @@ -1974,156 +1112,30 @@ sshpk@^1.7.0: jsbn "~0.1.0" 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" - stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" -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" - -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== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.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= - dependencies: - ansi-regex "^3.0.0" - -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - dependencies: - is-natural-number "^4.0.1" - -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= - -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" - 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" - 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" - 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" - -"thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" +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: - any-promise "^1.0.0" + safe-buffer "~5.2.0" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" +strip-json-comments@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -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.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" - 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" @@ -2131,9 +1143,10 @@ tough-cookie@>=2.3.3, tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.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" @@ -2145,84 +1158,64 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" -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" - dependencies: - media-typer "0.3.0" - mime-types "~2.1.18" - -typedarray-to-buffer@^3.1.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - 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" +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== -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" +type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -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" +utf-8-validate@5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" + integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== dependencies: - prepend-http "^1.0.1" - -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" - -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" + 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" +utf-8-validate@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777" + integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA== + dependencies: + node-gyp-build "^4.3.0" -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== -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" +util@^0.12.5: + 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" uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -2231,339 +1224,257 @@ verror@1.10.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" - dependencies: - underscore "1.8.3" - web3-eth-iban "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -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" - 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-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" - dependencies: - any-promise "1.3.0" - eventemitter3 "1.1.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" - 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" - -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" - dependencies: - eventemitter3 "1.1.1" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - -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" - 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" - -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" - dependencies: - ethers "4.0.0-beta.1" - underscore "1.8.3" - web3-utils "1.0.0-beta.36" - -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" - dependencies: - any-promise "1.3.0" - 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" - dependencies: - 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" - 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" - dependencies: - bn.js "4.11.6" - eth-lib "0.1.27" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randomhex "0.1.5" - underscore "1.8.3" - utf8 "2.1.1" - -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" - -"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": - version "1.0.26" - resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" - dependencies: - debug "^2.2.0" - nan "^2.3.3" - typedarray-to-buffer "^3.1.2" - yaeti "^0.0.6" - -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= +web3-core@^4.3.0, web3-core@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-4.3.1.tgz#5c3b5b59f1e31537a64237caa5fd83f5ffd7b0f3" + integrity sha512-xa3w5n/ESxp5HIbrwsYBhpAPx2KI5LprjRFEtRwP0GpqqhTcCSMMYoyItRqQQ+k9YnB0PoFpWJfJI6Qn5x8YUQ== + dependencies: + web3-errors "^1.1.4" + web3-eth-iban "^4.0.7" + web3-providers-http "^4.1.0" + web3-providers-ws "^4.0.7" + web3-types "^1.3.1" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + optionalDependencies: + web3-providers-ipc "^4.0.7" -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== +web3-errors@^1.1.3, web3-errors@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.1.4.tgz#5667a0a5f66fc936e101ef32032ccc1e8ca4d5a1" + integrity sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ== dependencies: - isexe "^2.0.0" + web3-types "^1.3.1" -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= +web3-eth-abi@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.1.4.tgz#56ae7ebb1385db1a948e69fb35f4057bff6743af" + integrity sha512-YLOBVVxxxLYKXjaiwZjEWYEnkMmmrm0nswZsvzSsINy/UgbWbzfoiZU+zn4YNWIEhORhx1p37iS3u/dP6VyC2w== dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" + abitype "0.7.1" + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" +web3-eth-accounts@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.1.0.tgz#5b5e6c60d457e7b829ec590021fc87ada8585920" + integrity sha512-UFtAsOANsvihTQ6SSvOKguupmQkResyR9M9JNuOxYpKh7+3W+sTnbLXw2UbOSYIsKlc1mpqqW9bVr1SjqHDpUQ== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + crc-32 "^1.2.2" + ethereum-cryptography "^2.0.0" + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-eth-contract@^4.1.2, web3-eth-contract@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.1.3.tgz#15dd4c978eaf0d8f894b2c1f3e9f94edd29ff57c" + integrity sha512-F6e3eyetUDiNOb78EDVJtNOb0H1GPz3xAZH8edSfYdhaxI9tTutP2V3p++kh2ZJ/RrdE2+xil7H/nPLgHymBvg== + dependencies: + web3-core "^4.3.1" + web3-errors "^1.1.4" + web3-eth "^4.3.1" + web3-eth-abi "^4.1.4" + web3-types "^1.3.1" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-eth-ens@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-4.0.8.tgz#f4e0a018ce6cc69e37007ee92063867feb5994f0" + integrity sha512-nj0JfeD45BbzVJcVYpUJnSo8iwDcY9CQ7CZhhIVVOFjvpMAPw0zEwjTvZEIQyCW61OoDG9xcBzwxe2tZoYhMRw== + dependencies: + "@adraffy/ens-normalize" "^1.8.8" + web3-core "^4.3.0" + web3-errors "^1.1.3" + web3-eth "^4.3.1" + web3-eth-contract "^4.1.2" + web3-net "^4.0.7" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-eth-iban@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz#ee504f845d7b6315f0be78fcf070ccd5d38e4aaf" + integrity sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ== + dependencies: + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-eth-personal@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-4.0.8.tgz#b51628c560de550ca8b354fa784f9556aae6065c" + integrity sha512-sXeyLKJ7ddQdMxz1BZkAwImjqh7OmKxhXoBNF3isDmD4QDpMIwv/t237S3q4Z0sZQamPa/pHebJRWVuvP8jZdw== dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" + web3-core "^4.3.0" + web3-eth "^4.3.1" + web3-rpc-methods "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" -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" +web3-eth@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.3.1.tgz#cb4224356716da71e694091aa3fbf10bcb813fb5" + integrity sha512-zJir3GOXooHQT85JB8SrufE+Voo5TtXdjhf1D8IGXmxM8MrhI8AT+Pgt4siBTupJcu5hF17iGmTP/Nj2XnaibQ== dependencies: - xhr-request "^1.0.1" - -xhr-request@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + setimmediate "^1.0.5" + web3-core "^4.3.0" + web3-errors "^1.1.3" + web3-eth-abi "^4.1.4" + web3-eth-accounts "^4.1.0" + web3-net "^4.0.7" + web3-providers-ws "^4.0.7" + web3-rpc-methods "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +web3-net@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-4.0.7.tgz#ed2c1bd700cf94be93a6dbd8bd8aa413d8681942" + integrity sha512-SzEaXFrBjY25iQGk5myaOfO9ZyfTwQEa4l4Ps4HDNVMibgZji3WPzpjq8zomVHMwi8bRp6VV7YS71eEsX7zLow== + dependencies: + web3-core "^4.3.0" + web3-rpc-methods "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + +web3-providers-http@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-4.1.0.tgz#8d7afda67d1d8542ca85b30f60a3d1fe1993b561" + integrity sha512-6qRUGAhJfVQM41E5t+re5IHYmb5hSaLc02BE2MaRQsz2xKA6RjmHpOA5h/+ojJxEpI9NI2CrfDKOAgtJfoUJQg== + dependencies: + cross-fetch "^4.0.0" + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + +web3-providers-ipc@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz#9ec4c8565053af005a5170ba80cddeb40ff3e3d3" + integrity sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g== + dependencies: + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + +web3-providers-ws@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-4.0.7.tgz#7a78a0dcf077e0e802da524fbb37d080b356c14b" + integrity sha512-n4Dal9/rQWjS7d6LjyEPM2R458V8blRm0eLJupDEJOOIBhGYlxw5/4FthZZ/cqB7y/sLVi7K09DdYx2MeRtU5w== + dependencies: + "@types/ws" "8.5.3" + isomorphic-ws "^5.0.0" + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-utils "^4.0.7" + ws "^8.8.1" + +web3-rpc-methods@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/web3-rpc-methods/-/web3-rpc-methods-1.1.3.tgz#4be8a85628d8b69846e2e0afa0ed71e3f6eaf163" + integrity sha512-XB6SsCZZPdZUMPIRqDxJkZFKMu0/Y+yaExAt+Z7RqmuM7xF55fJ/Qb84LQho8zarvUoYziy4jnIfs+SXImxQUw== dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" + web3-core "^4.3.0" + web3-types "^1.3.0" + web3-validator "^2.0.3" -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" +web3-types@^1.3.0, web3-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.3.1.tgz#cf6148ad46b68c5c89714613380b270d31e297be" + integrity sha512-8fXi7h/t95VKRtgU4sxprLPZpsTh3jYDfSghshIDBgUD/OoGe5S+syP24SUzBZYllZ/L+hMr2gdp/0bGJa8pYQ== + +web3-utils@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.0.7.tgz#7df497b7cdd06cdfe7d02036c45fecbe3382d137" + integrity sha512-sy8S6C2FIa5NNHc8DjND+Fx3S8KDAizuh5RbL1RX3h0PRbFgPfWzF5RfUns8gTt0mjJuOhs/IaDhrZfeTszG5A== dependencies: - cookiejar "^2.1.1" + ethereum-cryptography "^2.0.0" + web3-errors "^1.1.3" + web3-types "^1.3.0" + web3-validator "^2.0.3" -xhr@^2.0.4, xhr@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" +web3-validator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.3.tgz#e5dcd4b4902612cff21b7f8817dd233393999d97" + integrity sha512-fJbAQh+9LSNWy+l5Ze6HABreml8fra98o5+vS073T35jUcLbRZ0IOjF/ZPJhJNbJDt+jP1vseZsc3z3uX9mxxQ== + dependencies: + ethereum-cryptography "^2.0.0" + util "^0.12.5" + web3-errors "^1.1.3" + web3-types "^1.3.0" + zod "^3.21.4" + +web3@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/web3/-/web3-4.2.2.tgz#3562e0b918a95adb0798945624e8e9377c699fdb" + integrity sha512-im7weoHY7TW87nhFk10ysupZnsDJEO/xDpz985AgrTd/7KxExlzjjKd+4nue0WskUF0th0mgoMs1YaA8xUjCjw== + dependencies: + web3-core "^4.3.1" + web3-errors "^1.1.4" + web3-eth "^4.3.1" + web3-eth-abi "^4.1.4" + web3-eth-accounts "^4.1.0" + web3-eth-contract "^4.1.3" + web3-eth-ens "^4.0.8" + web3-eth-iban "^4.0.7" + web3-eth-personal "^4.0.8" + web3-net "^4.0.7" + web3-providers-http "^4.1.0" + web3-providers-ws "^4.0.7" + web3-rpc-methods "^1.1.3" + web3-types "^1.3.1" + web3-utils "^4.0.7" + web3-validator "^2.0.3" + +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== + +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: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" + tr46 "~0.0.3" + webidl-conversions "^3.0.0" -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" +which-typed-array@^1.1.11, which-typed-array@^1.1.2: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.4" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" +ws@^8.8.1: + version "8.14.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" + integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== -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" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.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" +zod@^3.21.4: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== From e17e6dc6c20c11ef8f7054cf165820f3b3b7cf0c Mon Sep 17 00:00:00 2001 From: Alina Sharon <52405288+laruh@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:38:37 +0700 Subject: [PATCH 2/4] chore(tests): hardhat migration from truffle and ganache (#5) #4 * add hardhat config, update deps and some tests, remove unnecessary files * remove `connect(accounts)`, use `should.be` instead of `expect().to.be` * remove `request`, `equest-promise-native`, `sol-merger` deps * update setup dev commands * use `connect` method instead of `from:address` as we use ethers V6 * update tests * Beautify js code * update readme and travis * update readme (fix docker command), remove env * call connect() when transfer NFTs * use `rejectedWith` with a more specific error * reduce duplication by contractRunner vars creation * remove rpc.Dockerfile, update workspace.Dockerfile and hardhat.config * use `to.be.rejectedWith` to match error message * error messages in EtomicSwap.sol, format code * update constants in tests * split require statements --- .env.empty | 3 - .gitignore | 5 +- .travis.yml | 3 +- README.md | 24 +- contracts/EtomicSwap.sol | 118 +- docker-compose.yml | 9 - hardhat.config.js | 10 + migrations/1_initial_migration.js | 5 - package.json | 15 +- rpc.Dockerfile | 15 - startRPC.js | 41 - test/EtomicSwap.js | 692 ++++--- truffle.js | 14 - workspace.Dockerfile | 11 +- yarn.lock | 3055 +++++++++++++++++++---------- 15 files changed, 2572 insertions(+), 1448 deletions(-) delete mode 100644 .env.empty create mode 100644 hardhat.config.js delete mode 100644 migrations/1_initial_migration.js delete mode 100644 rpc.Dockerfile delete mode 100644 startRPC.js delete mode 100644 truffle.js diff --git a/.env.empty b/.env.empty deleted file mode 100644 index 5c6b428..0000000 --- a/.env.empty +++ /dev/null @@ -1,3 +0,0 @@ -ALICE_PK= -BOB_PK= -ETH_RPC_URL=wss://ropsten.infura.io/ws \ No newline at end of file diff --git a/.gitignore b/.gitignore index 41f0d04..a306bb8 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,7 @@ typings/ .env .idea -merge \ No newline at end of file +merge + +artifacts +cache \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 941bb26..40d61e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,10 @@ services: - docker before_install: - - cp .env.empty .env - docker-compose build - docker-compose up -d script: - docker-compose exec workspace yarn - - docker-compose exec workspace truffle test + - docker-compose exec workspace npx hardhat test - docker-compose down \ No newline at end of file diff --git a/README.md b/README.md index 31c0c68..a712c04 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,21 @@ Despite example shows swap of ETH/ERC20 this approach will work also for ETH/ERC ## Project structure 1. `contracts` - Smart Contracts source code. -1. `migrations` - Deployment scripts. 1. `test` - Smart contracts unit tests. ## How to setup dev environment? +**Note:** +This setup supports both Docker Compose V1 (using `docker-compose` commands) and Docker Compose V2 (using `docker compose` commands). +Docker Compose V2 is preferable, as [from July 2023 Compose V1 stopped receiving updates](https://docs.docker.com/compose/). + 1. Install docker. -1. `cp .env.empty .env`. -1. Run `docker-compose build`. -1. Start containers `docker-compose up -d`. -1. Install project dependencies: `docker-compose exec workspace yarn`. -1. To run tests: `docker-compose exec workspace truffle test`. +1. Run `docker compose build`. +1. Start containers `docker compose up -d`. +1. Install project dependencies: `docker compose exec workspace yarn`. +1. To run tests: `docker compose exec workspace npx hardhat test`. +1. To clean artifacts and cache: `docker compose exec workspace npx hardhat clean`. +1. Stop containers `docker compose down`. ## Related links @@ -35,9 +39,9 @@ Despite example shows swap of ETH/ERC20 this approach will work also for ETH/ERC ## Useful links for smart contracts development -1. Truffle suite - https://github.com/trufflesuite/truffle -1. Ganache (EthereumJS Testrpc) - https://github.com/trufflesuite/ganache -1. OpenZeppelin Contracts - https://github.com/OpenZeppelin/openzeppelin-contracts +1. **Hardhat:** An Ethereum development environment. It facilitates building, testing, and deploying smart contracts. - https://hardhat.org +1. **Ethers.js:** A complete Ethereum library and wallet implementation in JavaScript. - https://github.com/ethers-io/ethers.js +1. **OpenZeppelin Contracts:** A library for secure smart contract development. It provides reusable contracts which are secure and tested. - https://github.com/OpenZeppelin/openzeppelin-contracts ## Contribution Guide @@ -52,5 +56,5 @@ Despite example shows swap of ETH/ERC20 this approach will work also for ETH/ERC Using Remix Online IDE is sufficient. There's no need to install anything locally. ### Notes for JetBrains or Visual Studio Code (VSCode) Users: -- These IDEs offer Solidity plugins, which can simplify your workflow. However, Remix Online IDE is also a viable option. +- These IDEs offer Solidity and HardHat plugins, which can simplify your workflow. However, Remix Online IDE is also a viable option. - To index JavaScript code, execute the Docker commands as mentioned. Necessary dependencies will be downloaded, enabling the IDE to index the rest of the code. \ No newline at end of file diff --git a/contracts/EtomicSwap.sol b/contracts/EtomicSwap.sol index c40f99c..7ac3bde 100644 --- a/contracts/EtomicSwap.sol +++ b/contracts/EtomicSwap.sol @@ -36,10 +36,11 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { bytes20 secretHash, uint64 lockTime ) external payable { + require(receiver != address(0), "Receiver cannot be the zero address"); + require(msg.value > 0, "Payment amount must be greater than 0"); require( - receiver != address(0) && - msg.value > 0 && - payments[id].state == PaymentState.Uninitialized + payments[id].state == PaymentState.Uninitialized, + "ETH payment already initialized" ); bytes20 paymentHash = ripemd160( @@ -65,10 +66,11 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { bytes20 secretHash, uint64 lockTime ) external payable { + require(receiver != address(0), "Receiver cannot be the zero address"); + require(amount > 0, "Payment amount must be greater than 0"); require( - receiver != address(0) && - amount > 0 && - payments[id].state == PaymentState.Uninitialized + payments[id].state == PaymentState.Uninitialized, + "ERC20 payment already initialized" ); bytes20 paymentHash = ripemd160( @@ -88,7 +90,11 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { // Now performing the external interaction IERC20 token = IERC20(tokenAddress); - require(token.transferFrom(msg.sender, address(this), amount)); + // Ensure that the token transfer from the sender to the contract is successful + require( + token.transferFrom(msg.sender, address(this), amount), + "ERC20 transfer failed: Insufficient balance or allowance" + ); } function receiverSpend( @@ -99,7 +105,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { address sender ) external { // Checks - require(payments[id].state == PaymentState.PaymentSent); + require( + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); bytes20 paymentHash = ripemd160( abi.encodePacked( msg.sender, @@ -109,7 +118,7 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { amount ) ); - require(paymentHash == payments[id].paymentHash); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); // Effects payments[id].state = PaymentState.ReceiverSpent; @@ -122,7 +131,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { payable(msg.sender).transfer(amount); } else { IERC20 token = IERC20(tokenAddress); - require(token.transfer(msg.sender, amount)); + require( + token.transfer(msg.sender, amount), + "ERC20 transfer failed: Contract may lack balance or token transfer was rejected" + ); } } @@ -133,11 +145,14 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint256 tokenId, address sender ) external { - // Checks + // Check if the payment state is PaymentSent require( - payments[id].state == PaymentState.PaymentSent && - msg.sender == tx.origin + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" ); + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + bytes20 paymentHash = ripemd160( abi.encodePacked( msg.sender, @@ -147,7 +162,7 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { tokenId ) ); - require(paymentHash == payments[id].paymentHash); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); // Effects payments[id].state = PaymentState.ReceiverSpent; @@ -168,11 +183,14 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint256 tokenId, address sender ) external { - // Checks + // Check if the payment state is PaymentSent require( - payments[id].state == PaymentState.PaymentSent && - msg.sender == tx.origin + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" ); + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + bytes20 paymentHash = ripemd160( abi.encodePacked( msg.sender, @@ -183,7 +201,7 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { amount ) ); - require(paymentHash == payments[id].paymentHash); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); // Effects payments[id].state = PaymentState.ReceiverSpent; @@ -203,7 +221,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { address tokenAddress, address receiver ) external { - require(payments[id].state == PaymentState.PaymentSent); + require( + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); bytes20 paymentHash = ripemd160( abi.encodePacked( receiver, @@ -213,9 +234,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { amount ) ); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); require( - paymentHash == payments[id].paymentHash && - block.timestamp >= payments[id].lockTime + block.timestamp >= payments[id].lockTime, + "Current timestamp didn't exceed payment lock time" ); payments[id].state = PaymentState.SenderRefunded; @@ -237,7 +259,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint256 tokenId, address receiver ) external { - require(payments[id].state == PaymentState.PaymentSent); + require( + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); bytes20 paymentHash = ripemd160( abi.encodePacked( receiver, @@ -247,9 +272,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { tokenId ) ); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); require( - paymentHash == payments[id].paymentHash && - block.timestamp >= payments[id].lockTime + block.timestamp >= payments[id].lockTime, + "Current timestamp didn't exceed payment lock time" ); payments[id].state = PaymentState.SenderRefunded; @@ -268,7 +294,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint256 tokenId, address receiver ) external { - require(payments[id].state == PaymentState.PaymentSent); + require( + payments[id].state == PaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); bytes20 paymentHash = ripemd160( abi.encodePacked( receiver, @@ -279,9 +308,10 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { amount ) ); + require(paymentHash == payments[id].paymentHash, "Invalid paymentHash"); require( - paymentHash == payments[id].paymentHash && - block.timestamp >= payments[id].lockTime + block.timestamp >= payments[id].lockTime, + "Current timestamp didn't exceed payment lock time" ); payments[id].state = PaymentState.SenderRefunded; @@ -308,15 +338,19 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint64 lockTime ) = abi.decode(data, (bytes32, address, address, bytes20, uint64)); + require(receiver != address(0), "Receiver must not be zero address"); + require(tokenAddress != address(0), "Token must not be zero address"); require( - receiver != address(0) && - tokenAddress != address(0) && - msg.sender == tokenAddress && - operator == from && - value > 0 && - payments[id].state == PaymentState.Uninitialized && - !isContract(receiver) + msg.sender == tokenAddress, + "Token address does not match sender" ); + require(operator == from, "Operator must be the sender"); + require(value > 0, "Value must be greater than 0"); + require( + payments[id].state == PaymentState.Uninitialized, + "ERC1155 payment must be Uninitialized" + ); + require(!isContract(receiver), "Receiver cannot be a contract"); bytes20 paymentHash = ripemd160( abi.encodePacked( @@ -372,14 +406,18 @@ contract EtomicSwap is ERC165, IERC1155Receiver, IERC721Receiver { uint64 lockTime ) = abi.decode(data, (bytes32, address, address, bytes20, uint64)); + require(receiver != address(0), "Receiver must not be zero address"); + require(tokenAddress != address(0), "Token must not be zero address"); + require( + msg.sender == tokenAddress, + "Token address does not match sender" + ); + require(operator == from, "Operator must be the sender"); require( - receiver != address(0) && - tokenAddress != address(0) && - msg.sender == tokenAddress && - operator == from && - payments[id].state == PaymentState.Uninitialized && - !isContract(receiver) + payments[id].state == PaymentState.Uninitialized, + "ERC721 payment must be Uninitialized" ); + require(!isContract(receiver), "Receiver cannot be a contract"); bytes20 paymentHash = ripemd160( abi.encodePacked(receiver, from, secretHash, tokenAddress, tokenId) diff --git a/docker-compose.yml b/docker-compose.yml index fc6ede1..a8e6443 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,9 @@ version: '2' services: - rpc: - build: - context: ./ - dockerfile: rpc.Dockerfile - ports: - - 8545 - workspace: build: context: ./ dockerfile: workspace.Dockerfile tty: true - env_file: - - .env volumes: - ./:/usr/src/workspace diff --git a/hardhat.config.js b/hardhat.config.js new file mode 100644 index 0000000..34e686b --- /dev/null +++ b/hardhat.config.js @@ -0,0 +1,10 @@ +require("@nomicfoundation/hardhat-ethers"); + +module.exports = { + solidity: "0.8.20", + networks: { + hardhat: { + // Hardhat Network's default settings are fine for most projects + } + } +}; diff --git a/migrations/1_initial_migration.js b/migrations/1_initial_migration.js deleted file mode 100644 index 4d5f3f9..0000000 --- a/migrations/1_initial_migration.js +++ /dev/null @@ -1,5 +0,0 @@ -var Migrations = artifacts.require("./Migrations.sol"); - -module.exports = function(deployer) { - deployer.deploy(Migrations); -}; diff --git a/package.json b/package.json index 8506dea..2816f2b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "description": "Etomic swap smart contract and helpers", "main": "index.js", "scripts": { - "rpc": "node startRPC.js", - "test": "truffle test", + "test": "npx hardhat test", "clean": "rm -rf merge", "merge": "node node_modules/sol-merger/bin/sol-merger.js './contracts/*.sol' ./merge" }, @@ -14,12 +13,12 @@ "dependencies": { "chai": "^4.3.10", "chai-as-promised": "^7.1.1", - "ganache": "^7.9.1", "@openzeppelin/contracts": "^5.0.0", - "request": "^2.83.0", - "request-promise-native": "^1.0.5", - "ripemd160": "^2.0.1", - "sol-merger": "^4.4.0", - "web3": "^4.2.2" + "ripemd160": "^2.0.1" + }, + "devDependencies": { + "hardhat": "^2.19.4", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "ethers": "^6.10.0" } } diff --git a/rpc.Dockerfile b/rpc.Dockerfile deleted file mode 100644 index c48276b..0000000 --- a/rpc.Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM node:19-bullseye-slim - -RUN apt-get update && apt-get install -y \ - git \ - python3 \ - make \ - g++ - -ADD . /usr/src/rpc - -WORKDIR /usr/src/rpc -RUN git config --global url."https://".insteadOf git:// -RUN yarn install - -CMD yarn rpc \ No newline at end of file diff --git a/startRPC.js b/startRPC.js deleted file mode 100644 index b4c9f82..0000000 --- a/startRPC.js +++ /dev/null @@ -1,41 +0,0 @@ -const TestRPC = require("ganache"); - -//create 10 accounts with 1000000 ETH Balance -const server = TestRPC.server({ - accounts: [ - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - { - balance: 0xd3c21bcecceda0000000 - }, - ], - debug: true, - logger: console -}); - -server.listen(8545); diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 3b8dfc7..c34469e 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -1,16 +1,24 @@ -const Swap = artifacts.require('EtomicSwap'); -const Token = artifacts.require('Token'); -const Erc721Token = artifacts.require('Erc721Token'); -const Erc1155Token = artifacts.require('Erc1155Token'); +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); const crypto = require('crypto'); const RIPEMD160 = require('ripemd160'); - -const EVMThrow = 'VM Exception while processing transaction'; +const { + AbiCoder +} = require("ethers"); require('chai') .use(require('chai-as-promised')) .should(); +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE = 'Invalid payment state. Must be PaymentSent'; +const INVALID_TIMESTAMP = 'Current timestamp didn\'t exceed payment lock time'; +const UNSUPPORTED_VALUE = 'unsupported addressable value (argument="target", value=null, code=INVALID_ARGUMENT, version=6.10.0)'; + /** * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. * @@ -23,15 +31,12 @@ require('chai') * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. */ async function advanceTimeAndMine(increaseAmount) { - await web3.currentProvider.request({ - method: 'evm_increaseTime', - params: [increaseAmount], - }); - await web3.currentProvider.request({ method: 'evm_mine' }); + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); } async function currentEvmTime() { - const block = await web3.eth.getBlock("latest"); + const block = await ethers.provider.getBlock("latest"); return block.timestamp; } @@ -47,593 +52,704 @@ const invalidSecretHex = '0x' + invalidSecret.toString('hex'); const zeroAddr = '0x0000000000000000000000000000000000000000'; -contract('EtomicSwap', function(accounts) { +describe("EtomicSwap", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + - beforeEach(async function () { - this.swap = await Swap.new(); - this.token = await Token.new(); - this.erc721token = await Erc721Token.new("MyNFT", "MNFT"); - this.erc1155token = await Erc1155Token.new("uri"); - await this.token.transfer(accounts[1], web3.utils.toWei('100')); + EtomicSwap = await ethers.getContractFactory("EtomicSwap"); + etomicSwap = await EtomicSwap.deploy(); + etomicSwap.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + token.waitForDeployment(); + + Erc721Token = await ethers.getContractFactory("Erc721Token"); + erc721token = await Erc721Token.deploy("MyNFT", "MNFT"); + erc721token.waitForDeployment(); + + Erc1155Token = await ethers.getContractFactory("Erc1155Token"); + erc1155token = await Erc1155Token.deploy("uri"); + erc1155token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); }); - it('should create contract with uninitialized payments', async function () { - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), PAYMENT_UNINITIALIZED); + it('should create contract with uninitialized payments', async function() { + const payment = await etomicSwap.payments(id); + expect(Number(payment[2])).to.equal(PAYMENT_UNINITIALIZED); }); it('should have correct ERC1155 token balance', async function() { const amount = 3; const tokenId = 1; - const balance = await this.erc1155token.balanceOf(accounts[0], tokenId); - assert.equal(balance.toNumber(), amount, "Balance of ERC1155 tokens in EtomicSwap contract is incorrect"); + const balance = await erc1155token.balanceOf(accounts[0].address, tokenId); + expect(Number(balance)).to.equal(amount, "Balance of ERC1155 tokens in EtomicSwap contract is incorrect"); }); - it('should allow to send ETH payment', async function () { + it('should allow to send ETH payment', async function() { const lockTime = await currentEvmTime() + 1000; const params = [ id, - accounts[1], + accounts[1].address, secretHash, lockTime ]; - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + // Make the ETH payment + await etomicSwap.connect(accounts[0]).ethPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; - const payment = await this.swap.payments(id); + const payment = await etomicSwap.payments(id); - // locktime - assert.equal(payment[1].valueOf(), lockTime); - // status - assert.equal(payment[2].valueOf(), PAYMENT_SENT); + expect(Number(payment[1])).to.equal(lockTime); // locktime + expect(Number(payment[2])).to.equal(PAYMENT_SENT); // status - // should not allow to send again - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.rejectedWith(EVMThrow); + // Check that it should not allow to send again + await etomicSwap.connect(accounts[0]).ethPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("ETH payment already initialized"); }); - it('should allow to send ERC20 payment', async function () { + it('should allow to send ERC20 payment', async function() { const lockTime = await currentEvmTime() + 1000; + const amount = ethers.parseEther('1'); + const params = [ id, - web3.utils.toWei('1'), - this.token.address, - accounts[1], + amount, + token.target, + accounts[1].address, secretHash, lockTime ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); - //check contract token balance - const balance = await this.token.balanceOf(this.swap.address); - assert.equal(balance.toString(), web3.utils.toWei('1')); + await token.approve(etomicSwap.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20Payment(...params).should.be.fulfilled; - const payment = await this.swap.payments(id); + // Check contract token balance + const balance = await token.balanceOf(etomicSwap.target); + expect(balance).to.equal(ethers.parseEther('1')); - // locktime - assert.equal(payment[1].valueOf(), lockTime); - // status - assert.equal(payment[2].valueOf(), PAYMENT_SENT); + const payment = await etomicSwap.payments(id); - // should not allow to deposit again - await this.swap.erc20Payment(...params).should.be.rejectedWith(EVMThrow); + // Check locktime and status + expect(payment[1]).to.equal(BigInt(lockTime)); + expect(payment[2]).to.equal(BigInt(PAYMENT_SENT)); + + // Should not allow to deposit again + await etomicSwapRunner0.erc20Payment(...params).should.be.rejectedWith("ERC20 payment already initialized"); }); - it('should allow to send ERC721 payment', async function () { + it('should allow to send ERC721 payment', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] in Erc721Token contract - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc721token.address, secretHash, lockTime] + [id, accounts[1].address, erc721token.target, secretHash, lockTime] ); - // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract - await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + + let erc721tokenRunner0 = erc721token.connect(accounts[0]); + + // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract. + // Explicitly specify the method signature. + await erc721tokenRunner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwap.target, tokenId, data); // Check the payment lockTime and state - const payment = await this.swap.payments(id); - assert.equal(payment[1].valueOf(), lockTime); - assert.equal(payment[2].valueOf(), PAYMENT_SENT); + const payment = await etomicSwap.payments(id); + expect(payment.lockTime).to.equal(BigInt(lockTime)); + expect(payment.state).to.equal(BigInt(PAYMENT_SENT)); // Check the ownership of the token - const tokenOwner = await this.erc721token.ownerOf(tokenId); - assert.equal(tokenOwner, this.swap.address); + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(etomicSwap.target); - // should not allow to send again - await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.rejectedWith(EVMThrow); + // Should not allow to send again ( reverted with custom error ERC721InsufficientApproval ) + await expect(erc721tokenRunner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwap.target, tokenId, data)).to.be.rejectedWith("ERC721InsufficientApproval"); }); - it('should allow to send ERC1155 payment', async function () { + it('should allow to send ERC1155 payment', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Token ID used in Erc1155Token contract const amountToSend = 2; // Amount of tokens to send - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id, accounts[1].address, erc1155token.target, secretHash, lockTime] ); + + let erc1155tokenRunner0 = erc1155token.connect(accounts[0]); + // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + await erc1155tokenRunner0.safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, amountToSend, data); // Check the payment lockTime and state - const payment = await this.swap.payments(id); - assert.equal(payment[1].valueOf(), lockTime); - assert.equal(payment[2].valueOf(), PAYMENT_SENT); + const payment = await etomicSwap.payments(id); + expect(payment.lockTime).to.equal(BigInt(lockTime)); + expect(payment.state).to.equal(BigInt(PAYMENT_SENT)); // Check the balance of the token in the swap contract - const tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); - assert.equal(tokenBalance.toNumber(), amountToSend); + const tokenBalance = await erc1155token.balanceOf(etomicSwap.target, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); - // should not allow to send same params again - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.rejectedWith(EVMThrow); + // Check sending same params again - should fail + await expect(erc1155tokenRunner0.safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, amountToSend, data)).to.be.rejectedWith("ERC1155InsufficientBalance"); // sender should be capable to send more tokens, if they have it const id1 = '0x' + crypto.randomBytes(32).toString('hex'); - const data1 = web3.eth.abi.encodeParameters( + const data1 = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id1, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id1, accounts[1].address, erc1155token.target, secretHash, lockTime] ); - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, 1, data1).should.be.fulfilled; + await erc1155tokenRunner0.safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, 1, data1).should.be.fulfilled; // Check sending more tokens than the sender owns - should fail const id2 = '0x' + crypto.randomBytes(32).toString('hex'); - const data2 = web3.eth.abi.encodeParameters( + const data2 = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id2, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id2, accounts[1].address, erc1155token.target, secretHash, lockTime] ); - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, 1, data2).should.be.rejectedWith(EVMThrow); + await expect(erc1155tokenRunner0.safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, 1, data2)).to.be.rejectedWith("ERC1155InsufficientBalance"); }); - it('should allow sender to refund ETH payment after locktime', async function () { + it('should allow sender to refund ETH payment after locktime', async function() { const lockTime = await currentEvmTime() + 1000; const params = [ id, - accounts[1], + accounts[1].address, secretHash, 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); + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); + + // Not allow to refund if payment was not sent + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, zeroAddr, accounts[1].address) + .should.be.rejectedWith(INVALID_PAYMENT_STATE); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + // Make the ETH payment + await etomicSwapRunner0.ethPayment(...params, { + value: ethers.parseEther('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); + // Not allow to refund before locktime + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, zeroAddr, accounts[1].address).should.be.rejectedWith(INVALID_TIMESTAMP); + // Simulate time passing to exceed the locktime await advanceTimeAndMine(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); + // Not allow to call refund from non-sender address + await etomicSwapRunner1.senderRefund(id, ethers.parseEther('1'), secretHash, zeroAddr, accounts[1].address).should.be.rejectedWith(INVALID_HASH); - // not allow to refund invalid amount - await this.swap.senderRefund(id, web3.utils.toWei('2'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + // Not allow to refund invalid amount + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('2'), secretHash, zeroAddr, accounts[1].address).should.be.rejectedWith(INVALID_HASH); - // success refund - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[0])); - const gasPrice = web3.utils.toWei('100', 'gwei'); + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('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 etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, zeroAddr, accounts[1].address, { + gasPrice + }).should.be.fulfilled; - const txFee = web3.utils.toBN(gasPrice).mul(web3.utils.toBN(tx.receipt.gasUsed)); - // check sender balance - assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(SENDER_REFUNDED)); - // not allow to refund again - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, zeroAddr, accounts[1]).should.be.rejectedWith(EVMThrow); + // Not allow to refund again + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, zeroAddr, accounts[1].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow sender to refund ERC20 payment after locktime', async function () { + it('should allow sender 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], + ethers.parseEther('1'), + token.target, + accounts[1].address, secretHash, lockTime ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); - // not allow to refund if payment was not sent - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); + await token.approve(etomicSwap.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20Payment(...params)).to.be.fulfilled; - // not allow to refund before locktime - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); + // Not allow to refund before locktime + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, token.target, accounts[1].address).should.be.rejectedWith(INVALID_TIMESTAMP); await advanceTimeAndMine(1000); - // not allow to call refund from non-sender address - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + // Not allow to call refund from non-sender address + await etomicSwapRunner1.senderRefund(id, ethers.parseEther('1'), secretHash, token.target, accounts[1].address) + .should.be.rejectedWith(INVALID_HASH); - // not allow to refund invalid amount - await this.swap.senderRefund(id, web3.utils.toWei('2'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); + // Not allow to refund invalid amount + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('2'), secretHash, token.target, accounts[1].address).should.be.rejectedWith(INVALID_HASH); - // success refund - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.fulfilled; + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, token.target, accounts[1].address).should.be.fulfilled; - const balanceAfter = web3.utils.toBN(await this.token.balanceOf(accounts[0])); + const balanceAfter = await token.balanceOf(accounts[0].address); - // check sender balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + // Check the state of the payment + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(SENDER_REFUNDED)); - // not allow to refund again - await this.swap.senderRefund(id, web3.utils.toWei('1'), secretHash, this.token.address, accounts[1]).should.be.rejectedWith(EVMThrow); + // Do not allow to refund again + await etomicSwapRunner0.senderRefund(id, ethers.parseEther('1'), secretHash, token.target, accounts[1].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow sender to refund ERC721 payment after locktime', async function () { + it('should allow sender to refund ERC721 payment after locktime', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc721token.address, secretHash, lockTime] + [id, accounts[1].address, erc721token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract - await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwap.target, tokenId, data).should.be.fulfilled; + + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); // Attempt refund before locktime - should fail - await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.senderRefundErc721(id, secretHash, erc721token.target, tokenId, accounts[1].address).should.be.rejectedWith(INVALID_TIMESTAMP); // Advance time past locktime await advanceTimeAndMine(1000); // Attempt refund from non-sender address - should fail - await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.senderRefundErc721(id, secretHash, erc721token.target, tokenId, accounts[1].address).should.be.rejectedWith(INVALID_HASH); // Successful refund by sender after locktime - await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.fulfilled; + await etomicSwapRunner0.senderRefundErc721(id, secretHash, erc721token.target, tokenId, accounts[1].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(SENDER_REFUNDED)); // Check the ownership of the token - should be back to the sender (accounts[0]) - const tokenOwner = await this.erc721token.ownerOf(tokenId); - assert.equal(tokenOwner, accounts[0]); + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(accounts[0].address); // Attempting refund again - should fail - await this.swap.senderRefundErc721(id, secretHash, this.erc721token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.senderRefundErc721(id, secretHash, erc721token.target, tokenId, accounts[1].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow sender to refund ERC1155 payment after locktime', async function () { + it('should allow sender to refund ERC1155 payment after locktime', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Token ID used in Erc1155Token contract const amountToSend = 3; // Amount of tokens to send - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id, accounts[1].address, erc1155token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, amountToSend, data).should.be.fulfilled; + + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); // Attempt refund before locktime - should fail - await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.senderRefundErc1155(id, amountToSend, secretHash, erc1155token.target, tokenId, accounts[1]).should.be.rejectedWith(INVALID_TIMESTAMP); // Advance time past locktime await advanceTimeAndMine(1000); // Attempt refund from non-sender address - should fail - await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.senderRefundErc1155(id, amountToSend, secretHash, erc1155token.target, tokenId, accounts[1].address).should.be.rejectedWith(INVALID_HASH); // Successful refund by sender after locktime - await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.fulfilled; + await etomicSwapRunner0.senderRefundErc1155(id, amountToSend, secretHash, erc1155token.target, tokenId, accounts[1].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), SENDER_REFUNDED); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(SENDER_REFUNDED)); // Check the balance of the token - should be back to the sender (accounts[0]) - const tokenBalance = await this.erc1155token.balanceOf(accounts[0], tokenId); - assert.equal(tokenBalance.toNumber(), amountToSend); + const tokenBalance = await erc1155token.balanceOf(accounts[0].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); // Attempting refund again - should fail - await this.swap.senderRefundErc1155(id, amountToSend, secretHash, this.erc1155token.address, tokenId, accounts[1], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.senderRefundErc1155(id, amountToSend, secretHash, erc1155token.target, tokenId, accounts[1].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ETH payment by revealing a secret', async function () { + it('should allow receiver to spend ETH payment by revealing a secret', async function() { const lockTime = await currentEvmTime() + 1000; const params = [ id, - accounts[1], + accounts[1].address, secretHash, lockTime ]; - // 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); + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + // Should not allow to spend uninitialized payment + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); - // should not allow to spend with invalid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), invalidSecretHex, 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); + // Make the ETH payment + await etomicSwapRunner0.ethPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; - // 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 invalid secret + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), invalidSecretHex, zeroAddr, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - // success spend - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - const gasPrice = web3.utils.toWei('100', 'gwei'); + // Should not allow to spend invalid amount + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('2'), secretHex, zeroAddr, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - 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)); + // Should not allow to claim from non-receiver address even with valid secret + await etomicSwapRunner0.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + // Success spend + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); - // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); + const gasPrice = ethers.parseUnits('100', 'gwei'); - const payment = await this.swap.payments(id); + const tx = await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address, { + gasPrice + }).should.be.fulfilled; - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasPrice * gasUsed; - // 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); + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(RECEIVER_SPENT)); + + // Should not allow to spend again + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address, { + gasPrice + }).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - 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', async function() { const lockTime = await currentEvmTime() + 1000; const params = [ id, - web3.utils.toWei('1'), - this.token.address, - accounts[1], + ethers.parseEther('1'), + token.target, + accounts[1].address, secretHash, lockTime ]; - // 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); + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); + + // Should not allow to spend uninitialized payment + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, token.address, accounts[0].address).should.be.rejectedWith(UNSUPPORTED_VALUE); - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + await token.approve(etomicSwap.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20Payment(...params).should.be.fulfilled; - // should not allow to spend with invalid secret - await this.swap.receiverSpend(id, web3.utils.toWei('1'), invalidSecretHex, 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); + // Should not allow to spend with invalid secret + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), invalidSecretHex, token.target, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - // 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 amount + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('2'), secretHex, token.target, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - // success spend - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + // Should not allow to claim from non-receiver address even with valid secret + await etomicSwapRunner0.receiverSpend(id, ethers.parseEther('1'), secretHex, token.target, accounts[0].address).should.be.rejectedWith(INVALID_HASH); - 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])); + // Success spend + const balanceBefore = await token.balanceOf(accounts[1]); - // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + const gasPrice = ethers.parseUnits('100', 'gwei'); - const payment = await this.swap.payments(id); + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, token.target, accounts[0].address, { + gasPrice + }).should.be.fulfilled; - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(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); + // Should not allow to spend again + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, token.target, accounts[0].address, { + gasPrice + }).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ERC721 payment by revealing a secret', async function () { + it('should allow receiver to spend ERC721 payment by revealing a secret', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc721token.address, secretHash, lockTime] + [id, accounts[1].address, erc721token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract - await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwap.target, tokenId, data).should.be.fulfilled; // Check the ownership of the token before receiver spend payment - should be owned by swap contract - const tokenOwnerBeforeReceiverSpend = await this.erc721token.ownerOf(tokenId); - assert.equal(tokenOwnerBeforeReceiverSpend, this.swap.address); + const tokenOwnerBeforeReceiverSpend = await erc721token.ownerOf(tokenId); + expect(tokenOwnerBeforeReceiverSpend).to.equal(etomicSwap.target); + + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); // Attempt to spend with invalid secret - should fail - await this.swap.receiverSpendErc721(id, invalidSecretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc721(id, invalidSecretHex, erc721token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_HASH); // Attempt to claim from non-receiver address even with valid secret - should fail - await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.receiverSpendErc721(id, secretHex, erc721token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_HASH); // Successful spend by receiver with valid secret - await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + await etomicSwapRunner1.receiverSpendErc721(id, secretHex, erc721token.target, tokenId, accounts[0].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(RECEIVER_SPENT)); // Check the ownership of the token - should be transferred to the receiver (accounts[1]) - const tokenOwner = await this.erc721token.ownerOf(tokenId); - assert.equal(tokenOwner, accounts[1]); + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(accounts[1].address); // Attempting to spend again - should fail - await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc721(id, secretHex, erc721token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ERC1155 payment by revealing a secret', async function () { + + it('should allow receiver to spend ERC1155 payment by revealing a secret', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Token ID used in Erc1155Token contract const amountToSend = 2; // Amount of tokens to send - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id, accounts[1].address, erc1155token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, amountToSend, data).should.be.fulfilled; // Check the balance of the token before receiver spend payment - should be in swap contract - let tokenBalanceBeforeReceiverSpend = await this.erc1155token.balanceOf(this.swap.address, tokenId); - assert.equal(tokenBalanceBeforeReceiverSpend.toNumber(), amountToSend); + let tokenBalanceBeforeReceiverSpend = await erc1155token.balanceOf(etomicSwap.target, tokenId); + expect(tokenBalanceBeforeReceiverSpend).to.equal(BigInt(amountToSend)); + + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); // Attempt to spend with invalid secret - should fail - await this.swap.receiverSpendErc1155(id, amountToSend, invalidSecretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc1155(id, amountToSend, invalidSecretHex, erc1155token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_HASH); // Attempt to claim from non-receiver address even with valid secret - should fail - await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[0] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner0.receiverSpendErc1155(id, amountToSend, secretHex, erc1155token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_HASH); // Successful spend by receiver with valid secret - await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + await etomicSwapRunner1.receiverSpendErc1155(id, amountToSend, secretHex, erc1155token.target, tokenId, accounts[0].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(RECEIVER_SPENT)); // Check the balance of the token - should be transferred to the receiver (accounts[1]) - let tokenBalance = await this.erc1155token.balanceOf(accounts[1], tokenId); - assert.equal(tokenBalance.toNumber(), amountToSend); + let tokenBalance = await erc1155token.balanceOf(accounts[1].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); // Check that the swap contract no longer holds the tokens - tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); - assert.equal(tokenBalance.toNumber(), 0); + tokenBalance = await erc1155token.balanceOf(etomicSwap.target, tokenId); + expect(tokenBalance).to.equal(BigInt(0)); // Attempting to spend again - should fail - await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc1155(id, amountToSend, secretHex, erc1155token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ETH payment by revealing a secret even 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; const params = [ id, - accounts[1], + accounts[1].address, secretHash, lockTime ]; - await this.swap.ethPayment(...params, { value: web3.utils.toWei('1') }).should.be.fulfilled; + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); + + // Make the ETH payment + await etomicSwapRunner0.ethPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; await advanceTimeAndMine(1000); - // success spend - const balanceBefore = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); - const gasPrice = web3.utils.toWei('100', 'gwei'); + // Success spend + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); - 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 gasPrice = ethers.parseUnits('100', 'gwei'); - const balanceAfter = web3.utils.toBN(await web3.eth.getBalance(accounts[1])); + const tx = await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address, { + gasPrice + }).should.be.fulfilled; - // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).add(txFee).toString(), web3.utils.toWei('1')); + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasPrice * gasUsed; - const payment = await this.swap.payments(id); + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(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); + // Should not allow to spend again + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, zeroAddr, accounts[0].address, { + gasPrice + }).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ERC20 payment by revealing a secret even 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; const params = [ id, - web3.utils.toWei('1'), - this.token.address, - accounts[1], + ethers.parseEther('1'), + token.target, + accounts[1].address, secretHash, lockTime ]; - await this.token.approve(this.swap.address, web3.utils.toWei('1')); - await this.swap.erc20Payment(...params).should.be.fulfilled; + let etomicSwapRunner0 = etomicSwap.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); - await advanceTimeAndMine(1000); + await token.approve(etomicSwap.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20Payment(...params)).to.be.fulfilled; - // success spend - const balanceBefore = web3.utils.toBN(await this.token.balanceOf(accounts[1])); + await advanceTimeAndMine(1000); - 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])); + // Success spend + const balanceBefore = await token.balanceOf(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); - // check receiver balance - assert.equal(balanceAfter.sub(balanceBefore).toString(), web3.utils.toWei('1')); + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, token.target, accounts[0].address, { + gasPrice + }).should.be.fulfilled; - const payment = await this.swap.payments(id); + const balanceAfter = await token.balanceOf(accounts[1]); + // Check receiver balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); - // status - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + // Check the state of the payment + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(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); + // Should not allow to spend again + await etomicSwapRunner1.receiverSpend(id, ethers.parseEther('1'), secretHex, token.target, accounts[0].address, { + gasPrice + }).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ERC721 payment by revealing a secret even after locktime', async function () { + it('should allow receiver to spend ERC721 payment by revealing a secret even after locktime', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc721token.address, secretHash, lockTime] + [id, accounts[1].address, erc721token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the token to the EtomicSwap contract - await this.erc721token.safeTransferFrom(accounts[0], this.swap.address, tokenId, data).should.be.fulfilled; + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwap.target, tokenId, data).should.be.fulfilled; await advanceTimeAndMine(1000); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); + // Successful spend by receiver with valid secret even after locktime - await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + await etomicSwapRunner1.receiverSpendErc721(id, secretHex, erc721token.target, tokenId, accounts[0].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(RECEIVER_SPENT)); // Check the ownership of the token - should be transferred to the receiver (accounts[1]) - const tokenOwner = await this.erc721token.ownerOf(tokenId); - assert.equal(tokenOwner, accounts[1]); + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(accounts[1].address); // Attempting to spend again - should fail - await this.swap.receiverSpendErc721(id, secretHex, this.erc721token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc721(id, secretHex, erc721token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); - it('should allow receiver to spend ERC1155 payment by revealing a secret even after locktime', async function () { + it('should allow receiver to spend ERC1155 payment by revealing a secret even after locktime', async function() { const lockTime = await currentEvmTime() + 1000; const tokenId = 1; // Token ID used in Erc1155Token contract const amountToSend = 2; // Amount of tokens to send - const data = web3.eth.abi.encodeParameters( + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( ['bytes32', 'address', 'address', 'bytes20', 'uint64'], - [id, accounts[1], this.erc1155token.address, secretHash, lockTime] + [id, accounts[1].address, erc1155token.target, secretHash, lockTime] ); // Call safeTransferFrom directly to transfer the tokens to the EtomicSwap contract - await this.erc1155token.safeTransferFrom(accounts[0], this.swap.address, tokenId, amountToSend, data).should.be.fulfilled; + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwap.target, tokenId, amountToSend, data).should.be.fulfilled; await advanceTimeAndMine(1000); + let etomicSwapRunner1 = etomicSwap.connect(accounts[1]); + // Successful spend by receiver with valid secret even after locktime - await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.fulfilled; + await etomicSwapRunner1.receiverSpendErc1155(id, amountToSend, secretHex, erc1155token.target, tokenId, accounts[0].address).should.be.fulfilled; // Check the state of the payment - const payment = await this.swap.payments(id); - assert.equal(payment[2].valueOf(), RECEIVER_SPENT); + const payment = await etomicSwap.payments(id); + expect(payment.state).to.equal(BigInt(RECEIVER_SPENT)); // Check the balance of the token - should be transferred to the receiver (accounts[1]) - let tokenBalance = await this.erc1155token.balanceOf(accounts[1], tokenId); - assert.equal(tokenBalance.toNumber(), amountToSend); + let tokenBalance = await erc1155token.balanceOf(accounts[1].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); // Check that the swap contract no longer holds the tokens - tokenBalance = await this.erc1155token.balanceOf(this.swap.address, tokenId); - assert.equal(tokenBalance.toNumber(), 0); + tokenBalance = await erc1155token.balanceOf(etomicSwap.target, tokenId); + expect(tokenBalance).to.equal(BigInt(0)); // Attempting to spend again - should fail - await this.swap.receiverSpendErc1155(id, amountToSend, secretHex, this.erc1155token.address, tokenId, accounts[0], { from: accounts[1] }).should.be.rejectedWith(EVMThrow); + await etomicSwapRunner1.receiverSpendErc1155(id, amountToSend, secretHex, erc1155token.target, tokenId, accounts[0].address).should.be.rejectedWith(INVALID_PAYMENT_STATE); }); -}); +}); \ No newline at end of file diff --git a/truffle.js b/truffle.js deleted file mode 100644 index fb3f280..0000000 --- a/truffle.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - networks: { - development: { - host: "rpc", - port: 8545, - network_id: "*" // Match any network id - } - }, - compilers: { - solc: { - version: "0.8.20", - } - }, -}; diff --git a/workspace.Dockerfile b/workspace.Dockerfile index 8e5913a..f851c71 100644 --- a/workspace.Dockerfile +++ b/workspace.Dockerfile @@ -1,11 +1,6 @@ -FROM node:19-bullseye-slim +FROM node:20-bullseye-slim -RUN apt-get update && apt-get install -y \ - git \ - python3 \ - make \ - g++ - -RUN npm i -g truffle@5.11.5 VOLUME /usr/src/workspace WORKDIR /usr/src/workspace + +RUN yarn install diff --git a/yarn.lock b/yarn.lock index a1c90b6..9885f81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,76 +2,736 @@ # yarn lockfile v1 -"@adraffy/ens-normalize@^1.8.8": +"@adraffy/ens-normalize@1.10.0": version "1.10.0" resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== -"@ethereumjs/rlp@^4.0.1": +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": + 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", "@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", "@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", "@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", "@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/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@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", "@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", "@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/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + +"@ethersproject/hash@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/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + dependencies: + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/pbkdf2" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@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", "@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.1", "@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/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@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/providers@5.7.2", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@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/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@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/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@ethersproject/strings@5.7.0", "@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.7.0", "@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/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/hdnode" "^5.7.0" + "@ethersproject/json-wallets" "^5.7.0" + "@ethersproject/keccak256" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wordlists" "^5.7.0" + +"@ethersproject/web@5.7.1", "@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" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + +"@fastify/busboy@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" + integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== + +"@metamask/eth-sig-util@^4.0.0": version "4.0.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" - integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" -"@noble/curves@1.1.0", "@noble/curves@~1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== dependencies: - "@noble/hashes" "1.3.1" + "@noble/hashes" "1.3.2" -"@noble/hashes@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": +"@noble/hashes@1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@nomicfoundation/ethereumjs-block@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz#13a7968f5964f1697da941281b7f7943b0465d04" + integrity sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + +"@nomicfoundation/ethereumjs-blockchain@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz#45323b673b3d2fab6b5008535340d1b8fea7d446" + integrity sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-ethash" "3.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + +"@nomicfoundation/ethereumjs-common@4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz#a15d1651ca36757588fdaf2a7d381a150662a3c3" + integrity sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.2" + crc-32 "^1.2.0" + +"@nomicfoundation/ethereumjs-ethash@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz#da77147f806401ee996bfddfa6487500118addca" + integrity sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-evm@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz#4c2f4b84c056047102a4fa41c127454e3f0cfcf6" + integrity sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ== + dependencies: + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/ethereumjs-rlp@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz#4fee8dc58a53ac6ae87fb1fca7c15dc06c6b5dea" + integrity sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA== + +"@nomicfoundation/ethereumjs-statemanager@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz#3ba4253b29b1211cafe4f9265fee5a0d780976e0" + integrity sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + js-sdsl "^4.1.4" + +"@nomicfoundation/ethereumjs-trie@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz#9a6dbd28482dca1bc162d12b3733acab8cd12835" + integrity sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@types/readable-stream" "^2.3.13" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + +"@nomicfoundation/ethereumjs-tx@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz#117813b69c0fdc14dd0446698a64be6df71d7e56" + integrity sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-util@9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz#16bdc1bb36f333b8a3559bbb4b17dac805ce904d" + integrity sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ== + dependencies: + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + ethereum-cryptography "0.1.3" + +"@nomicfoundation/ethereumjs-vm@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz#3b0852cb3584df0e18c182d0672a3596c9ca95e6" + integrity sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + +"@nomicfoundation/hardhat-ethers@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz#0422c2123dec7c42e7fb2be8e1691f1d9708db56" + integrity sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw== + dependencies: + debug "^4.1.1" + lodash.isequal "^4.5.0" + +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" + integrity sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w== + +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz#6e25ccdf6e2d22389c35553b64fe6f3fdaec432c" + integrity sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA== + +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz#0a224ea50317139caeebcdedd435c28a039d169c" + integrity sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA== + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz#dfa085d9ffab9efb2e7b383aed3f557f7687ac2b" + integrity sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg== + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz#c9e06b5d513dd3ab02a7ac069c160051675889a4" + integrity sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w== + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz#8d328d16839e52571f72f2998c81e46bf320f893" + integrity sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA== + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz#9b49d0634b5976bb5ed1604a1e1b736f390959bb" + integrity sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz#e2867af7264ebbcc3131ef837878955dd6a3676f" + integrity sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz#0685f78608dd516c8cdfb4896ed451317e559585" + integrity sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz#c9a44f7108646f083b82e851486e0f6aeb785836" + integrity sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw== + +"@nomicfoundation/solidity-analyzer@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz#f5f4d36d3f66752f59a57e7208cd856f3ddf6f2d" + integrity sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg== + optionalDependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.1" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" + "@openzeppelin/contracts@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c" - integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.1.tgz#93da90fc209a0a4ff09c1deb037fbb35e4020890" + integrity sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w== "@scure/base@~1.1.0": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" - integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" + integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== -"@scure/bip32@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" - integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== dependencies: - "@noble/curves" "~1.1.0" - "@noble/hashes" "~1.3.1" + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== dependencies: - "@noble/hashes" "~1.3.0" + "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" -"@trufflesuite/bigint-buffer@1.1.10": - version "1.1.10" - resolved "https://registry.yarnpkg.com/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.10.tgz#a1d9ca22d3cad1a138b78baaf15543637a3e1692" - integrity sha512-pYIQC5EcMmID74t26GCC67946mgTJFiLXOT/BYozgrd4UEY2JHEGLhWi9cMiQCt5BSqFEvKkCHNnoj82SRjiEw== +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@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: - node-gyp-build "4.4.0" - -"@trufflesuite/uws-js-unofficial@20.30.0-unofficial.0": - version "20.30.0-unofficial.0" - resolved "https://registry.yarnpkg.com/@trufflesuite/uws-js-unofficial/-/uws-js-unofficial-20.30.0-unofficial.0.tgz#2fbc2f8ef7e82fbeea6abaf7e8a9d42a02b479d3" - integrity sha512-r5X0aOQcuT6pLwTRLD+mPnAM/nlKtvIK4Z+My++A8tTOR0qTjNRx8UB8jzRj3D+p9PMAp5LnpCUUGmz7/TppwA== - dependencies: - ws "8.13.0" - optionalDependencies: - bufferutil "4.0.7" - utf-8-validate "6.0.3" + "@types/node" "*" "@types/bn.js@^5.1.0": version "5.1.5" @@ -80,39 +740,49 @@ dependencies: "@types/node" "*" -"@types/lru-cache@5.1.1": +"@types/lru-cache@^5.1.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== "@types/node@*": - version "20.9.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298" - integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw== + version "20.11.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.15.tgz#b853a86cfedbc768360c552b4653302b4e7417bf" + integrity sha512-gscmuADZfvNULx1eyirVbr3kVOVZtpQtzKMCZpeSZcN6MfbkRXAR4s9/gsQ4CzxLHw6EStDtKLNtSDL3vbq05A== dependencies: undici-types "~5.26.4" -"@types/seedrandom@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.1.tgz#1254750a4fec4aff2ebec088ccd0bb02e91fedb4" - integrity sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== -"@types/ws@8.5.3": - version "8.5.3" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" - integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== +"@types/pbkdf2@^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" + integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== dependencies: "@types/node" "*" -abitype@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.7.1.tgz#16db20abe67de80f6183cf75f3de1ff86453b745" - integrity sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ== +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" -abstract-level@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== +"@types/secp256k1@^4.0.1": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" + integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== + dependencies: + "@types/node" "*" + +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3, abstract-level@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.4.tgz#3ad8d684c51cc9cbc9cf9612a7100b716c414b57" + integrity sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg== dependencies: buffer "^6.0.3" catering "^2.1.0" @@ -122,98 +792,158 @@ abstract-level@1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" -abstract-leveldown@7.2.0, abstract-leveldown@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" - integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== - dependencies: - buffer "^6.0.3" - catering "^2.0.0" - is-buffer "^2.0.5" - level-concat-iterator "^3.0.0" - level-supports "^2.0.1" - queue-microtask "^1.2.3" +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" + debug "4" -antlr4ts@^0.5.0-alpha.4: - version "0.5.0-alpha.4" - resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" - integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== dependencies: - safer-buffer "~2.1.0" + string-width "^4.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" +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -async-eventemitter@0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: - async "^2.4.0" + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -async@^2.4.0: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== +ansi-styles@^3.2.1: + 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: - lodash "^4.17.14" + color-convert "^1.9.0" -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" -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== +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" +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== 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== + +base-x@^3.0.2: + 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.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" - dependencies: - tweetnacl "^0.14.3" +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bigint-crypto-utils@^3.0.23: + version "3.3.0" + resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz#72ad00ae91062cf07f2b1def9594006c279c1d77" + integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +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== -bn.js@^4.11.9: +bn.js@^4.11.0, bn.js@^4.11.8, 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.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== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -222,11 +952,78 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.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== +browser-level@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" + integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.1" + module-error "^1.0.2" + run-parallel-limit "^1.1.0" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.2.0: + version "1.2.0" + 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" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +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: + base-x "^3.0.2" + +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: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +buffer-from@^1.0.0: + 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-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -235,34 +1032,22 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bufferutil@4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" - integrity sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A== - dependencies: - node-gyp-build "^4.3.0" - -bufferutil@4.0.7: - 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== -call-bind@^1.0.2, call-bind@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" +camelcase@^6.0.0, camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== -catering@^2.0.0, catering@^2.1.0: +catering@^2.1.0, catering@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== @@ -270,13 +1055,14 @@ catering@^2.0.0, catering@^2.1.0: 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.3.10: - version "4.3.10" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" - integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== + version "4.4.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== dependencies: assertion-error "^1.1.0" check-error "^1.0.3" @@ -286,97 +1072,172 @@ chai@^4.3.10: pathval "^1.1.1" type-detect "^4.0.8" -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" -check-error@^1.0.3: +check-error@^1.0.2, check-error@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== dependencies: get-func-name "^2.0.2" -cli-color@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" - integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== +chokidar@3.5.3, chokidar@^3.4.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +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: - d "^1.0.1" - es5-ext "^0.10.61" - es6-iterator "^2.0.3" - memoizee "^0.4.15" - timers-ext "^0.1.7" + inherits "^2.0.1" + safe-buffer "^5.0.1" -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +classic-level@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.4.1.tgz#169ecf9f9c6200ad42a98c8576af449c1badbaee" + integrity sha512-qGx/KJl3bvtOHrGau2WklEZuXhS3zme+jf+fsu6Ej7W7IP/C49v7KNlWIsT1jZu0YnfzSIYDGcEWpCa1wKGWXQ== + dependencies: + abstract-level "^1.0.2" + catering "^2.1.0" + module-error "^1.0.1" + napi-macros "^2.2.2" + node-gyp-build "^4.3.0" -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: - delayed-stream "~1.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.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@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +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== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== 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== -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" +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -crc-32@^1.2.2: +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== -cross-fetch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== - dependencies: - node-fetch "^2.6.12" - -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: - es5-ext "^0.10.9" + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" -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== +create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: - 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" - dependencies: - assert-plus "^1.0.0" + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" -debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.3: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + deep-eql@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" @@ -384,27 +1245,17 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" -define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +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== -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.5.2, 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== @@ -417,186 +1268,263 @@ elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emittery@0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026" - integrity sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ== - -es5-ext@^0.10.35, 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" - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, 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== +enquirer@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - next-tick "^1.1.0" + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" -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" - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -es6-symbol@^3.1.1, es6-symbol@~3.1.1: +escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -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.0.1" - ext "^1.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -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.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -ethereum-cryptography@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" - integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== - dependencies: - "@noble/curves" "1.1.0" - "@noble/hashes" "1.3.1" - "@scure/bip32" "1.3.1" - "@scure/bip39" "1.2.1" +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +ethereum-cryptography@0.1.3, 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" -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" +ethereum-cryptography@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, 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" + +ethers@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.10.0.tgz#20f3c63c60d59a993f8090ad423d8a3854b3b1cd" + integrity sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + +ethjs-util@0.1.6, 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" + +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: - d "1" - es5-ext "~0.10.14" + md5.js "^1.3.4" + safe-buffer "^5.1.1" -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== +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 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" + to-regex-range "^5.0.1" -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -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-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" - -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== +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 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" + locate-path "^6.0.0" + path-exists "^4.0.0" -form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.12.1: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" -fs-extra@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== +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.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.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== -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -ganache@^7.9.1: - version "7.9.1" - resolved "https://registry.yarnpkg.com/ganache/-/ganache-7.9.1.tgz#94f8518215c7989ff5fd542db80bd47d7c7da786" - integrity sha512-Tqhd4J3cpiLeYTD6ek/zlchSB107IVPMIm4ypyg+xz1sdkeALUnYYZnmY4Bdjqj3i6QwtlZPCu7U4qKy7HlWTA== - dependencies: - "@trufflesuite/bigint-buffer" "1.1.10" - "@trufflesuite/uws-js-unofficial" "20.30.0-unofficial.0" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "5.1.1" - "@types/seedrandom" "3.0.1" - abstract-level "1.0.3" - abstract-leveldown "7.2.0" - async-eventemitter "0.2.4" - emittery "0.10.0" - keccak "3.0.2" - leveldown "6.1.0" - secp256k1 "4.0.3" - optionalDependencies: - bufferutil "4.0.5" - utf-8-validate "5.0.7" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +get-caller-file@^2.0.5: + 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.1, get-func-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" + is-glob "^4.0.1" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: - assert-plus "^1.0.0" + 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" -glob@^7.1.7: +glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -608,78 +1536,97 @@ glob@^7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -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== - -graceful-fs@^4.2.0: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - dependencies: - ajv "^5.3.0" - har-schema "^2.0.0" - -has-property-descriptors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -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-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-symbols "^1.0.2" +hardhat@^2.19.4: + version "2.19.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.5.tgz#6017c35ae2844b669e9bcc84c3d05346d4ef031c" + integrity sha512-vx8R7zWCYVgM56vA6o0Wqx2bIIptkN4TMs9QwDqZVNGRhMzBfzqUeEYbp+69gxWp1neg2V2nYQUaaUv7aom1kw== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@nomicfoundation/ethereumjs-vm" "7.0.2" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + 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.1" - safe-buffer "^5.0.1" + 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" -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== hmac-drbg@^1.0.1: version "1.0.1" @@ -690,135 +1637,162 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" +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 "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" + agent-base "6" + debug "4" + +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" ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +immutable@^4.0.0-rc.12: + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + 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.4: +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== -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== +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + binary-extensions "^2.0.0" is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - -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-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -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-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-typed-array@^1.1.3: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: - which-typed-array "^1.1.11" + is-extglob "^2.1.1" -is-typedarray@~1.0.0: +is-hex-prefixed@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== -isomorphic-ws@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" - integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -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" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +js-sdsl@^4.1.4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== -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" +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== -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: - universalify "^2.0.0" + argparse "^2.0.1" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== 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" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" +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" -keccak@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== +keccak@^3.0.0, keccak@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" readable-stream "^3.6.0" -level-concat-iterator@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" - integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== - dependencies: - catering "^2.1.0" - -level-supports@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" - integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== + optionalDependencies: + graceful-fs "^4.1.9" level-supports@^4.0.0: version "4.0.1" @@ -833,25 +1807,48 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" -leveldown@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.0.tgz#7ab1297706f70c657d1a72b31b40323aa612b9ee" - integrity sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w== +level@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.1.tgz#737161db1bc317193aca4e7b6f436e7e1df64379" + integrity sha512-oPBGkheysuw7DmzFQYyFe8NAia5jFLAgEnkgWnK3OXAuJr8qFT+xBQIwokAZPME2bhPFzS8hlYcL16m8UZrtwQ== dependencies: - abstract-leveldown "^7.2.0" - napi-macros "~2.0.0" - node-gyp-build "^4.3.0" + abstract-level "^1.0.4" + browser-level "^1.0.1" + classic-level "^1.2.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.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== +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== -lodash@^4.17.14: +lodash@^4.17.11: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -859,53 +1856,105 @@ loupe@^2.3.6: dependencies: get-func-name "^2.0.1" -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== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: - es5-ext "~0.10.2" + yallist "^3.0.2" -memoizee@^0.4.15: - 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.0.1" - es5-ext "^0.10.53" - es6-weak-map "^2.0.3" - event-emitter "^0.3.5" - is-promise "^2.2.2" - lru-queue "^0.1.0" - next-tick "^1.1.0" - timers-ext "^0.1.7" +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" +md5.js@^1.3.4: + 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: - mime-db "~1.36.0" + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +memory-level@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" + integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== + dependencies: + abstract-level "^1.0.0" + functional-red-black-tree "^1.0.1" + module-error "^1.0.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== 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.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@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" -minimatch@^3.1.1: +minimatch@^3.0.4, 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" -module-error@^1.0.1: +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha@^10.0.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +module-error@^1.0.1, module-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== @@ -915,84 +1964,156 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -napi-macros@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" - integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -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== +napi-macros@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.2.2.tgz#817fef20c3e0e40a963fbf7b37d1600bd0201044" + integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== 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.12: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-gyp-build@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.4.0.tgz#42e99687ce87ddeaf3a10b99dc06abc11021f3f4" - integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== - node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" - integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== + version "4.8.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" + integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +obliterator@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" + integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== once@^1.3.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" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +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-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.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 sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + 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-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +pbkdf2@^3.0.17: + 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" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -queue-microtask@^1.2.3: +queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +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" + +raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" @@ -1002,66 +2123,85 @@ readable-stream@^3.6.0: 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" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: - lodash "^4.13.1" + picomatch "^2.2.1" -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" - dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - -request@^2.83.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - 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 sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -ripemd160@^2.0.1: +require-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +rimraf@^2.2.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +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.0.1, safe-buffer@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" +rlp@^2.2.3: + 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" + +run-parallel-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" + integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== + dependencies: + queue-microtask "^1.2.2" -safe-buffer@~5.2.0: +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +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.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== -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +safe-buffer@~5.1.1: + 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": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -secp256k1@4.0.3: +scrypt-js@3.0.1, scrypt-js@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +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== @@ -1070,51 +2210,89 @@ secp256k1@4.0.3: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -set-function-length@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== +semver@^5.5.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: - define-data-property "^1.1.1" - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" + randombytes "^2.1.0" 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== -sol-merger@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/sol-merger/-/sol-merger-4.4.0.tgz#d637cb50d1553dde1f9fb19833bf6ea01ba2da11" - integrity sha512-eYlgsVAeTPiIpLwRCnu8vdhAI40mt8I9BAnwdHazF+8ggWd0EuucQYxs4v+GyjC/5cmCfPMJ55T37tgk/zXqSg== - dependencies: - antlr4ts "^0.5.0-alpha.4" - cli-color "^2.0.3" - commander "^4.0.1" - debug "^4.3.4" - fs-extra "^10.0.0" - glob "^7.1.7" - strip-json-comments "^3.0.1" - -sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - 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" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -stealthy-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + 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" + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +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== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +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== + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" string_decoder@^1.1.1: version "1.3.0" @@ -1123,358 +2301,227 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -strip-json-comments@^3.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +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" + +strip-json-comments@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -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== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: - es5-ext "~0.10.46" - next-tick "1" + has-flag "^4.0.0" -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" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - psl "^1.1.24" - punycode "^1.4.1" + has-flag "^3.0.0" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: - safe-buffer "^5.0.1" + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +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== -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw== + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== type-detect@^4.0.0, type-detect@^4.0.8: 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@^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-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type@^2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" - integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -utf-8-validate@5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.7.tgz#c15a19a6af1f7ad9ec7ddc425747ca28c3644922" - integrity sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q== +undici@^5.14.0: + version "5.28.2" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.2.tgz#fea200eac65fc7ecaff80a023d1a0543423b4c91" + integrity sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w== dependencies: - node-gyp-build "^4.3.0" + "@fastify/busboy" "^2.0.0" -utf-8-validate@6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.3.tgz#7d8c936d854e86b24d1d655f138ee27d2636d777" - integrity sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA== - dependencies: - node-gyp-build "^4.3.0" +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 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.5: - 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" +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -web3-core@^4.3.0, web3-core@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-4.3.1.tgz#5c3b5b59f1e31537a64237caa5fd83f5ffd7b0f3" - integrity sha512-xa3w5n/ESxp5HIbrwsYBhpAPx2KI5LprjRFEtRwP0GpqqhTcCSMMYoyItRqQQ+k9YnB0PoFpWJfJI6Qn5x8YUQ== - dependencies: - web3-errors "^1.1.4" - web3-eth-iban "^4.0.7" - web3-providers-http "^4.1.0" - web3-providers-ws "^4.0.7" - web3-types "^1.3.1" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - optionalDependencies: - web3-providers-ipc "^4.0.7" +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -web3-errors@^1.1.3, web3-errors@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.1.4.tgz#5667a0a5f66fc936e101ef32032ccc1e8ca4d5a1" - integrity sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ== +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: - web3-types "^1.3.1" + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" -web3-eth-abi@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-4.1.4.tgz#56ae7ebb1385db1a948e69fb35f4057bff6743af" - integrity sha512-YLOBVVxxxLYKXjaiwZjEWYEnkMmmrm0nswZsvzSsINy/UgbWbzfoiZU+zn4YNWIEhORhx1p37iS3u/dP6VyC2w== - dependencies: - abitype "0.7.1" - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -web3-eth-accounts@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-4.1.0.tgz#5b5e6c60d457e7b829ec590021fc87ada8585920" - integrity sha512-UFtAsOANsvihTQ6SSvOKguupmQkResyR9M9JNuOxYpKh7+3W+sTnbLXw2UbOSYIsKlc1mpqqW9bVr1SjqHDpUQ== - dependencies: - "@ethereumjs/rlp" "^4.0.1" - crc-32 "^1.2.2" - ethereum-cryptography "^2.0.0" - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-eth-contract@^4.1.2, web3-eth-contract@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-4.1.3.tgz#15dd4c978eaf0d8f894b2c1f3e9f94edd29ff57c" - integrity sha512-F6e3eyetUDiNOb78EDVJtNOb0H1GPz3xAZH8edSfYdhaxI9tTutP2V3p++kh2ZJ/RrdE2+xil7H/nPLgHymBvg== - dependencies: - web3-core "^4.3.1" - web3-errors "^1.1.4" - web3-eth "^4.3.1" - web3-eth-abi "^4.1.4" - web3-types "^1.3.1" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-eth-ens@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-4.0.8.tgz#f4e0a018ce6cc69e37007ee92063867feb5994f0" - integrity sha512-nj0JfeD45BbzVJcVYpUJnSo8iwDcY9CQ7CZhhIVVOFjvpMAPw0zEwjTvZEIQyCW61OoDG9xcBzwxe2tZoYhMRw== - dependencies: - "@adraffy/ens-normalize" "^1.8.8" - web3-core "^4.3.0" - web3-errors "^1.1.3" - web3-eth "^4.3.1" - web3-eth-contract "^4.1.2" - web3-net "^4.0.7" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-eth-iban@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz#ee504f845d7b6315f0be78fcf070ccd5d38e4aaf" - integrity sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ== - dependencies: - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-eth-personal@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-4.0.8.tgz#b51628c560de550ca8b354fa784f9556aae6065c" - integrity sha512-sXeyLKJ7ddQdMxz1BZkAwImjqh7OmKxhXoBNF3isDmD4QDpMIwv/t237S3q4Z0sZQamPa/pHebJRWVuvP8jZdw== - dependencies: - web3-core "^4.3.0" - web3-eth "^4.3.1" - web3-rpc-methods "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -web3-eth@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-4.3.1.tgz#cb4224356716da71e694091aa3fbf10bcb813fb5" - integrity sha512-zJir3GOXooHQT85JB8SrufE+Voo5TtXdjhf1D8IGXmxM8MrhI8AT+Pgt4siBTupJcu5hF17iGmTP/Nj2XnaibQ== - dependencies: - setimmediate "^1.0.5" - web3-core "^4.3.0" - web3-errors "^1.1.3" - web3-eth-abi "^4.1.4" - web3-eth-accounts "^4.1.0" - web3-net "^4.0.7" - web3-providers-ws "^4.0.7" - web3-rpc-methods "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -web3-net@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-4.0.7.tgz#ed2c1bd700cf94be93a6dbd8bd8aa413d8681942" - integrity sha512-SzEaXFrBjY25iQGk5myaOfO9ZyfTwQEa4l4Ps4HDNVMibgZji3WPzpjq8zomVHMwi8bRp6VV7YS71eEsX7zLow== - dependencies: - web3-core "^4.3.0" - web3-rpc-methods "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - -web3-providers-http@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-4.1.0.tgz#8d7afda67d1d8542ca85b30f60a3d1fe1993b561" - integrity sha512-6qRUGAhJfVQM41E5t+re5IHYmb5hSaLc02BE2MaRQsz2xKA6RjmHpOA5h/+ojJxEpI9NI2CrfDKOAgtJfoUJQg== - dependencies: - cross-fetch "^4.0.0" - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - -web3-providers-ipc@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz#9ec4c8565053af005a5170ba80cddeb40ff3e3d3" - integrity sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g== - dependencies: - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - -web3-providers-ws@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-4.0.7.tgz#7a78a0dcf077e0e802da524fbb37d080b356c14b" - integrity sha512-n4Dal9/rQWjS7d6LjyEPM2R458V8blRm0eLJupDEJOOIBhGYlxw5/4FthZZ/cqB7y/sLVi7K09DdYx2MeRtU5w== - dependencies: - "@types/ws" "8.5.3" - isomorphic-ws "^5.0.0" - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-utils "^4.0.7" - ws "^8.8.1" - -web3-rpc-methods@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/web3-rpc-methods/-/web3-rpc-methods-1.1.3.tgz#4be8a85628d8b69846e2e0afa0ed71e3f6eaf163" - integrity sha512-XB6SsCZZPdZUMPIRqDxJkZFKMu0/Y+yaExAt+Z7RqmuM7xF55fJ/Qb84LQho8zarvUoYziy4jnIfs+SXImxQUw== - dependencies: - web3-core "^4.3.0" - web3-types "^1.3.0" - web3-validator "^2.0.3" +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== -web3-types@^1.3.0, web3-types@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.3.1.tgz#cf6148ad46b68c5c89714613380b270d31e297be" - integrity sha512-8fXi7h/t95VKRtgU4sxprLPZpsTh3jYDfSghshIDBgUD/OoGe5S+syP24SUzBZYllZ/L+hMr2gdp/0bGJa8pYQ== - -web3-utils@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.0.7.tgz#7df497b7cdd06cdfe7d02036c45fecbe3382d137" - integrity sha512-sy8S6C2FIa5NNHc8DjND+Fx3S8KDAizuh5RbL1RX3h0PRbFgPfWzF5RfUns8gTt0mjJuOhs/IaDhrZfeTszG5A== - dependencies: - ethereum-cryptography "^2.0.0" - web3-errors "^1.1.3" - web3-types "^1.3.0" - web3-validator "^2.0.3" - -web3-validator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.3.tgz#e5dcd4b4902612cff21b7f8817dd233393999d97" - integrity sha512-fJbAQh+9LSNWy+l5Ze6HABreml8fra98o5+vS073T35jUcLbRZ0IOjF/ZPJhJNbJDt+jP1vseZsc3z3uX9mxxQ== - dependencies: - ethereum-cryptography "^2.0.0" - util "^0.12.5" - web3-errors "^1.1.3" - web3-types "^1.3.0" - zod "^3.21.4" - -web3@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/web3/-/web3-4.2.2.tgz#3562e0b918a95adb0798945624e8e9377c699fdb" - integrity sha512-im7weoHY7TW87nhFk10ysupZnsDJEO/xDpz985AgrTd/7KxExlzjjKd+4nue0WskUF0th0mgoMs1YaA8xUjCjw== - dependencies: - web3-core "^4.3.1" - web3-errors "^1.1.4" - web3-eth "^4.3.1" - web3-eth-abi "^4.1.4" - web3-eth-accounts "^4.1.0" - web3-eth-contract "^4.1.3" - web3-eth-ens "^4.0.8" - web3-eth-iban "^4.0.7" - web3-eth-personal "^4.0.8" - web3-net "^4.0.7" - web3-providers-http "^4.1.0" - web3-providers-ws "^4.0.7" - web3-rpc-methods "^1.1.3" - web3-types "^1.3.1" - web3-utils "^4.0.7" - web3-validator "^2.0.3" - -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== +ws@^7.4.6: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -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" +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -which-typed-array@^1.1.11, which-typed-array@^1.1.2: - version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -ws@8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@^8.8.1: - version "8.14.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" - integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== - -zod@^3.21.4: - version "3.22.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" - integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 124445a6f1cd61892bdcaa3cec786eee91b7e5f5 Mon Sep 17 00:00:00 2001 From: Artem Vitae <15745003+artemii235@users.noreply.github.com> Date: Wed, 28 Feb 2024 03:30:18 +0700 Subject: [PATCH 3/4] feat(trading-proto-upgrade): PoC (#6) This Implements EtomicSwapV2 contract containing functions needed to support Trading Protocol Upgrade V2. --- contracts/EtomicSwapV2.sol | 485 +++++++++++++ package.json | 6 +- test/EtomicSwap.js | 1 - test/EtomicSwapV2.js | 1369 ++++++++++++++++++++++++++++++++++++ 4 files changed, 1856 insertions(+), 5 deletions(-) create mode 100644 contracts/EtomicSwapV2.sol create mode 100644 test/EtomicSwapV2.js diff --git a/contracts/EtomicSwapV2.sol b/contracts/EtomicSwapV2.sol new file mode 100644 index 0000000..86e8ac8 --- /dev/null +++ b/contracts/EtomicSwapV2.sol @@ -0,0 +1,485 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract EtomicSwapV2 { + using SafeERC20 for IERC20; + + enum MakerPaymentState { + Uninitialized, + PaymentSent, + TakerSpent, + MakerRefunded + } + + struct MakerPayment { + bytes20 paymentHash; + uint32 paymentLockTime; + MakerPaymentState state; + } + + event MakerPaymentSent(bytes32 id); + event MakerPaymentSpent(bytes32 id); + event MakerPaymentRefundedTimelock(bytes32 id); + event MakerPaymentRefundedSecret(bytes32 id); + + mapping(bytes32 => MakerPayment) public makerPayments; + + enum TakerPaymentState { + Uninitialized, + PaymentSent, + TakerApproved, + MakerSpent, + TakerRefunded + } + + struct TakerPayment { + bytes20 paymentHash; + uint32 preApproveLockTime; + uint32 paymentLockTime; + TakerPaymentState state; + } + + event TakerPaymentSent(bytes32 id); + event TakerPaymentApproved(bytes32 id); + event TakerPaymentSpent(bytes32 id, bytes32 secret); + event TakerPaymentRefundedSecret(bytes32 id, bytes32 secret); + event TakerPaymentRefundedTimelock(bytes32 id); + + mapping(bytes32 => TakerPayment) public takerPayments; + + address public immutable dexFeeAddress; + + constructor(address feeAddress) { + require(feeAddress != address(0), "feeAddress must not be zero address"); + + dexFeeAddress = feeAddress; + } + + function ethMakerPayment( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 paymentLockTime + ) external payable { + require(makerPayments[id].state == MakerPaymentState.Uninitialized, "Maker payment is already initialized"); + require(taker != address(0), "Taker must not be zero address"); + require(msg.value > 0, "ETH value must be greater than zero"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.value, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + address(0) + ) + ); + + makerPayments[id] = MakerPayment(paymentHash, paymentLockTime, MakerPaymentState.PaymentSent); + + emit MakerPaymentSent(id); + } + + function erc20MakerPayment( + bytes32 id, + uint256 amount, + address tokenAddress, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 paymentLockTime + ) external { + require(makerPayments[id].state == MakerPaymentState.Uninitialized, "Maker payment is already initialized"); + require(amount > 0, "Amount must not be zero"); + require(taker != address(0), "Taker must not be zero address"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + makerPayments[id] = MakerPayment(paymentHash, paymentLockTime, MakerPaymentState.PaymentSent); + + emit MakerPaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + token.safeTransferFrom(msg.sender, address(this), amount); + } + + function spendMakerPayment( + bytes32 id, + uint256 amount, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress + ) external { + require(makerPayments[id].state == MakerPaymentState.PaymentSent, "Invalid payment state. Must be PaymentSent"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress + ) + ); + require(paymentHash == makerPayments[id].paymentHash, "Invalid paymentHash"); + + makerPayments[id].state = MakerPaymentState.TakerSpent; + + emit MakerPaymentSpent(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } + + function refundMakerPaymentTimelock( + bytes32 id, + uint256 amount, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } + + function refundMakerPaymentSecret( + bytes32 id, + uint256 amount, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } + + function ethTakerPayment( + bytes32 id, + uint256 dexFee, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external payable { + require(takerPayments[id].state == TakerPaymentState.Uninitialized, "Taker payment is already initialized"); + require(receiver != address(0), "Receiver must not be zero address"); + require(msg.value > 0, "ETH value must be greater than zero"); + require(msg.value > dexFee, "ETH value must be greater than dex fee"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.value - dexFee, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + address(0) + ) + ); + + takerPayments[id] = TakerPayment(paymentHash, preApproveLockTime, paymentLockTime, TakerPaymentState.PaymentSent); + + emit TakerPaymentSent(id); + } + + function erc20TakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address tokenAddress, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external { + require(takerPayments[id].state == TakerPaymentState.Uninitialized, "ERC20 v2 payment is already initialized"); + require(amount > 0, "Amount must not be zero"); + require(dexFee > 0, "Dex fee must not be zero"); + require(receiver != address(0), "Receiver must not be zero address"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + takerPayments[id] = TakerPayment(paymentHash, preApproveLockTime, paymentLockTime, TakerPaymentState.PaymentSent); + + emit TakerPaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + token.safeTransferFrom(msg.sender, address(this), amount + dexFee); + } + + function takerPaymentApprove( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerApproved; + + emit TakerPaymentApproved(id); + } + + function spendTakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress + ) external { + require(takerPayments[id].state == TakerPaymentState.TakerApproved, "Invalid payment state. Must be TakerApproved"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + msg.sender, + taker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress + ) + ); + require(paymentHash == takerPayments[id].paymentHash, "Invalid paymentHash"); + + takerPayments[id].state = TakerPaymentState.MakerSpent; + + emit TakerPaymentSpent(id, makerSecret); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + payable(dexFeeAddress).transfer(dexFee); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + token.safeTransfer(dexFeeAddress, dexFee); + } + } + + function refundTakerPaymentTimelock( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent || takerPayments[id].state == TakerPaymentState.TakerApproved, + "Invalid payment state. Must be PaymentSent or TakerApproved" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + if (takerPayments[id].state == TakerPaymentState.TakerApproved) { + require( + block.timestamp >= takerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + } + + if (takerPayments[id].state == TakerPaymentState.PaymentSent) { + require( + block.timestamp >= takerPayments[id].preApproveLockTime, + "Current timestamp didn't exceed payment pre-approve lock time" + ); + } + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedTimelock(id); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } + + function refundTakerPaymentSecret( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedSecret(id, takerSecret); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } +} diff --git a/package.json b/package.json index 2816f2b..a02d4e8 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,10 @@ { "name": "ETOMIC_SWAP", "version": "1.0.0", - "description": "Etomic swap smart contract and helpers", + "description": "Etomic swap smart contracts and helpers", "main": "index.js", "scripts": { - "test": "npx hardhat test", - "clean": "rm -rf merge", - "merge": "node node_modules/sol-merger/bin/sol-merger.js './contracts/*.sol' ./merge" + "test": "npx hardhat test" }, "author": "ortgma@gmail.com", "license": "ISC", diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index c34469e..8673bd4 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -57,7 +57,6 @@ describe("EtomicSwap", function() { beforeEach(async function() { accounts = await ethers.getSigners(); - EtomicSwap = await ethers.getContractFactory("EtomicSwap"); etomicSwap = await EtomicSwap.deploy(); etomicSwap.waitForDeployment(); diff --git a/test/EtomicSwapV2.js b/test/EtomicSwapV2.js new file mode 100644 index 0000000..e1dee14 --- /dev/null +++ b/test/EtomicSwapV2.js @@ -0,0 +1,1369 @@ +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); +const crypto = require('crypto'); +const RIPEMD160 = require('ripemd160'); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE_SENT = 'Invalid payment state. Must be PaymentSent'; +const INVALID_PAYMENT_STATE_APPROVED = 'Invalid payment state. Must be TakerApproved'; +const REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment refund lock time'; +const PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment pre-approve lock time'; + +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); +} + +async function currentEvmTime() { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +} + +const id = '0x' + crypto.randomBytes(32).toString('hex'); +const [TAKER_PAYMENT_UNINITIALIZED, TAKER_PAYMENT_SENT, TAKER_PAYMENT_APPROVED, MAKER_SPENT, TAKER_REFUNDED] = [0, 1, 2, 3, 4]; +const [MAKER_PAYMENT_UNINITIALIZED, MAKER_PAYMENT_SENT, TAKER_SPENT, MAKER_REFUNDED] = [0, 1, 2, 3]; + +const takerSecret = crypto.randomBytes(32); +const takerSecretHash = '0x' + crypto.createHash('sha256').update(takerSecret).digest('hex'); + +const makerSecret = crypto.randomBytes(32); +const makerSecretHash = '0x' + crypto.createHash('sha256').update(makerSecret).digest('hex'); + +const invalidSecret = crypto.randomBytes(32); + +const zeroAddr = '0x0000000000000000000000000000000000000000'; +const dexFeeAddr = '0x7777777777777777777777777777777777777777'; + +describe("EtomicSwapV2", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + + EtomicSwapV2 = await ethers.getContractFactory("EtomicSwapV2"); + etomicSwapV2 = await EtomicSwapV2.deploy(dexFeeAddr); + await etomicSwapV2.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + await token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); + }); + + it('should create contract with uninitialized payments', async function() { + const takerPayment = await etomicSwapV2.takerPayments(id); + expect(Number(takerPayment[3])).to.equal(TAKER_PAYMENT_UNINITIALIZED); + + const makerPayment = await etomicSwapV2.makerPayments(id); + expect(Number(makerPayment[2])).to.equal(MAKER_PAYMENT_UNINITIALIZED); + }); + + it('should allow maker to send ETH payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapV2.connect(accounts[0]).ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const payment = await etomicSwapV2.makerPayments(id); + + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Check that it should not allow to send again + await etomicSwapV2.connect(accounts[0]).ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("Maker payment is already initialized"); + }); + + it('should allow maker to send ERC20 payment', async function() { + const currentTime = await currentEvmTime(); + + const paymentLockTime = currentTime + 100; + + const payment_params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20MakerPayment(...payment_params).should.be.fulfilled; + + // Check contract token balance + const balance = await token.balanceOf(etomicSwapV2.target); + expect(balance).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapV2.makerPayments(id); + + // Check locktime and status + expect(payment[1]).to.equal(BigInt(paymentLockTime)); + expect(payment[2]).to.equal(BigInt(MAKER_PAYMENT_SENT)); + + // Should not allow to send payment again + await etomicSwapRunner0.erc20MakerPayment(...payment_params).should.be.rejectedWith("Maker payment is already initialized"); + }); + + it('should allow taker to spend ETH maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + + const makerSwapRunner = etomicSwapV2.connect(accounts[0]); + const takerSwapRunner = etomicSwapV2.connect(accounts[1]); + + // Make the ETH payment + await makerSwapRunner.ethMakerPayment(...payment_params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const spendParamsInvalidSecret = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + invalidSecret, + zeroAddr, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParamsInvalidAmount = [ + id, + ethers.parseEther('0.9'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidAmount).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + // should not allow to spend from non-taker address + await etomicSwapV2.connect(accounts[2]).spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const spendTx = await takerSwapRunner.spendMakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const spendReceipt = await spendTx.wait(); + const gasUsed = ethers.parseUnits(spendReceipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapV2.makerPayments(id); + + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // should not allow to spend again + await takerSwapRunner.spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to spend ERC20 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, // taker + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + + const makerSwapRunner = etomicSwapV2.connect(accounts[0]); + const takerSwapRunner = etomicSwapV2.connect(accounts[1]); + + // Make the ERC20 payment + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + await makerSwapRunner.erc20MakerPayment(...payment_params).should.be.fulfilled; + + const contractBalance = await token.balanceOf(etomicSwapV2.target); + expect(contractBalance).to.equal(ethers.parseEther('1')); + + const spendParamsInvalidSecret = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + invalidSecret, + token.target, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParamsInvalidAmount = [ + id, + ethers.parseEther('0.9'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidAmount).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + ethers.parseEther('1'), + accounts[0].address, // maker + takerSecretHash, + makerSecret, + token.target, + ]; + + // should not allow to spend from non-taker address + await etomicSwapV2.connect(accounts[2]).spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await token.balanceOf(accounts[1].address); + + const gasPrice = ethers.parseUnits('100', 'gwei'); + await takerSwapRunner.spendMakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check taker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapV2.makerPayments(id); + + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // should not allow to spend again + await takerSwapRunner.spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ETH payment after locktime', async function() { + const lockTime = (await ethers.provider.getBlock('latest')).timestamp + 1000; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams) + .should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to refund before locktime + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + let invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + await etomicSwapRunner0.refundMakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC20 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20MakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check maker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ETH payment using taker secret', async function() { + const lockTime = (await ethers.provider.getBlock('latest')).timestamp + 1000; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams) + .should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + let invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + await etomicSwapRunner0.refundMakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC20 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20MakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check maker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to send ETH payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const params = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapV2.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const payment = await etomicSwapV2.takerPayments(id); + + expect(Number(payment[1])).to.equal(immediateRefundLockTime); + expect(Number(payment[2])).to.equal(paymentLockTime); + expect(Number(payment[3])).to.equal(TAKER_PAYMENT_SENT); + + // Check that it should not allow to send again + await etomicSwapV2.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("Taker payment is already initialized"); + }); + + it('should allow taker to send ERC20 payment', async function() { + const currentTime = await currentEvmTime(); + + const immediateRefundLockTime = currentTime + 10; + const paymentLockTime = currentTime + 100; + + const payment_params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20TakerPayment(...payment_params).should.be.fulfilled; + + // Check contract token balance + const balance = await token.balanceOf(etomicSwapV2.target); + expect(balance).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapV2.takerPayments(id); + + // Check locktime and status + expect(payment[1]).to.equal(BigInt(immediateRefundLockTime)); + expect(payment[2]).to.equal(BigInt(paymentLockTime)); + expect(payment[3]).to.equal(BigInt(TAKER_PAYMENT_SENT)); + + // Should not allow to send payment again + await etomicSwapRunner0.erc20TakerPayment(...payment_params).should.be.rejectedWith("ERC20 v2 payment is already initialized"); + }); + + it('should allow maker to spend ETH taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapV2.connect(accounts[0]).ethTakerPayment(...payment_params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const spendParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + // should not allow to spend before payment is approved by taker + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapV2.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapV2.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const spendTx = await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const spendReceipt = await spendTx.wait(); + const gasUsed = ethers.parseUnits(spendReceipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await ethers.provider.getBalance(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapV2.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow maker to spend ERC20 taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + token.target, + accounts[1].address, // receiver + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + + // Make the ERC20 payment + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + await etomicSwapV2.connect(accounts[0]).erc20TakerPayment(...payment_params).should.be.fulfilled; + + const contractBalance = await token.balanceOf(etomicSwapV2.target); + expect(contractBalance).to.equal(ethers.parseEther('1')); + + const spendParams = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, // tokenAddress + ]; + + // should not allow to spend before taker's approval + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapV2.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapV2.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await token.balanceOf(accounts[1].address); + + const gasPrice = ethers.parseUnits('100', 'gwei'); + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await token.balanceOf(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapV2.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow taker to refund approved ETH payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + // Not allow to refund before locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ETH payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + await advanceTimeAndMine(2000); + + // Not allow to refund before pre-approve locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(3000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund approved ERC20 payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapV2.connect(accounts[1]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ERC20 payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapV2.connect(accounts[1]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await advanceTimeAndMine(2000); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ETH payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ERC20 payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapV2.connect(accounts[1]); + + await token.approve(etomicSwapV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); +}); \ No newline at end of file From 5e15641cbf41766cd5b37b4d71842c270773f788 Mon Sep 17 00:00:00 2001 From: Alina Sharon <52405288+laruh@users.noreply.github.com> Date: Wed, 8 May 2024 21:19:17 +0700 Subject: [PATCH 4/4] feat(nft-swap): nft swap PoC and multi standalone swap contracts v2 (#7) --- contracts/EtomicSwapMakerNftV2.sol | 415 +++++++++ contracts/EtomicSwapMakerV2.sol | 230 +++++ contracts/EtomicSwapNft.sol | 720 +++++++++++++++ contracts/EtomicSwapTakerV2.sol | 310 +++++++ docker-compose.yml | 2 + hardhat.config.js | 4 +- test/EtomicSwap.js | 8 +- test/EtomicSwapMakerNftV2Test.js | 487 +++++++++++ test/EtomicSwapMakerV2Test.js | 551 ++++++++++++ test/EtomicSwapNft.js | 1300 ++++++++++++++++++++++++++++ test/EtomicSwapTakerV2Test.js | 885 +++++++++++++++++++ 11 files changed, 4907 insertions(+), 5 deletions(-) create mode 100644 contracts/EtomicSwapMakerNftV2.sol create mode 100644 contracts/EtomicSwapMakerV2.sol create mode 100644 contracts/EtomicSwapNft.sol create mode 100644 contracts/EtomicSwapTakerV2.sol create mode 100644 test/EtomicSwapMakerNftV2Test.js create mode 100644 test/EtomicSwapMakerV2Test.js create mode 100644 test/EtomicSwapNft.js create mode 100644 test/EtomicSwapTakerV2Test.js diff --git a/contracts/EtomicSwapMakerNftV2.sol b/contracts/EtomicSwapMakerNftV2.sol new file mode 100644 index 0000000..e19ff33 --- /dev/null +++ b/contracts/EtomicSwapMakerNftV2.sol @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +contract EtomicSwapMakerNftV2 is ERC165, IERC1155Receiver, IERC721Receiver { + enum MakerPaymentState { + Uninitialized, + PaymentSent, + TakerSpent, + MakerRefunded + } + + struct MakerPayment { + bytes20 paymentHash; + uint32 paymentLockTime; + MakerPaymentState state; + } + + event MakerPaymentSent(bytes32 id); + event MakerPaymentSpent(bytes32 id); + event MakerPaymentRefundedTimelock(bytes32 id); + event MakerPaymentRefundedSecret(bytes32 id); + + mapping(bytes32 => MakerPayment) public makerPayments; + + function spendErc721MakerPayment( + bytes32 id, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress, + tokenId + ) + ); + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + // Effects + makerPayments[id].state = MakerPaymentState.TakerSpent; + + // Event Emission + emit MakerPaymentSpent(id); + + // Interactions + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function spendErc1155MakerPayment( + bytes32 id, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress, + tokenId, + amount + ) + ); + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + // Effects + makerPayments[id].state = MakerPaymentState.TakerSpent; + + // Event Emission + emit MakerPaymentSpent(id); + + // Interactions + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function refundErc721MakerPaymentTimelock( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress, + tokenId + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function refundErc1155MakerPaymentTimelock( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress, + tokenId, + amount + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + // Interactions + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function refundErc721MakerPaymentSecret( + bytes32 id, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress, + tokenId + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function refundErc1155MakerPaymentSecret( + bytes32 id, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress, + tokenId, + amount + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + struct HTLCParams { + bytes32 id; + address taker; + address tokenAddress; + bytes32 takerSecretHash; + bytes32 makerSecretHash; + uint32 paymentLockTime; + } + + function onERC1155Received( + address operator, + address from, + uint256 tokenId, + uint256 value, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + HTLCParams memory params = abi.decode(data, (HTLCParams)); + + require( + makerPayments[params.id].state == MakerPaymentState.Uninitialized, + "Maker ERC1155 payment must be Uninitialized" + ); + require(params.taker != address(0), "Taker must not be zero address"); + require( + params.tokenAddress != address(0), + "Token must not be zero address" + ); + require( + msg.sender == params.tokenAddress, + "Token address does not match sender" + ); + require(operator == from, "Operator must be the sender"); + require(value > 0, "Value must be greater than 0"); + require(!isContract(params.taker), "Taker cannot be a contract"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + params.taker, + from, + params.takerSecretHash, + params.makerSecretHash, + params.tokenAddress, + tokenId, + value + ) + ); + + makerPayments[params.id] = MakerPayment( + paymentHash, + params.paymentLockTime, + MakerPaymentState.PaymentSent + ); + emit MakerPaymentSent(params.id); + + // Return this magic value to confirm receipt of ERC1155 token + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, /* operator */ + address, /* from */ + uint256[] calldata, /* ids */ + uint256[] calldata, /* values */ + bytes calldata /* data */ + ) external pure override returns (bytes4) { + revert("Batch transfers not supported"); + } + + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC165, IERC165) + returns (bool) + { + return + interfaceId == type(IERC1155Receiver).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + super.supportsInterface(interfaceId); + } + + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + HTLCParams memory params = abi.decode(data, (HTLCParams)); + + require( + makerPayments[params.id].state == MakerPaymentState.Uninitialized, + "Maker ERC721 payment must be Uninitialized" + ); + require(params.taker != address(0), "Taker must not be zero address"); + require( + params.tokenAddress != address(0), + "Token must not be zero address" + ); + require( + msg.sender == params.tokenAddress, + "Token address does not match sender" + ); + require(operator == from, "Operator must be the sender"); + require(!isContract(params.taker), "Taker cannot be a contract"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + params.taker, + from, + params.takerSecretHash, + params.makerSecretHash, + params.tokenAddress, + tokenId + ) + ); + + makerPayments[params.id] = MakerPayment( + paymentHash, + params.paymentLockTime, + MakerPaymentState.PaymentSent + ); + emit MakerPaymentSent(params.id); + + // Return this magic value to confirm receipt of ERC721 token + return this.onERC721Received.selector; + } + + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } +} diff --git a/contracts/EtomicSwapMakerV2.sol b/contracts/EtomicSwapMakerV2.sol new file mode 100644 index 0000000..4b9755a --- /dev/null +++ b/contracts/EtomicSwapMakerV2.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract EtomicSwapMakerV2 { + using SafeERC20 for IERC20; + + enum MakerPaymentState { + Uninitialized, + PaymentSent, + TakerSpent, + MakerRefunded + } + + struct MakerPayment { + bytes20 paymentHash; + uint32 paymentLockTime; + MakerPaymentState state; + } + + event MakerPaymentSent(bytes32 id); + event MakerPaymentSpent(bytes32 id); + event MakerPaymentRefundedTimelock(bytes32 id); + event MakerPaymentRefundedSecret(bytes32 id); + + mapping(bytes32 => MakerPayment) public makerPayments; + + function ethMakerPayment( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 paymentLockTime + ) external payable { + require( + makerPayments[id].state == MakerPaymentState.Uninitialized, + "Maker payment is already initialized" + ); + require(taker != address(0), "Taker must not be zero address"); + require(msg.value > 0, "ETH value must be greater than zero"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.value, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + address(0) + ) + ); + + makerPayments[id] = MakerPayment( + paymentHash, + paymentLockTime, + MakerPaymentState.PaymentSent + ); + + emit MakerPaymentSent(id); + } + + function erc20MakerPayment( + bytes32 id, + uint256 amount, + address tokenAddress, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 paymentLockTime + ) external { + require( + makerPayments[id].state == MakerPaymentState.Uninitialized, + "Maker payment is already initialized" + ); + require(amount > 0, "Amount must not be zero"); + require(taker != address(0), "Taker must not be zero address"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + makerPayments[id] = MakerPayment( + paymentHash, + paymentLockTime, + MakerPaymentState.PaymentSent + ); + + emit MakerPaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + token.safeTransferFrom(msg.sender, address(this), amount); + } + + function spendMakerPayment( + bytes32 id, + uint256 amount, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress + ) + ); + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.TakerSpent; + + emit MakerPaymentSpent(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } + + function refundMakerPaymentTimelock( + bytes32 id, + uint256 amount, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } + + function refundMakerPaymentSecret( + bytes32 id, + uint256 amount, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + } + } +} diff --git a/contracts/EtomicSwapNft.sol b/contracts/EtomicSwapNft.sol new file mode 100644 index 0000000..2229ddd --- /dev/null +++ b/contracts/EtomicSwapNft.sol @@ -0,0 +1,720 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +contract EtomicSwapNft is ERC165, IERC1155Receiver, IERC721Receiver { + using SafeERC20 for IERC20; + + enum MakerPaymentState { + Uninitialized, + PaymentSent, + TakerSpent, + MakerRefunded + } + + struct MakerPayment { + bytes20 paymentHash; + uint32 paymentLockTime; + MakerPaymentState state; + } + + event MakerPaymentSent(bytes32 id); + event MakerPaymentSpent(bytes32 id); + event MakerPaymentRefundedTimelock(bytes32 id); + event MakerPaymentRefundedSecret(bytes32 id); + + mapping(bytes32 => MakerPayment) public makerPayments; + + enum TakerPaymentState { + Uninitialized, + PaymentSent, + TakerApproved, + MakerSpent, + TakerRefunded + } + + struct TakerPayment { + bytes20 paymentHash; + uint32 preApproveLockTime; + uint32 paymentLockTime; + TakerPaymentState state; + } + + event TakerPaymentSent(bytes32 id); + event TakerPaymentApproved(bytes32 id); + event TakerPaymentSpent(bytes32 id, bytes32 secret); + event TakerPaymentRefundedSecret(bytes32 id, bytes32 secret); + event TakerPaymentRefundedTimelock(bytes32 id); + + mapping(bytes32 => TakerPayment) public takerPayments; + + address public immutable dexFeeAddress; + + constructor(address feeAddress) { + require( + feeAddress != address(0), + "feeAddress must not be zero address" + ); + + dexFeeAddress = feeAddress; + } + + function spendErc721MakerPayment( + bytes32 id, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress, + tokenId + ) + ); + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + // Effects + makerPayments[id].state = MakerPaymentState.TakerSpent; + + // Event Emission + emit MakerPaymentSpent(id); + + // Interactions + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function spendErc1155MakerPayment( + bytes32 id, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + // Check if the function caller is an externally owned account (EOA) + require(msg.sender == tx.origin, "Caller must be an EOA"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.sender, + maker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress, + tokenId, + amount + ) + ); + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + // Effects + makerPayments[id].state = MakerPaymentState.TakerSpent; + + // Event Emission + emit MakerPaymentSpent(id); + + // Interactions + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function refundErc721MakerPaymentTimelock( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress, + tokenId + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function refundErc1155MakerPaymentTimelock( + bytes32 id, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress, + tokenId, + amount + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + require( + block.timestamp >= makerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedTimelock(id); + + // Interactions + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function refundErc721MakerPaymentSecret( + bytes32 id, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress, + tokenId + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + IERC721 token = IERC721(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId); + } + + function refundErc1155MakerPaymentSecret( + bytes32 id, + address taker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress, + uint256 tokenId, + uint256 amount + ) external { + require( + makerPayments[id].state == MakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + taker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress, + tokenId, + amount + ) + ); + + require( + paymentHash == makerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + makerPayments[id].state = MakerPaymentState.MakerRefunded; + + emit MakerPaymentRefundedSecret(id); + + IERC1155 token = IERC1155(tokenAddress); + token.safeTransferFrom(address(this), msg.sender, tokenId, amount, ""); + } + + function ethTakerPayment( + bytes32 id, + uint256 dexFee, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external payable { + require( + takerPayments[id].state == TakerPaymentState.Uninitialized, + "Taker payment is already initialized" + ); + require(receiver != address(0), "Receiver must not be zero address"); + require(msg.value > 0, "ETH value must be greater than zero"); + require(msg.value > dexFee, "ETH value must be greater than dex fee"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.value - dexFee, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + address(0) + ) + ); + + takerPayments[id] = TakerPayment( + paymentHash, + preApproveLockTime, + paymentLockTime, + TakerPaymentState.PaymentSent + ); + + emit TakerPaymentSent(id); + } + + function erc20TakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address tokenAddress, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external { + require( + takerPayments[id].state == TakerPaymentState.Uninitialized, + "ERC20 v2 payment is already initialized" + ); + require(amount > 0, "Amount must not be zero"); + require(dexFee > 0, "Dex fee must not be zero"); + require(receiver != address(0), "Receiver must not be zero address"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + takerPayments[id] = TakerPayment( + paymentHash, + preApproveLockTime, + paymentLockTime, + TakerPaymentState.PaymentSent + ); + + emit TakerPaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + token.safeTransferFrom(msg.sender, address(this), amount + dexFee); + } + + function takerPaymentApprove( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerApproved; + + emit TakerPaymentApproved(id); + } + + function spendTakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.TakerApproved, + "Invalid payment state. Must be TakerApproved" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + msg.sender, + taker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress + ) + ); + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.MakerSpent; + + emit TakerPaymentSpent(id, makerSecret); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + payable(dexFeeAddress).transfer(dexFee); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + token.safeTransfer(dexFeeAddress, dexFee); + } + } + + function refundTakerPaymentTimelock( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent || + takerPayments[id].state == TakerPaymentState.TakerApproved, + "Invalid payment state. Must be PaymentSent or TakerApproved" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + if (takerPayments[id].state == TakerPaymentState.TakerApproved) { + require( + block.timestamp >= takerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + } + + if (takerPayments[id].state == TakerPaymentState.PaymentSent) { + require( + block.timestamp >= takerPayments[id].preApproveLockTime, + "Current timestamp didn't exceed payment pre-approve lock time" + ); + } + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedTimelock(id); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } + + function refundTakerPaymentSecret( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedSecret(id, takerSecret); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } + + struct HTLCParams { + bytes32 id; + address taker; + address tokenAddress; + bytes32 takerSecretHash; + bytes32 makerSecretHash; + uint32 paymentLockTime; + } + + function onERC1155Received( + address operator, + address from, + uint256 tokenId, + uint256 value, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + HTLCParams memory params = abi.decode(data, (HTLCParams)); + + require( + makerPayments[params.id].state == MakerPaymentState.Uninitialized, + "Maker ERC1155 payment must be Uninitialized" + ); + require(params.taker != address(0), "Taker must not be zero address"); + require( + params.tokenAddress != address(0), + "Token must not be zero address" + ); + require( + msg.sender == params.tokenAddress, + "Token address does not match sender" + ); + require(operator == from, "Operator must be the sender"); + require(value > 0, "Value must be greater than 0"); + require(!isContract(params.taker), "Taker cannot be a contract"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + params.taker, + from, + params.takerSecretHash, + params.makerSecretHash, + params.tokenAddress, + tokenId, + value + ) + ); + + makerPayments[params.id] = MakerPayment( + paymentHash, + params.paymentLockTime, + MakerPaymentState.PaymentSent + ); + emit MakerPaymentSent(params.id); + + // Return this magic value to confirm receipt of ERC1155 token + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, /* operator */ + address, /* from */ + uint256[] calldata, /* ids */ + uint256[] calldata, /* values */ + bytes calldata /* data */ + ) external pure override returns (bytes4) { + revert("Batch transfers not supported"); + } + + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC165, IERC165) + returns (bool) + { + return + interfaceId == type(IERC1155Receiver).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + super.supportsInterface(interfaceId); + } + + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external override returns (bytes4) { + // Decode the data to extract HTLC parameters + HTLCParams memory params = abi.decode(data, (HTLCParams)); + + require( + makerPayments[params.id].state == MakerPaymentState.Uninitialized, + "Maker ERC721 payment must be Uninitialized" + ); + require(params.taker != address(0), "Taker must not be zero address"); + require( + params.tokenAddress != address(0), + "Token must not be zero address" + ); + require( + msg.sender == params.tokenAddress, + "Token address does not match sender" + ); + require(operator == from, "Operator must be the sender"); + require(!isContract(params.taker), "Taker cannot be a contract"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + params.taker, + from, + params.takerSecretHash, + params.makerSecretHash, + params.tokenAddress, + tokenId + ) + ); + + makerPayments[params.id] = MakerPayment( + paymentHash, + params.paymentLockTime, + MakerPaymentState.PaymentSent + ); + emit MakerPaymentSent(params.id); + + // Return this magic value to confirm receipt of ERC721 token + return this.onERC721Received.selector; + } + + function isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } +} diff --git a/contracts/EtomicSwapTakerV2.sol b/contracts/EtomicSwapTakerV2.sol new file mode 100644 index 0000000..71e8f3b --- /dev/null +++ b/contracts/EtomicSwapTakerV2.sol @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.20; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract EtomicSwapTakerV2 { + using SafeERC20 for IERC20; + + enum TakerPaymentState { + Uninitialized, + PaymentSent, + TakerApproved, + MakerSpent, + TakerRefunded + } + + struct TakerPayment { + bytes20 paymentHash; + uint32 preApproveLockTime; + uint32 paymentLockTime; + TakerPaymentState state; + } + + event TakerPaymentSent(bytes32 id); + event TakerPaymentApproved(bytes32 id); + event TakerPaymentSpent(bytes32 id, bytes32 secret); + event TakerPaymentRefundedSecret(bytes32 id, bytes32 secret); + event TakerPaymentRefundedTimelock(bytes32 id); + + mapping(bytes32 => TakerPayment) public takerPayments; + + address public immutable dexFeeAddress; + + constructor(address feeAddress) { + require( + feeAddress != address(0), + "feeAddress must not be zero address" + ); + + dexFeeAddress = feeAddress; + } + + function ethTakerPayment( + bytes32 id, + uint256 dexFee, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external payable { + require( + takerPayments[id].state == TakerPaymentState.Uninitialized, + "Taker payment is already initialized" + ); + require(receiver != address(0), "Receiver must not be zero address"); + require(msg.value > 0, "ETH value must be greater than zero"); + require(msg.value > dexFee, "ETH value must be greater than dex fee"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + msg.value - dexFee, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + address(0) + ) + ); + + takerPayments[id] = TakerPayment( + paymentHash, + preApproveLockTime, + paymentLockTime, + TakerPaymentState.PaymentSent + ); + + emit TakerPaymentSent(id); + } + + function erc20TakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address tokenAddress, + address receiver, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + uint32 preApproveLockTime, + uint32 paymentLockTime + ) external { + require( + takerPayments[id].state == TakerPaymentState.Uninitialized, + "ERC20 v2 payment is already initialized" + ); + require(amount > 0, "Amount must not be zero"); + require(dexFee > 0, "Dex fee must not be zero"); + require(receiver != address(0), "Receiver must not be zero address"); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + receiver, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + takerPayments[id] = TakerPayment( + paymentHash, + preApproveLockTime, + paymentLockTime, + TakerPaymentState.PaymentSent + ); + + emit TakerPaymentSent(id); + + // Now performing the external interaction + IERC20 token = IERC20(tokenAddress); + token.safeTransferFrom(msg.sender, address(this), amount + dexFee); + } + + function takerPaymentApprove( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerApproved; + + emit TakerPaymentApproved(id); + } + + function spendTakerPayment( + bytes32 id, + uint256 amount, + uint256 dexFee, + address taker, + bytes32 takerSecretHash, + bytes32 makerSecret, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.TakerApproved, + "Invalid payment state. Must be TakerApproved" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + msg.sender, + taker, + takerSecretHash, + sha256(abi.encodePacked(makerSecret)), + tokenAddress + ) + ); + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.MakerSpent; + + emit TakerPaymentSpent(id, makerSecret); + + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(amount); + payable(dexFeeAddress).transfer(dexFee); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, amount); + token.safeTransfer(dexFeeAddress, dexFee); + } + } + + function refundTakerPaymentTimelock( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecretHash, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent || + takerPayments[id].state == TakerPaymentState.TakerApproved, + "Invalid payment state. Must be PaymentSent or TakerApproved" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + takerSecretHash, + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + if (takerPayments[id].state == TakerPaymentState.TakerApproved) { + require( + block.timestamp >= takerPayments[id].paymentLockTime, + "Current timestamp didn't exceed payment refund lock time" + ); + } + + if (takerPayments[id].state == TakerPaymentState.PaymentSent) { + require( + block.timestamp >= takerPayments[id].preApproveLockTime, + "Current timestamp didn't exceed payment pre-approve lock time" + ); + } + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedTimelock(id); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } + + function refundTakerPaymentSecret( + bytes32 id, + uint256 amount, + uint256 dexFee, + address maker, + bytes32 takerSecret, + bytes32 makerSecretHash, + address tokenAddress + ) external { + require( + takerPayments[id].state == TakerPaymentState.PaymentSent, + "Invalid payment state. Must be PaymentSent" + ); + + bytes20 paymentHash = ripemd160( + abi.encodePacked( + amount, + dexFee, + maker, + msg.sender, + sha256(abi.encodePacked(takerSecret)), + makerSecretHash, + tokenAddress + ) + ); + + require( + paymentHash == takerPayments[id].paymentHash, + "Invalid paymentHash" + ); + + takerPayments[id].state = TakerPaymentState.TakerRefunded; + + emit TakerPaymentRefundedSecret(id, takerSecret); + + uint256 total_amount = amount + dexFee; + if (tokenAddress == address(0)) { + payable(msg.sender).transfer(total_amount); + } else { + IERC20 token = IERC20(tokenAddress); + token.safeTransfer(msg.sender, total_amount); + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml index a8e6443..2d22927 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,3 +7,5 @@ services: tty: true volumes: - ./:/usr/src/workspace + ports: + - "8545:8545" diff --git a/hardhat.config.js b/hardhat.config.js index 34e686b..2585a2c 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -4,7 +4,9 @@ module.exports = { solidity: "0.8.20", networks: { hardhat: { - // Hardhat Network's default settings are fine for most projects + chainId: 1337, // or another number that Remix will accept + host: "0.0.0.0", // Listen on all network interfaces + port: 8545 // Ensure this matches the port exposed in docker-compose } } }; diff --git a/test/EtomicSwap.js b/test/EtomicSwap.js index 8673bd4..094971d 100644 --- a/test/EtomicSwap.js +++ b/test/EtomicSwap.js @@ -59,19 +59,19 @@ describe("EtomicSwap", function() { EtomicSwap = await ethers.getContractFactory("EtomicSwap"); etomicSwap = await EtomicSwap.deploy(); - etomicSwap.waitForDeployment(); + await etomicSwap.waitForDeployment(); Token = await ethers.getContractFactory("Token"); token = await Token.deploy(); - token.waitForDeployment(); + await token.waitForDeployment(); Erc721Token = await ethers.getContractFactory("Erc721Token"); erc721token = await Erc721Token.deploy("MyNFT", "MNFT"); - erc721token.waitForDeployment(); + await erc721token.waitForDeployment(); Erc1155Token = await ethers.getContractFactory("Erc1155Token"); erc1155token = await Erc1155Token.deploy("uri"); - erc1155token.waitForDeployment(); + await erc1155token.waitForDeployment(); await token.transfer(accounts[1].address, ethers.parseEther('100')); }); diff --git a/test/EtomicSwapMakerNftV2Test.js b/test/EtomicSwapMakerNftV2Test.js new file mode 100644 index 0000000..b0512a2 --- /dev/null +++ b/test/EtomicSwapMakerNftV2Test.js @@ -0,0 +1,487 @@ +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); +const crypto = require('crypto'); +const {AbiCoder} = require("ethers"); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE_SENT = 'Invalid payment state. Must be PaymentSent'; +const REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment refund lock time'; + +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); +} + +async function currentEvmTime() { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +} + +const id = '0x' + crypto.randomBytes(32).toString('hex'); +const [MAKER_PAYMENT_UNINITIALIZED, MAKER_PAYMENT_SENT, TAKER_SPENT, MAKER_REFUNDED] = [0, 1, 2, 3]; + +const takerSecret = crypto.randomBytes(32); +const takerSecretHash = '0x' + crypto.createHash('sha256').update(takerSecret).digest('hex'); + +const makerSecret = crypto.randomBytes(32); +const makerSecretHash = '0x' + crypto.createHash('sha256').update(makerSecret).digest('hex'); + +const invalidSecret = crypto.randomBytes(32); + +describe("EtomicSwapMakerNftV2", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + + EtomicSwapMakerNftV2 = await ethers.getContractFactory("EtomicSwapMakerNftV2"); + etomicSwapMakerNftV2 = await EtomicSwapMakerNftV2.deploy(); + await etomicSwapMakerNftV2.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + await token.waitForDeployment(); + + Erc721Token = await ethers.getContractFactory("Erc721Token"); + erc721token = await Erc721Token.deploy("MyNFT", "MNFT"); + await erc721token.waitForDeployment(); + + Erc1155Token = await ethers.getContractFactory("Erc1155Token"); + erc1155token = await Erc1155Token.deploy("uri"); + await erc1155token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); + }); + + it('should create contract with uninitialized payments', async function() { + const makerPayment = await etomicSwapMakerNftV2.makerPayments(id); + expect(Number(makerPayment[2])).to.equal(MAKER_PAYMENT_UNINITIALIZED); + }); + + it('should allow maker to send ERC721 payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] in Erc721Token contract + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + const makerErc721Runner0 = erc721token.connect(accounts[0]); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + // Explicitly specify the method signature. + const tx = await makerErc721Runner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapMakerNftV2.target, tokenId, data).should.be.fulfilled; + const receipt = await tx.wait(); + console.log(`Gas Used: ${receipt.gasUsed.toString()}`); + + // Check the payment lockTime and state + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Should not allow to send again ( reverted with custom error ERC721InsufficientApproval ) + await expect(makerErc721Runner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapMakerNftV2.target, tokenId, data)).to.be.rejectedWith("ERC721InsufficientApproval"); + }); + + it('should allow maker to send ERC1155 payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + const makerErc1155Runner0 = erc1155token.connect(accounts[0]); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + const tx = await makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data).should.be.fulfilled; + const receipt = await tx.wait(); + console.log(`Gas Used: ${receipt.gasUsed.toString()}`); + + // Check the payment lockTime and state + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Check the balance of the token in the swap contract + const tokenBalance = await erc1155token.balanceOf(etomicSwapMakerNftV2.target, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Check sending same params again - should fail + await expect(makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data)).to.be.rejectedWith("ERC1155InsufficientBalance"); + + // Maker should be capable to send more tokens, if they have it. Note: Check Erc1155.sol file. By default, ERC1155 is minted with 3 value. + const id1 = '0x' + crypto.randomBytes(32).toString('hex'); + const data1 = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id1, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + await makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, 1, data1).should.be.fulfilled; + + // Check sending more tokens than the sender owns - should fail + const id2 = '0x' + crypto.randomBytes(32).toString('hex'); + const data2 = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id2, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + await expect(makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data2)).to.be.rejectedWith("ERC1155InsufficientBalance"); + }); + + it('should allow taker to spend ERC721 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapMakerNftV2.target, tokenId, data).should.be.fulfilled; + + // Check the ownership of the token before Taker spend Maker ERC721 payment - should be owned by Swap NFT contract + const tokenOwnerBeforeTakerSpend = await erc721token.ownerOf(tokenId); + expect(tokenOwnerBeforeTakerSpend).to.equal(etomicSwapMakerNftV2.target); + + const takerSwapRunner = etomicSwapMakerNftV2.connect(accounts[1]); + + const spendParamsInvalidSecret = [ + id, + accounts[0].address, + takerSecretHash, + invalidSecret, + erc721token.target, + tokenId + ]; + // Attempt to spend with invalid secret - should fail + await takerSwapRunner.spendErc721MakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + accounts[0].address, + takerSecretHash, + makerSecret, + erc721token.target, + tokenId + ]; + + // should not allow to spend from non-taker address even with valid secret + await etomicSwapMakerNftV2.connect(accounts[2]).spendErc721MakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // Successful spend by Taker with valid secret + await takerSwapRunner.spendErc721MakerPayment(...spendParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // Check the ownership of the token - should be transferred to the Taker (accounts[1]) + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(accounts[1].address); + + // should not allow to spend again + await takerSwapRunner.spendErc721MakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }) + + it('should allow taker to spend ERC1155 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Check the balance of the token before Taker spend Maker ERC1155 payment - should be in Swap NFT contract + let tokenBalanceBeforeTakerSpend = await erc1155token.balanceOf(etomicSwapMakerNftV2.target, tokenId); + expect(tokenBalanceBeforeTakerSpend).to.equal(BigInt(amountToSend)); + + const takerSwapRunner = etomicSwapMakerNftV2.connect(accounts[1]); + + const spendParamsInvalidSecret = [ + id, + accounts[0].address, + takerSecretHash, + invalidSecret, + erc1155token.target, + tokenId, + amountToSend + ]; + // Attempt to spend with invalid secret - should fail + await takerSwapRunner.spendErc1155MakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + accounts[0].address, + takerSecretHash, + makerSecret, + erc1155token.target, + tokenId, + amountToSend + ]; + + // should not allow to spend from non-taker address even with valid secret + await etomicSwapMakerNftV2.connect(accounts[2]).spendErc1155MakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // Successful spend by Taker with valid secret + await takerSwapRunner.spendErc1155MakerPayment(...spendParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // Check the balance of the token - should be transferred to the Taker (accounts[1]) + let tokenBalance = await erc1155token.balanceOf(accounts[1].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Check that the Swap NFT contract no longer holds the tokens + tokenBalance = await erc1155token.balanceOf(etomicSwapMakerNftV2.target, tokenId); + expect(tokenBalance).to.equal(BigInt(0)); + + // should not allow to spend again + await takerSwapRunner.spendErc1155MakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC721 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapMakerNftV2.connect(accounts[0]); + + // Not allow maker to refund if payment was not sent + const refundParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc721token.target, + tokenId + ]; + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapMakerNftV2.target, tokenId, data).should.be.fulfilled; + + // Not allow to refund before locktime + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-maker address + await etomicSwapMakerNftV2.connect(accounts[1]).refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker after locktime + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow maker to refund again + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC1155 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 3; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapMakerNftV2.connect(accounts[0]); + + const refundParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc1155token.target, + tokenId, + amountToSend + ]; + + // Not allow maker to refund if payment was not sent + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Not allow to refund before locktime + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-maker address + await etomicSwapMakerNftV2.connect(accounts[1]).refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH) + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc1155token.target, + tokenId, + 2 + ]; + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker after locktime + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Check the balance of the token - should be back to the maker (accounts[0]) + const tokenBalance = await erc1155token.balanceOf(accounts[0].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Do not allow to refund again + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC721 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapMakerNftV2.connect(accounts[0]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc721token.target, + tokenId + ]; + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapMakerNftV2.target, tokenId, data).should.be.fulfilled; + + // Not allow to call refund from non-maker address + await etomicSwapMakerNftV2.connect(accounts[1]).refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker using taker secret + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow maker to refund again + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC1155 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 3; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapMakerNftV2.connect(accounts[0]); + + const refundParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc1155token.target, + tokenId, + amountToSend + ]; + + // Not allow maker to refund if payment was not sent + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the etomicSwapMakerNftV2 contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapMakerNftV2.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Not allow to call refund from non-maker address + await etomicSwapMakerNftV2.connect(accounts[1]).refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc1155token.target, + tokenId, + 2 + ]; + await makerSwapRunner.refundErc1155MakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.fulfilled; + + // Successful refund by maker using taker secret + const payment = await etomicSwapMakerNftV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + +}); + diff --git a/test/EtomicSwapMakerV2Test.js b/test/EtomicSwapMakerV2Test.js new file mode 100644 index 0000000..5ab0da9 --- /dev/null +++ b/test/EtomicSwapMakerV2Test.js @@ -0,0 +1,551 @@ +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); +const crypto = require('crypto'); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE_SENT = 'Invalid payment state. Must be PaymentSent'; +const REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment refund lock time'; + +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); +} + +async function currentEvmTime() { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +} + +const id = '0x' + crypto.randomBytes(32).toString('hex'); +const [MAKER_PAYMENT_UNINITIALIZED, MAKER_PAYMENT_SENT, TAKER_SPENT, MAKER_REFUNDED] = [0, 1, 2, 3]; + +const takerSecret = crypto.randomBytes(32); +const takerSecretHash = '0x' + crypto.createHash('sha256').update(takerSecret).digest('hex'); + +const makerSecret = crypto.randomBytes(32); +const makerSecretHash = '0x' + crypto.createHash('sha256').update(makerSecret).digest('hex'); + +const invalidSecret = crypto.randomBytes(32); + +const zeroAddr = '0x0000000000000000000000000000000000000000'; + +describe("EtomicSwapMakerV2", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + + EtomicSwapMakerV2 = await ethers.getContractFactory("EtomicSwapMakerV2"); + etomicSwapMakerV2 = await EtomicSwapMakerV2.deploy(); + await etomicSwapMakerV2.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + await token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); + }); + + it('should create contract with uninitialized maker payments', async function() { + const makerPayment = await etomicSwapMakerV2.makerPayments(id); + expect(Number(makerPayment[2])).to.equal(MAKER_PAYMENT_UNINITIALIZED); + }); + + it('should allow maker to send ETH payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + + // Make the ETH payment + await etomicSwapMakerV2.connect(accounts[0]).ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const payment = await etomicSwapMakerV2.makerPayments(id); + + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Check that it should not allow to send again + await etomicSwapMakerV2.connect(accounts[0]).ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("Maker payment is already initialized"); + }); + + it('should allow maker to send ERC20 payment', async function() { + const currentTime = await currentEvmTime(); + + const paymentLockTime = currentTime + 100; + + const payment_params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapMakerV2.connect(accounts[0]); + + await token.approve(etomicSwapMakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20MakerPayment(...payment_params).should.be.fulfilled; + + // Check contract token balance + const balance = await token.balanceOf(etomicSwapMakerV2.target); + expect(balance).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapMakerV2.makerPayments(id); + + // Check locktime and status + expect(payment[1]).to.equal(BigInt(paymentLockTime)); + expect(payment[2]).to.equal(BigInt(MAKER_PAYMENT_SENT)); + + // Should not allow to send payment again + await etomicSwapRunner0.erc20MakerPayment(...payment_params).should.be.rejectedWith("Maker payment is already initialized"); + }); + + it('should allow taker to spend ETH maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + + const makerSwapRunner = etomicSwapMakerV2.connect(accounts[0]); + const takerSwapRunner = etomicSwapMakerV2.connect(accounts[1]); + + // Make the ETH payment + await makerSwapRunner.ethMakerPayment(...payment_params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const spendParamsInvalidSecret = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + invalidSecret, + zeroAddr, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParamsInvalidAmount = [ + id, + ethers.parseEther('0.9'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidAmount).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + // should not allow to spend from non-taker address + await etomicSwapMakerV2.connect(accounts[2]).spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const spendTx = await takerSwapRunner.spendMakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const spendReceipt = await spendTx.wait(); + const gasUsed = ethers.parseUnits(spendReceipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapMakerV2.makerPayments(id); + + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // should not allow to spend again + await takerSwapRunner.spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to spend ERC20 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, // taker + takerSecretHash, + makerSecretHash, + paymentLockTime + ]; + + const makerSwapRunner = etomicSwapMakerV2.connect(accounts[0]); + const takerSwapRunner = etomicSwapMakerV2.connect(accounts[1]); + + // Make the ERC20 payment + await token.approve(etomicSwapMakerV2.target, ethers.parseEther('1')); + await makerSwapRunner.erc20MakerPayment(...payment_params).should.be.fulfilled; + + const contractBalance = await token.balanceOf(etomicSwapMakerV2.target); + expect(contractBalance).to.equal(ethers.parseEther('1')); + + const spendParamsInvalidSecret = [ + id, + ethers.parseEther('1'), + accounts[0].address, + takerSecretHash, + invalidSecret, + token.target, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParamsInvalidAmount = [ + id, + ethers.parseEther('0.9'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + await takerSwapRunner.spendMakerPayment(...spendParamsInvalidAmount).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + ethers.parseEther('1'), + accounts[0].address, // maker + takerSecretHash, + makerSecret, + token.target, + ]; + + // should not allow to spend from non-taker address + await etomicSwapMakerV2.connect(accounts[2]).spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await token.balanceOf(accounts[1].address); + + const gasPrice = ethers.parseUnits('100', 'gwei'); + await takerSwapRunner.spendMakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check taker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapMakerV2.makerPayments(id); + + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // should not allow to spend again + await takerSwapRunner.spendMakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ETH payment after locktime', async function() { + const lockTime = (await ethers.provider.getBlock('latest')).timestamp + 1000; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapMakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapMakerV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams) + .should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to refund before locktime + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + let invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + await etomicSwapRunner0.refundMakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapMakerV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC20 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapMakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapMakerV2.connect(accounts[1]); + + await token.approve(etomicSwapMakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20MakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check maker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapMakerV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundMakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ETH payment using taker secret', async function() { + const lockTime = (await ethers.provider.getBlock('latest')).timestamp + 1000; + const params = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapMakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapMakerV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams) + .should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethMakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + let invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + await etomicSwapRunner0.refundMakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapMakerV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC20 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const params = [ + id, + ethers.parseEther('1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + lockTime + ]; + + let etomicSwapRunner0 = etomicSwapMakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapMakerV2.connect(accounts[1]); + + await token.approve(etomicSwapMakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20MakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.9'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundMakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check maker balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapMakerV2.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundMakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); +}); diff --git a/test/EtomicSwapNft.js b/test/EtomicSwapNft.js new file mode 100644 index 0000000..b549d57 --- /dev/null +++ b/test/EtomicSwapNft.js @@ -0,0 +1,1300 @@ +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); +const crypto = require('crypto'); +const {AbiCoder} = require("ethers"); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE_SENT = 'Invalid payment state. Must be PaymentSent'; +const INVALID_PAYMENT_STATE_APPROVED = 'Invalid payment state. Must be TakerApproved'; +const REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment refund lock time'; +const PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment pre-approve lock time'; + +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); +} + +async function currentEvmTime() { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +} + +const id = '0x' + crypto.randomBytes(32).toString('hex'); +const [TAKER_PAYMENT_UNINITIALIZED, TAKER_PAYMENT_SENT, TAKER_PAYMENT_APPROVED, MAKER_SPENT, TAKER_REFUNDED] = [0, 1, 2, 3, 4]; +const [MAKER_PAYMENT_UNINITIALIZED, MAKER_PAYMENT_SENT, TAKER_SPENT, MAKER_REFUNDED] = [0, 1, 2, 3]; + +const takerSecret = crypto.randomBytes(32); +const takerSecretHash = '0x' + crypto.createHash('sha256').update(takerSecret).digest('hex'); + +const makerSecret = crypto.randomBytes(32); +const makerSecretHash = '0x' + crypto.createHash('sha256').update(makerSecret).digest('hex'); + +const invalidSecret = crypto.randomBytes(32); + +const zeroAddr = '0x0000000000000000000000000000000000000000'; +const dexFeeAddr = '0x8888888888888888888888888888888888888888'; + +describe("etomicSwapNft", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + + EtomicSwapNft = await ethers.getContractFactory("EtomicSwapNft"); + etomicSwapNft = await EtomicSwapNft.deploy(dexFeeAddr); + await etomicSwapNft.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + await token.waitForDeployment(); + + Erc721Token = await ethers.getContractFactory("Erc721Token"); + erc721token = await Erc721Token.deploy("MyNFT", "MNFT"); + await erc721token.waitForDeployment(); + + Erc1155Token = await ethers.getContractFactory("Erc1155Token"); + erc1155token = await Erc1155Token.deploy("uri"); + await erc1155token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); + }); + + it('should create contract with uninitialized payments', async function() { + const takerPayment = await etomicSwapNft.takerPayments(id); + expect(Number(takerPayment[3])).to.equal(TAKER_PAYMENT_UNINITIALIZED); + + const makerPayment = await etomicSwapNft.makerPayments(id); + expect(Number(makerPayment[2])).to.equal(MAKER_PAYMENT_UNINITIALIZED); + }); + + it('should allow maker to send ERC721 payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Assuming token ID 1 is minted to accounts[0] in Erc721Token contract + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + const makerErc721Runner0 = erc721token.connect(accounts[0]); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + // Explicitly specify the method signature. + const tx = await makerErc721Runner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapNft.target, tokenId, data).should.be.fulfilled; + const receipt = await tx.wait(); + console.log(`Gas Used: ${receipt.gasUsed.toString()}`); + + // Check the payment lockTime and state + const payment = await etomicSwapNft.makerPayments(id); + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Should not allow to send again ( reverted with custom error ERC721InsufficientApproval ) + await expect(makerErc721Runner0['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapNft.target, tokenId, data)).to.be.rejectedWith("ERC721InsufficientApproval"); + }); + + it('should allow maker to send ERC1155 payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + const makerErc1155Runner0 = erc1155token.connect(accounts[0]); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + const tx = await makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data).should.be.fulfilled; + const receipt = await tx.wait(); + console.log(`Gas Used: ${receipt.gasUsed.toString()}`); + + // Check the payment lockTime and state + const payment = await etomicSwapNft.makerPayments(id); + expect(Number(payment[1])).to.equal(paymentLockTime); + expect(Number(payment[2])).to.equal(MAKER_PAYMENT_SENT); + + // Check the balance of the token in the swap contract + const tokenBalance = await erc1155token.balanceOf(etomicSwapNft.target, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Check sending same params again - should fail + await expect(makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data)).to.be.rejectedWith("ERC1155InsufficientBalance"); + + // Maker should be capable to send more tokens, if they have it. Note: Check Erc1155.sol file. By default, ERC1155 is minted with 3 value. + const id1 = '0x' + crypto.randomBytes(32).toString('hex'); + const data1 = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id1, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + await makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, 1, data1).should.be.fulfilled; + + // Check sending more tokens than the sender owns - should fail + const id2 = '0x' + crypto.randomBytes(32).toString('hex'); + const data2 = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id2, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + await expect(makerErc1155Runner0.safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data2)).to.be.rejectedWith("ERC1155InsufficientBalance"); + }); + + it('should allow taker to spend ERC721 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapNft.target, tokenId, data).should.be.fulfilled; + + // Check the ownership of the token before Taker spend Maker ERC721 payment - should be owned by Swap NFT contract + const tokenOwnerBeforeTakerSpend = await erc721token.ownerOf(tokenId); + expect(tokenOwnerBeforeTakerSpend).to.equal(etomicSwapNft.target); + + const takerSwapRunner = etomicSwapNft.connect(accounts[1]); + + const spendParamsInvalidSecret = [ + id, + accounts[0].address, + takerSecretHash, + invalidSecret, + erc721token.target, + tokenId + ]; + // Attempt to spend with invalid secret - should fail + await takerSwapRunner.spendErc721MakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + accounts[0].address, + takerSecretHash, + makerSecret, + erc721token.target, + tokenId + ]; + + // should not allow to spend from non-taker address even with valid secret + await etomicSwapNft.connect(accounts[2]).spendErc721MakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // Successful spend by Taker with valid secret + await takerSwapRunner.spendErc721MakerPayment(...spendParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapNft.makerPayments(id); + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // Check the ownership of the token - should be transferred to the Taker (accounts[1]) + const tokenOwner = await erc721token.ownerOf(tokenId); + expect(tokenOwner).to.equal(accounts[1].address); + + // should not allow to spend again + await takerSwapRunner.spendErc721MakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }) + + it('should allow taker to spend ERC1155 maker payment', async function() { + let currentTime = await currentEvmTime(); + const paymentLockTime = currentTime + 100; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 2; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, paymentLockTime] + ); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Check the balance of the token before Taker spend Maker ERC1155 payment - should be in Swap NFT contract + let tokenBalanceBeforeTakerSpend = await erc1155token.balanceOf(etomicSwapNft.target, tokenId); + expect(tokenBalanceBeforeTakerSpend).to.equal(BigInt(amountToSend)); + + const takerSwapRunner = etomicSwapNft.connect(accounts[1]); + + const spendParamsInvalidSecret = [ + id, + accounts[0].address, + takerSecretHash, + invalidSecret, + erc1155token.target, + tokenId, + amountToSend + ]; + // Attempt to spend with invalid secret - should fail + await takerSwapRunner.spendErc1155MakerPayment(...spendParamsInvalidSecret).should.be.rejectedWith(INVALID_HASH); + + const spendParams = [ + id, + accounts[0].address, + takerSecretHash, + makerSecret, + erc1155token.target, + tokenId, + amountToSend + ]; + + // should not allow to spend from non-taker address even with valid secret + await etomicSwapNft.connect(accounts[2]).spendErc1155MakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // Successful spend by Taker with valid secret + await takerSwapRunner.spendErc1155MakerPayment(...spendParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapNft.makerPayments(id); + expect(Number(payment[2])).to.equal(TAKER_SPENT); + + // Check the balance of the token - should be transferred to the Taker (accounts[1]) + let tokenBalance = await erc1155token.balanceOf(accounts[1].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Check that the Swap NFT contract no longer holds the tokens + tokenBalance = await erc1155token.balanceOf(etomicSwapNft.target, tokenId); + expect(tokenBalance).to.equal(BigInt(0)); + + // should not allow to spend again + await takerSwapRunner.spendErc1155MakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC721 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapNft.connect(accounts[0]); + + // Not allow maker to refund if payment was not sent + const refundParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc721token.target, + tokenId + ]; + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapNft.target, tokenId, data).should.be.fulfilled; + + // Not allow to refund before locktime + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-maker address + await etomicSwapNft.connect(accounts[1]).refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker after locktime + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapNft.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow maker to refund again + await makerSwapRunner.refundErc721MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC1155 payment after locktime', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 3; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapNft.connect(accounts[0]); + + const refundParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc1155token.target, + tokenId, + amountToSend + ]; + + // Not allow maker to refund if payment was not sent + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Not allow to refund before locktime + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-maker address + await etomicSwapNft.connect(accounts[1]).refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH) + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + accounts[1].address, + takerSecretHash, + makerSecretHash, + erc1155token.target, + tokenId, + 2 + ]; + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker after locktime + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapNft.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Check the balance of the token - should be back to the maker (accounts[0]) + const tokenBalance = await erc1155token.balanceOf(accounts[0].address, tokenId); + expect(tokenBalance).to.equal(BigInt(amountToSend)); + + // Do not allow to refund again + await makerSwapRunner.refundErc1155MakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC721 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc721token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapNft.connect(accounts[0]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc721token.target, + tokenId + ]; + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC721 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + // Explicitly specify the method signature. + await erc721token.connect(accounts[0])['safeTransferFrom(address,address,uint256,bytes)'](accounts[0].address, etomicSwapNft.target, tokenId, data).should.be.fulfilled; + + // Not allow to call refund from non-maker address + await etomicSwapNft.connect(accounts[1]).refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Successful refund by maker using taker secret + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.fulfilled; + + // Check the state of the payment + const payment = await etomicSwapNft.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Not allow maker to refund again + await makerSwapRunner.refundErc721MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow maker to refund ERC1155 payment using taker secret', async function() { + const lockTime = await currentEvmTime() + 1000; + const tokenId = 1; // Token ID used in Erc1155Token contract + const amountToSend = 3; // Amount of tokens to send + + const abiCoder = new AbiCoder(); + const data = abiCoder.encode( + ['bytes32', 'address', 'address', 'bytes32', 'bytes32','uint32'], + [id, accounts[1].address, erc1155token.target, takerSecretHash, makerSecretHash, lockTime] + ); + + let makerSwapRunner = etomicSwapNft.connect(accounts[0]); + + const refundParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc1155token.target, + tokenId, + amountToSend + ]; + + // Not allow maker to refund if payment was not sent + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the Maker ERC1155 payment. Call safeTransferFrom directly to transfer the token to the EtomicSwapNft contract. + await erc1155token.connect(accounts[0]).safeTransferFrom(accounts[0].address, etomicSwapNft.target, tokenId, amountToSend, data).should.be.fulfilled; + + // Not allow to call refund from non-maker address + await etomicSwapNft.connect(accounts[1]).refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + accounts[1].address, + takerSecret, + makerSecretHash, + erc1155token.target, + tokenId, + 2 + ]; + await makerSwapRunner.refundErc1155MakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.fulfilled; + + // Successful refund by maker using taker secret + const payment = await etomicSwapNft.makerPayments(id); + expect(payment.state).to.equal(BigInt(MAKER_REFUNDED)); + + // Do not allow to refund again + await makerSwapRunner.refundErc1155MakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to send ETH payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const params = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapNft.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const payment = await etomicSwapNft.takerPayments(id); + + expect(Number(payment[1])).to.equal(immediateRefundLockTime); + expect(Number(payment[2])).to.equal(paymentLockTime); + expect(Number(payment[3])).to.equal(TAKER_PAYMENT_SENT); + + // Check that it should not allow to send again + await etomicSwapNft.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("Taker payment is already initialized"); + }); + + it('should allow taker to send ERC20 payment', async function() { + const currentTime = await currentEvmTime(); + + const immediateRefundLockTime = currentTime + 10; + const paymentLockTime = currentTime + 100; + + const paymentParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapNft.connect(accounts[0]); + + await token.approve(etomicSwapNft.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20TakerPayment(...paymentParams).should.be.fulfilled; + + // Check contract token balance + const balance = await token.balanceOf(etomicSwapNft.target); + expect(balance).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapNft.takerPayments(id); + + // Check locktime and status + expect(payment[1]).to.equal(BigInt(immediateRefundLockTime)); + expect(payment[2]).to.equal(BigInt(paymentLockTime)); + expect(payment[3]).to.equal(BigInt(TAKER_PAYMENT_SENT)); + + // Should not allow to send payment again + await etomicSwapRunner0.erc20TakerPayment(...paymentParams).should.be.rejectedWith("ERC20 v2 payment is already initialized"); + }); + + it('should allow maker to spend ETH taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const paymentParams = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapNft.connect(accounts[0]).ethTakerPayment(...paymentParams, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const spendParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + // should not allow to spend before payment is approved by taker + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapNft.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapNft.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const spendTx = await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const spendReceipt = await spendTx.wait(); + const gasUsed = ethers.parseUnits(spendReceipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await ethers.provider.getBalance(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapNft.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow maker to spend ERC20 taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const paymentParams = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + token.target, + accounts[1].address, // receiver + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + + // Make the ERC20 payment + await token.approve(etomicSwapNft.target, ethers.parseEther('1')); + await etomicSwapNft.connect(accounts[0]).erc20TakerPayment(...paymentParams).should.be.fulfilled; + + const contractBalance = await token.balanceOf(etomicSwapNft.target); + expect(contractBalance).to.equal(ethers.parseEther('1')); + + const spendParams = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, // tokenAddress + ]; + + // should not allow to spend before taker's approval + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapNft.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapNft.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await token.balanceOf(accounts[1].address); + + const gasPrice = ethers.parseUnits('100', 'gwei'); + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await token.balanceOf(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapNft.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapNft.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow taker to refund approved ETH payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime + ]; + + let takerSwapRunner = etomicSwapNft.connect(accounts[0]); + let makerSwapRunner = etomicSwapNft.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + // Not allow to refund before locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-taker address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ETH payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapNft.connect(accounts[0]); + let makerSwapRunner = etomicSwapNft.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + await advanceTimeAndMine(2000); + + // Not allow to refund before pre-approve locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(3000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund approved ERC20 payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapNft.connect(accounts[0]); + let makerSwapRunner = etomicSwapNft.connect(accounts[1]); + + await token.approve(etomicSwapNft.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ERC20 payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapNft.connect(accounts[0]); + let makerSwapRunner = etomicSwapNft.connect(accounts[1]); + + await token.approve(etomicSwapNft.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await advanceTimeAndMine(2000); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ETH payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapNft.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapNft.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ERC20 payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapNft.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapNft.connect(accounts[1]); + + await token.approve(etomicSwapNft.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapNft.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); +}); \ No newline at end of file diff --git a/test/EtomicSwapTakerV2Test.js b/test/EtomicSwapTakerV2Test.js new file mode 100644 index 0000000..e80f458 --- /dev/null +++ b/test/EtomicSwapTakerV2Test.js @@ -0,0 +1,885 @@ +const { + expect +} = require("chai"); +const { + ethers +} = require("hardhat"); +const crypto = require('crypto'); + +require('chai') + .use(require('chai-as-promised')) + .should(); + +const INVALID_HASH = 'Invalid paymentHash'; +const INVALID_PAYMENT_STATE_SENT = 'Invalid payment state. Must be PaymentSent'; +const INVALID_PAYMENT_STATE_APPROVED = 'Invalid payment state. Must be TakerApproved'; +const REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment refund lock time'; +const PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED = 'Current timestamp didn\'t exceed payment pre-approve lock time'; + +/** + * Advances the Ethereum Virtual Machine (EVM) time by a specified amount and then mines a new block. + * + * @param {number} increaseAmount The amount of time to advance in seconds. + * + * This function is used in Ethereum smart contract testing to simulate the passage of time. In the EVM, + * time is measured based on block timestamps. The 'evm_increaseTime' method increases the EVM's internal + * clock, but this change only affects the next mined block. Therefore, 'evm_mine' is called immediately + * afterwards to mine a new block, ensuring that the blockchain's timestamp is updated to reflect the time + * change. This approach is essential for testing time-dependent contract features like lock periods or deadlines. + */ +async function advanceTimeAndMine(increaseAmount) { + await ethers.provider.send("evm_increaseTime", [increaseAmount]); + await ethers.provider.send("evm_mine"); +} + +async function currentEvmTime() { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +} + +const id = '0x' + crypto.randomBytes(32).toString('hex'); +const [TAKER_PAYMENT_UNINITIALIZED, TAKER_PAYMENT_SENT, TAKER_PAYMENT_APPROVED, MAKER_SPENT, TAKER_REFUNDED] = [0, 1, 2, 3, 4]; + +const takerSecret = crypto.randomBytes(32); +const takerSecretHash = '0x' + crypto.createHash('sha256').update(takerSecret).digest('hex'); + +const makerSecret = crypto.randomBytes(32); +const makerSecretHash = '0x' + crypto.createHash('sha256').update(makerSecret).digest('hex'); + +const invalidSecret = crypto.randomBytes(32); + +const zeroAddr = '0x0000000000000000000000000000000000000000'; +const dexFeeAddr = '0x9999999999999999999999999999999999999999'; + +describe("EtomicSwapTakerV2", function() { + + beforeEach(async function() { + accounts = await ethers.getSigners(); + + EtomicSwapTakerV2 = await ethers.getContractFactory("EtomicSwapTakerV2"); + etomicSwapTakerV2 = await EtomicSwapTakerV2.deploy(dexFeeAddr); + await etomicSwapTakerV2.waitForDeployment(); + + Token = await ethers.getContractFactory("Token"); + token = await Token.deploy(); + await token.waitForDeployment(); + + await token.transfer(accounts[1].address, ethers.parseEther('100')); + }); + + it('should create contract with uninitialized payments', async function() { + const takerPayment = await etomicSwapTakerV2.takerPayments(id); + expect(Number(takerPayment[3])).to.equal(TAKER_PAYMENT_UNINITIALIZED); + }); + + it('should allow taker to send ETH payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const params = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapTakerV2.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const payment = await etomicSwapTakerV2.takerPayments(id); + + expect(Number(payment[1])).to.equal(immediateRefundLockTime); + expect(Number(payment[2])).to.equal(paymentLockTime); + expect(Number(payment[3])).to.equal(TAKER_PAYMENT_SENT); + + // Check that it should not allow to send again + await etomicSwapTakerV2.connect(accounts[0]).ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.rejectedWith("Taker payment is already initialized"); + }); + + it('should allow taker to send ERC20 payment', async function() { + const currentTime = await currentEvmTime(); + + const immediateRefundLockTime = currentTime + 10; + const paymentLockTime = currentTime + 100; + + const payment_params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapTakerV2.connect(accounts[0]); + + await token.approve(etomicSwapTakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await etomicSwapRunner0.erc20TakerPayment(...payment_params).should.be.fulfilled; + + // Check contract token balance + const balance = await token.balanceOf(etomicSwapTakerV2.target); + expect(balance).to.equal(ethers.parseEther('1')); + + const payment = await etomicSwapTakerV2.takerPayments(id); + + // Check locktime and status + expect(payment[1]).to.equal(BigInt(immediateRefundLockTime)); + expect(payment[2]).to.equal(BigInt(paymentLockTime)); + expect(payment[3]).to.equal(BigInt(TAKER_PAYMENT_SENT)); + + // Should not allow to send payment again + await etomicSwapRunner0.erc20TakerPayment(...payment_params).should.be.rejectedWith("ERC20 v2 payment is already initialized"); + }); + + it('should allow maker to spend ETH taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + // Make the ETH payment + await etomicSwapTakerV2.connect(accounts[0]).ethTakerPayment(...payment_params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const spendParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + // should not allow to spend before payment is approved by taker + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapTakerV2.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapTakerV2.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + zeroAddr, + ]; + + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await ethers.provider.getBalance(accounts[1].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const spendTx = await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const spendReceipt = await spendTx.wait(); + const gasUsed = ethers.parseUnits(spendReceipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[1].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await ethers.provider.getBalance(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapTakerV2.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow maker to spend ERC20 taker payment', async function() { + let currentTime = await currentEvmTime(); + const immediateRefundLockTime = currentTime + 100; + const paymentLockTime = currentTime + 100; + const payment_params = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + token.target, + accounts[1].address, // receiver + takerSecretHash, + makerSecretHash, + immediateRefundLockTime, + paymentLockTime + ]; + + // Make the ERC20 payment + await token.approve(etomicSwapTakerV2.target, ethers.parseEther('1')); + await etomicSwapTakerV2.connect(accounts[0]).erc20TakerPayment(...payment_params).should.be.fulfilled; + + const contractBalance = await token.balanceOf(etomicSwapTakerV2.target); + expect(contractBalance).to.equal(ethers.parseEther('1')); + + const spendParams = [ + id, + ethers.parseEther('0.9'), // amount + ethers.parseEther('0.1'), // dexFee + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, // tokenAddress + ]; + + // should not allow to spend before taker's approval + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await etomicSwapTakerV2.connect(accounts[0]).takerPaymentApprove(...approveParams).should.be.fulfilled; + + // should not allow to spend from invalid address + await etomicSwapTakerV2.connect(accounts[0]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_HASH); + + // should not allow to spend with invalid amounts + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[0].address, + takerSecretHash, + makerSecret, + token.target, + ]; + + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + const balanceBefore = await token.balanceOf(accounts[1].address); + + const gasPrice = ethers.parseUnits('100', 'gwei'); + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams, { + gasPrice + }).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[1].address); + // Check receiver balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('0.9')); + + const dexFeeAddrBalance = await token.balanceOf(dexFeeAddr); + expect(dexFeeAddrBalance).to.equal(ethers.parseEther('0.1')); + + const payment = await etomicSwapTakerV2.takerPayments(id); + + expect(Number(payment[3])).to.equal(MAKER_SPENT); + + // Do not allow to spend again + await etomicSwapTakerV2.connect(accounts[1]).spendTakerPayment(...spendParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_APPROVED); + }); + + it('should allow taker to refund approved ETH payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapTakerV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapTakerV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr, + ]; + + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + // Not allow to refund before locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ETH payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapTakerV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapTakerV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await takerSwapRunner.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + await advanceTimeAndMine(2000); + + // Not allow to refund before pre-approve locktime + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + // Simulate time passing to exceed the locktime + await advanceTimeAndMine(3000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + zeroAddr + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await takerSwapRunner.refundTakerPaymentTimelock(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund approved ERC20 payment after locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapTakerV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapTakerV2.connect(accounts[1]); + + await token.approve(etomicSwapTakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + const approveParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.takerPaymentApprove(...approveParams).should.be.fulfilled; + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund non-approved ERC20 payment only after pre-approve locktime', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let takerSwapRunner = etomicSwapTakerV2.connect(accounts[0]); + let makerSwapRunner = etomicSwapTakerV2.connect(accounts[1]); + + await token.approve(etomicSwapTakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(takerSwapRunner.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await advanceTimeAndMine(2000); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(PRE_APPROVE_REFUND_TIMESTAMP_NOT_REACHED); + + await advanceTimeAndMine(1000); + + // Not allow to call refund from non-sender address + await makerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecretHash, + makerSecretHash, + token.target, + ]; + + await takerSwapRunner.refundTakerPaymentTimelock(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await takerSwapRunner.refundTakerPaymentTimelock(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ETH payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.1'), // dexFee + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapTakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapTakerV2.connect(accounts[1]); + + // Not allow to refund if payment was not sent + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + + // Make the ETH payment + await etomicSwapRunner0.ethTakerPayment(...params, { + value: ethers.parseEther('1') + }).should.be.fulfilled; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + zeroAddr, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await ethers.provider.getBalance(accounts[0].address); + const gasPrice = ethers.parseUnits('100', 'gwei'); + + const tx = await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams, { + gasPrice + }).should.be.fulfilled; + + const receipt = await tx.wait(); + const gasUsed = ethers.parseUnits(receipt.gasUsed.toString(), 'wei'); + const txFee = gasUsed * gasPrice; + + const balanceAfter = await ethers.provider.getBalance(accounts[0].address); + // Check sender balance + expect((balanceAfter - balanceBefore + txFee)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); + + it('should allow taker to refund ERC20 payment using secret', async function() { + const preApproveLockTime = await currentEvmTime() + 3000; + const paymentLockTime = await currentEvmTime() + 1000; + + const params = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + token.target, + accounts[1].address, + takerSecretHash, + makerSecretHash, + preApproveLockTime, + paymentLockTime, + ]; + + let etomicSwapRunner0 = etomicSwapTakerV2.connect(accounts[0]); + let etomicSwapRunner1 = etomicSwapTakerV2.connect(accounts[1]); + + await token.approve(etomicSwapTakerV2.target, ethers.parseEther('1')); + // Make the ERC20 payment + await expect(etomicSwapRunner0.erc20TakerPayment(...params)).to.be.fulfilled; + + const refundParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + // Not allow to call refund from non-sender address + await etomicSwapRunner1.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_HASH); + + // Not allow to refund invalid amount + const invalidAmountParams = [ + id, + ethers.parseEther('0.8'), + ethers.parseEther('0.1'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidAmountParams).should.be.rejectedWith(INVALID_HASH); + + const invalidDexFeeParams = [ + id, + ethers.parseEther('0.9'), + ethers.parseEther('0.2'), + accounts[1].address, + takerSecret, + makerSecretHash, + token.target, + ]; + + await etomicSwapRunner0.refundTakerPaymentSecret(...invalidDexFeeParams).should.be.rejectedWith(INVALID_HASH); + + // Success refund + const balanceBefore = await token.balanceOf(accounts[0].address); + + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.fulfilled; + + const balanceAfter = await token.balanceOf(accounts[0].address); + + // Check sender balance + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + expect((balanceAfter - balanceBefore)).to.equal(ethers.parseEther('1')); + + // Check the state of the payment + const payment = await etomicSwapTakerV2.takerPayments(id); + expect(payment.state).to.equal(BigInt(TAKER_REFUNDED)); + + // Do not allow to refund again + await etomicSwapRunner0.refundTakerPaymentSecret(...refundParams).should.be.rejectedWith(INVALID_PAYMENT_STATE_SENT); + }); +});