From 66ba8c4a0ee926c9c98ba5e2bb57f0e7e708a776 Mon Sep 17 00:00:00 2001 From: Neuti Yoo <103201346+neutiyoo@users.noreply.github.com> Date: Tue, 10 May 2022 02:20:39 +0900 Subject: [PATCH 01/20] Remove redundant ABIEncoderV2 pragma (#539) --- contracts/Bridge.sol | 1 - contracts/CentrifugeAsset.sol | 1 - contracts/Forwarder.sol | 1 - contracts/TestContracts.sol | 1 - contracts/handlers/ERC1155Handler.sol | 1 - contracts/handlers/ERC20Handler.sol | 1 - contracts/handlers/ERC721Handler.sol | 1 - contracts/handlers/GenericHandler.sol | 1 - 8 files changed, 8 deletions(-) diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 58939d79..cd12f5e5 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "./utils/AccessControl.sol"; import "./utils/Pausable.sol"; diff --git a/contracts/CentrifugeAsset.sol b/contracts/CentrifugeAsset.sol index d1f62e4f..af3ac9b8 100644 --- a/contracts/CentrifugeAsset.sol +++ b/contracts/CentrifugeAsset.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; /** @title Represents a bridged Centrifuge asset. diff --git a/contracts/Forwarder.sol b/contracts/Forwarder.sol index 7b078e38..600c4964 100644 --- a/contracts/Forwarder.sol +++ b/contracts/Forwarder.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; diff --git a/contracts/TestContracts.sol b/contracts/TestContracts.sol index 63488327..6aeb1342 100644 --- a/contracts/TestContracts.sol +++ b/contracts/TestContracts.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "./utils/SafeCast.sol"; import "./handlers/HandlerHelpers.sol"; diff --git a/contracts/handlers/ERC1155Handler.sol b/contracts/handlers/ERC1155Handler.sol index 90e86fd9..f39de918 100644 --- a/contracts/handlers/ERC1155Handler.sol +++ b/contracts/handlers/ERC1155Handler.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "../interfaces/IDepositExecute.sol"; import "./HandlerHelpers.sol"; diff --git a/contracts/handlers/ERC20Handler.sol b/contracts/handlers/ERC20Handler.sol index 3a3ff374..45a1751f 100644 --- a/contracts/handlers/ERC20Handler.sol +++ b/contracts/handlers/ERC20Handler.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "../interfaces/IDepositExecute.sol"; import "./HandlerHelpers.sol"; diff --git a/contracts/handlers/ERC721Handler.sol b/contracts/handlers/ERC721Handler.sol index dee7ac7a..71e25548 100644 --- a/contracts/handlers/ERC721Handler.sol +++ b/contracts/handlers/ERC721Handler.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "../interfaces/IDepositExecute.sol"; import "./HandlerHelpers.sol"; diff --git a/contracts/handlers/GenericHandler.sol b/contracts/handlers/GenericHandler.sol index b750742f..fbce0b78 100644 --- a/contracts/handlers/GenericHandler.sol +++ b/contracts/handlers/GenericHandler.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -pragma experimental ABIEncoderV2; import "../interfaces/IGenericHandler.sol"; From 963103bfa81bcdfef2dfb7f041de7d0b3004bb70 Mon Sep 17 00:00:00 2001 From: Tanya Bushenyova Date: Wed, 11 May 2022 13:55:13 +0300 Subject: [PATCH 02/20] Viatrix/fee handler (#519) * WIP: Basic FeeHandler * WIP: Basic FeeHandler * Fee handler with oracle * FeeHandler: fixes after comments * Fix after review * Simplify abi decoding * Added expiration time to oracle data * sign oracle message by ethers.js * Remove prefix from signature * Add FeeCollected event * Add FeeDistributed event Co-authored-by: Oleksii Matiiasevych Co-authored-by: Kirill --- contracts/Bridge.sol | 48 +- contracts/handlers/fee/BasicFeeHandler.sol | 95 + .../handlers/fee/FeeHandlerWithOracle.sol | 194 + contracts/interfaces/IBridge.sol | 7 + contracts/interfaces/IERCHandler.sol | 7 + contracts/interfaces/IFeeHandler.sol | 62 + package-lock.json | 21765 +--------------- test/contractBridge/admin.js | 21 +- test/contractBridge/cancelDepositProposal.js | 1 - test/contractBridge/constructor.js | 9 +- test/contractBridge/createDepositProposal.js | 4 +- test/contractBridge/depositERC1155.js | 10 +- test/contractBridge/depositERC20.js | 13 +- test/contractBridge/depositERC721.js | 7 +- test/contractBridge/depositGeneric.js | 12 +- .../executeWithFailedHandler.js | 2 +- test/contractBridge/fee.js | 121 - test/contractBridge/voteDepositProposal.js | 1 - .../voteDepositProposalWithRealForwarder.js | 1 - .../voteDepositProposalWithTestForwarder.js | 1 - test/e2e/erc1155/differentChainsMock.js | 7 +- test/e2e/erc1155/sameChain.js | 4 +- test/e2e/erc20/differentChainsMock.js | 7 +- test/e2e/erc20/sameChain.js | 4 +- test/e2e/erc721/differentChainsMock.js | 7 +- test/e2e/erc721/sameChain.js | 4 +- test/gasBenchmarks/deployments.js | 2 +- test/gasBenchmarks/deposits.js | 11 +- test/gasBenchmarks/executeProposal.js | 5 +- test/gasBenchmarks/voteProposal.js | 2 +- test/handlers/erc1155/burnList.js | 2 +- test/handlers/erc1155/deposit.js | 4 +- test/handlers/erc1155/depositBurn.js | 5 +- test/handlers/erc20/burnList.js | 2 +- test/handlers/erc20/constructor.js | 2 +- test/handlers/erc20/deposit.js | 7 +- test/handlers/erc20/depositBurn.js | 3 +- test/handlers/erc20/isWhitelisted.js | 2 +- .../erc20/setResourceIDAndContractAddress.js | 2 +- test/handlers/erc721/burnList.js | 2 +- test/handlers/erc721/deposit.js | 5 +- test/handlers/erc721/depositBurn.js | 5 +- test/handlers/fee/basic/calculateFee.js | 75 + test/handlers/fee/basic/changeFee.js | 53 + test/handlers/fee/basic/collectFee.js | 153 + test/handlers/fee/basic/distributeFee.js | 121 + test/handlers/fee/withOracle/admin.js | 57 + test/handlers/fee/withOracle/calculateFee.js | 201 + test/handlers/fee/withOracle/collectFee.js | 203 + test/handlers/fee/withOracle/distributeFee.js | 182 + test/handlers/generic/constructor.js | 6 +- test/handlers/generic/deposit.js | 13 +- test/handlers/generic/executeProposal.js | 5 +- test/helpers.js | 49 +- 54 files changed, 1706 insertions(+), 21887 deletions(-) create mode 100644 contracts/handlers/fee/BasicFeeHandler.sol create mode 100644 contracts/handlers/fee/FeeHandlerWithOracle.sol create mode 100644 contracts/interfaces/IFeeHandler.sol delete mode 100644 test/contractBridge/fee.js create mode 100644 test/handlers/fee/basic/calculateFee.js create mode 100644 test/handlers/fee/basic/changeFee.js create mode 100644 test/handlers/fee/basic/collectFee.js create mode 100644 test/handlers/fee/basic/distributeFee.js create mode 100644 test/handlers/fee/withOracle/admin.js create mode 100644 test/handlers/fee/withOracle/calculateFee.js create mode 100644 test/handlers/fee/withOracle/collectFee.js create mode 100644 test/handlers/fee/withOracle/distributeFee.js diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index cd12f5e5..0a225766 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -8,6 +8,7 @@ import "./utils/SafeCast.sol"; import "./interfaces/IDepositExecute.sol"; import "./interfaces/IERCHandler.sol"; import "./interfaces/IGenericHandler.sol"; +import "./interfaces/IFeeHandler.sol"; /** @title Facilitates deposits, creation and voting of deposit proposals, and deposit executions. @@ -21,9 +22,10 @@ contract Bridge is Pausable, AccessControl, SafeMath { uint8 public _domainID; uint8 public _relayerThreshold; - uint128 public _fee; uint40 public _expiry; + IFeeHandler public _feeHandler; + enum ProposalStatus {Inactive, Active, Passed, Executed, Cancelled} struct Proposal { @@ -45,6 +47,7 @@ contract Bridge is Pausable, AccessControl, SafeMath { event RelayerThresholdChanged(uint256 newThreshold); event RelayerAdded(address relayer); event RelayerRemoved(address relayer); + event FeeHandlerChanged(address newFeeHandler); event Deposit( uint8 destinationDomainID, bytes32 resourceID, @@ -125,10 +128,9 @@ contract Bridge is Pausable, AccessControl, SafeMath { @param initialRelayers Addresses that should be initially granted the relayer role. @param initialRelayerThreshold Number of votes needed for a deposit proposal to be considered passed. */ - constructor (uint8 domainID, address[] memory initialRelayers, uint256 initialRelayerThreshold, uint256 fee, uint256 expiry) public { + constructor (uint8 domainID, address[] memory initialRelayers, uint256 initialRelayerThreshold, uint256 expiry) public { _domainID = domainID; _relayerThreshold = initialRelayerThreshold.toUint8(); - _fee = fee.toUint128(); _expiry = expiry.toUint40(); _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); @@ -315,13 +317,13 @@ contract Bridge is Pausable, AccessControl, SafeMath { } /** - @notice Changes deposit fee. + @notice Changes deposit fee handler contract address. @notice Only callable by admin. - @param newFee Value {_fee} will be updated to. + @param newFeeHandler Address {_feeHandler} will be updated to. */ - function adminChangeFee(uint256 newFee) external onlyAdmin { - require(_fee != newFee, "Current fee is equal to new fee"); - _fee = newFee.toUint128(); + function adminChangeFeeHandler(address newFeeHandler) external onlyAdmin { + _feeHandler = IFeeHandler(newFeeHandler); + emit FeeHandlerChanged(newFeeHandler); } /** @@ -342,25 +344,31 @@ contract Bridge is Pausable, AccessControl, SafeMath { @notice Only callable when Bridge is not paused. @param destinationDomainID ID of chain deposit will be bridged to. @param resourceID ResourceID used to find address of handler to be used for deposit. - @param data Additional data to be passed to specified handler. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. @notice Emits {Deposit} event with all necessary parameters and a handler response. - ERC20Handler: responds with an empty data. - ERC721Handler: responds with the deposited token metadata acquired by calling a tokenURI method in the token contract. - GenericHandler: responds with the raw bytes returned from the call to the target contract. */ - function deposit(uint8 destinationDomainID, bytes32 resourceID, bytes calldata data) external payable whenNotPaused { - require(msg.value == _fee, "Incorrect fee supplied"); + function deposit(uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external payable whenNotPaused { + address sender = _msgSender(); + if (address(_feeHandler) == address(0)) { + require(msg.value == 0, "no FeeHandler, msg.value != 0"); + } else { + // Reverts on failure + _feeHandler.collectFee{value: msg.value}(sender, _domainID, destinationDomainID, resourceID, depositData, feeData); + } address handler = _resourceIDToHandlerAddress[resourceID]; require(handler != address(0), "resourceID not mapped to handler"); uint64 depositNonce = ++_depositCounts[destinationDomainID]; - address sender = _msgSender(); IDepositExecute depositHandler = IDepositExecute(handler); - bytes memory handlerResponse = depositHandler.deposit(resourceID, sender, data); + bytes memory handlerResponse = depositHandler.deposit(resourceID, sender, depositData); - emit Deposit(destinationDomainID, resourceID, depositNonce, sender, data, handlerResponse); + emit Deposit(destinationDomainID, resourceID, depositNonce, sender, depositData, handlerResponse); } /** @@ -489,16 +497,4 @@ contract Bridge is Pausable, AccessControl, SafeMath { emit ProposalEvent(domainID, depositNonce, ProposalStatus.Executed, dataHash); } - - /** - @notice Transfers eth in the contract to the specified addresses. The parameters addrs and amounts are mapped 1-1. - This means that the address at index 0 for addrs will receive the amount (in WEI) from amounts at index 0. - @param addrs Array of addresses to transfer {amounts} to. - @param amounts Array of amonuts to transfer to {addrs}. - */ - function transferFunds(address payable[] calldata addrs, uint[] calldata amounts) external onlyAdmin { - for (uint256 i = 0; i < addrs.length; i++) { - addrs[i].transfer(amounts[i]); - } - } } diff --git a/contracts/handlers/fee/BasicFeeHandler.sol b/contracts/handlers/fee/BasicFeeHandler.sol new file mode 100644 index 00000000..1b78f92a --- /dev/null +++ b/contracts/handlers/fee/BasicFeeHandler.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; +pragma experimental ABIEncoderV2; + +import "../../interfaces/IFeeHandler.sol"; +import "../../utils/AccessControl.sol"; + +/** + @title Handles deposit fees. + @author ChainSafe Systems. + @notice This contract is intended to be used with the Bridge contract. + */ +contract BasicFeeHandler is IFeeHandler, AccessControl { + address public immutable _bridgeAddress; + + uint256 public _fee; + + event FeeChanged( + uint256 newFee + ); + + modifier onlyBridge() { + _onlyBridge(); + _; + } + + function _onlyBridge() private view { + require(msg.sender == _bridgeAddress, "sender must be bridge contract"); + } + + /** + @param bridgeAddress Contract address of previously deployed Bridge. + */ + constructor(address bridgeAddress) public { + _bridgeAddress = bridgeAddress; + _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + /** + @notice Collects fee for deposit. + @param sender Sender of the deposit. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + */ + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridge { + require(msg.value == _fee, "Incorrect fee supplied"); + emit FeeCollected(sender, fromDomainID, destinationDomainID, resourceID, _fee, address(0)); + } + + /** + @notice Calculates fee for deposit. + @param sender Sender of the deposit. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + @return Returns the fee amount. + */ + function calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external view returns(uint256, address) { + return (_fee, address(0)); + } + + /** + @notice Sets new value of the fee. + @notice Only callable by admin. + @param newFee Value {_fee} will be updated to. + */ + function changeFee(uint256 newFee) external onlyAdmin { + require(_fee != newFee, "Current fee is equal to new fee"); + _fee = newFee; + emit FeeChanged(newFee); + } + + /** + @notice Transfers eth in the contract to the specified addresses. The parameters addrs and amounts are mapped 1-1. + This means that the address at index 0 for addrs will receive the amount (in WEI) from amounts at index 0. + @param addrs Array of addresses to transfer {amounts} to. + @param amounts Array of amonuts to transfer to {addrs}. + */ + function transferFee(address payable[] calldata addrs, uint[] calldata amounts) external onlyAdmin { + require(addrs.length == amounts.length, "addrs[], amounts[]: diff length"); + for (uint256 i = 0; i < addrs.length; i++) { + (bool success,) = addrs[i].call{value: amounts[i]}(""); + require(success, "Fee ether transfer failed"); + emit FeeDistributed(address(0), addrs[i], amounts[i]); + } + } + + modifier onlyAdmin() { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); + _; + } +} diff --git a/contracts/handlers/fee/FeeHandlerWithOracle.sol b/contracts/handlers/fee/FeeHandlerWithOracle.sol new file mode 100644 index 00000000..d51e75f0 --- /dev/null +++ b/contracts/handlers/fee/FeeHandlerWithOracle.sol @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +import "../../interfaces/IFeeHandler.sol"; +import "../../interfaces/IERCHandler.sol"; +import "../../interfaces/IBridge.sol"; +import "../../ERC20Safe.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/** + @title Handles deposit fees based on Effective rates provided by Fee oracle. + @author ChainSafe Systems. + @notice This contract is intended to be used with the Bridge contract. + */ +contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { + address public immutable _bridgeAddress; + + address public _oracleAddress; + + uint32 public _gasUsed; + uint16 public _feePercent; // multiplied by 100 to avoid precision loss + + struct OracleMessageType { + // Base Effective Rate - effective rate between base currencies of source and dest networks (eg. MATIC/ETH) + uint256 ber; + // Token Effective Rate - rate between base currency of destination network and token that is being trasferred (eg. MATIC/USDT) + uint256 ter; + uint256 dstGasPrice; + uint256 expiresAt; + uint8 fromDomainID; + uint8 toDomainID; + bytes32 resourceID; + } + + struct FeeDataType { + bytes message; + bytes sig; + uint256 amount; + } + + /** + @param bridgeAddress Contract address of previously deployed Bridge. + */ + constructor(address bridgeAddress) public { + _bridgeAddress = bridgeAddress; + _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + // Admin functions + + /** + @notice Sets the fee oracle address for signature verification. + @param oracleAddress Fee oracle address. + */ + function setFeeOracle(address oracleAddress) external onlyAdmin { + _oracleAddress = oracleAddress; + } + + /** + @notice Sets the fee properties. + @param gasUsed Gas used for transfer. + @param feePercent Added to fee amount. total fee = fee + fee * feePercent + */ + function setFeeProperties(uint32 gasUsed, uint16 feePercent) external onlyAdmin { + _gasUsed = gasUsed; + _feePercent = feePercent; + } + + /** + @notice Collects fee for deposit. + @param sender Sender of the deposit. + @param fromDomainID ID of the source chain. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + */ + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridge { + require(msg.value == 0, "collectFee: msg.value != 0"); + (uint256 fee, address tokenAddress) = _calculateFee(sender, fromDomainID, destinationDomainID, resourceID, depositData, feeData); + lockERC20(tokenAddress, sender, address(this), fee); + emit FeeCollected(sender, fromDomainID, destinationDomainID, resourceID, fee, tokenAddress); + } + + /** + @notice Calculates fee for deposit. + @param sender Sender of the deposit. + @param fromDomainID ID of the source chain. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + @return fee Returns the fee amount. + @return tokenAddress Returns the address of the token to be used for fee. + */ + function calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external view returns(uint256 fee, address tokenAddress) { + return _calculateFee(sender, fromDomainID, destinationDomainID, resourceID, depositData, feeData); + } + + function _calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) internal view returns(uint256 fee, address tokenAddress) { + /** + Message: + ber * 10^18: uint256 + ter * 10^18: uint256 + dstGasPrice: uint256 + expiresAt: uint256 + fromDomainID: uint8 encoded as uint256 + toDomainID: uint8 encoded as uint256 + resourceID: bytes32 + sig: bytes(65 bytes) + + total in bytes: + message: + 32 * 7 = 224 + message + sig: + 224 + 65 = 289 + + amount: uint256 + total: 321 + */ + + require(feeData.length == 321, "Incorrect feeData length"); + + FeeDataType memory feeDataDecoded; + + feeDataDecoded.message = bytes(feeData[: 224]); + feeDataDecoded.sig = bytes(feeData[224: 289]); + feeDataDecoded.amount = abi.decode(feeData[289:], (uint256)); + + OracleMessageType memory oracleMessage = abi.decode(feeDataDecoded.message, (OracleMessageType)); + require(block.timestamp <= oracleMessage.expiresAt, "Obsolete oracle data"); + require((oracleMessage.fromDomainID == fromDomainID) + && (oracleMessage.toDomainID == destinationDomainID) + && (oracleMessage.resourceID == resourceID), + "Incorrect deposit params" + ); + + bytes32 messageHash = keccak256(feeDataDecoded.message); + + verifySig(messageHash, feeDataDecoded.sig, _oracleAddress); + + address tokenHandler = IBridge(_bridgeAddress)._resourceIDToHandlerAddress(resourceID); + address tokenAddress = IERCHandler(tokenHandler)._resourceIDToTokenContractAddress(resourceID); + + // txCost = dstGasPrice * _gasUsed * Token Effective Rate (rate of dest base currency to token) + uint256 txCost = oracleMessage.dstGasPrice * _gasUsed * oracleMessage.ter / 1e18; + + fee = feeDataDecoded.amount * _feePercent / 1e4; // 100 for percent and 100 to avoid precision loss + + if (fee < txCost) { + fee = txCost; + } + return (fee, tokenAddress); + } + + /** + @notice Transfers tokens from the contract to the specified addresses. The parameters addrs and amounts are mapped 1-1. + This means that the address at index 0 for addrs will receive the amount of tokens from amounts at index 0. + @param resourceID ResourceID of the token. + @param addrs Array of addresses to transfer {amounts} to. + @param amounts Array of amounts to transfer to {addrs}. + */ + function transferFee(bytes32 resourceID, address[] calldata addrs, uint[] calldata amounts) external onlyAdmin { + require(addrs.length == amounts.length, "addrs[], amounts[]: diff length"); + address tokenHandler = IBridge(_bridgeAddress)._resourceIDToHandlerAddress(resourceID); + address tokenAddress = IERCHandler(tokenHandler)._resourceIDToTokenContractAddress(resourceID); + for (uint256 i = 0; i < addrs.length; i++) { + releaseERC20(tokenAddress, addrs[i], amounts[i]); + emit FeeDistributed(tokenAddress, addrs[i], amounts[i]); + } + } + + function verifySig(bytes32 message, bytes memory signature, address signerAddress) internal view { + address signerAddressRecovered = ECDSA.recover(message, signature); + require(signerAddressRecovered == signerAddress, 'Invalid signature'); + } + + modifier onlyAdmin() { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); + _; + } + + modifier onlyBridge() { + _onlyBridge(); + _; + } + + function _onlyBridge() private view { + require(msg.sender == _bridgeAddress, "sender must be bridge contract"); + } +} diff --git a/contracts/interfaces/IBridge.sol b/contracts/interfaces/IBridge.sol index 4f36d63d..514514ee 100644 --- a/contracts/interfaces/IBridge.sol +++ b/contracts/interfaces/IBridge.sol @@ -11,4 +11,11 @@ interface IBridge { @return uint8 The {_domainID} that is currently set for the Bridge contract. */ function _domainID() external returns (uint8); + + /** + @notice Exposing getter for {_resourceIDToHandlerAddress}. + @param resourceID ResourceID to be used when making deposits. + @return address The {handlerAddress} that is currently set for the resourceID. + */ + function _resourceIDToHandlerAddress(bytes32 resourceID) external view returns (address); } \ No newline at end of file diff --git a/contracts/interfaces/IERCHandler.sol b/contracts/interfaces/IERCHandler.sol index 121e6164..fdf06a0f 100644 --- a/contracts/interfaces/IERCHandler.sol +++ b/contracts/interfaces/IERCHandler.sol @@ -23,4 +23,11 @@ interface IERCHandler { @param data ABI-encoded withdrawal params relevant to the handler. */ function withdraw(bytes memory data) external; + + /** + @notice Exposing getter for {_resourceIDToTokenContractAddress}. + @param resourceID ResourceID to be used. + @return address The {tokenContractAddress} that is currently set for the resourceID. + */ + function _resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address); } diff --git a/contracts/interfaces/IFeeHandler.sol b/contracts/interfaces/IFeeHandler.sol new file mode 100644 index 00000000..c2c1a331 --- /dev/null +++ b/contracts/interfaces/IFeeHandler.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; + +/** + @title Interface to be used with fee handlers. + @author ChainSafe Systems. + */ +interface IFeeHandler { + + /** + @notice This event is emitted when the fee is collected. + @param sender Sender of the deposit. + @param fromDomainID ID of the source chain. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param fee Collected fee amount. + @param tokenAddress Address of the token in which the fee was collected (0 for the base currency). + */ + event FeeCollected( + address sender, + uint8 fromDomainID, + uint8 destinationDomainID, + bytes32 resourceID, + uint256 fee, + address tokenAddress + ); + + /** + @notice This event is emitted when the fee is distributed to an address. + @param tokenAddress Address of the token in which the fee was collected (0 for the base currency). + @param recipient Address that receives the distributed fee. + @param amount Amount that is distributed. + */ + event FeeDistributed( + address tokenAddress, + address recipient, + uint256 amount + ); + + /** + @notice Collects fee for deposit. + @param sender Sender of the deposit. + @param fromDomainID ID of the source chain. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + */ + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external; + + /** + @notice Calculates fee for deposit. + @param sender Sender of the deposit. + @param fromDomainID ID of the source chain. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + @return Returns the fee amount. + */ + function calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external view returns(uint256, address); +} diff --git a/package-lock.json b/package-lock.json index 5589cfba..0b219a63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21583 +1,14 @@ { "name": "@chainsafe/chainbridge-contracts", "version": "2.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "@chainsafe/chainbridge-contracts", - "version": "2.0.0", - "license": "GPL-3.0-only", - "devDependencies": { - "@babel/core": "^7.17.4", - "@codechecks/client": "^0.1.12", - "@openzeppelin/contracts": "^4.5.0", - "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-node-resolve": "^13.1.3", - "@typechain/ethers-v5": "^9.0.0", - "commander": "^9.0.0", - "coveralls": "^3.1.1", - "eth-sig-util": "^3.0.1", - "ethereumjs-wallet": "^1.0.2", - "ethers": "^5.5.4", - "ganache-cli": "^6.9.1", - "lodash.template": "^4.5.0", - "rimraf": "^3.0.2", - "rollup": "^2.67.2", - "rollup-plugin-node-polyfills": "^0.2.1", - "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-typescript2": "^0.31.2", - "solidity-coverage": "^0.7.20", - "truffle": "^5.4.32", - "truffle-assertions": "^0.9.2", - "typechain": "^7.0.0", - "typescript": "^4.5.5" - }, - "peerDependencies": { - "ethers": ">= 5.0.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@apollo/protobufjs": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.2.tgz", - "integrity": "sha512-vF+zxhPiLtkwxONs6YanSt1EpwpGilThpneExUN5K3tCymuxNnVq2yojTvnpRjv2QfsEIt/n7ozPIIzBLwGIDQ==", - "dev": true, - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.0", - "@types/node": "^10.1.0", - "long": "^4.0.0" - }, - "bin": { - "apollo-pbjs": "bin/pbjs", - "apollo-pbts": "bin/pbts" - } - }, - "node_modules/@apollo/protobufjs/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "dev": true, - "optional": true - }, - "node_modules/@apollographql/apollo-tools": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.2.tgz", - "integrity": "sha512-KxZiw0Us3k1d0YkJDhOpVH5rJ+mBfjXcgoRoCcslbgirjgLotKMzOcx4PZ7YTEvvEROmvG7X3Aon41GvMmyGsw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8", - "npm": ">=6" - } - }, - "node_modules/@apollographql/graphql-playground-html": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz", - "integrity": "sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw==", - "dev": true, - "optional": true, - "dependencies": { - "xss": "^1.0.8" - } - }, - "node_modules/@apollographql/graphql-upload-8-fork": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-upload-8-fork/-/graphql-upload-8-fork-8.1.3.tgz", - "integrity": "sha512-ssOPUT7euLqDXcdVv3Qs4LoL4BPtfermW1IOouaqEmj36TpHYDmYDIbKoSQxikd9vtMumFnP87OybH7sC9fJ6g==", - "dev": true, - "optional": true, - "dependencies": { - "@types/express": "*", - "@types/fs-capacitor": "*", - "@types/koa": "*", - "busboy": "^0.3.1", - "fs-capacitor": "^2.0.4", - "http-errors": "^1.7.3", - "object-path": "^0.11.4" - }, - "engines": { - "node": ">=8.5" - } - }, - "node_modules/@apollographql/graphql-upload-8-fork/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "optional": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollographql/graphql-upload-8-fork/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "optional": true - }, - "node_modules/@apollographql/graphql-upload-8-fork/node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", - "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.17.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.4.tgz", - "integrity": "sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.2", - "@babel/parser": "^7.17.3", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", - "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.17.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", - "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.0", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", - "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.0.tgz", - "integrity": "sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@codechecks/client": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@codechecks/client/-/client-0.1.12.tgz", - "integrity": "sha512-2GHHvhO3kaOyxFXxOaiznlY8ARmz33/p+WQdhc2y6wzWw5eOl2wSwg1eZxx3LsWlAnB963Y4bd1YjZcGIhKRzA==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.3", - "chalk": "^2.4.2", - "commander": "^2.19.0", - "debug": "^4.1.1", - "execa": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "js-yaml": "^3.13.1", - "json5": "^2.1.0", - "lodash": "^4.17.11", - "marked": "^0.7.0", - "marked-terminal": "^3.3.0", - "mkdirp": "^0.5.1", - "ms": "^2.1.1", - "promise": "^8.0.2", - "request": "^2.88.0", - "request-promise": "^4.2.2", - "ts-essentials": "^1.0.2", - "ts-node": "^8.0.2", - "url-join": "^4.0.0" - }, - "bin": { - "codechecks": "dist/runner.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@codechecks/client/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/@consento/sync-randombytes": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@consento/sync-randombytes/-/sync-randombytes-1.0.5.tgz", - "integrity": "sha512-mPJ2XvrTLQGEdhleDuSIkWtVWnvmhREOC1FjorV1nlK49t/52Z9X1d618gTj6nlQghRLiYvcd8oL4vZ2YZuDIQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.4.3", - "seedrandom": "^3.0.5" - } - }, - "node_modules/@ethereumjs/common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz", - "integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==", - "dev": true, - "dependencies": { - "crc-32": "^1.2.0", - "ethereumjs-util": "^7.1.0" - } - }, - "node_modules/@ethereumjs/tx": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz", - "integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.4.0", - "ethereumjs-util": "^7.1.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.5.0.tgz", - "integrity": "sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz", - "integrity": "sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz", - "integrity": "sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.5.0.tgz", - "integrity": "sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/rlp": "^5.5.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.5.0.tgz", - "integrity": "sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.5.0.tgz", - "integrity": "sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/properties": "^5.5.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.5.0.tgz", - "integrity": "sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "bn.js": "^4.11.9" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz", - "integrity": "sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.5.0.tgz", - "integrity": "sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.5.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.5.0.tgz", - "integrity": "sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.5.0.tgz", - "integrity": "sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/@ethersproject/logger": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz", - "integrity": "sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.5.2.tgz", - "integrity": "sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.5.0.tgz", - "integrity": "sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.5.3.tgz", - "integrity": "sha512-ZHXxXXXWHuwCQKrgdpIkbzMNJMvs+9YWemanwp1fA7XZEv7QlilseysPvQe0D7Q7DlkJX/w/bGA1MdgK2TbGvA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/basex": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/networks": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/web": "^5.5.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/random": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.5.1.tgz", - "integrity": "sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.5.0.tgz", - "integrity": "sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.5.0.tgz", - "integrity": "sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.5.0.tgz", - "integrity": "sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.5.0.tgz", - "integrity": "sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.5.0.tgz", - "integrity": "sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/rlp": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.5.1.tgz", - "integrity": "sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/base64": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "node_modules/@graphql-tools/batch-execute": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.1.tgz", - "integrity": "sha512-63kHY8ZdoO5FoeDXYHnAak1R3ysMViMPwWC2XUblFckuVLMUPmB2ONje8rjr2CvzWBHAW8c1Zsex+U3xhKtGIA==", - "dev": true, - "optional": true, - "dependencies": { - "@graphql-tools/utils": "^8.5.1", - "dataloader": "2.0.0", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - } - }, - "node_modules/@graphql-tools/delegate": { - "version": "8.4.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.4.3.tgz", - "integrity": "sha512-hKTJdJXJnKL0+2vpU+Kt7OHQTIXZ9mBmNBwHsYiG5WNArz/vNI7910r6TC2XMf/e7zhyyK+mXxMDBmDQkkJagA==", - "dev": true, - "optional": true, - "dependencies": { - "@graphql-tools/batch-execute": "^8.3.1", - "@graphql-tools/schema": "^8.3.1", - "@graphql-tools/utils": "^8.5.4", - "dataloader": "2.0.0", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - } - }, - "node_modules/@graphql-tools/merge": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.2.tgz", - "integrity": "sha512-2DyqhIOMUMKbCPqo8p6xSdll2OBcBxGdOrxlJJlFQvinsSaYqp/ct3dhAxNtzaIcvSVgXvttQqfD7O2ziFtE7Q==", - "dev": true, - "optional": true, - "dependencies": { - "@graphql-tools/utils": "^8.5.1", - "tslib": "~2.3.0" - } - }, - "node_modules/@graphql-tools/schema": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", - "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", - "dev": true, - "optional": true, - "dependencies": { - "@graphql-tools/merge": "^8.2.1", - "@graphql-tools/utils": "^8.5.1", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - } - }, - "node_modules/@graphql-tools/utils": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.1.tgz", - "integrity": "sha512-uxcfHCocp4ENoIiovPxUWZEHOnbXqj3ekWc0rm7fUhW93a1xheARNHcNKhwMTR+UKXVJbTFQdGI1Rl5XdyvDBg==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "~2.3.0" - } - }, - "node_modules/@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "optional": true, - "dependencies": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@improbable-eng/grpc-web": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.13.0.tgz", - "integrity": "sha512-vaxxT+Qwb7GPqDQrBV4vAAfH0HywgOLw6xGIKXd9Q8hcV63CQhmS3p4+pZ9/wVvt4Ph3ZDK9fdC983b9aGMUFg==", - "dev": true, - "optional": true, - "dependencies": { - "browser-headers": "^0.4.0" - } - }, - "node_modules/@josephg/resolvable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", - "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==", - "dev": true, - "optional": true - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@ledgerhq/devices": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", - "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/logs": "^5.50.0", - "rxjs": "6", - "semver": "^7.3.5" - } - }, - "node_modules/@ledgerhq/devices/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@ledgerhq/errors": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", - "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", - "dev": true, - "optional": true - }, - "node_modules/@ledgerhq/hw-transport": { - "version": "5.51.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", - "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "events": "^3.3.0" - } - }, - "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "5.53.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-5.53.1.tgz", - "integrity": "sha512-A/f+xcrkIAZiJrvPpDvsrjxQX4cI2kbdiunQkwsYmOG3Bp4z89ZnsBiC7YBst4n2/g+QgTg0/KPVtODU5djooQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/devices": "^5.51.1", - "@ledgerhq/errors": "^5.50.0", - "@ledgerhq/hw-transport": "^5.51.1", - "@ledgerhq/logs": "^5.50.0" - } - }, - "node_modules/@ledgerhq/logs": { - "version": "5.50.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", - "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", - "dev": true, - "optional": true - }, - "node_modules/@multiformats/base-x": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz", - "integrity": "sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==", - "dev": true, - "optional": true - }, - "node_modules/@nodefactory/filsnap-adapter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@nodefactory/filsnap-adapter/-/filsnap-adapter-0.2.2.tgz", - "integrity": "sha512-nbaYMwVopOXN2bWOdDY3il6gGL9qMuCmMN4WPuoxzJjSnAMJNqEeSe6MNNJ/fYBLipZcJfAtirNXRrFLFN+Tvw==", - "dev": true, - "optional": true - }, - "node_modules/@nodefactory/filsnap-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@nodefactory/filsnap-types/-/filsnap-types-0.2.2.tgz", - "integrity": "sha512-XT1tE2vrYF2D0tSNNekgjqKRpqPQn4W72eKul9dDCul/8ykouhqnVTyjFHYvBhlBWE0PK3nmG7i83QvhgGSiMw==", - "dev": true, - "optional": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@openzeppelin/contracts": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", - "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==", - "dev": true - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "dev": true, - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=", - "dev": true, - "optional": true - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", - "dev": true, - "optional": true - }, - "node_modules/@redux-saga/core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz", - "integrity": "sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.6.3", - "@redux-saga/deferred": "^1.1.2", - "@redux-saga/delay-p": "^1.1.2", - "@redux-saga/is": "^1.1.2", - "@redux-saga/symbols": "^1.1.2", - "@redux-saga/types": "^1.1.0", - "redux": "^4.0.4", - "typescript-tuple": "^2.2.1" - } - }, - "node_modules/@redux-saga/core/node_modules/redux": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz", - "integrity": "sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.9.2" - } - }, - "node_modules/@redux-saga/deferred": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz", - "integrity": "sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ==", - "dev": true - }, - "node_modules/@redux-saga/delay-p": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz", - "integrity": "sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g==", - "dev": true, - "dependencies": { - "@redux-saga/symbols": "^1.1.2" - } - }, - "node_modules/@redux-saga/is": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz", - "integrity": "sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w==", - "dev": true, - "dependencies": { - "@redux-saga/symbols": "^1.1.2", - "@redux-saga/types": "^1.1.0" - } - }, - "node_modules/@redux-saga/symbols": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz", - "integrity": "sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ==", - "dev": true - }, - "node_modules/@redux-saga/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz", - "integrity": "sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==", - "dev": true - }, - "node_modules/@repeaterjs/repeater": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", - "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==", - "dev": true, - "optional": true - }, - "node_modules/@rollup/plugin-babel": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz", - "integrity": "sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz", - "integrity": "sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^2.38.3" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz", - "integrity": "sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^2.42.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@solidity-parser/parser": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz", - "integrity": "sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw==", - "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@textile/buckets": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@textile/buckets/-/buckets-6.2.2.tgz", - "integrity": "sha512-oagOO305aDJypvwRcjC4xSDAvLgAeNRzDHzzK2fyBVz30ymYAxOLSXKUqgHyHTl36fKfZ6QvYUxshtPvUSEwbQ==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@repeaterjs/repeater": "^3.0.4", - "@textile/buckets-grpc": "2.6.6", - "@textile/context": "^0.12.1", - "@textile/crypto": "^4.2.1", - "@textile/grpc-authentication": "^3.4.3", - "@textile/grpc-connection": "^2.5.2", - "@textile/grpc-transport": "^0.5.2", - "@textile/hub-grpc": "2.6.6", - "@textile/hub-threads-client": "^5.5.2", - "@textile/security": "^0.9.1", - "@textile/threads-id": "^0.6.1", - "abort-controller": "^3.0.0", - "cids": "^1.1.4", - "it-drain": "^1.0.3", - "loglevel": "^1.6.8", - "native-abort-controller": "^1.0.3", - "paramap-it": "^0.1.1" - } - }, - "node_modules/@textile/buckets-grpc": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@textile/buckets-grpc/-/buckets-grpc-2.6.6.tgz", - "integrity": "sha512-Gg+96RviTLNnSX8rhPxFgREJn3Ss2wca5Szk60nOenW+GoVIc+8dtsA9bE/6Vh5Gn85zAd17m1C2k6PbJK8x3Q==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@types/google-protobuf": "^3.7.4", - "google-protobuf": "^3.13.0" - } - }, - "node_modules/@textile/buckets/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/@textile/buckets/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/buckets/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/@textile/buckets/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/buckets/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/@textile/buckets/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@textile/buckets/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@textile/context": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@textile/context/-/context-0.12.1.tgz", - "integrity": "sha512-3UDkz0YjwpWt8zY8NBkZ9UqqlR2L9Gv6t2TAXAQT+Rh/3/X0IAFGQlAaFT5wdGPN2nqbXDeEOFfkMs/T2K02Iw==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@textile/security": "^0.9.1" - } - }, - "node_modules/@textile/crypto": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@textile/crypto/-/crypto-4.2.1.tgz", - "integrity": "sha512-7qxFLrXiSq5Tf3Wh3Oh6JKJMitF/6N3/AJyma6UAA8iQnAZBF98ShWz9tR59a3dvmGTc9MlyplOm16edbccscg==", - "dev": true, - "optional": true, - "dependencies": { - "@types/ed2curve": "^0.2.2", - "ed2curve": "^0.3.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "multibase": "^3.1.0", - "tweetnacl": "^1.0.3" - } - }, - "node_modules/@textile/crypto/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/crypto/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true, - "optional": true - }, - "node_modules/@textile/grpc-authentication": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@textile/grpc-authentication/-/grpc-authentication-3.4.3.tgz", - "integrity": "sha512-9kSjtcfavzfL/FGHXGiW5ft+74xzfozBFsT4+um3BQE5tkO6VYezpqNyGy+/1Hu7gtV97xhqEeKjuX9ZW8HURQ==", - "dev": true, - "optional": true, - "dependencies": { - "@textile/context": "^0.12.1", - "@textile/crypto": "^4.2.1", - "@textile/grpc-connection": "^2.5.2", - "@textile/hub-threads-client": "^5.5.2", - "@textile/security": "^0.9.1" - } - }, - "node_modules/@textile/grpc-connection": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@textile/grpc-connection/-/grpc-connection-2.5.2.tgz", - "integrity": "sha512-icvBwzT6+hhCjMTv0CEMpssGBIZpHQ5e4PKNqeeTYm68VivP3eCYUGqflzMJud6a2SwXMs7naThBYWI23vaOfQ==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.12.0", - "@textile/context": "^0.12.1", - "@textile/grpc-transport": "^0.5.2" - } - }, - "node_modules/@textile/grpc-connection/node_modules/@improbable-eng/grpc-web": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.12.0.tgz", - "integrity": "sha512-uJjgMPngreRTYPBuo6gswMj1gK39Wbqre/RgE0XnSDXJRg6ST7ZhuS53dFE6Vc2CX4jxgl+cO+0B3op8LA4Q0Q==", - "dev": true, - "optional": true, - "dependencies": { - "browser-headers": "^0.4.0" - } - }, - "node_modules/@textile/grpc-powergate-client": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@textile/grpc-powergate-client/-/grpc-powergate-client-2.6.2.tgz", - "integrity": "sha512-ODe22lveqPiSkBsxnhLIRKQzZVwvyqDVx6WBPQJZI4yxrja5SDOq6/yH2Dtmqyfxg8BOobFvn+tid3wexRZjnQ==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.14.0", - "@types/google-protobuf": "^3.15.2", - "google-protobuf": "^3.17.3" - } - }, - "node_modules/@textile/grpc-powergate-client/node_modules/@improbable-eng/grpc-web": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", - "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", - "dev": true, - "optional": true, - "dependencies": { - "browser-headers": "^0.4.1" - } - }, - "node_modules/@textile/grpc-transport": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@textile/grpc-transport/-/grpc-transport-0.5.2.tgz", - "integrity": "sha512-XEC+Ubs7/pibZU2AHDJLeCEAVNtgEWmEXBXYJubpp4SVviuGUyd4h+zvqLw4FiIBGtlxx1u//cmzANhL0Ew7Rw==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@types/ws": "^7.2.6", - "isomorphic-ws": "^4.0.1", - "loglevel": "^1.6.6", - "ws": "^7.2.1" - } - }, - "node_modules/@textile/hub": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@textile/hub/-/hub-6.3.2.tgz", - "integrity": "sha512-MyAGNOxVyXpFYPscPaJxlsQL0G90cdy1bfw8xu25Gy6xdDi0tYuvtff//p422YUrYd4MGPOFX2pul61JwtLlsw==", - "dev": true, - "optional": true, - "dependencies": { - "@textile/buckets": "^6.2.2", - "@textile/crypto": "^4.2.1", - "@textile/grpc-authentication": "^3.4.3", - "@textile/hub-filecoin": "^2.2.2", - "@textile/hub-grpc": "2.6.6", - "@textile/hub-threads-client": "^5.5.2", - "@textile/security": "^0.9.1", - "@textile/threads-id": "^0.6.1", - "@textile/users": "^6.2.2", - "loglevel": "^1.6.8", - "multihashes": "3.1.2" - } - }, - "node_modules/@textile/hub-filecoin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@textile/hub-filecoin/-/hub-filecoin-2.2.2.tgz", - "integrity": "sha512-RxvKfXkuhOCvD/qv6rg3tXfkkPN1OF9xXX8o2MeZcXt64TdD6hxJy9lUES5FpAKSkjvalfXA0e2TxaFrT4erjg==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.12.0", - "@textile/context": "^0.12.1", - "@textile/crypto": "^4.2.1", - "@textile/grpc-authentication": "^3.4.3", - "@textile/grpc-connection": "^2.5.2", - "@textile/grpc-powergate-client": "^2.6.2", - "@textile/hub-grpc": "2.6.6", - "@textile/security": "^0.9.1", - "event-iterator": "^2.0.0", - "loglevel": "^1.6.8" - } - }, - "node_modules/@textile/hub-filecoin/node_modules/@improbable-eng/grpc-web": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.12.0.tgz", - "integrity": "sha512-uJjgMPngreRTYPBuo6gswMj1gK39Wbqre/RgE0XnSDXJRg6ST7ZhuS53dFE6Vc2CX4jxgl+cO+0B3op8LA4Q0Q==", - "dev": true, - "optional": true, - "dependencies": { - "browser-headers": "^0.4.0" - } - }, - "node_modules/@textile/hub-filecoin/node_modules/event-iterator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", - "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==", - "dev": true, - "optional": true - }, - "node_modules/@textile/hub-grpc": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@textile/hub-grpc/-/hub-grpc-2.6.6.tgz", - "integrity": "sha512-PHoLUE1lq0hyiVjIucPHRxps8r1oafXHIgmAR99+Lk4TwAF2MXx5rfxYhg1dEJ3ches8ZuNbVGkiNIXroIoZ8Q==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@types/google-protobuf": "^3.7.4", - "google-protobuf": "^3.13.0" - } - }, - "node_modules/@textile/hub-threads-client": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@textile/hub-threads-client/-/hub-threads-client-5.5.2.tgz", - "integrity": "sha512-j18fK6R0u5hRvbXz3X5Cp+GMLOTCodNnEVVyPP3dxuMt60+hMtcFdbc80NW58RU6an9C6iv1BGK+BMbry3HkSQ==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@textile/context": "^0.12.1", - "@textile/hub-grpc": "2.6.6", - "@textile/security": "^0.9.1", - "@textile/threads-client": "^2.3.2", - "@textile/threads-id": "^0.6.1", - "@textile/users-grpc": "2.6.6", - "loglevel": "^1.7.0" - } - }, - "node_modules/@textile/hub/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/hub/node_modules/multihashes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-3.1.2.tgz", - "integrity": "sha512-AP4IoV/YzkNrfbQKZE3OMPibrmy350OmCd6cJkwyM8oExaXIlOY4UnOOVSQtAEuq/LR01XfXKCESidzZvSwHCQ==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/hub/node_modules/uint8arrays": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz", - "integrity": "sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@textile/hub/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@textile/multiaddr": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@textile/multiaddr/-/multiaddr-0.6.1.tgz", - "integrity": "sha512-OQK/kXYhtUA8yN41xltCxCiCO98Pkk8yMgUdhPDAhogvptvX4k9g6Rg0Yob18uBwN58AYUg075V//SWSK1kUCQ==", - "dev": true, - "optional": true, - "dependencies": { - "@textile/threads-id": "^0.6.1", - "multiaddr": "^8.1.2", - "varint": "^6.0.0" - } - }, - "node_modules/@textile/multiaddr/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@textile/security": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@textile/security/-/security-0.9.1.tgz", - "integrity": "sha512-pmiSOUezV/udTMoQsvyEZwZFfN0tMo6dOAof4VBqyFdDZZV6doeI5zTDpqSJZTg69n0swfWxsHw96ZWQIoWvsw==", - "dev": true, - "optional": true, - "dependencies": { - "@consento/sync-randombytes": "^1.0.5", - "fast-sha256": "^1.3.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "multibase": "^3.1.0" - } - }, - "node_modules/@textile/security/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/threads-client": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@textile/threads-client/-/threads-client-2.3.2.tgz", - "integrity": "sha512-T3zaMSufY6Crxk3rDfn71wm6phF6nTfNo3F+MHmwCNpxFaztngT11Ao0UkyGlBLK8A4PoxElkXP02BTunue75g==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@textile/context": "^0.12.1", - "@textile/crypto": "^4.2.1", - "@textile/grpc-transport": "^0.5.2", - "@textile/multiaddr": "^0.6.1", - "@textile/security": "^0.9.1", - "@textile/threads-client-grpc": "^1.1.1", - "@textile/threads-id": "^0.6.1", - "@types/to-json-schema": "^0.2.0", - "fastestsmallesttextencoderdecoder": "^1.0.22", - "to-json-schema": "^0.2.5" - } - }, - "node_modules/@textile/threads-client-grpc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@textile/threads-client-grpc/-/threads-client-grpc-1.1.2.tgz", - "integrity": "sha512-LPL6+skRww44VPuqJz8qXOHBkwPlL7+zUKfndjo2duOq+RZilDm40uLXwnM1/eVmAo1A7mb9XIJAo0u7qYtmCg==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.14.0", - "@types/google-protobuf": "^3.15.5", - "google-protobuf": "^3.17.3" - } - }, - "node_modules/@textile/threads-client-grpc/node_modules/@improbable-eng/grpc-web": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", - "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", - "dev": true, - "optional": true, - "dependencies": { - "browser-headers": "^0.4.1" - } - }, - "node_modules/@textile/threads-id": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@textile/threads-id/-/threads-id-0.6.1.tgz", - "integrity": "sha512-KwhbLjZ/eEquPorGgHFotw4g0bkKLTsqQmnsIxFeo+6C1mz40PQu4IOvJwohHr5GL6wedjlobry4Jj+uI3N+0w==", - "dev": true, - "optional": true, - "dependencies": { - "@consento/sync-randombytes": "^1.0.4", - "multibase": "^3.1.0", - "varint": "^6.0.0" - } - }, - "node_modules/@textile/threads-id/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@textile/threads-id/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@textile/users": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@textile/users/-/users-6.2.2.tgz", - "integrity": "sha512-aAT2NwnyZLgNRx5ve0qeQkrBK9Ek6nwSn1kh9mGTXemRP6JYGboqx1nJOHbxB6gA6sLP/K30xCwE6B+TQg6wDQ==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@textile/buckets-grpc": "2.6.6", - "@textile/context": "^0.12.1", - "@textile/crypto": "^4.2.1", - "@textile/grpc-authentication": "^3.4.3", - "@textile/grpc-connection": "^2.5.2", - "@textile/grpc-transport": "^0.5.2", - "@textile/hub-grpc": "2.6.6", - "@textile/hub-threads-client": "^5.5.2", - "@textile/security": "^0.9.1", - "@textile/threads-id": "^0.6.1", - "@textile/users-grpc": "2.6.6", - "event-iterator": "^2.0.0", - "loglevel": "^1.7.0" - } - }, - "node_modules/@textile/users-grpc": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@textile/users-grpc/-/users-grpc-2.6.6.tgz", - "integrity": "sha512-pzI/jAWJx1/NqvSj03ukn2++aDNRdnyjwgbxh2drrsuxRZyCQEa1osBAA+SDkH5oeRf6dgxrc9dF8W1Ttjn0Yw==", - "dev": true, - "optional": true, - "dependencies": { - "@improbable-eng/grpc-web": "^0.13.0", - "@types/google-protobuf": "^3.7.4", - "google-protobuf": "^3.13.0" - } - }, - "node_modules/@textile/users/node_modules/event-iterator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", - "integrity": "sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/abi-utils": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.8.tgz", - "integrity": "sha512-n/9ojMthWuP1hg9JveuxctxWoRoKTh+/17RTSwlTlXTyP/kfoNxr1JcLecybXUDOIsLJ4uskqxVUZQDvj1B0PQ==", - "dev": true, - "dependencies": { - "change-case": "3.0.2", - "faker": "^5.3.1", - "fast-check": "^2.12.1" - } - }, - "node_modules/@truffle/code-utils": { - "version": "1.2.32", - "resolved": "https://registry.npmjs.org/@truffle/code-utils/-/code-utils-1.2.32.tgz", - "integrity": "sha512-OUP1zO8kkIGt+PhCfLZqai8K9Kel5eDYKvr/Z3ubt4RyTSb1rNwtnmJbiEszVhdsO7/Qi/w/vbW0ebS0clcjyg==", - "dev": true, - "dependencies": { - "cbor": "^5.1.0" - } - }, - "node_modules/@truffle/codec": { - "version": "0.11.25", - "resolved": "https://registry.npmjs.org/@truffle/codec/-/codec-0.11.25.tgz", - "integrity": "sha512-ZLKxSBznktm6sxHvyoyytfgh9XKxn1Sx7ByG6vLeJX5+2kUeAZ/RrtVm8Zd03vxr8WvmzWiU9jL7RFFH5NdpMw==", - "dev": true, - "dependencies": { - "@truffle/abi-utils": "^0.2.8", - "@truffle/compile-common": "^0.7.26", - "big.js": "^5.2.2", - "bn.js": "^5.1.3", - "cbor": "^5.1.0", - "debug": "^4.3.1", - "lodash.clonedeep": "^4.5.0", - "lodash.escaperegexp": "^4.1.2", - "lodash.partition": "^4.6.0", - "lodash.sum": "^4.0.2", - "semver": "^7.3.4", - "utf8": "^3.0.0", - "web3-utils": "1.5.3" - } - }, - "node_modules/@truffle/codec/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/@truffle/codec/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/codec/node_modules/eth-lib/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/codec/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@truffle/codec/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/codec/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/compile-common": { - "version": "0.7.26", - "resolved": "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.26.tgz", - "integrity": "sha512-eHcplTfknX8ezBxxJgKBH6+AD3ufwo+fnlJd+JnMmPb6ndMcxyDpP/eepjLSNfzUdQSkd9n7ECvA0QIOdnNQuQ==", - "dev": true, - "dependencies": { - "@truffle/error": "^0.0.15", - "colors": "1.4.0" - } - }, - "node_modules/@truffle/compile-common/node_modules/@truffle/error": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.15.tgz", - "integrity": "sha512-keiYGlVAH7GLggqMpB+XorT7NkOlr3qeBc56thI2WP0eas3qstlyrc0WvckXJ2LXrOfcR2uH6f0Nk6FIxaKXSA==", - "dev": true - }, - "node_modules/@truffle/compile-common/node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@truffle/config": { - "version": "1.3.17", - "resolved": "https://registry.npmjs.org/@truffle/config/-/config-1.3.17.tgz", - "integrity": "sha512-1pmBu3rzv3nixoiIXJMqVDsGIAw2zxj8uIImeTqCE/2/y3x4eDY5U9fzqqD/Iss2me7lwc+LWkIS49icj86Ejg==", - "dev": true, - "optional": true, - "dependencies": { - "@truffle/error": "^0.0.15", - "@truffle/events": "^0.1.0", - "@truffle/provider": "^0.2.45", - "conf": "^10.0.2", - "find-up": "^2.1.0", - "lodash.assignin": "^4.2.0", - "lodash.merge": "^4.6.2", - "module": "^1.2.5", - "original-require": "^1.0.1" - } - }, - "node_modules/@truffle/config/node_modules/@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@truffle/config/node_modules/@truffle/error": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.15.tgz", - "integrity": "sha512-keiYGlVAH7GLggqMpB+XorT7NkOlr3qeBc56thI2WP0eas3qstlyrc0WvckXJ2LXrOfcR2uH6f0Nk6FIxaKXSA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/@truffle/interface-adapter": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.5.11.tgz", - "integrity": "sha512-HXLm+r1KdT8nHzJht1iK6EnHBKIjSYHdDfebBMCqmRCsMoUXvUJ0KsIxvDG758MafB12pjx5gsNn4XzzfksSBQ==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^5.1.3", - "ethers": "^4.0.32", - "web3": "1.5.3" - } - }, - "node_modules/@truffle/config/node_modules/@truffle/interface-adapter/node_modules/ethers": { - "version": "4.0.49", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", - "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", - "dev": true, - "optional": true, - "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.4", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/@truffle/config/node_modules/@truffle/interface-adapter/node_modules/ethers/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/@truffle/interface-adapter/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/@truffle/interface-adapter/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/@truffle/provider": { - "version": "0.2.45", - "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.45.tgz", - "integrity": "sha512-PGxdqUeubLTjTDFVhVhcSNx3/RfH/bTIQYwjb6v/Gd+6BvNN87d0FQWdEHp3/PnywXEeRDWg4HZDpWBYRqwwEw==", - "dev": true, - "optional": true, - "dependencies": { - "@truffle/error": "^0.0.15", - "@truffle/interface-adapter": "^0.5.11", - "web3": "1.5.3" - } - }, - "node_modules/@truffle/config/node_modules/@types/node": { - "version": "12.20.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.43.tgz", - "integrity": "sha512-HCfJdaYqJX3BCzeihgZrD7b85Cu05OC/GVJ4kEYIflwUs4jbnUlLLWoq7hw1LBcdvUyehO+gr6P5JQ895/2ZfA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/config/node_modules/eth-lib/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "optional": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/@truffle/config/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "optional": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "optional": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "optional": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@truffle/config/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/@truffle/config/node_modules/web3": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.5.3.tgz", - "integrity": "sha512-eyBg/1K44flfv0hPjXfKvNwcUfIVDI4NX48qHQe6wd7C8nPSdbWqo9vLy6ksZIt9NLa90HjI8HsGYgnMSUxn6w==", - "dev": true, - "optional": true, - "dependencies": { - "web3-bzz": "1.5.3", - "web3-core": "1.5.3", - "web3-eth": "1.5.3", - "web3-eth-personal": "1.5.3", - "web3-net": "1.5.3", - "web3-shh": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-bzz": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.5.3.tgz", - "integrity": "sha512-SlIkAqG0eS6cBS9Q2eBOTI1XFzqh83RqGJWnyrNZMDxUwsTVHL+zNnaPShVPvrWQA1Ub5b0bx1Kc5+qJVxsTJg==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.5.3.tgz", - "integrity": "sha512-ACTbu8COCu+0eUNmd9pG7Q9EVsNkAg2w3Y7SqhDr+zjTgbSHZV01jXKlapm9z+G3AN/BziV3zGwudClJ4u4xXQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-requestmanager": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core-helpers": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.5.3.tgz", - "integrity": "sha512-Ip1IjB3S8vN7Kf1PPjK41U5gskmMk6IJQlxIVuS8/1U7n/o0jC8krqtpRwiMfAgYyw3TXwBFtxSRTvJtnLyXZw==", - "dev": true, - "optional": true, - "dependencies": { - "web3-eth-iban": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core-method": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.5.3.tgz", - "integrity": "sha512-8wJrwQ2qD9ibWieF9oHXwrJsUGrv3XAtEkNeyvyNMpktNTIjxJ2jaFGQUuLiyUrMubD18XXgLk4JS6PJU4Loeg==", - "dev": true, - "optional": true, - "dependencies": { - "@ethereumjs/common": "^2.4.0", - "@ethersproject/transactions": "^5.0.0-beta.135", - "web3-core-helpers": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core-promievent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.5.3.tgz", - "integrity": "sha512-CFfgqvk3Vk6PIAxtLLuX+pOMozxkKCY+/GdGr7weMh033mDXEPvwyVjoSRO1PqIKj668/hMGQsVoIgbyxkJ9Mg==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core-requestmanager": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.5.3.tgz", - "integrity": "sha512-9k/Bze2rs8ONix5IZR+hYdMNQv+ark2Ek2kVcrFgWO+LdLgZui/rn8FikPunjE+ub7x7pJaKCgVRbYFXjo3ZWg==", - "dev": true, - "optional": true, - "dependencies": { - "util": "^0.12.0", - "web3-core-helpers": "1.5.3", - "web3-providers-http": "1.5.3", - "web3-providers-ipc": "1.5.3", - "web3-providers-ws": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-core-subscriptions": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.5.3.tgz", - "integrity": "sha512-L2m9vG1iRN6thvmv/HQwO2YLhOQlmZU8dpLG6GSo9FBN14Uch868Swk0dYVr3rFSYjZ/GETevSXU+O+vhCummA==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.5.3.tgz", - "integrity": "sha512-saFurA1L23Bd7MEf7cBli6/jRdMhD4X/NaMiO2mdMMCXlPujoudlIJf+VWpRWJpsbDFdu7XJ2WHkmBYT5R3p1Q==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-eth-accounts": "1.5.3", - "web3-eth-contract": "1.5.3", - "web3-eth-ens": "1.5.3", - "web3-eth-iban": "1.5.3", - "web3-eth-personal": "1.5.3", - "web3-net": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-abi": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.5.3.tgz", - "integrity": "sha512-i/qhuFsoNrnV130CSRYX/z4SlCfSQ4mHntti5yTmmQpt70xZKYZ57BsU0R29ueSQ9/P+aQrL2t2rqkQkAloUxg==", - "dev": true, - "optional": true, - "dependencies": { - "@ethersproject/abi": "5.0.7", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-accounts": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.5.3.tgz", - "integrity": "sha512-pdGhXgeBaEJENMvRT6W9cmji3Zz/46ugFSvmnLLw79qi5EH7XJhKISNVb41eWCrs4am5GhI67GLx5d2s2a72iw==", - "dev": true, - "optional": true, - "dependencies": { - "@ethereumjs/common": "^2.3.0", - "@ethereumjs/tx": "^3.2.1", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-util": "^7.0.10", - "scrypt-js": "^3.0.1", - "uuid": "3.3.2", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-contract": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.5.3.tgz", - "integrity": "sha512-Gdlt1L6cdHe83k7SdV6xhqCytVtOZkjD0kY/15x441AuuJ4JLubCHuqu69k2Dr3tWifHYVys/vG8QE/W16syGg==", - "dev": true, - "optional": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-ens": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.5.3.tgz", - "integrity": "sha512-QmGFFtTGElg0E+3xfCIFhiUF+1imFi9eg/cdsRMUZU4F1+MZCC/ee+IAelYLfNTGsEslCqfAusliKOT9DdGGnw==", - "dev": true, - "optional": true, - "dependencies": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-eth-contract": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-iban": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.5.3.tgz", - "integrity": "sha512-vMzmGqolYZvRHwP9P4Nf6G8uYM5aTLlQu2a34vz78p0KlDC+eV1th3+90Qeaupa28EG7OO0IT1F0BejiIauOPw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-eth-iban/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/config/node_modules/web3-eth-personal": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.5.3.tgz", - "integrity": "sha512-JzibJafR7ak/Icas8uvos3BmUNrZw1vShuNR5Cxjo+vteOC8XMqz1Vr7RH65B4bmlfb3bm9xLxetUHO894+Sew==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "^12.12.6", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-net": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-net": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.5.3.tgz", - "integrity": "sha512-0W/xHIPvgVXPSdLu0iZYnpcrgNnhzHMC888uMlGP5+qMCt8VuflUZHy7tYXae9Mzsg1kxaJAS5lHVNyeNw4CoQ==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-method": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-providers-http": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.3.tgz", - "integrity": "sha512-5DpUyWGHtDAr2RYmBu34Fu+4gJuBAuNx2POeiJIooUtJ+Mu6pIx4XkONWH6V+Ez87tZAVAsFOkJRTYuzMr3rPw==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core-helpers": "1.5.3", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-providers-ipc": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.5.3.tgz", - "integrity": "sha512-JmeAptugVpmXI39LGxUSAymx0NOFdgpuI1hGQfIhbEAcd4sv7fhfd5D+ZU4oLHbRI8IFr4qfGU0uhR8BXhDzlg==", - "dev": true, - "optional": true, - "dependencies": { - "oboe": "2.1.5", - "web3-core-helpers": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-providers-ws": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.5.3.tgz", - "integrity": "sha512-6DhTw4Q7nm5CFYEUHOJM0gAb3xFx+9gWpVveg3YxJ/ybR1BUvEWo3bLgIJJtX56cYX0WyY6DS35a7f0LOI1kVg==", - "dev": true, - "optional": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.3", - "websocket": "^1.0.32" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-shh": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.5.3.tgz", - "integrity": "sha512-COfEXfsqoV/BkcsNLRxQqnWc1Teb8/9GxdGag5GtPC5gQC/vsN+7hYVJUwNxY9LtJPKYTij2DHHnx6UkITng+Q==", - "dev": true, - "optional": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-net": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/config/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/db": { - "version": "0.5.50", - "resolved": "https://registry.npmjs.org/@truffle/db/-/db-0.5.50.tgz", - "integrity": "sha512-NXoF1jxkV6ux+u6e94WXrqcMQy3xEAJHoAzKZMK93ic6vh52FJA1iY05XtYQaFgs4Wcetxqn9Fj4aKbVoAkvkg==", - "dev": true, - "optional": true, - "dependencies": { - "@graphql-tools/delegate": "^8.4.3", - "@graphql-tools/schema": "^8.3.1", - "@truffle/abi-utils": "^0.2.8", - "@truffle/code-utils": "^1.2.32", - "@truffle/config": "^1.3.17", - "apollo-server": "^2.18.2", - "debug": "^4.3.1", - "fs-extra": "^9.1.0", - "graphql": "^15.3.0", - "graphql-tag": "^2.11.0", - "json-stable-stringify": "^1.0.1", - "jsondown": "^1.0.0", - "pascal-case": "^2.0.1", - "pluralize": "^8.0.0", - "pouchdb": "7.1.1", - "pouchdb-adapter-memory": "^7.1.1", - "pouchdb-adapter-node-websql": "^7.0.0", - "pouchdb-debug": "^7.1.1", - "pouchdb-find": "^7.0.0", - "web3-utils": "1.5.3" - } - }, - "node_modules/@truffle/db-loader": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@truffle/db-loader/-/db-loader-0.1.0.tgz", - "integrity": "sha512-6pSKFt3UhZkZXyWTjE1+GsADnBEQ3qX2CtfSiPa4jRDxzf3zeWdZzj5HP4KnDqucbteZtS/E8uNNOZ14tk1Cag==", - "dev": true, - "optionalDependencies": { - "@truffle/db": "^0.5.50" - } - }, - "node_modules/@truffle/db/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/db/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@truffle/db/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "node_modules/@truffle/db/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@truffle/db/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger": { - "version": "9.2.14", - "resolved": "https://registry.npmjs.org/@truffle/debugger/-/debugger-9.2.14.tgz", - "integrity": "sha512-hSMN3KvbRpxeNHIBdgaWX/GEcuoamrGAKNqPnut+jhLTXrdFf9Wu5dF3P3wZfJxV6UkdVawaxmAKcL8V2/rgoA==", - "dev": true, - "dependencies": { - "@truffle/abi-utils": "^0.2.8", - "@truffle/codec": "^0.11.25", - "@truffle/source-map-utils": "^1.3.69", - "bn.js": "^5.1.3", - "debug": "^4.3.1", - "json-pointer": "^0.6.1", - "json-stable-stringify": "^1.0.1", - "lodash.merge": "^4.6.2", - "lodash.sum": "^4.0.2", - "lodash.zipwith": "^4.2.0", - "redux": "^3.7.2", - "redux-saga": "1.0.0", - "reselect-tree": "^1.3.5", - "semver": "^7.3.4", - "web3": "1.5.3", - "web3-eth-abi": "1.5.3" - } - }, - "node_modules/@truffle/debugger/node_modules/@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "dev": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/@truffle/debugger/node_modules/@types/node": { - "version": "12.20.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.43.tgz", - "integrity": "sha512-HCfJdaYqJX3BCzeihgZrD7b85Cu05OC/GVJ4kEYIflwUs4jbnUlLLWoq7hw1LBcdvUyehO+gr6P5JQ895/2ZfA==", - "dev": true - }, - "node_modules/@truffle/debugger/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/@truffle/debugger/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/debugger/node_modules/eth-lib/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/debugger/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@truffle/debugger/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/@truffle/debugger/node_modules/web3": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.5.3.tgz", - "integrity": "sha512-eyBg/1K44flfv0hPjXfKvNwcUfIVDI4NX48qHQe6wd7C8nPSdbWqo9vLy6ksZIt9NLa90HjI8HsGYgnMSUxn6w==", - "dev": true, - "dependencies": { - "web3-bzz": "1.5.3", - "web3-core": "1.5.3", - "web3-eth": "1.5.3", - "web3-eth-personal": "1.5.3", - "web3-net": "1.5.3", - "web3-shh": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-bzz": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.5.3.tgz", - "integrity": "sha512-SlIkAqG0eS6cBS9Q2eBOTI1XFzqh83RqGJWnyrNZMDxUwsTVHL+zNnaPShVPvrWQA1Ub5b0bx1Kc5+qJVxsTJg==", - "dev": true, - "dependencies": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.5.3.tgz", - "integrity": "sha512-ACTbu8COCu+0eUNmd9pG7Q9EVsNkAg2w3Y7SqhDr+zjTgbSHZV01jXKlapm9z+G3AN/BziV3zGwudClJ4u4xXQ==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-requestmanager": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core-helpers": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.5.3.tgz", - "integrity": "sha512-Ip1IjB3S8vN7Kf1PPjK41U5gskmMk6IJQlxIVuS8/1U7n/o0jC8krqtpRwiMfAgYyw3TXwBFtxSRTvJtnLyXZw==", - "dev": true, - "dependencies": { - "web3-eth-iban": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core-method": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.5.3.tgz", - "integrity": "sha512-8wJrwQ2qD9ibWieF9oHXwrJsUGrv3XAtEkNeyvyNMpktNTIjxJ2jaFGQUuLiyUrMubD18XXgLk4JS6PJU4Loeg==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.4.0", - "@ethersproject/transactions": "^5.0.0-beta.135", - "web3-core-helpers": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core-promievent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.5.3.tgz", - "integrity": "sha512-CFfgqvk3Vk6PIAxtLLuX+pOMozxkKCY+/GdGr7weMh033mDXEPvwyVjoSRO1PqIKj668/hMGQsVoIgbyxkJ9Mg==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core-requestmanager": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.5.3.tgz", - "integrity": "sha512-9k/Bze2rs8ONix5IZR+hYdMNQv+ark2Ek2kVcrFgWO+LdLgZui/rn8FikPunjE+ub7x7pJaKCgVRbYFXjo3ZWg==", - "dev": true, - "dependencies": { - "util": "^0.12.0", - "web3-core-helpers": "1.5.3", - "web3-providers-http": "1.5.3", - "web3-providers-ipc": "1.5.3", - "web3-providers-ws": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-core-subscriptions": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.5.3.tgz", - "integrity": "sha512-L2m9vG1iRN6thvmv/HQwO2YLhOQlmZU8dpLG6GSo9FBN14Uch868Swk0dYVr3rFSYjZ/GETevSXU+O+vhCummA==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.5.3.tgz", - "integrity": "sha512-saFurA1L23Bd7MEf7cBli6/jRdMhD4X/NaMiO2mdMMCXlPujoudlIJf+VWpRWJpsbDFdu7XJ2WHkmBYT5R3p1Q==", - "dev": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-eth-accounts": "1.5.3", - "web3-eth-contract": "1.5.3", - "web3-eth-ens": "1.5.3", - "web3-eth-iban": "1.5.3", - "web3-eth-personal": "1.5.3", - "web3-net": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-abi": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.5.3.tgz", - "integrity": "sha512-i/qhuFsoNrnV130CSRYX/z4SlCfSQ4mHntti5yTmmQpt70xZKYZ57BsU0R29ueSQ9/P+aQrL2t2rqkQkAloUxg==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "5.0.7", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-accounts": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.5.3.tgz", - "integrity": "sha512-pdGhXgeBaEJENMvRT6W9cmji3Zz/46ugFSvmnLLw79qi5EH7XJhKISNVb41eWCrs4am5GhI67GLx5d2s2a72iw==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.3.0", - "@ethereumjs/tx": "^3.2.1", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-util": "^7.0.10", - "scrypt-js": "^3.0.1", - "uuid": "3.3.2", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-contract": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.5.3.tgz", - "integrity": "sha512-Gdlt1L6cdHe83k7SdV6xhqCytVtOZkjD0kY/15x441AuuJ4JLubCHuqu69k2Dr3tWifHYVys/vG8QE/W16syGg==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-ens": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.5.3.tgz", - "integrity": "sha512-QmGFFtTGElg0E+3xfCIFhiUF+1imFi9eg/cdsRMUZU4F1+MZCC/ee+IAelYLfNTGsEslCqfAusliKOT9DdGGnw==", - "dev": true, - "dependencies": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-promievent": "1.5.3", - "web3-eth-abi": "1.5.3", - "web3-eth-contract": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-iban": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.5.3.tgz", - "integrity": "sha512-vMzmGqolYZvRHwP9P4Nf6G8uYM5aTLlQu2a34vz78p0KlDC+eV1th3+90Qeaupa28EG7OO0IT1F0BejiIauOPw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-iban/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/debugger/node_modules/web3-eth-personal": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.5.3.tgz", - "integrity": "sha512-JzibJafR7ak/Icas8uvos3BmUNrZw1vShuNR5Cxjo+vteOC8XMqz1Vr7RH65B4bmlfb3bm9xLxetUHO894+Sew==", - "dev": true, - "dependencies": { - "@types/node": "^12.12.6", - "web3-core": "1.5.3", - "web3-core-helpers": "1.5.3", - "web3-core-method": "1.5.3", - "web3-net": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-net": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.5.3.tgz", - "integrity": "sha512-0W/xHIPvgVXPSdLu0iZYnpcrgNnhzHMC888uMlGP5+qMCt8VuflUZHy7tYXae9Mzsg1kxaJAS5lHVNyeNw4CoQ==", - "dev": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-method": "1.5.3", - "web3-utils": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-providers-http": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.3.tgz", - "integrity": "sha512-5DpUyWGHtDAr2RYmBu34Fu+4gJuBAuNx2POeiJIooUtJ+Mu6pIx4XkONWH6V+Ez87tZAVAsFOkJRTYuzMr3rPw==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.5.3", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-providers-ipc": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.5.3.tgz", - "integrity": "sha512-JmeAptugVpmXI39LGxUSAymx0NOFdgpuI1hGQfIhbEAcd4sv7fhfd5D+ZU4oLHbRI8IFr4qfGU0uhR8BXhDzlg==", - "dev": true, - "dependencies": { - "oboe": "2.1.5", - "web3-core-helpers": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-providers-ws": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.5.3.tgz", - "integrity": "sha512-6DhTw4Q7nm5CFYEUHOJM0gAb3xFx+9gWpVveg3YxJ/ybR1BUvEWo3bLgIJJtX56cYX0WyY6DS35a7f0LOI1kVg==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.3", - "websocket": "^1.0.32" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-shh": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.5.3.tgz", - "integrity": "sha512-COfEXfsqoV/BkcsNLRxQqnWc1Teb8/9GxdGag5GtPC5gQC/vsN+7hYVJUwNxY9LtJPKYTij2DHHnx6UkITng+Q==", - "dev": true, - "dependencies": { - "web3-core": "1.5.3", - "web3-core-method": "1.5.3", - "web3-core-subscriptions": "1.5.3", - "web3-net": "1.5.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/debugger/node_modules/web3-utils/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/error": { - "version": "0.0.14", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.14.tgz", - "integrity": "sha512-utJx+SZYoMqk8wldQG4gCVKhV8GwMJbWY7sLXFT/D8wWZTnE2peX7URFJh/cxkjTRCO328z1s2qewkhyVsu2HA==", - "dev": true - }, - "node_modules/@truffle/events": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@truffle/events/-/events-0.1.0.tgz", - "integrity": "sha512-EhSnZdcJVFSge8sM0pU/Aa++YbzTLr++bPVDGib/P4z1FWjNOiJ0bklqvv1+oYXh6IzZLB+4WDOTPQxoKaMrAw==", - "dev": true, - "optional": true, - "dependencies": { - "emittery": "^0.4.1", - "ora": "^3.4.0", - "web3-utils": "1.5.3" - } - }, - "node_modules/@truffle/events/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/events/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@truffle/interface-adapter": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.5.6.tgz", - "integrity": "sha512-c8+5iAYduWQVTLcv6P0DiIR/nvv3E92vzkyIeeXcfyS+rmrxpEnWwL4Fs63LGpmt5Th0Fo0w+nTa2Qz4sfDRWA==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.3", - "ethers": "^4.0.32", - "web3": "1.5.2" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/ethers": { - "version": "4.0.49", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", - "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", - "dev": true, - "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.4", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/ethers/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/@truffle/interface-adapter/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true - }, - "node_modules/@truffle/interface-adapter/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true - }, - "node_modules/@truffle/preserve": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@truffle/preserve/-/preserve-0.2.6.tgz", - "integrity": "sha512-ipyLNwbhAIIxdf48fUXrpNdgJ/kmmT9U/cvGfjw8GUTAl455K99Fbv+ZZloyQ4Tuuy3THOPQsQ+6ClI6QW8aiw==", - "dev": true, - "optional": true, - "dependencies": { - "spinnies": "^0.5.1" - } - }, - "node_modules/@truffle/preserve-fs": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@truffle/preserve-fs/-/preserve-fs-0.2.6.tgz", - "integrity": "sha512-NEf92IYPRknv8BB13S2Y6UR6whYxNS0gxYyHayBTUttvAVGBz8TnWvtRxPMNiDx5Ui6pbNL3hGL7M46TG1GL1A==", - "dev": true, - "optional": true, - "dependencies": { - "@truffle/preserve": "^0.2.6" - } - }, - "node_modules/@truffle/preserve-to-buckets": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@truffle/preserve-to-buckets/-/preserve-to-buckets-0.2.6.tgz", - "integrity": "sha512-dKnxz9yJ0iGRVtYPTfBa84Zz+YF0BC/dLsI0qXnRACQV4kiwtppSHfJaFu0z+FqTWmF9qnpjxXuQvXwSzILU6g==", - "dev": true, - "optional": true, - "dependencies": { - "@textile/hub": "^6.0.2", - "@truffle/preserve": "^0.2.6", - "cids": "^1.1.5", - "ipfs-http-client": "^48.2.2", - "isomorphic-ws": "^4.0.1", - "iter-tools": "^7.0.2", - "ws": "^7.4.3" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@truffle/preserve-to-buckets/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/preserve-to-filecoin": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@truffle/preserve-to-filecoin/-/preserve-to-filecoin-0.2.7.tgz", - "integrity": "sha512-hQBCvcvgnSsKGKS3RZaFSHKFjP6553HATNaw3ee55Pgyp+Qzy2c+d6x34Mu23A+6qsfeVoGJ2BoPGwT4JSJkrA==", - "dev": true, - "optional": true, - "dependencies": { - "@truffle/preserve": "^0.2.6", - "cids": "^1.1.5", - "delay": "^5.0.0", - "filecoin.js": "^0.0.5-alpha" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/@truffle/preserve-to-filecoin/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/@truffle/preserve-to-ipfs": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@truffle/preserve-to-ipfs/-/preserve-to-ipfs-0.2.7.tgz", - "integrity": "sha512-gAf73biK/OX3+MoA092tKrw7r398v05q7yTJ85P2sQdN2Mj9dmiIZ7iDOccu47LtrYFAbar9NWBllDx1kqK3zQ==", - "dev": true, - "optional": true, - "dependencies": { - "@truffle/preserve": "^0.2.6", - "ipfs-http-client": "^48.2.2", - "iter-tools": "^7.0.2" - } - }, - "node_modules/@truffle/provider": { - "version": "0.2.40", - "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.40.tgz", - "integrity": "sha512-D36Jl/r1yyqXRw9Q9grP+4eNlJT8R7lQamMYpdfefsng7Igz7YuI9yHi9Y6QZxHZvoh+CXcTiTQZQA3xafFIGg==", - "dev": true, - "dependencies": { - "@truffle/error": "^0.0.14", - "@truffle/interface-adapter": "^0.5.6", - "web3": "1.5.2" - } - }, - "node_modules/@truffle/source-map-utils": { - "version": "1.3.69", - "resolved": "https://registry.npmjs.org/@truffle/source-map-utils/-/source-map-utils-1.3.69.tgz", - "integrity": "sha512-DVgSskFl0fYO+dbqAkvAyyhttAfS6WUwPvoqUpzJ8EiiTbj6OuMi0V2nAAFaYmjnv+3THkYPdBNpeWXJdfc5og==", - "dev": true, - "dependencies": { - "@truffle/code-utils": "^1.2.32", - "@truffle/codec": "^0.11.25", - "debug": "^4.3.1", - "json-pointer": "^0.6.1", - "node-interval-tree": "^1.3.3", - "web3-utils": "1.5.3" - } - }, - "node_modules/@truffle/source-map-utils/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/@truffle/source-map-utils/node_modules/web3-utils": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz", - "integrity": "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@ts-type/package-dts": { - "version": "1.0.58", - "resolved": "https://registry.npmjs.org/@ts-type/package-dts/-/package-dts-1.0.58.tgz", - "integrity": "sha512-Ry5RPZDAnSz/gyLtjd2a2yNC07CZ/PCOsuDzYj3phOolIgEH68HXRw6SbsDlavnVUEenDYj5GUM10gQ5iVEbVQ==", - "dev": true, - "dependencies": { - "@types/semver": "^7.3.9", - "ts-type": "^2.1.4" - }, - "peerDependencies": { - "@types/bluebird": "*", - "@types/node": "*", - "ts-toolbelt": "*" - } - }, - "node_modules/@typechain/ethers-v5": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-9.0.0.tgz", - "integrity": "sha512-bAanuPl1L2itaUdMvor/QvwnIH+TM/CmG00q17Ilv3ZZMeJ2j8HcarhgJUZ9pBY1teBb85P8cC03dz3mSSx+tQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/bytes": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^7.0.0", - "typescript": ">=4.0.0" - } - }, - "node_modules/@typechain/ethers-v5/node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true, - "peer": true - }, - "node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "optional": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==", - "dev": true, - "optional": true - }, - "node_modules/@types/cookies": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", - "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.10", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", - "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==", - "dev": true, - "optional": true - }, - "node_modules/@types/ed2curve": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@types/ed2curve/-/ed2curve-0.2.2.tgz", - "integrity": "sha512-G1sTX5xo91ydevQPINbL2nfgVAj/s1ZiqZxC8OCWduwu+edoNGUm5JXtTkg9F3LsBZbRI46/0HES4CPUE2wc9g==", - "dev": true, - "optional": true, - "dependencies": { - "tweetnacl": "^1.0.0" - } - }, - "node_modules/@types/ed2curve/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true, - "optional": true - }, - "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/fs-capacitor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", - "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/google-protobuf": { - "version": "3.15.5", - "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.5.tgz", - "integrity": "sha512-6bgv24B+A2bo9AfzReeg5StdiijKzwwnRflA8RLd1V4Yv995LeTmo0z69/MPbBDFSiZWdZHQygLo/ccXhMEDgw==", - "dev": true, - "optional": true - }, - "node_modules/@types/http-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", - "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", - "dev": true, - "optional": true - }, - "node_modules/@types/http-errors": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", - "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", - "dev": true, - "optional": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true, - "optional": true - }, - "node_modules/@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", - "dev": true, - "optional": true - }, - "node_modules/@types/koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", - "dev": true, - "optional": true, - "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "node_modules/@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/koa": "*" - } - }, - "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==", - "dev": true, - "optional": true - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true, - "optional": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "16.9.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.4.tgz", - "integrity": "sha512-KDazLNYAGIuJugdbULwFZULF9qQ13yNWEBFnfVpqlpgAAo6H/qnM9RjBgh0A0kmHf3XxAKLdN5mTIng9iUvVLA==", - "dev": true - }, - "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true, - "optional": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true, - "optional": true - }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/semver": { - "version": "7.3.9", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", - "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==", - "dev": true - }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/to-json-schema": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@types/to-json-schema/-/to-json-schema-0.2.1.tgz", - "integrity": "sha512-DlvjodmdSrih054SrUqgS3bIZ93allrfbzjFUFmUhAtC60O+B/doLfgB8stafkEFyrU/zXWtPlX/V1H94iKv/A==", - "dev": true, - "optional": true, - "dependencies": { - "@types/json-schema": "*" - } - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@wry/equality": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", - "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "^1.9.3" - } - }, - "node_modules/@wry/equality/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - }, - "node_modules/@yarn-tool/resolve-package": { - "version": "1.0.42", - "resolved": "https://registry.npmjs.org/@yarn-tool/resolve-package/-/resolve-package-1.0.42.tgz", - "integrity": "sha512-1BAsoiD6jGAaPc7mRH0UxIVXgRSTv7fnhwfKkaFUYpqsU4ZR7KIigZTMcb2bujtlzKQbNneMPQGjiqe3F8cmlw==", - "dev": true, - "dependencies": { - "@ts-type/package-dts": "^1.0.58", - "pkg-dir": "< 6 >= 5", - "tslib": "^2.3.1", - "upath2": "^3.1.12" - }, - "peerDependencies": { - "@types/node": "*" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@yarn-tool/resolve-package/node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@zondax/filecoin-signing-tools": { - "resolved": "git+ssh://git@github.com/Digital-MOB-Filecoin/filecoin-signing-tools-js.git#8f8e92157cac2556d35cab866779e9a8ea8a4e25", - "dev": true, - "optional": true, - "dependencies": { - "axios": "^0.20.0", - "base32-decode": "^1.0.0", - "base32-encode": "^1.1.1", - "bip32": "^2.0.5", - "bip39": "^3.0.2", - "blakejs": "^1.1.0", - "bn.js": "^5.1.2", - "ipld-dag-cbor": "^0.17.0", - "leb128": "0.0.5", - "secp256k1": "^4.0.1" - } - }, - "node_modules/@zondax/filecoin-signing-tools/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true, - "optional": true - }, - "node_modules/@zxing/text-encoding": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", - "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", - "dev": true, - "optional": true - }, - "node_modules/101": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/101/-/101-1.6.3.tgz", - "integrity": "sha512-4dmQ45yY0Dx24Qxp+zAsNLlMF6tteCyfVzgbulvSyC7tCyd3V8sW76sS0tHq8NpcbXfWTKasfyfzU1Kd86oKzw==", - "dev": true, - "optional": true, - "dependencies": { - "clone": "^1.0.2", - "deep-eql": "^0.1.3", - "keypather": "^1.10.2" - } - }, - "node_modules/abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "dev": true, - "optional": true - }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "optional": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abstract-leveldown": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", - "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, - "optional": true, - "dependencies": { - "xtend": "~4.0.0" - } - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true, - "optional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", - "dev": true, - "optional": true, - "dependencies": { - "acorn": "^2.1.0" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "dev": true, - "optional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "dev": true, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", - "dev": true - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "optional": true, - "dependencies": { - "ajv": "^8.0.0" - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "optional": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "optional": true - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansicolors": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", - "dev": true - }, - "node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "dev": true - }, - "node_modules/any-signal": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-2.1.2.tgz", - "integrity": "sha512-B+rDnWasMi/eWcajPcCWSlYc7muXOrcYrqgyzcdKisl2H/WTlQ0gip1KyQfr0ZlxJdsuWCj/LWwQm7fhyhRfIQ==", - "dev": true, - "optional": true, - "dependencies": { - "abort-controller": "^3.0.0", - "native-abort-controller": "^1.0.3" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/apollo-cache-control": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.14.0.tgz", - "integrity": "sha512-qN4BCq90egQrgNnTRMUHikLZZAprf3gbm8rC5Vwmc6ZdLolQ7bFsa769Hqi6Tq/lS31KLsXBLTOsRbfPHph12w==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-server-env": "^3.1.0", - "apollo-server-plugin-base": "^0.13.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/apollo-datasource": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.9.0.tgz", - "integrity": "sha512-y8H99NExU1Sk4TvcaUxTdzfq2SZo6uSj5dyh75XSQvbpH6gdAXIW9MaBcvlNC7n0cVPsidHmOcHOWxJ/pTXGjA==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-graphql": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.9.5.tgz", - "integrity": "sha512-RGt5k2JeBqrmnwRM0VOgWFiGKlGJMfmiif/4JvdaEqhMJ+xqe/9cfDYzXfn33ke2eWixsAbjEbRfy8XbaN9nTw==", - "dev": true, - "optional": true, - "dependencies": { - "core-js-pure": "^3.10.2", - "lodash.sortby": "^4.7.0", - "sha.js": "^2.4.11" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-link": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", - "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-utilities": "^1.3.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3", - "zen-observable-ts": "^0.8.21" - } - }, - "node_modules/apollo-link/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - }, - "node_modules/apollo-reporting-protobuf": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.8.0.tgz", - "integrity": "sha512-B3XmnkH6Y458iV6OsA7AhfwvTgeZnFq9nPVjbxmLKnvfkEl8hYADtz724uPa0WeBiD7DSFcnLtqg9yGmCkBohg==", - "dev": true, - "optional": true, - "dependencies": { - "@apollo/protobufjs": "1.2.2" - } - }, - "node_modules/apollo-server": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/apollo-server/-/apollo-server-2.25.3.tgz", - "integrity": "sha512-+eUY2//DLkU7RkJLn6CTl1P89/ZMHuUQnWqv8La2iJ2hLT7Me+nMx+hgHl3LqlT/qDstQ8qA45T85FuCayplmQ==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-server-core": "^2.25.3", - "apollo-server-express": "^2.25.3", - "express": "^4.0.0", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.8", - "stoppable": "^1.1.0" - } - }, - "node_modules/apollo-server-caching": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.7.0.tgz", - "integrity": "sha512-MsVCuf/2FxuTFVhGLK13B+TZH9tBd2qkyoXKKILIiGcZ5CDUEBO14vIV63aNkMkS1xxvK2U4wBcuuNj/VH2Mkw==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-core": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.25.3.tgz", - "integrity": "sha512-Midow3uZoJ9TjFNeCNSiWElTVZlvmB7G7tG6PPoxIR9Px90/v16Q6EzunDIO0rTJHRC3+yCwZkwtf8w2AcP0sA==", - "dev": true, - "optional": true, - "dependencies": { - "@apollographql/apollo-tools": "^0.5.0", - "@apollographql/graphql-playground-html": "1.6.27", - "@apollographql/graphql-upload-8-fork": "^8.1.3", - "@josephg/resolvable": "^1.0.0", - "@types/ws": "^7.0.0", - "apollo-cache-control": "^0.14.0", - "apollo-datasource": "^0.9.0", - "apollo-graphql": "^0.9.0", - "apollo-reporting-protobuf": "^0.8.0", - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0", - "apollo-server-errors": "^2.5.0", - "apollo-server-plugin-base": "^0.13.0", - "apollo-server-types": "^0.9.0", - "apollo-tracing": "^0.15.0", - "async-retry": "^1.2.1", - "fast-json-stable-stringify": "^2.0.0", - "graphql-extensions": "^0.15.0", - "graphql-tag": "^2.11.0", - "graphql-tools": "^4.0.8", - "loglevel": "^1.6.7", - "lru-cache": "^6.0.0", - "sha.js": "^2.4.11", - "subscriptions-transport-ws": "^0.9.19", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-core/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/apollo-server-env": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-3.1.0.tgz", - "integrity": "sha512-iGdZgEOAuVop3vb0F2J3+kaBVi4caMoxefHosxmgzAbbSpvWehB8Y1QiSyyMeouYC38XNVk5wnZl+jdGSsWsIQ==", - "dev": true, - "optional": true, - "dependencies": { - "node-fetch": "^2.6.1", - "util.promisify": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-errors": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.5.0.tgz", - "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-express": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.25.3.tgz", - "integrity": "sha512-tTFYn0oKH2qqLwVj7Ez2+MiKleXACODiGh5IxsB7VuYCPMAi9Yl8iUSlwTjQUvgCWfReZjnf0vFL2k5YhDlrtQ==", - "dev": true, - "optional": true, - "dependencies": { - "@apollographql/graphql-playground-html": "1.6.27", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "2.8.10", - "@types/express": "^4.17.12", - "@types/express-serve-static-core": "^4.17.21", - "accepts": "^1.3.5", - "apollo-server-core": "^2.25.3", - "apollo-server-types": "^0.9.0", - "body-parser": "^1.18.3", - "cors": "^2.8.5", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.8", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.19", - "type-is": "^1.6.16" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-express/node_modules/@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "dev": true, - "optional": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/apollo-server-plugin-base": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.13.0.tgz", - "integrity": "sha512-L3TMmq2YE6BU6I4Tmgygmd0W55L+6XfD9137k+cWEBFu50vRY4Re+d+fL5WuPkk5xSPKd/PIaqzidu5V/zz8Kg==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-server-types": "^0.9.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-server-types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.9.0.tgz", - "integrity": "sha512-qk9tg4Imwpk732JJHBkhW0jzfG0nFsLqK2DY6UhvJf7jLnRePYsPxWfPiNkxni27pLE2tiNlCwoDFSeWqpZyBg==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-reporting-protobuf": "^0.8.0", - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/apollo-tracing": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.15.0.tgz", - "integrity": "sha512-UP0fztFvaZPHDhIB/J+qGuy6hWO4If069MGC98qVs0I8FICIGu4/8ykpX3X3K6RtaQ56EDAWKykCxFv4ScxMeA==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-server-env": "^3.1.0", - "apollo-server-plugin-base": "^0.13.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/apollo-utilities": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", - "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", - "dev": true, - "optional": true, - "dependencies": { - "@wry/equality": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0" - } - }, - "node_modules/apollo-utilities/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - }, - "node_modules/app-module-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", - "dev": true - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/are-we-there-yet/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/argsarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz", - "integrity": "sha1-bnIHtOzbObCviDA/pa4ivajfYcs=", - "dev": true, - "optional": true - }, - "node_modules/arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "optional": true, - "dependencies": { - "arr-flatten": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.map": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", - "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array.prototype.map/node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/assert-args": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-args/-/assert-args-1.2.1.tgz", - "integrity": "sha1-QEEDoUUqMv53iYgR5U5ZCoqTc70=", - "dev": true, - "optional": true, - "dependencies": { - "101": "^1.2.0", - "compound-subject": "0.0.1", - "debug": "^2.2.0", - "get-prototype-of": "0.0.0", - "is-capitalized": "^1.0.0", - "is-class": "0.0.4" - } - }, - "node_modules/assert-args/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/assert-args/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dev": true, - "optional": true, - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "optional": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/atomically": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", - "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/axios": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", - "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", - "dev": true, - "optional": true, - "dependencies": { - "follow-redirects": "^1.10.0" - } - }, - "node_modules/babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/babel-code-frame/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "dependencies": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "node_modules/babel-generator/node_modules/jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.22.0" - } - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "node_modules/babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "node_modules/babel-traverse/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/babel-traverse/node_modules/globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-traverse/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "dependencies": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "node_modules/babel-types/node_modules/to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true, - "bin": { - "babylon": "bin/babylon.js" - } - }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true, - "optional": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base32-decode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base32-decode/-/base32-decode-1.0.0.tgz", - "integrity": "sha512-KNWUX/R7wKenwE/G/qFMzGScOgVntOmbE27vvc6GrniDGYb6a5+qWcuoXl8WIOQL7q0TpK7nZDm1Y04Yi3Yn5g==", - "dev": true, - "optional": true - }, - "node_modules/base32-encode": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base32-encode/-/base32-encode-1.2.0.tgz", - "integrity": "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==", - "dev": true, - "optional": true, - "dependencies": { - "to-data-view": "^1.1.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/bigi": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", - "integrity": "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU=", - "dev": true, - "optional": true - }, - "node_modules/bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip-schnorr": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/bip-schnorr/-/bip-schnorr-0.6.4.tgz", - "integrity": "sha512-dNKw7Lea8B0wMIN4OjEmOk/Z5qUGqoPDY0P2QttLqGk1hmDPytLWW8PR5Pb6Vxy6CprcdEgfJpOjUu+ONQveyg==", - "dev": true, - "optional": true, - "dependencies": { - "bigi": "^1.4.2", - "ecurve": "^1.0.6", - "js-sha256": "^0.9.0", - "randombytes": "^2.1.0", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/bip-schnorr/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "optional": true - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", - "dev": true, - "optional": true - }, - "node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", - "dev": true, - "optional": true - }, - "node_modules/bitcore-lib": { - "version": "8.25.25", - "resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.25.25.tgz", - "integrity": "sha512-H6qNCVl4M8/MglXhvc04mmeus1d6nrmqTJGQ+xezJLvL7hs7R3dyBPtOqSP3YSw0iq/GWspMd8f5OOlyXVipJQ==", - "dev": true, - "optional": true, - "dependencies": { - "bech32": "=2.0.0", - "bip-schnorr": "=0.6.4", - "bn.js": "=4.11.8", - "bs58": "^4.0.1", - "buffer-compare": "=1.1.1", - "elliptic": "^6.5.3", - "inherits": "=2.0.1", - "lodash": "^4.17.20" - } - }, - "node_modules/bitcore-lib/node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", - "dev": true, - "optional": true - }, - "node_modules/bitcore-lib/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true, - "optional": true - }, - "node_modules/bitcore-lib/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true, - "optional": true - }, - "node_modules/bitcore-mnemonic": { - "version": "8.25.25", - "resolved": "https://registry.npmjs.org/bitcore-mnemonic/-/bitcore-mnemonic-8.25.25.tgz", - "integrity": "sha512-7HvRxHrmd+Rh0Ohl0SEDMKQBAM+FoevXbCFnxGju6H+uZjtWMOToHA8vUg0+B91pfEMjdt9mQVB/wSA8GMqnCA==", - "dev": true, - "optional": true, - "dependencies": { - "bitcore-lib": "^8.25.25", - "unorm": "^1.4.1" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/blakejs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz", - "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==", - "dev": true - }, - "node_modules/blob-to-it": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/blob-to-it/-/blob-to-it-1.0.4.tgz", - "integrity": "sha512-iCmk0W4NdbrWgRRuxOriU8aM5ijeVLI61Zulsmg/lUHNr7pYjoj+U77opLefNagevtrrbMt3JQ5Qip7ar178kA==", - "dev": true, - "optional": true, - "dependencies": { - "browser-readablestream-to-it": "^1.0.3" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/borc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", - "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", - "dev": true, - "optional": true, - "dependencies": { - "bignumber.js": "^9.0.0", - "buffer": "^5.5.0", - "commander": "^2.15.0", - "ieee754": "^1.1.13", - "iso-url": "~0.4.7", - "json-text-sequence": "~0.1.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/borc/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "optional": true - }, - "node_modules/borc/node_modules/iso-url": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", - "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/browser-headers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", - "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==", - "dev": true, - "optional": true - }, - "node_modules/browser-readablestream-to-it": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz", - "integrity": "sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==", - "dev": true, - "optional": true - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "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" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-rsa/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dev": true, - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", - "dev": true, - "optional": true - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-compare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz", - "integrity": "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY=", - "dev": true, - "optional": true - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-pipe": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/buffer-pipe/-/buffer-pipe-0.0.3.tgz", - "integrity": "sha512-GlxfuD/NrKvCNs0Ut+7b1IHjylfdegMBxQIlZHj7bObKVQBxB5S84gtm2yu1mQ8/sSggceWBDPY0cPXgvX2MuA==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/bufferutil": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", - "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", - "dev": true, - "dependencies": { - "node-gyp-build": "^4.2.0" - } - }, - "node_modules/builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "dev": true, - "optional": true, - "dependencies": { - "dicer": "0.3.0" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001312", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", - "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/cardinal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", - "dev": true, - "dependencies": { - "ansicolors": "~0.3.2", - "redeyed": "~2.1.0" - }, - "bin": { - "cdl": "bin/cdl.js" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/cbor": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz", - "integrity": "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==", - "dev": true, - "dependencies": { - "bignumber.js": "^9.0.1", - "nofilter": "^1.0.4" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/change-case": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.0.2.tgz", - "integrity": "sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==", - "dev": true, - "dependencies": { - "camel-case": "^3.0.0", - "constant-case": "^2.0.0", - "dot-case": "^2.1.0", - "header-case": "^1.0.0", - "is-lower-case": "^1.1.0", - "is-upper-case": "^1.1.0", - "lower-case": "^1.1.1", - "lower-case-first": "^1.0.0", - "no-case": "^2.3.2", - "param-case": "^2.1.0", - "pascal-case": "^2.0.0", - "path-case": "^2.1.0", - "sentence-case": "^2.1.0", - "snake-case": "^2.1.0", - "swap-case": "^1.1.0", - "title-case": "^2.1.0", - "upper-case": "^1.1.1", - "upper-case-first": "^1.1.0" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "dev": true, - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/chokidar/node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/chokidar/node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/cids/node_modules/multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "dev": true, - "dependencies": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true, - "optional": true - }, - "node_modules/class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "dev": true - }, - "node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "optional": true, - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-table": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", - "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", - "dev": true, - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true, - "optional": true - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-logger": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.6.tgz", - "integrity": "sha1-5WJF7ymCJlcRDHy3WpzXhstp7Rs=", - "dev": true - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.1.tgz", - "integrity": "sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==", - "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "chalk": "^2.4.2", - "table-layout": "^1.0.1", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/commander": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", - "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/compound-subject": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/compound-subject/-/compound-subject-0.0.1.tgz", - "integrity": "sha1-JxVUaYoVrmCLHfyv0wt7oeqJLEs=", - "dev": true, - "optional": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz", - "integrity": "sha1-87gKz54fSOOHXAaItBtsMWAu6hw=", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "optional": true, - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "~2.0.0", - "typedarray": "~0.0.5" - } - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~0.10.x", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - }, - "node_modules/conf": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/conf/-/conf-10.1.1.tgz", - "integrity": "sha512-z2civwq/k8TMYtcn3SVP0Peso4otIWnHtcTuHhQ0zDZDdP4NTxqEc8owfkz4zBsdMYdn/LFcE+ZhbCeqkhtq3Q==", - "dev": true, - "optional": true, - "dependencies": { - "ajv": "^8.6.3", - "ajv-formats": "^2.1.1", - "atomically": "^1.7.0", - "debounce-fn": "^4.0.0", - "dot-prop": "^6.0.1", - "env-paths": "^2.2.1", - "json-schema-typed": "^7.0.3", - "onetime": "^5.1.2", - "pkg-up": "^3.1.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/conf/node_modules/ajv": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", - "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", - "dev": true, - "optional": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "node_modules/conf/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "optional": true - }, - "node_modules/conf/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/conf/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "optional": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/conf/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true - }, - "node_modules/constant-case": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz", - "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=", - "dev": true, - "dependencies": { - "snake-case": "^2.1.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "dev": true, - "dependencies": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "node_modules/core-js-pure": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.0.tgz", - "integrity": "sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg==", - "dev": true, - "optional": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", - "dev": true, - "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - }, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "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" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=", - "dev": true, - "optional": true - }, - "node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true, - "optional": true - }, - "node_modules/cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "dev": true, - "optional": true, - "dependencies": { - "cssom": "0.3.x" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dataloader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz", - "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ==", - "dev": true, - "optional": true - }, - "node_modules/death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", - "dev": true - }, - "node_modules/debounce-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", - "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", - "dev": true, - "optional": true, - "dependencies": { - "mimic-fn": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/debounce-fn/node_modules/mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/debug-fabulous": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.0.4.tgz", - "integrity": "sha1-+gccXYdIRoVCSAdCHKSxawsaB2M=", - "dev": true, - "optional": true, - "dependencies": { - "debug": "2.X", - "lazy-debug-legacy": "0.0.X", - "object-assign": "4.1.0" - } - }, - "node_modules/debug-fabulous/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/debug-fabulous/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/debug-fabulous/node_modules/object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "optional": true, - "dependencies": { - "type-detect": "0.1.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "optional": true, - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/deferred-leveldown": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", - "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "~6.2.1", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deferred-leveldown/node_modules/abstract-leveldown": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", - "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "node_modules/delimit-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", - "integrity": "sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs=", - "dev": true, - "optional": true - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/deprecated-decorator": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", - "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=", - "dev": true, - "optional": true - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "node_modules/detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-port": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", - "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "dev": true, - "optional": true, - "dependencies": { - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-over-http-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz", - "integrity": "sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "^4.3.1", - "native-fetch": "^3.0.0", - "receptacle": "^1.3.2" - } - }, - "node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dev": true, - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/dot-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz", - "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dev": true, - "optional": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", - "dev": true, - "optional": true - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "optional": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/duplexify/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/duplexify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ecurve": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/ecurve/-/ecurve-1.0.6.tgz", - "integrity": "sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w==", - "dev": true, - "optional": true, - "dependencies": { - "bigi": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ed2curve": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz", - "integrity": "sha512-8w2fmmq3hv9rCrcI7g9hms2pMunQr1JINfcjwR9tAyZqhtyaMN991lF/ZfHfr5tzZQ8c7y7aBgZbjfbd0fjFwQ==", - "dev": true, - "optional": true, - "dependencies": { - "tweetnacl": "1.x.x" - } - }, - "node_modules/ed2curve/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true, - "optional": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/electron-fetch": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.7.4.tgz", - "integrity": "sha512-+fBLXEy4CJWQ5bz8dyaeSG1hD6JJ15kBZyj3eh24pIVrd3hLM47H/umffrdQfS6GZ0falF0g9JT9f3Rs6AVUhw==", - "dev": true, - "optional": true, - "dependencies": { - "encoding": "^0.1.13" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.71", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz", - "integrity": "sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/emittery": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.4.1.tgz", - "integrity": "sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding-down": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", - "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "^6.2.1", - "inherits": "^2.0.3", - "level-codec": "^9.0.0", - "level-errors": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding-down/node_modules/abstract-leveldown": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", - "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.5.0", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/end-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/end-stream/-/end-stream-0.1.0.tgz", - "integrity": "sha1-MgA/P0OKKwFDFoE3+PpumGbIHtU=", - "dev": true, - "optional": true, - "dependencies": { - "write-stream": "~0.4.3" - } - }, - "node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "optional": true - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.6.tgz", - "integrity": "sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-string": "^1.0.7", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "node_modules/es-get-iterator": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", - "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-denodeify": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-denodeify/-/es6-denodeify-0.1.5.tgz", - "integrity": "sha1-MdTV/pxVA+ElRgQ5MQ4WoqPznB8=", - "dev": true, - "optional": true - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/escodegen/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esdoc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esdoc/-/esdoc-1.1.0.tgz", - "integrity": "sha512-vsUcp52XJkOWg9m1vDYplGZN2iDzvmjDL5M/Mp8qkoDG3p2s0yIQCIjKR5wfPBaM3eV14a6zhQNYiNTCVzPnxA==", - "dev": true, - "dependencies": { - "babel-generator": "6.26.1", - "babel-traverse": "6.26.0", - "babylon": "6.18.0", - "cheerio": "1.0.0-rc.2", - "color-logger": "0.0.6", - "escape-html": "1.0.3", - "fs-extra": "5.0.0", - "ice-cap": "0.0.4", - "marked": "0.3.19", - "minimist": "1.2.0", - "taffydb": "2.7.3" - }, - "bin": { - "esdoc": "out/src/ESDocCLI.js" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/esdoc/node_modules/fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/esdoc/node_modules/marked": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", - "dev": true, - "bin": { - "marked": "bin/marked" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esdoc/node_modules/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", - "dev": true, - "dependencies": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - } - }, - "node_modules/eth-lib": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", - "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/eth-lib/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/eth-sig-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.1.tgz", - "integrity": "sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ==", - "dev": true, - "dependencies": { - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^5.1.1", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.0" - } - }, - "node_modules/eth-sig-util/node_modules/ethereumjs-util": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", - "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "^0.1.3", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/eth-sig-util/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true - }, - "node_modules/ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", - "dev": true, - "dependencies": { - "js-sha3": "^0.8.0" - } - }, - "node_modules/ethereum-bloom-filters/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "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" - } - }, - "node_modules/ethereum-cryptography/node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", - "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, - "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" - } - }, - "node_modules/ethereumjs-util": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz", - "integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethereumjs-util/node_modules/@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-util/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/ethereumjs-wallet": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-1.0.2.tgz", - "integrity": "sha512-CCWV4RESJgRdHIvFciVQFnCHfqyhXWchTPlkfp28Qc53ufs+doi5I/cV2+xeK9+qEo25XCWfP9MiL+WEPAZfdA==", - "dev": true, - "dependencies": { - "aes-js": "^3.1.2", - "bs58check": "^2.1.2", - "ethereum-cryptography": "^0.1.3", - "ethereumjs-util": "^7.1.2", - "randombytes": "^2.1.0", - "scrypt-js": "^3.0.1", - "utf8": "^3.0.0", - "uuid": "^8.3.2" - } - }, - "node_modules/ethereumjs-wallet/node_modules/@types/bn.js": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", - "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ethereumjs-wallet/node_modules/aes-js": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", - "dev": true - }, - "node_modules/ethereumjs-wallet/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/ethereumjs-wallet/node_modules/ethereumjs-util": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz", - "integrity": "sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==", - "dev": true, - "dependencies": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ethereumjs-wallet/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/ethers": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.5.4.tgz", - "integrity": "sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "5.5.0", - "@ethersproject/abstract-provider": "5.5.1", - "@ethersproject/abstract-signer": "5.5.0", - "@ethersproject/address": "5.5.0", - "@ethersproject/base64": "5.5.0", - "@ethersproject/basex": "5.5.0", - "@ethersproject/bignumber": "5.5.0", - "@ethersproject/bytes": "5.5.0", - "@ethersproject/constants": "5.5.0", - "@ethersproject/contracts": "5.5.0", - "@ethersproject/hash": "5.5.0", - "@ethersproject/hdnode": "5.5.0", - "@ethersproject/json-wallets": "5.5.0", - "@ethersproject/keccak256": "5.5.0", - "@ethersproject/logger": "5.5.0", - "@ethersproject/networks": "5.5.2", - "@ethersproject/pbkdf2": "5.5.0", - "@ethersproject/properties": "5.5.0", - "@ethersproject/providers": "5.5.3", - "@ethersproject/random": "5.5.1", - "@ethersproject/rlp": "5.5.0", - "@ethersproject/sha2": "5.5.0", - "@ethersproject/signing-key": "5.5.0", - "@ethersproject/solidity": "5.5.0", - "@ethersproject/strings": "5.5.0", - "@ethersproject/transactions": "5.5.0", - "@ethersproject/units": "5.5.0", - "@ethersproject/wallet": "5.5.0", - "@ethersproject/web": "5.5.1", - "@ethersproject/wordlists": "5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/contracts": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.5.0.tgz", - "integrity": "sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.5.0", - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/transactions": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/hdnode": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.5.0.tgz", - "integrity": "sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/basex": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/pbkdf2": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/wordlists": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/json-wallets": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz", - "integrity": "sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hdnode": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/pbkdf2": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/strings": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/ethers/node_modules/@ethersproject/pbkdf2": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz", - "integrity": "sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/sha2": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/solidity": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.5.0.tgz", - "integrity": "sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/sha2": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/units": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.5.0.tgz", - "integrity": "sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag==", - "dev": true, - "dependencies": { - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/constants": "^5.5.0", - "@ethersproject/logger": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/wallet": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.5.0.tgz", - "integrity": "sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q==", - "dev": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.5.0", - "@ethersproject/abstract-signer": "^5.5.0", - "@ethersproject/address": "^5.5.0", - "@ethersproject/bignumber": "^5.5.0", - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/hdnode": "^5.5.0", - "@ethersproject/json-wallets": "^5.5.0", - "@ethersproject/keccak256": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/random": "^5.5.0", - "@ethersproject/signing-key": "^5.5.0", - "@ethersproject/transactions": "^5.5.0", - "@ethersproject/wordlists": "^5.5.0" - } - }, - "node_modules/ethers/node_modules/@ethersproject/wordlists": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.5.0.tgz", - "integrity": "sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q==", - "dev": true, - "dependencies": { - "@ethersproject/bytes": "^5.5.0", - "@ethersproject/hash": "^5.5.0", - "@ethersproject/logger": "^5.5.0", - "@ethersproject/properties": "^5.5.0", - "@ethersproject/strings": "^5.5.0" - } - }, - "node_modules/ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ethjs-unit/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/event-iterator": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-1.2.0.tgz", - "integrity": "sha512-Daq7YUl0Mv1i4QEgzGQlz0jrx7hUFNyLGbiF+Ap7NCMCjDLCCnolyj6s0TAc6HmrBziO5rNVHsPwGMp7KdRPvw==", - "dev": true, - "optional": true - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/exit-on-epipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "optional": true, - "dependencies": { - "is-posix-bracket": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "optional": true, - "dependencies": { - "fill-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-range/node_modules/fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "optional": true, - "dependencies": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-range/node_modules/is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "optional": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-range/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "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.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/express/node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ext": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.5.0.tgz", - "integrity": "sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q==", - "dev": true, - "dependencies": { - "type": "^2.5.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "optional": true, - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/faker": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", - "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==", - "dev": true - }, - "node_modules/fast-check": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-2.21.0.tgz", - "integrity": "sha512-hkTRytqMceXfnSwPnryIqKkxKJjfcvtVqJrWRb8tgmfyUsGajIgQqDFxCJ+As+l9VLUCcmx6XIYoXeQe2Ih0UA==", - "dev": true, - "dependencies": { - "pure-rand": "^5.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-fifo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.1.0.tgz", - "integrity": "sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g==", - "dev": true, - "optional": true - }, - "node_modules/fast-future": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fast-future/-/fast-future-1.0.2.tgz", - "integrity": "sha1-hDWpqqAteSSNF9cE52JZMB2ZKAo=", - "dev": true, - "optional": true - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-sha256": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", - "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", - "dev": true, - "optional": true - }, - "node_modules/fastestsmallesttextencoderdecoder": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", - "dev": true, - "optional": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fetch-cookie": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.7.0.tgz", - "integrity": "sha512-Mm5pGlT3agW6t71xVM7vMZPIvI7T4FaTuFW4jari6dVzYHFDb3WZZsGpN22r/o3XMdkM0E7sPd1EGeyVbH2Tgg==", - "dev": true, - "optional": true, - "dependencies": { - "es6-denodeify": "^0.1.1", - "tough-cookie": "^2.3.1" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/filecoin.js": { - "version": "0.0.5-alpha", - "resolved": "https://registry.npmjs.org/filecoin.js/-/filecoin.js-0.0.5-alpha.tgz", - "integrity": "sha512-xPrB86vDnTPfmvtN/rJSrhl4M77694ruOgNXd0+5gP67mgmCDhStLCqcr+zHIDRgDpraf7rY+ELbwjXZcQNdpQ==", - "dev": true, - "optional": true, - "dependencies": { - "@ledgerhq/hw-transport-webusb": "^5.22.0", - "@nodefactory/filsnap-adapter": "^0.2.1", - "@nodefactory/filsnap-types": "^0.2.1", - "@zondax/filecoin-signing-tools": "github:Digital-MOB-Filecoin/filecoin-signing-tools-js", - "bignumber.js": "^9.0.0", - "bitcore-lib": "^8.22.2", - "bitcore-mnemonic": "^8.22.2", - "btoa-lite": "^1.0.0", - "events": "^3.2.0", - "isomorphic-ws": "^4.0.1", - "node-fetch": "^2.6.0", - "rpc-websockets": "^5.3.1", - "scrypt-async": "^2.0.1", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1", - "websocket": "^1.0.31", - "ws": "^7.3.1" - } - }, - "node_modules/filecoin.js/node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true, - "optional": true - }, - "node_modules/filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", - "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "optional": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "optional": true, - "dependencies": { - "for-in": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-capacitor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", - "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8.5" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "dependencies": { - "minipass": "^2.6.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true, - "optional": true - }, - "node_modules/ganache-cli": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.2.tgz", - "integrity": "sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw==", - "bundleDependencies": [ - "source-map-support", - "yargs", - "ethereumjs-util" - ], - "deprecated": "ganache-cli is now ganache; visit https://trfl.io/g7 for details", - "dev": true, - "license": "MIT", - "dependencies": { - "ethereumjs-util": "6.2.1", - "source-map-support": "0.5.12", - "yargs": "13.2.4" - }, - "bin": { - "ganache-cli": "cli.js" - } - }, - "node_modules/ganache-cli/node_modules/@types/bn.js": { - "version": "4.11.6", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-cli/node_modules/@types/node": { - "version": "14.11.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/@types/pbkdf2": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-cli/node_modules/@types/secp256k1": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ganache-cli/node_modules/ansi-regex": { - "version": "4.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/base-x": { - "version": "3.0.8", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-cli/node_modules/blakejs": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/ganache-cli/node_modules/bn.js": { - "version": "4.11.9", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/brorand": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/browserify-aes": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "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" - } - }, - "node_modules/ganache-cli/node_modules/bs58": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/ganache-cli/node_modules/bs58check": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-cli/node_modules/buffer-from": { - "version": "1.1.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/buffer-xor": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/cipher-base": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ganache-cli/node_modules/cliui": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/ganache-cli/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/ganache-cli/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/create-hash": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/ganache-cli/node_modules/create-hmac": { - "version": "1.1.7", - "dev": true, - "inBundle": true, - "license": "MIT", - "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" - } - }, - "node_modules/ganache-cli/node_modules/cross-spawn": { - "version": "6.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/ganache-cli/node_modules/decamelize": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/elliptic": { - "version": "6.5.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "node_modules/ganache-cli/node_modules/emoji-regex": { - "version": "7.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/end-of-stream": { - "version": "1.4.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/ganache-cli/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "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" - } - }, - "node_modules/ganache-cli/node_modules/ethereumjs-util": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "MPL-2.0", - "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" - } - }, - "node_modules/ganache-cli/node_modules/ethjs-util": { - "version": "0.1.6", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/evp_bytestokey": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/ganache-cli/node_modules/execa": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/find-up": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/ganache-cli/node_modules/get-stream": { - "version": "4.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/hash-base": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/hash.js": { - "version": "1.1.7", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/ganache-cli/node_modules/hmac-drbg": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/ganache-cli/node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/invert-kv": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/is-hex-prefixed": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/is-stream": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/keccak": { - "version": "3.0.1", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache-cli/node_modules/lcid": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "invert-kv": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/locate-path": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/map-age-cleaner": { - "version": "0.1.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/md5.js": { - "version": "1.3.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/ganache-cli/node_modules/mem": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/minimalistic-assert": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/nice-try": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/node-addon-api": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/node-gyp-build": { - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/ganache-cli/node_modules/npm-run-path": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/once": { - "version": "1.4.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ganache-cli/node_modules/os-locale": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-defer": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/p-finally": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/p-is-promise": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ganache-cli/node_modules/p-locate": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/path-key": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ganache-cli/node_modules/pbkdf2": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "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" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/ganache-cli/node_modules/pump": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/ganache-cli/node_modules/randombytes": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/ganache-cli/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ganache-cli/node_modules/require-directory": { - "version": "2.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/require-main-filename": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/ripemd160": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/ganache-cli/node_modules/rlp": { - "version": "2.2.6", - "dev": true, - "inBundle": true, - "license": "MPL-2.0", - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/ganache-cli/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/scrypt-js": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/secp256k1": { - "version": "4.0.2", - "dev": true, - "hasInstallScript": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/ganache-cli/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/ganache-cli/node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/setimmediate": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/sha.js": { - "version": "2.4.11", - "dev": true, - "inBundle": true, - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/ganache-cli/node_modules/shebang-command": { - "version": "1.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/shebang-regex": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/signal-exit": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/source-map-support": { - "version": "0.5.12", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/ganache-cli/node_modules/string_decoder": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/ganache-cli/node_modules/string-width": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/strip-ansi": { - "version": "5.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/strip-eof": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ganache-cli/node_modules/strip-hex-prefix": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/ganache-cli/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/ganache-cli/node_modules/which": { - "version": "1.3.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/ganache-cli/node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/wrap-ansi": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ganache-cli/node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/y18n": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/ganache-cli/node_modules/yargs": { - "version": "13.2.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" - } - }, - "node_modules/ganache-cli/node_modules/yargs-parser": { - "version": "13.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "optional": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "node_modules/get-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz", - "integrity": "sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==", - "dev": true, - "optional": true - }, - "node_modules/get-prototype-of": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/get-prototype-of/-/get-prototype-of-0.0.0.tgz", - "integrity": "sha1-mHcr0QcW0W3rSzIlFsRp78oorEQ=", - "dev": true, - "optional": true - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/ghost-testrpc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", - "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "node-emoji": "^1.10.0" - }, - "bin": { - "testrpc-sc": "index.js" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "optional": true, - "dependencies": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-base/node_modules/glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "optional": true, - "dependencies": { - "is-glob": "^2.0.0" - } - }, - "node_modules/glob-base/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-base/node_modules/is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "optional": true, - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "optional": true, - "dependencies": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/glob-stream/node_modules/braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "optional": true, - "dependencies": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "optional": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-stream/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-stream/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "node_modules/glob-stream/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "optional": true, - "dependencies": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/micromatch/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/micromatch/node_modules/is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "optional": true, - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-stream/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/glob-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - }, - "node_modules/glob-stream/node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dev": true, - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", - "dev": true, - "optional": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/google-protobuf": { - "version": "3.19.4", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.19.4.tgz", - "integrity": "sha512-OIPNCxsG2lkIvf+P5FNfJ/Km95CsXOBecS9ZcAU6m2Rq3svc0Apl9nB3GMDNKfQ9asNv4KjyAqGwPQFrVle3Yg==", - "dev": true, - "optional": true - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/graphql": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", - "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/graphql-extensions": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.15.0.tgz", - "integrity": "sha512-bVddVO8YFJPwuACn+3pgmrEg6I8iBuYLuwvxiE+lcQQ7POotVZxm2rgGw0PvVYmWWf3DT7nTVDZ5ROh/ALp8mA==", - "dev": true, - "optional": true, - "dependencies": { - "@apollographql/apollo-tools": "^0.5.0", - "apollo-server-env": "^3.1.0", - "apollo-server-types": "^0.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/graphql-subscriptions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.2.1.tgz", - "integrity": "sha512-95yD/tKi24q8xYa7Q9rhQN16AYj5wPbrb8tmHGM3WRc9EBmWrG/0kkMl+tQG8wcEuE9ibR4zyOM31p5Sdr2v4g==", - "dev": true, - "optional": true, - "dependencies": { - "iterall": "^1.3.0" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/graphql-tools": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.8.tgz", - "integrity": "sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg==", - "dev": true, - "optional": true, - "dependencies": { - "apollo-link": "^1.2.14", - "apollo-utilities": "^1.0.1", - "deprecated-decorator": "^0.1.6", - "iterall": "^1.1.3", - "uuid": "^3.1.0" - } - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/gulp-sourcemaps": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.12.1.tgz", - "integrity": "sha1-tDfR89mAzyboEYSCNxjOFa5ll7Y=", - "dev": true, - "optional": true, - "dependencies": { - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "4.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "0.0.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom": "2.X", - "through2": "2.X", - "vinyl": "1.X" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gulp-sourcemaps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/header-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", - "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.3" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=", - "dev": true - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/ice-cap": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/ice-cap/-/ice-cap-0.0.4.tgz", - "integrity": "sha1-im0xq0ysjUtW3k+pRt8zUlYbbhg=", - "dev": true, - "dependencies": { - "cheerio": "0.20.0", - "color-logger": "0.0.3" - } - }, - "node_modules/ice-cap/node_modules/cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", - "dev": true, - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "lodash": "^4.1.0" - }, - "engines": { - "node": ">= 0.6" - }, - "optionalDependencies": { - "jsdom": "^7.0.2" - } - }, - "node_modules/ice-cap/node_modules/color-logger": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz", - "integrity": "sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg=", - "dev": true - }, - "node_modules/ice-cap/node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/ice-cap/node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "node_modules/ice-cap/node_modules/htmlparser2/node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "node_modules/ice-cap/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/ice-cap/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/ice-cap/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "dev": true, - "dependencies": { - "punycode": "2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/idna-uts46-hx/node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", - "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", - "dev": true, - "optional": true, - "dependencies": { - "minimatch": "^3.0.4" - } - }, - "node_modules/immediate": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", - "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", - "dev": true, - "optional": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ipfs-core-types": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ipfs-core-types/-/ipfs-core-types-0.2.1.tgz", - "integrity": "sha512-q93+93qSybku6woZaajE9mCrHeVoMzNtZ7S5m/zx0+xHRhnoLlg8QNnGGsb5/+uFQt/RiBArsIw/Q61K9Jwkzw==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.1.5", - "multiaddr": "^8.0.0", - "peer-id": "^0.14.1" - } - }, - "node_modules/ipfs-core-types/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-core-types/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-core-types/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-core-types/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-core-utils": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/ipfs-core-utils/-/ipfs-core-utils-0.6.1.tgz", - "integrity": "sha512-UFIklwE3CFcsNIhYFDuz0qB7E2QtdFauRfc76kskgiqhGWcjqqiDeND5zBCrAy0u8UMaDqAbFl02f/mIq1yKXw==", - "dev": true, - "optional": true, - "dependencies": { - "any-signal": "^2.0.0", - "blob-to-it": "^1.0.1", - "browser-readablestream-to-it": "^1.0.1", - "cids": "^1.1.5", - "err-code": "^2.0.3", - "ipfs-core-types": "^0.2.1", - "ipfs-utils": "^5.0.0", - "it-all": "^1.0.4", - "it-map": "^1.0.4", - "it-peekable": "^1.0.1", - "multiaddr": "^8.0.0", - "multiaddr-to-uri": "^6.0.0", - "parse-duration": "^0.4.4", - "timeout-abort-controller": "^1.1.1", - "uint8arrays": "^1.1.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-core-utils/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/multicodec/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-core-utils/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-core-utils/node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-core-utils/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-core-utils/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-http-client": { - "version": "48.2.2", - "resolved": "https://registry.npmjs.org/ipfs-http-client/-/ipfs-http-client-48.2.2.tgz", - "integrity": "sha512-f3ppfWe913SJLvunm0UgqdA1dxVZSGQJPaEVJtqgjxPa5x0fPDiBDdo60g2MgkW1W6bhF9RGlxvHHIE9sv/tdg==", - "dev": true, - "optional": true, - "dependencies": { - "any-signal": "^2.0.0", - "bignumber.js": "^9.0.0", - "cids": "^1.1.5", - "debug": "^4.1.1", - "form-data": "^3.0.0", - "ipfs-core-types": "^0.2.1", - "ipfs-core-utils": "^0.6.1", - "ipfs-utils": "^5.0.0", - "ipld-block": "^0.11.0", - "ipld-dag-cbor": "^0.17.0", - "ipld-dag-pb": "^0.20.0", - "ipld-raw": "^6.0.0", - "it-last": "^1.0.4", - "it-map": "^1.0.4", - "it-tar": "^1.2.2", - "it-to-stream": "^0.1.2", - "merge-options": "^2.0.0", - "multiaddr": "^8.0.0", - "multibase": "^3.0.0", - "multicodec": "^2.0.1", - "multihashes": "^3.0.1", - "nanoid": "^3.1.12", - "native-abort-controller": "~0.0.3", - "parse-duration": "^0.4.4", - "stream-to-it": "^0.2.2", - "uint8arrays": "^1.1.0" - }, - "engines": { - "node": ">=10.3.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/cids/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/cids/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/cids/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/cids/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-http-client/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-http-client/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "optional": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ipfs-http-client/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/multicodec": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-2.1.3.tgz", - "integrity": "sha512-0tOH2Gtio39uO41o+2xl9UhRkCWxU5ZmZSbFCh/OjGzkWJI8e6lkN/s4Mj1YfyWoBod+2+S3W+6wO6nhkwN8pA==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "1.1.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/multihashes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-3.1.2.tgz", - "integrity": "sha512-AP4IoV/YzkNrfbQKZE3OMPibrmy350OmCd6cJkwyM8oExaXIlOY4UnOOVSQtAEuq/LR01XfXKCESidzZvSwHCQ==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^3.1.0", - "uint8arrays": "^2.0.5", - "varint": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipfs-http-client/node_modules/multihashes/node_modules/uint8arrays": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz", - "integrity": "sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipfs-http-client/node_modules/native-abort-controller": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/native-abort-controller/-/native-abort-controller-0.0.3.tgz", - "integrity": "sha512-YIxU5nWqSHG1Xbu3eOu3pdFRD882ivQpIcu6AiPVe2oSVoRbfYW63DVkZm3g1gHiMtZSvZzF6THSzTGEBYl8YA==", - "dev": true, - "optional": true, - "dependencies": { - "globalthis": "^1.0.1" - } - }, - "node_modules/ipfs-http-client/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipfs-utils": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-5.0.1.tgz", - "integrity": "sha512-28KZPgO4Uf5duT2ORLAYfboUp98iUshDD7yRAfbNxNAR8Dtidfn6o20rZfoXnkri2zKBVIPlJkuCPmPJB+6erg==", - "dev": true, - "optional": true, - "dependencies": { - "abort-controller": "^3.0.0", - "any-signal": "^2.1.0", - "buffer": "^6.0.1", - "electron-fetch": "^1.7.2", - "err-code": "^2.0.0", - "fs-extra": "^9.0.1", - "is-electron": "^2.2.0", - "iso-url": "^1.0.0", - "it-glob": "0.0.10", - "it-to-stream": "^0.1.2", - "merge-options": "^2.0.0", - "nanoid": "^3.1.3", - "native-abort-controller": "0.0.3", - "native-fetch": "^2.0.0", - "node-fetch": "^2.6.0", - "stream-to-it": "^0.2.0" - } - }, - "node_modules/ipfs-utils/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "optional": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/ipfs-utils/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ipfs-utils/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "node_modules/ipfs-utils/node_modules/native-abort-controller": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/native-abort-controller/-/native-abort-controller-0.0.3.tgz", - "integrity": "sha512-YIxU5nWqSHG1Xbu3eOu3pdFRD882ivQpIcu6AiPVe2oSVoRbfYW63DVkZm3g1gHiMtZSvZzF6THSzTGEBYl8YA==", - "dev": true, - "optional": true, - "dependencies": { - "globalthis": "^1.0.1" - } - }, - "node_modules/ipfs-utils/node_modules/native-fetch": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/native-fetch/-/native-fetch-2.0.1.tgz", - "integrity": "sha512-gv4Bea+ga9QdXINurpkEqun3ap3vnB+WYoe4c8ddqUYEH7B2h6iD39RF8uVN7OwmSfMY3RDxkvBnoI4e2/vLXQ==", - "dev": true, - "optional": true, - "dependencies": { - "globalthis": "^1.0.1" - } - }, - "node_modules/ipfs-utils/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/ipld-block": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/ipld-block/-/ipld-block-0.11.1.tgz", - "integrity": "sha512-sDqqLqD5qh4QzGq6ssxLHUCnH4emCf/8F8IwjQM2cjEEIEHMUj57XhNYgmGbemdYPznUhffxFGEHsruh5+HQRw==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-block/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-block/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-block/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-block/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-block/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipld-block/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-block/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipld-dag-cbor": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/ipld-dag-cbor/-/ipld-dag-cbor-0.17.1.tgz", - "integrity": "sha512-Bakj/cnxQBdscORyf4LRHxQJQfoaY8KWc7PWROQgX+aw5FCzBt8ga0VM/59K+ABOznsqNvyLR/wz/oYImOpXJw==", - "dev": true, - "optional": true, - "dependencies": { - "borc": "^2.1.2", - "cids": "^1.0.0", - "is-circular": "^1.0.2", - "multicodec": "^3.0.1", - "multihashing-async": "^2.0.0", - "uint8arrays": "^2.1.3" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-dag-cbor/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-dag-cbor/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multicodec/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-cbor/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipld-dag-cbor/node_modules/uint8arrays": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz", - "integrity": "sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-cbor/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipld-dag-pb": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/ipld-dag-pb/-/ipld-dag-pb-0.20.0.tgz", - "integrity": "sha512-zfM0EdaolqNjAxIrtpuGKvXxWk5YtH9jKinBuQGTcngOsWFQhyybGCTJHGNGGtRjHNJi2hz5Udy/8pzv4kcKyg==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "multicodec": "^2.0.0", - "multihashing-async": "^2.0.0", - "protons": "^2.0.0", - "reset": "^0.1.0", - "run": "^1.4.0", - "stable": "^0.1.8", - "uint8arrays": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/cids/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-pb/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/multicodec": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-2.1.3.tgz", - "integrity": "sha512-0tOH2Gtio39uO41o+2xl9UhRkCWxU5ZmZSbFCh/OjGzkWJI8e6lkN/s4Mj1YfyWoBod+2+S3W+6wO6nhkwN8pA==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "1.1.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-dag-pb/node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-dag-pb/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipld-dag-pb/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/ipld-raw": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ipld-raw/-/ipld-raw-6.0.0.tgz", - "integrity": "sha512-UK7fjncAzs59iu/o2kwYtb8jgTtW6B+cNWIiNpAJkfRwqoMk1xD/6i25ktzwe4qO8gQgoR9RxA5ibC23nq8BLg==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.0.0", - "multicodec": "^2.0.0", - "multihashing-async": "^2.0.0" - } - }, - "node_modules/ipld-raw/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/ipld-raw/node_modules/cids/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-raw/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-raw/node_modules/multicodec": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-2.1.3.tgz", - "integrity": "sha512-0tOH2Gtio39uO41o+2xl9UhRkCWxU5ZmZSbFCh/OjGzkWJI8e6lkN/s4Mj1YfyWoBod+2+S3W+6wO6nhkwN8pA==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "1.1.0", - "varint": "^6.0.0" - } - }, - "node_modules/ipld-raw/node_modules/multicodec/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-raw/node_modules/multicodec/node_modules/uint8arrays": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz", - "integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/ipld-raw/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ipld-raw/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/ipld-raw/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/ipld-raw/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "optional": true - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-capitalized": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-capitalized/-/is-capitalized-1.0.0.tgz", - "integrity": "sha1-TIRktNkdPk7rRIid0s2PGwrEwTY=", - "dev": true, - "optional": true - }, - "node_modules/is-circular": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-circular/-/is-circular-1.0.2.tgz", - "integrity": "sha512-YttjnrswnUYRVJvxCvu8z+PGMUSzC2JttP0OEXezlAEdp3EXzhf7IZ3j0gRAybJBQupedIZFhY61Tga6E0qASA==", - "dev": true, - "optional": true - }, - "node_modules/is-class": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz", - "integrity": "sha1-4FdFFwW7NOOePjNZjJOpg3KWtzY=", - "dev": true, - "optional": true - }, - "node_modules/is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-electron": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz", - "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==", - "dev": true, - "optional": true - }, - "node_modules/is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "optional": true, - "dependencies": { - "is-primitive": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=", - "dev": true, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/is-ip": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", - "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", - "dev": true, - "optional": true, - "dependencies": { - "ip-regex": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lower-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", - "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=", - "dev": true, - "dependencies": { - "lower-case": "^1.1.0" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-upper-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", - "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=", - "dev": true, - "dependencies": { - "upper-case": "^1.1.0" - } - }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "node_modules/is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/iso-constants": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/iso-constants/-/iso-constants-0.1.2.tgz", - "integrity": "sha512-OTCM5ZCQsHBCI4Wdu4tSxvDIkmDHd5EwJDps5mKqnQnWJSKlnwMs3EDZ4n3Fh1tmkWkDlyd2vCDbEYuPbyrUNQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/iso-random-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/iso-random-stream/-/iso-random-stream-2.0.2.tgz", - "integrity": "sha512-yJvs+Nnelic1L2vH2JzWvvPQFA4r7kSTnpST/+LkAQjSz0hos2oqLD+qIVi9Qk38Hoe7mNDt3j0S27R58MVjLQ==", - "dev": true, - "optional": true, - "dependencies": { - "events": "^3.3.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/iso-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-1.2.1.tgz", - "integrity": "sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==", - "dev": true, - "optional": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "optional": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "dev": true, - "optional": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/it-all": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/it-all/-/it-all-1.0.6.tgz", - "integrity": "sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==", - "dev": true, - "optional": true - }, - "node_modules/it-concat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/it-concat/-/it-concat-1.0.3.tgz", - "integrity": "sha512-sjeZQ1BWQ9U/W2oI09kZgUyvSWzQahTkOkLIsnEPgyqZFaF9ME5gV6An4nMjlyhXKWQMKEakQU8oRHs2SdmeyA==", - "dev": true, - "optional": true, - "dependencies": { - "bl": "^4.0.0" - } - }, - "node_modules/it-drain": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-1.0.5.tgz", - "integrity": "sha512-r/GjkiW1bZswC04TNmUnLxa6uovme7KKwPhc+cb1hHU65E3AByypHH6Pm91WHuvqfFsm+9ws0kPtDBV3/8vmIg==", - "dev": true, - "optional": true - }, - "node_modules/it-glob": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/it-glob/-/it-glob-0.0.10.tgz", - "integrity": "sha512-p1PR15djgPV7pxdLOW9j4WcJdla8+91rJdUU2hU2Jm68vkxpIEXK55VHBeH8Lvqh2vqLtM83t8q4BuJxue6niA==", - "dev": true, - "optional": true, - "dependencies": { - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4" - } - }, - "node_modules/it-glob/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/it-glob/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "node_modules/it-glob/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/it-last": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/it-last/-/it-last-1.0.6.tgz", - "integrity": "sha512-aFGeibeiX/lM4bX3JY0OkVCFkAw8+n9lkukkLNivbJRvNz8lI3YXv5xcqhFUV2lDJiraEK3OXRDbGuevnnR67Q==", - "dev": true, - "optional": true - }, - "node_modules/it-map": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/it-map/-/it-map-1.0.6.tgz", - "integrity": "sha512-XT4/RM6UHIFG9IobGlQPFQUrlEKkU4eBUFG3qhWhfAdh1JfF2x11ShCrKCdmZ0OiZppPfoLuzcfA4cey6q3UAQ==", - "dev": true, - "optional": true - }, - "node_modules/it-peekable": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/it-peekable/-/it-peekable-1.0.3.tgz", - "integrity": "sha512-5+8zemFS+wSfIkSZyf0Zh5kNN+iGyccN02914BY4w/Dj+uoFEoPSvj5vaWn8pNZJNSxzjW0zHRxC3LUb2KWJTQ==", - "dev": true, - "optional": true - }, - "node_modules/it-reader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/it-reader/-/it-reader-2.1.0.tgz", - "integrity": "sha512-hSysqWTO9Tlwc5EGjVf8JYZzw0D2FsxD/g+eNNWrez9zODxWt6QlN6JAMmycK72Mv4jHEKEXoyzUN4FYGmJaZw==", - "dev": true, - "optional": true, - "dependencies": { - "bl": "^4.0.0" - } - }, - "node_modules/it-tar": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/it-tar/-/it-tar-1.2.2.tgz", - "integrity": "sha512-M8V4a9I+x/vwXTjqvixcEZbQZHjwDIb8iUQ+D4M2QbhAdNs3WKVSl+45u5/F2XFx6jYMFOGzMVlKNK/uONgNIA==", - "dev": true, - "optional": true, - "dependencies": { - "bl": "^4.0.0", - "buffer": "^5.4.3", - "iso-constants": "^0.1.2", - "it-concat": "^1.0.0", - "it-reader": "^2.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/it-to-stream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/it-to-stream/-/it-to-stream-0.1.2.tgz", - "integrity": "sha512-DTB5TJRZG3untmZehcaFN0kGWl2bNv7tnJRgQHAO9QEt8jfvVRrebZtnD5NZd4SCj4WVPjl0LSrugNWE/UaZRQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.6.0", - "fast-fifo": "^1.0.0", - "get-iterator": "^1.0.2", - "p-defer": "^3.0.0", - "p-fifo": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/iter-tools": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/iter-tools/-/iter-tools-7.2.0.tgz", - "integrity": "sha512-wU0BpT8CaJCvXuhBy3WvshLhDwrsrrxWv77B4cSECnqWRm0tv2ozQRQm7M5dCkzoaQCLyRmGO0P2jDVSw5Hjvw==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/runtime": "^7.12.1" - } - }, - "node_modules/iterall": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", - "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", - "dev": true, - "optional": true - }, - "node_modules/iterate-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", - "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", - "dev": true - }, - "node_modules/iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "dependencies": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, - "node_modules/js-sha256": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", - "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==", - "dev": true, - "optional": true - }, - "node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "dev": true, - "optional": true, - "dependencies": { - "abab": "^1.0.0", - "acorn": "^2.4.0", - "acorn-globals": "^1.0.4", - "cssom": ">= 0.3.0 < 0.4.0", - "cssstyle": ">= 0.2.29 < 0.3.0", - "escodegen": "^1.6.1", - "nwmatcher": ">= 1.3.7 < 2.0.0", - "parse5": "^1.5.1", - "request": "^2.55.0", - "sax": "^1.1.4", - "symbol-tree": ">= 3.1.0 < 4.0.0", - "tough-cookie": "^2.2.0", - "webidl-conversions": "^2.0.0", - "whatwg-url-compat": "~0.6.5", - "xml-name-validator": ">= 2.0.1 < 3.0.0" - } - }, - "node_modules/jsdom/node_modules/acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "dev": true, - "optional": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "dev": true, - "optional": true - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "dev": true, - "optional": true - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-pointer": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.1.tgz", - "integrity": "sha512-3OvjqKdCBvH41DLpV4iSt6v2XhZXV1bPB4OROuknvUXI7ZQNofieCPkmE26stEJ9zdQuvIxDHCuYhfgxFAAs+Q==", - "dev": true, - "dependencies": { - "foreach": "^2.0.4" - } - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-schema-typed": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", - "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", - "dev": true, - "optional": true - }, - "node_modules/json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "dependencies": { - "jsonify": "~0.0.0" - } - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true, - "optional": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/json-text-sequence": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", - "integrity": "sha1-py8hfcSvxGKf/1/rME3BvVGi89I=", - "dev": true, - "optional": true, - "dependencies": { - "delimit-stream": "0.1.0" - } - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsondown": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jsondown/-/jsondown-1.0.0.tgz", - "integrity": "sha512-p6XxPaq59aXwcdDQV3ISMA5xk+1z6fJuctcwwSdR9iQgbYOcIrnknNrhcMGG+0FaUfKHGkdDpQNaZrovfBoyOw==", - "dev": true, - "optional": true, - "dependencies": { - "memdown": "1.4.1", - "mkdirp": "0.5.1" - } - }, - "node_modules/jsondown/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true, - "optional": true - }, - "node_modules/jsondown/node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "optional": true, - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "node_modules/jsonschema": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", - "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/keccak": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", - "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", - "dev": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/keypair": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/keypair/-/keypair-1.0.4.tgz", - "integrity": "sha512-zwhgOhhniaL7oxMgUMKKw5219PWWABMO+dgMnzJOQ2/5L3XJtTJGhW2PEXlxXj9zaccdReZJZ83+4NPhVfNVDg==", - "dev": true, - "optional": true - }, - "node_modules/keypather": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/keypather/-/keypather-1.10.2.tgz", - "integrity": "sha1-4ESWMtSz5RbyHMAUznxWRP3c5hQ=", - "dev": true, - "optional": true, - "dependencies": { - "101": "^1.0.0" - } - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lazy-debug-legacy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz", - "integrity": "sha1-U3cWwHduTPeePtG2IfdljCkRsbE=", - "dev": true, - "optional": true - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "dependencies": { - "invert-kv": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", - "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } - }, - "node_modules/leb128": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/leb128/-/leb128-0.0.5.tgz", - "integrity": "sha512-elbNtfmu3GndZbesVF6+iQAfVjOXW9bM/aax9WwMlABZW+oK9sbAZEXoewaPHmL34sxa8kVwWsru8cNE/yn2gg==", - "dev": true, - "optional": true, - "dependencies": { - "bn.js": "^5.0.0", - "buffer-pipe": "0.0.3" - } - }, - "node_modules/leb128/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true, - "optional": true - }, - "node_modules/level": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/level/-/level-5.0.1.tgz", - "integrity": "sha512-wcak5OQeA4rURGacqS62R/xNHjCYnJSQDBOlm4KNUGJVE9bWv2B04TclqReYejN+oD65PzD4FsqeWoI5wNC5Lg==", - "dev": true, - "optional": true, - "dependencies": { - "level-js": "^4.0.0", - "level-packager": "^5.0.0", - "leveldown": "^5.0.0", - "opencollective-postinstall": "^2.0.0" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/level-codec": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.1.tgz", - "integrity": "sha512-ajFP0kJ+nyq4i6kptSM+mAvJKLOg1X5FiFPtLG9M5gCEZyBmgDi3FkDrvlMkEzrUn1cWxtvVmrvoS4ASyO/q+Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-concat-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", - "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", - "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", - "dev": true, - "optional": true, - "dependencies": { - "errno": "~0.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-iterator-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", - "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.4.0", - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-js": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/level-js/-/level-js-4.0.2.tgz", - "integrity": "sha512-PeGjZsyMG4O89KHiez1zoMJxStnkM+oBIqgACjoo5PJqFiSUUm3GNod/KcbqN5ktyZa8jkG7I1T0P2u6HN9lIg==", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "~6.0.1", - "immediate": "~3.2.3", - "inherits": "^2.0.3", - "ltgt": "^2.1.2", - "typedarray-to-buffer": "~3.1.5" - } - }, - "node_modules/level-js/node_modules/abstract-leveldown": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.0.3.tgz", - "integrity": "sha512-jzewKKpZbaYUa6HTThnrl+GrJhzjEAeuc7hTVpZdzg7kupXZFoqQDFwyOwLNbmJKJlmzw8yiipMPkDiuKkT06Q==", - "dev": true, - "optional": true, - "dependencies": { - "level-concat-iterator": "~2.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-js/node_modules/immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true, - "optional": true - }, - "node_modules/level-packager": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz", - "integrity": "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==", - "dev": true, - "optional": true, - "dependencies": { - "encoding-down": "^6.3.0", - "levelup": "^4.3.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-packager/node_modules/levelup": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", - "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", - "dev": true, - "optional": true, - "dependencies": { - "deferred-leveldown": "~5.3.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~4.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "optional": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-write-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/level-write-stream/-/level-write-stream-1.0.0.tgz", - "integrity": "sha1-P3+7Z5pVE3wP6zA97nZuEu4Twdw=", - "dev": true, - "optional": true, - "dependencies": { - "end-stream": "~0.1.0" - } - }, - "node_modules/leveldown": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.0.2.tgz", - "integrity": "sha512-Ib6ygFYBleS8x2gh3C1AkVsdrUShqXpe6jSTnZ6sRycEXKhqVf+xOSkhgSnjidpPzyv0d95LJVFrYQ4NuXAqHA==", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "~6.0.0", - "fast-future": "~1.0.2", - "napi-macros": "~1.8.1", - "node-gyp-build": "~3.8.0" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/leveldown/node_modules/abstract-leveldown": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.0.3.tgz", - "integrity": "sha512-jzewKKpZbaYUa6HTThnrl+GrJhzjEAeuc7hTVpZdzg7kupXZFoqQDFwyOwLNbmJKJlmzw8yiipMPkDiuKkT06Q==", - "dev": true, - "optional": true, - "dependencies": { - "level-concat-iterator": "~2.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/leveldown/node_modules/node-gyp-build": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.8.0.tgz", - "integrity": "sha512-bYbpIHyRqZ7sVWXxGpz8QIRug5JZc/hzZH4GbdT9HTZi6WmKCZ8GLvP8OZ9TTiIBvwPFKgtGrlWQSXDAvYdsPw==", - "dev": true, - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/levelup": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.0.2.tgz", - "integrity": "sha512-cx9PmLENwbGA3svWBEbeO2HazpOSOYSXH4VA+ahVpYyurvD+SDSfURl29VBY2qgyk+Vfy2dJd71SBRckj/EZVA==", - "dev": true, - "optional": true, - "dependencies": { - "deferred-leveldown": "~5.0.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~4.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/levelup/node_modules/abstract-leveldown": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.0.3.tgz", - "integrity": "sha512-jzewKKpZbaYUa6HTThnrl+GrJhzjEAeuc7hTVpZdzg7kupXZFoqQDFwyOwLNbmJKJlmzw8yiipMPkDiuKkT06Q==", - "dev": true, - "optional": true, - "dependencies": { - "level-concat-iterator": "~2.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/levelup/node_modules/deferred-leveldown": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.0.1.tgz", - "integrity": "sha512-BXohsvTedWOLkj2n/TY+yqVlrCWa2Zs8LSxh3uCAgFOru7/pjxKyZAexGa1j83BaKloER4PqUyQ9rGPJLt9bqA==", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "~6.0.0", - "inherits": "^2.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libp2p-crypto": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.19.7.tgz", - "integrity": "sha512-Qb5o/3WFKF2j6mYSt4UBPyi2kbKl3jYV0podBJoJCw70DlpM5Xc+oh3fFY9ToSunu8aSQQ5GY8nutjXgX/uGRA==", - "dev": true, - "optional": true, - "dependencies": { - "err-code": "^3.0.1", - "is-typedarray": "^1.0.0", - "iso-random-stream": "^2.0.0", - "keypair": "^1.0.1", - "multiformats": "^9.4.5", - "node-forge": "^0.10.0", - "pem-jwk": "^2.0.0", - "protobufjs": "^6.11.2", - "secp256k1": "^4.0.0", - "uint8arrays": "^3.0.0", - "ursa-optional": "^0.10.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/libp2p-crypto/node_modules/err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", - "dev": true, - "optional": true - }, - "node_modules/libp2p-crypto/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "node_modules/lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true - }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true, - "optional": true - }, - "node_modules/lodash.assigninwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assigninwith/-/lodash.assigninwith-4.2.0.tgz", - "integrity": "sha1-rwLJhDKshtk9ppW0voAUAZcXNq8=", - "dev": true, - "optional": true - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=", - "dev": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", - "integrity": "sha1-oIYCrBLk+4P5H8H7ejYKTZujUgU=", - "dev": true, - "optional": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", - "dev": true, - "optional": true - }, - "node_modules/lodash.partition": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz", - "integrity": "sha1-o45GtzRp4EILDaEhLmbUFL42S6Q=", - "dev": true - }, - "node_modules/lodash.rest": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.5.tgz", - "integrity": "sha1-lU73UEkmIDjJbR/Jiyj9r58Hcqo=", - "dev": true, - "optional": true - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true, - "optional": true - }, - "node_modules/lodash.sum": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lodash.sum/-/lodash.sum-4.0.2.tgz", - "integrity": "sha1-rZDjl5ZdgD1PH/eqWy0Bl/O0Y3s=", - "dev": true - }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "dependencies": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "node_modules/lodash.tostring": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/lodash.tostring/-/lodash.tostring-4.1.4.tgz", - "integrity": "sha1-Vgwn0fjq3eA8LM4Zj+9cAx2CmPs=", - "dev": true, - "optional": true - }, - "node_modules/lodash.without": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz", - "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=", - "dev": true, - "optional": true - }, - "node_modules/lodash.xor": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.xor/-/lodash.xor-4.5.0.tgz", - "integrity": "sha1-TUjtfpgJWwYyWCunFNP/iuj7HbY=", - "dev": true, - "optional": true - }, - "node_modules/lodash.zipwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.zipwith/-/lodash.zipwith-4.2.0.tgz", - "integrity": "sha1-r6zwP9LzhK8p4mPDxr2juA4/Uf0=", - "dev": true - }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/loglevel": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", - "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "dev": true, - "optional": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "node_modules/lower-case-first": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz", - "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=", - "dev": true, - "dependencies": { - "lower-case": "^1.1.2" - } - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true, - "optional": true - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-stream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.6.tgz", - "integrity": "sha1-0u9OuBGihkTHqJiZhcacL91JaCc=", - "dev": true, - "optional": true - }, - "node_modules/marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", - "dev": true, - "bin": { - "marked": "bin/marked" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/marked-terminal": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-3.3.0.tgz", - "integrity": "sha512-+IUQJ5VlZoAFsM5MHNT7g3RHSkA3eETqhRCdXv4niUMAKHQ7lb1yvAcuGPmm4soxhmtX13u4Li6ZToXtvSEH+A==", - "dev": true, - "dependencies": { - "ansi-escapes": "^3.1.0", - "cardinal": "^2.1.1", - "chalk": "^2.4.1", - "cli-table": "^0.3.1", - "node-emoji": "^1.4.1", - "supports-hyperlinks": "^1.0.1" - } - }, - "node_modules/math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true, - "optional": true - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memdown": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", - "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, - "optional": true, - "dependencies": { - "abstract-leveldown": "~2.7.1", - "functional-red-black-tree": "^1.0.1", - "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-2.0.0.tgz", - "integrity": "sha512-S7xYIeWHl2ZUKF7SDeBhGg6rfv5bKxVBdk95s/I7wVF8d+hjLSztJ/B271cnUiF6CAFduEQ5Zn3HYwAjT16DlQ==", - "dev": true, - "optional": true, - "dependencies": { - "is-plain-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-options/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/merge-stream/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/merge-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/merge-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "dev": true, - "dependencies": { - "mime-db": "1.49.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "dependencies": { - "minipass": "^2.9.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "dev": true, - "dependencies": { - "mkdirp": "*" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.2.tgz", - "integrity": "sha512-I8FRAcuACNMLQn3lS4qeWLxXqLvGf6r2CaLstDpZmMUUSmvW6Cnm1AuHxgbc7ctZVRcfwspCRbDHymPsi3dkJw==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.2", - "debug": "4.1.1", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.0", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/mocha/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/mocha/node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/mocha/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mocha/node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/wrap-ansi/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/mocha/node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/mocha/node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/mocha/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mock-fs": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", - "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==", - "dev": true - }, - "node_modules/module": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/module/-/module-1.2.5.tgz", - "integrity": "sha1-tQPrBs3BNHP1aBhCaXTN5+xZvxU=", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "1.1.3", - "concat-stream": "1.5.1", - "lodash.template": "4.2.4", - "map-stream": "0.0.6", - "tildify": "1.2.0", - "vinyl-fs": "2.4.3", - "yargs": "4.6.0" - }, - "bin": { - "module": "dist/cli.js" - } - }, - "node_modules/module/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/module/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/module/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "optional": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/module/node_modules/lodash.template": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.2.4.tgz", - "integrity": "sha1-0FPBno50442WW/T7SV2A8Qnn96Q=", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "lodash._reinterpolate": "~3.0.0", - "lodash.assigninwith": "^4.0.0", - "lodash.keys": "^4.0.0", - "lodash.rest": "^4.0.0", - "lodash.templatesettings": "^4.0.0", - "lodash.tostring": "^4.0.0" - } - }, - "node_modules/module/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "optional": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/module/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multiaddr": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz", - "integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.0.0", - "class-is": "^1.1.0", - "dns-over-http-resolver": "^1.0.0", - "err-code": "^2.0.3", - "is-ip": "^3.1.0", - "multibase": "^3.0.0", - "uint8arrays": "^1.1.0", - "varint": "^5.0.0" - } - }, - "node_modules/multiaddr-to-uri": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/multiaddr-to-uri/-/multiaddr-to-uri-6.0.0.tgz", - "integrity": "sha512-OjpkVHOXEmIKMO8WChzzQ7aZQcSQX8squxmvtDbRpy7/QNmJ3Z7jv6qyD74C28QtaeNie8O8ngW2AkeiMmKP7A==", - "dev": true, - "optional": true, - "dependencies": { - "multiaddr": "^8.0.0" - } - }, - "node_modules/multiaddr/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/multiaddr/node_modules/cids/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multiaddr/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/multiaddr/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multiaddr/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/multiaddr/node_modules/multicodec/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/multiaddr/node_modules/multicodec/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/multiaddr/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multiaddr/node_modules/multihashes/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multiaddr/node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "dev": true, - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "node_modules/multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "dev": true, - "dependencies": { - "varint": "^5.0.0" - } - }, - "node_modules/multiformats": { - "version": "9.6.3", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.6.3.tgz", - "integrity": "sha512-yfXKI66fL0nFzt0nJl26i4wV1qAqbAEIBvfFbkbsne9GrLz6IHvHUoRyxUtlJcdP181ssOgjama6E/VSk4pbrA==", - "dev": true, - "optional": true - }, - "node_modules/multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - } - }, - "node_modules/multihashes/node_modules/multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "dev": true, - "dependencies": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "node_modules/multihashing-async": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/multihashing-async/-/multihashing-async-2.1.4.tgz", - "integrity": "sha512-sB1MiQXPSBTNRVSJc2zM157PXgDtud2nMFUEIvBrsq5Wv96sUclMRK/ecjoP1T/W61UJBqt4tCTwMkUpt2Gbzg==", - "dev": true, - "optional": true, - "dependencies": { - "blakejs": "^1.1.0", - "err-code": "^3.0.0", - "js-sha3": "^0.8.0", - "multihashes": "^4.0.1", - "murmurhash3js-revisited": "^3.0.0", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashing-async/node_modules/err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", - "dev": true, - "optional": true - }, - "node_modules/multihashing-async/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true, - "optional": true - }, - "node_modules/multihashing-async/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashing-async/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/multihashing-async/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/murmurhash3js-revisited": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz", - "integrity": "sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, - "node_modules/nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", - "dev": true, - "optional": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-macros": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-1.8.2.tgz", - "integrity": "sha512-Tr0DNY4RzTaBG2W2m3l7ZtFuJChTH6VZhXVhkGGjF/4cZTt+i8GcM9ozD+30Lmr4mDoZ5Xx34t2o4GJqYWDGcg==", - "dev": true, - "optional": true - }, - "node_modules/native-abort-controller": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/native-abort-controller/-/native-abort-controller-1.0.4.tgz", - "integrity": "sha512-zp8yev7nxczDJMoP6pDxyD20IU0T22eX8VwN2ztDccKvSZhRaV33yP1BGwKSZfXuqWUzsXopVFjBdau9OOAwMQ==", - "dev": true, - "optional": true - }, - "node_modules/native-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/native-fetch/-/native-fetch-3.0.0.tgz", - "integrity": "sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==", - "dev": true, - "optional": true - }, - "node_modules/needle": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", - "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "optional": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-interval-tree": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-interval-tree/-/node-interval-tree-1.3.3.tgz", - "integrity": "sha512-K9vk96HdTK5fEipJwxSvIIqwTqr4e3HRJeJrNxBSeVMNSC/JWARRaX7etOLOuTmrRMeOI/K5TCJu3aWIwZiNTw==", - "dev": true, - "dependencies": { - "shallowequal": "^1.0.2" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/node-pre-gyp": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", - "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", - "dev": true, - "optional": true, - "dependencies": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/node-pre-gyp/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "optional": true, - "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/node-pre-gyp/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/node-pre-gyp/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true - }, - "node_modules/nofilter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz", - "integrity": "sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/noop-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz", - "integrity": "sha1-XzPUfxPSFQ35PgywNmmemC94/78=", - "dev": true, - "optional": true - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, - "optional": true, - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true, - "optional": true - }, - "node_modules/npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dev": true, - "optional": true, - "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "dev": true, - "dependencies": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/number-to-bn/node_modules/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=", - "dev": true - }, - "node_modules/nwmatcher": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", - "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", - "dev": true, - "optional": true - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", - "dev": true - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-path": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", - "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", - "dev": true, - "optional": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/object.getownpropertydescriptors/node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dev": true, - "optional": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "optional": true, - "dependencies": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/oboe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", - "integrity": "sha1-VVQoTFQ6ImbXo48X4HOCH73jk80=", - "dev": true, - "dependencies": { - "http-https": "^1.0.0" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "optional": true, - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true, - "optional": true, - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", - "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-spinners": "^2.0.0", - "log-symbols": "^2.2.0", - "strip-ansi": "^5.2.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "optional": true, - "dependencies": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" - } - }, - "node_modules/ordered-read-streams/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/ordered-read-streams/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/original-require": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", - "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", - "dev": true - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "dependencies": { - "lcid": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-defer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", - "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-fifo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-fifo/-/p-fifo-1.0.0.tgz", - "integrity": "sha512-IjoCxXW48tqdtDFz6fqo5q1UfFVjjVZe8TC1QRflvNUJtNfCUhxOUw6MOVZhDPjqhSzc26xKdugsO17gmzd5+A==", - "dev": true, - "optional": true, - "dependencies": { - "fast-fifo": "^1.0.0", - "p-defer": "^3.0.0" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/paramap-it": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/paramap-it/-/paramap-it-0.1.1.tgz", - "integrity": "sha512-3uZmCAN3xCw7Am/4ikGzjjR59aNMJVXGSU7CjG2Z6DfOAdhnLdCOd0S0m1sTkN4ov9QhlE3/jkzyu953hq0uwQ==", - "dev": true, - "optional": true, - "dependencies": { - "event-iterator": "^1.0.0" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-duration": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.4.4.tgz", - "integrity": "sha512-KbAJuYGUhZkB9gotDiKLnZ7Z3VTacK3fgwmDdB6ZVDtJbMBT6MfLga0WJaYpPDu0mzqT0NgHtHDt5PY4l0nidg==", - "dev": true, - "optional": true - }, - "node_modules/parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "optional": true, - "dependencies": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-glob/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-glob/node_modules/is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "optional": true, - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-headers": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz", - "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==", - "dev": true - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz", - "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=", - "dev": true, - "dependencies": { - "camel-case": "^3.0.0", - "upper-case-first": "^1.1.0" - } - }, - "node_modules/path-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz", - "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-network-drive": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/path-is-network-drive/-/path-is-network-drive-1.0.13.tgz", - "integrity": "sha512-Hg74mRN6mmXV+gTm3INjFK40ncAmC/Lo4qoQaSZ+GT3hZzlKdWQSqAjqyPeW0SvObP2W073WyYEBWY9d3wOm3A==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-strip-sep": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/path-strip-sep/-/path-strip-sep-1.0.10.tgz", - "integrity": "sha512-JpCy+8LAJQQTO1bQsb/84s1g+/Stm3h39aOpPRBQ/paMUGVPPZChLTOTKHoaCkc/6sKuF7yVsnq5Pe1S6xQGcA==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "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" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/peer-id": { - "version": "0.14.8", - "resolved": "https://registry.npmjs.org/peer-id/-/peer-id-0.14.8.tgz", - "integrity": "sha512-GpuLpob/9FrEFvyZrKKsISEkaBYsON2u0WtiawLHj1ii6ewkoeRiSDFLyIefYhw0jGvQoeoZS05jaT52X7Bvig==", - "dev": true, - "optional": true, - "dependencies": { - "cids": "^1.1.5", - "class-is": "^1.1.0", - "libp2p-crypto": "^0.19.0", - "minimist": "^1.2.5", - "multihashes": "^4.0.2", - "protobufjs": "^6.10.2", - "uint8arrays": "^2.0.5" - }, - "bin": { - "peer-id": "src/bin.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/peer-id/node_modules/cids": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/cids/-/cids-1.1.9.tgz", - "integrity": "sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "multicodec": "^3.0.1", - "multihashes": "^4.0.1", - "uint8arrays": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0", - "npm": ">=3.0.0" - } - }, - "node_modules/peer-id/node_modules/cids/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/peer-id/node_modules/multibase": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz", - "integrity": "sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/peer-id/node_modules/multicodec": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.2.1.tgz", - "integrity": "sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw==", - "dev": true, - "optional": true, - "dependencies": { - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - } - }, - "node_modules/peer-id/node_modules/multicodec/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/peer-id/node_modules/multihashes": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.3.tgz", - "integrity": "sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^4.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.2" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/peer-id/node_modules/multihashes/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/peer-id/node_modules/multihashes/node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true, - "optional": true - }, - "node_modules/peer-id/node_modules/uint8arrays": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.10.tgz", - "integrity": "sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/peer-id/node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, - "optional": true - }, - "node_modules/pem-jwk": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pem-jwk/-/pem-jwk-2.0.0.tgz", - "integrity": "sha512-rFxu7rVoHgQ5H9YsP50dDWf0rHjreVA2z0yPiWr5WdH/UHb29hKtF7h6l8vNd1cbYR1t0QL+JKhW55a2ZV4KtA==", - "dev": true, - "optional": true, - "dependencies": { - "asn1.js": "^5.0.1" - }, - "bin": { - "pem-jwk": "bin/pem-jwk.js" - }, - "engines": { - "node": ">=5.10.0" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz", - "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "load-json-file": "^1.1.0", - "object-assign": "^4.0.1", - "symbol": "^0.2.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "optional": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "optional": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "optional": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "optional": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pouchdb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/pouchdb/-/pouchdb-7.1.1.tgz", - "integrity": "sha512-8bXWclixNJZqokvxGHRsG19zehSJiaZaz4dVYlhXhhUctz7gMcNTElHjPBzBdZlKKvt9aFDndmXN1VVE53Co8g==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "buffer-from": "1.1.0", - "clone-buffer": "1.0.0", - "double-ended-queue": "2.1.0-0", - "fetch-cookie": "0.7.0", - "immediate": "3.0.6", - "inherits": "2.0.3", - "level": "5.0.1", - "level-codec": "9.0.1", - "level-write-stream": "1.0.0", - "leveldown": "5.0.2", - "levelup": "4.0.2", - "ltgt": "2.2.1", - "node-fetch": "2.4.1", - "readable-stream": "1.0.33", - "spark-md5": "3.0.0", - "through2": "3.0.1", - "uuid": "3.2.1", - "vuvuzela": "1.0.3" - } - }, - "node_modules/pouchdb-abstract-mapreduce": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.2.2.tgz", - "integrity": "sha512-7HWN/2yV2JkwMnGnlp84lGvFtnm0Q55NiBUdbBcaT810+clCGKvhssBCrXnmwShD1SXTwT83aszsgiSfW+SnBA==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.2.2", - "pouchdb-collate": "7.2.2", - "pouchdb-collections": "7.2.2", - "pouchdb-errors": "7.2.2", - "pouchdb-fetch": "7.2.2", - "pouchdb-mapreduce-utils": "7.2.2", - "pouchdb-md5": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-adapter-leveldb-core": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-leveldb-core/-/pouchdb-adapter-leveldb-core-7.2.2.tgz", - "integrity": "sha512-K9UGf1Ivwe87mjrMqN+1D07tO/DfU7ariVDrGffuOjvl+3BcvUF25IWrxsBObd4iPOYCH7NVQWRpojhBgxULtQ==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "buffer-from": "1.1.1", - "double-ended-queue": "2.1.0-0", - "levelup": "4.4.0", - "pouchdb-adapter-utils": "7.2.2", - "pouchdb-binary-utils": "7.2.2", - "pouchdb-collections": "7.2.2", - "pouchdb-errors": "7.2.2", - "pouchdb-json": "7.2.2", - "pouchdb-md5": "7.2.2", - "pouchdb-merge": "7.2.2", - "pouchdb-utils": "7.2.2", - "sublevel-pouchdb": "7.2.2", - "through2": "3.0.2" - } - }, - "node_modules/pouchdb-adapter-leveldb-core/node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-leveldb-core/node_modules/levelup": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", - "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", - "dev": true, - "optional": true, - "dependencies": { - "deferred-leveldown": "~5.3.0", - "level-errors": "~2.0.0", - "level-iterator-stream": "~4.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pouchdb-adapter-leveldb-core/node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/pouchdb-adapter-memory": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-memory/-/pouchdb-adapter-memory-7.2.2.tgz", - "integrity": "sha512-9o+zdItPEq7rIrxdkUxgsLNaZkDJAGEqqoYgeYdrHidOCZnlhxhX3g7/R/HcpDKC513iEPqJWDJQSfeT6nVKkw==", - "dev": true, - "optional": true, - "dependencies": { - "memdown": "1.4.1", - "pouchdb-adapter-leveldb-core": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-adapter-node-websql": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-node-websql/-/pouchdb-adapter-node-websql-7.0.0.tgz", - "integrity": "sha512-fNaOMO8bvMrRTSfmH4RSLSpgnKahRcCA7Z0jg732PwRbGvvMdGbreZwvKPPD1fg2tm2ZwwiXWK2G3+oXyoqZYw==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-adapter-websql-core": "7.0.0", - "pouchdb-utils": "7.0.0", - "websql": "1.0.0" - } - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/pouchdb-binary-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-7.0.0.tgz", - "integrity": "sha512-yUktdOPIPvOVouCjJN3uop+bCcpdPwePrLm9eUAZNgEYnUFu0njdx7Q0WRsZ7UJ6l75HinL5ZHk4bnvEt86FLw==", - "dev": true, - "optional": true, - "dependencies": { - "buffer-from": "1.1.0" - } - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/pouchdb-collections": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-7.0.0.tgz", - "integrity": "sha512-DaoUr/vU24Q3gM6ghj0va9j/oBanPwkbhkvnqSyC3Dm5dgf5pculNxueLF9PKMo3ycApoWzHMh6N2N8KJbDU2Q==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/pouchdb-errors": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-7.0.0.tgz", - "integrity": "sha512-dTusY8nnTw4HIztCrNl7AoGgwvS1bVf/3/97hDaGc4ytn72V9/4dK8kTqlimi3UpaurohYRnqac0SGXYP8vgXA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/pouchdb-md5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-7.0.0.tgz", - "integrity": "sha512-yaSJKhLA3QlgloKUQeb2hLdT3KmUmPfoYdryfwHZuPTpXIRKTnMQTR9qCIRUszc0ruBpDe53DRslCgNUhAyTNQ==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.0.0", - "spark-md5": "3.0.0" - } - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/pouchdb-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-7.0.0.tgz", - "integrity": "sha512-1bnoX1KdZYHv9wicDIFdO0PLiVIMzNDUBUZ/yOJZ+6LW6niQCB8aCv09ZztmKfSQcU5nnN3fe656tScBgP6dOQ==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "clone-buffer": "1.0.0", - "immediate": "3.0.6", - "inherits": "2.0.3", - "pouchdb-collections": "7.0.0", - "pouchdb-errors": "7.0.0", - "pouchdb-md5": "7.0.0", - "uuid": "3.2.1" - } - }, - "node_modules/pouchdb-adapter-node-websql/node_modules/uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/pouchdb-adapter-utils": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-utils/-/pouchdb-adapter-utils-7.2.2.tgz", - "integrity": "sha512-2CzZkTyTyHZkr3ePiWFMTiD5+56lnembMjaTl8ohwegM0+hYhRyJux0biAZafVxgIL4gnCUC4w2xf6WVztzKdg==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.2.2", - "pouchdb-collections": "7.2.2", - "pouchdb-errors": "7.2.2", - "pouchdb-md5": "7.2.2", - "pouchdb-merge": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-adapter-websql-core": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-websql-core/-/pouchdb-adapter-websql-core-7.0.0.tgz", - "integrity": "sha512-NyMaH0bl20SdJdOCzd+fwXo8JZ15a48/MAwMcIbXzsRHE4DjFNlRcWAcjUP6uN4Ezc+Gx+r2tkBBMf71mIz1Aw==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-adapter-utils": "7.0.0", - "pouchdb-binary-utils": "7.0.0", - "pouchdb-collections": "7.0.0", - "pouchdb-errors": "7.0.0", - "pouchdb-json": "7.0.0", - "pouchdb-merge": "7.0.0", - "pouchdb-utils": "7.0.0" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-adapter-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-adapter-utils/-/pouchdb-adapter-utils-7.0.0.tgz", - "integrity": "sha512-UWKPC6jkz6mHUzZefrU7P5X8ZGvBC8LSNZ7BIp0hWvJE6c20cnpDwedTVDpZORcCbVJpDmFOHBYnOqEIblPtbA==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.0.0", - "pouchdb-collections": "7.0.0", - "pouchdb-errors": "7.0.0", - "pouchdb-md5": "7.0.0", - "pouchdb-merge": "7.0.0", - "pouchdb-utils": "7.0.0" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-binary-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-7.0.0.tgz", - "integrity": "sha512-yUktdOPIPvOVouCjJN3uop+bCcpdPwePrLm9eUAZNgEYnUFu0njdx7Q0WRsZ7UJ6l75HinL5ZHk4bnvEt86FLw==", - "dev": true, - "optional": true, - "dependencies": { - "buffer-from": "1.1.0" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-collections": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-7.0.0.tgz", - "integrity": "sha512-DaoUr/vU24Q3gM6ghj0va9j/oBanPwkbhkvnqSyC3Dm5dgf5pculNxueLF9PKMo3ycApoWzHMh6N2N8KJbDU2Q==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-errors": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-7.0.0.tgz", - "integrity": "sha512-dTusY8nnTw4HIztCrNl7AoGgwvS1bVf/3/97hDaGc4ytn72V9/4dK8kTqlimi3UpaurohYRnqac0SGXYP8vgXA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-json/-/pouchdb-json-7.0.0.tgz", - "integrity": "sha512-w0bNRu/7VmmCrFWMYAm62n30wvJJUT2SokyzeTyj3hRohj4GFwTRg1mSZ+iAmxgRKOFE8nzZstLG/WAB4Ymjew==", - "dev": true, - "optional": true, - "dependencies": { - "vuvuzela": "1.0.3" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-md5": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-7.0.0.tgz", - "integrity": "sha512-yaSJKhLA3QlgloKUQeb2hLdT3KmUmPfoYdryfwHZuPTpXIRKTnMQTR9qCIRUszc0ruBpDe53DRslCgNUhAyTNQ==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.0.0", - "spark-md5": "3.0.0" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-merge": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-7.0.0.tgz", - "integrity": "sha512-tci5u6NpznQhGcPv4ho1h0miky9rs+ds/T9zQ9meQeDZbUojXNaX1Jxsb0uYEQQ+HMqdcQs3Akdl0/u0mgwPGg==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/pouchdb-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-7.0.0.tgz", - "integrity": "sha512-1bnoX1KdZYHv9wicDIFdO0PLiVIMzNDUBUZ/yOJZ+6LW6niQCB8aCv09ZztmKfSQcU5nnN3fe656tScBgP6dOQ==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "clone-buffer": "1.0.0", - "immediate": "3.0.6", - "inherits": "2.0.3", - "pouchdb-collections": "7.0.0", - "pouchdb-errors": "7.0.0", - "pouchdb-md5": "7.0.0", - "uuid": "3.2.1" - } - }, - "node_modules/pouchdb-adapter-websql-core/node_modules/uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/pouchdb-binary-utils": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-7.2.2.tgz", - "integrity": "sha512-shacxlmyHbUrNfE6FGYpfyAJx7Q0m91lDdEAaPoKZM3SzAmbtB1i+OaDNtYFztXjJl16yeudkDb3xOeokVL3Qw==", - "dev": true, - "optional": true, - "dependencies": { - "buffer-from": "1.1.1" - } - }, - "node_modules/pouchdb-binary-utils/node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-collate": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-collate/-/pouchdb-collate-7.2.2.tgz", - "integrity": "sha512-/SMY9GGasslknivWlCVwXMRMnQ8myKHs4WryQ5535nq1Wj/ehpqWloMwxEQGvZE1Sda3LOm7/5HwLTcB8Our+w==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-collections": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-7.2.2.tgz", - "integrity": "sha512-6O9zyAYlp3UdtfneiMYuOCWdUCQNo2bgdjvNsMSacQX+3g8WvIoFQCYJjZZCpTttQGb+MHeRMr8m2U95lhJTew==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-debug": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/pouchdb-debug/-/pouchdb-debug-7.2.1.tgz", - "integrity": "sha512-eP3ht/AKavLF2RjTzBM6S9gaI2/apcW6xvaKRQhEdOfiANqerFuksFqHCal3aikVQuDO+cB/cw+a4RyJn/glBw==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "3.1.0" - } - }, - "node_modules/pouchdb-debug/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/pouchdb-debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-errors": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-7.2.2.tgz", - "integrity": "sha512-6GQsiWc+7uPfgEHeavG+7wuzH3JZW29Dnrvz8eVbDFE50kVFxNDVm3EkYHskvo5isG7/IkOx7PV7RPTA3keG3g==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "2.0.4" - } - }, - "node_modules/pouchdb-fetch": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-fetch/-/pouchdb-fetch-7.2.2.tgz", - "integrity": "sha512-lUHmaG6U3zjdMkh8Vob9GvEiRGwJfXKE02aZfjiVQgew+9SLkuOxNw3y2q4d1B6mBd273y1k2Lm0IAziRNxQnA==", - "dev": true, - "optional": true, - "dependencies": { - "abort-controller": "3.0.0", - "fetch-cookie": "0.10.1", - "node-fetch": "2.6.0" - } - }, - "node_modules/pouchdb-fetch/node_modules/fetch-cookie": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.10.1.tgz", - "integrity": "sha512-beB+VEd4cNeVG1PY+ee74+PkuCQnik78pgLi5Ah/7qdUfov8IctU0vLUbBT8/10Ma5GMBeI4wtxhGrEfKNYs2g==", - "dev": true, - "optional": true, - "dependencies": { - "tough-cookie": "^2.3.3 || ^3.0.1 || ^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pouchdb-fetch/node_modules/node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true, - "optional": true, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/pouchdb-find": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-find/-/pouchdb-find-7.2.2.tgz", - "integrity": "sha512-BmFeFVQ0kHmDehvJxNZl9OmIztCjPlZlVSdpijuFbk/Fi1EFPU1BAv3kLC+6DhZuOqU/BCoaUBY9sn66pPY2ag==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-abstract-mapreduce": "7.2.2", - "pouchdb-collate": "7.2.2", - "pouchdb-errors": "7.2.2", - "pouchdb-fetch": "7.2.2", - "pouchdb-md5": "7.2.2", - "pouchdb-selector-core": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-json": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-json/-/pouchdb-json-7.2.2.tgz", - "integrity": "sha512-3b2S2ynN+aoB7aCNyDZc/4c0IAdx/ir3nsHB+/RrKE9cM3QkQYbnnE3r/RvOD1Xvr6ji/KOCBie+Pz/6sxoaug==", - "dev": true, - "optional": true, - "dependencies": { - "vuvuzela": "1.0.3" - } - }, - "node_modules/pouchdb-mapreduce-utils": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-7.2.2.tgz", - "integrity": "sha512-rAllb73hIkU8rU2LJNbzlcj91KuulpwQu804/F6xF3fhZKC/4JQMClahk+N/+VATkpmLxp1zWmvmgdlwVU4HtQ==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "inherits": "2.0.4", - "pouchdb-collections": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-md5": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-7.2.2.tgz", - "integrity": "sha512-c/RvLp2oSh8PLAWU5vFBnp6ejJABIdKqboZwRRUrWcfGDf+oyX8RgmJFlYlzMMOh4XQLUT1IoaDV8cwlsuryZw==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-binary-utils": "7.2.2", - "spark-md5": "3.0.1" - } - }, - "node_modules/pouchdb-md5/node_modules/spark-md5": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.1.tgz", - "integrity": "sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-merge": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz", - "integrity": "sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb-selector-core": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-selector-core/-/pouchdb-selector-core-7.2.2.tgz", - "integrity": "sha512-XYKCNv9oiNmSXV5+CgR9pkEkTFqxQGWplnVhO3W9P154H08lU0ZoNH02+uf+NjZ2kjse7Q1fxV4r401LEcGMMg==", - "dev": true, - "optional": true, - "dependencies": { - "pouchdb-collate": "7.2.2", - "pouchdb-utils": "7.2.2" - } - }, - "node_modules/pouchdb-utils": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-7.2.2.tgz", - "integrity": "sha512-XmeM5ioB4KCfyB2MGZXu1Bb2xkElNwF1qG+zVFbQsKQij0zvepdOUfGuWvLRHxTOmt4muIuSOmWZObZa3NOgzQ==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "0.0.1", - "clone-buffer": "1.0.0", - "immediate": "3.3.0", - "inherits": "2.0.4", - "pouchdb-collections": "7.2.2", - "pouchdb-errors": "7.2.2", - "pouchdb-md5": "7.2.2", - "uuid": "8.1.0" - } - }, - "node_modules/pouchdb-utils/node_modules/uuid": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz", - "integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==", - "dev": true, - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/pouchdb/node_modules/buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/node-fetch": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.4.1.tgz", - "integrity": "sha512-P9UbpFK87NyqBZzUuDBDz4f6Yiys8xm8j7ACDbi6usvFm6KItklQUKjeoqTrYS/S1k6I8oaOC2YLLDr/gg26Mw==", - "dev": true, - "optional": true, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/pouchdb/node_modules/readable-stream": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", - "integrity": "sha1-OjYN1mwbHX/UcFOJhg7aHQ9hEmw=", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/pouchdb/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - }, - "node_modules/pouchdb/node_modules/through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "2 || 3" - } - }, - "node_modules/pouchdb/node_modules/through2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pouchdb/node_modules/through2/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/pouchdb/node_modules/uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true, - "optional": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", - "dev": true, - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true, - "optional": true - }, - "node_modules/promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", - "dev": true, - "dependencies": { - "asap": "~2.0.6" - } - }, - "node_modules/promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "dependencies": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", - "dev": true, - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/protocol-buffers-schema": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", - "dev": true, - "optional": true - }, - "node_modules/protons": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/protons/-/protons-2.0.3.tgz", - "integrity": "sha512-j6JikP/H7gNybNinZhAHMN07Vjr1i4lVupg598l4I9gSTjJqOvKnwjzYX2PzvBTSVf2eZ2nWv4vG+mtW8L6tpA==", - "dev": true, - "optional": true, - "dependencies": { - "protocol-buffers-schema": "^3.3.1", - "signed-varint": "^2.0.1", - "uint8arrays": "^3.0.0", - "varint": "^5.0.0" - } - }, - "node_modules/protons/node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", - "dev": true, - "optional": true, - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true, - "optional": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-5.0.0.tgz", - "integrity": "sha512-lD2/y78q+7HqBx2SaT6OT4UcwtvXNRfEpzYEzl0EQ+9gZq2Qi3fa0HDnYPeqQwhlHJFBUhT7AO3mLU3+8bynHA==", - "dev": true - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "node_modules/randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "optional": true, - "dependencies": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/randomatic/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-pkg/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/receptacle": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/receptacle/-/receptacle-1.3.2.tgz", - "integrity": "sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dev": true, - "dependencies": { - "minimatch": "3.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/redeyed": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", - "dev": true, - "dependencies": { - "esprima": "~4.0.0" - } - }, - "node_modules/reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/redux": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", - "dev": true, - "dependencies": { - "lodash": "^4.2.1", - "lodash-es": "^4.2.1", - "loose-envify": "^1.1.0", - "symbol-observable": "^1.0.3" - } - }, - "node_modules/redux-saga": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redux-saga/-/redux-saga-1.0.0.tgz", - "integrity": "sha512-GvJWs/SzMvEQgeaw6sRMXnS2FghlvEGsHiEtTLpJqc/FHF3I5EE/B+Hq5lyHZ8LSoT2r/X/46uWvkdCnK9WgHA==", - "dev": true, - "dependencies": { - "@redux-saga/core": "^1.0.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "optional": true, - "dependencies": { - "is-equal-shallow": "^0.1.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "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.3", - "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.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", - "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.19" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "node_modules/reselect": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", - "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==", - "dev": true - }, - "node_modules/reselect-tree": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/reselect-tree/-/reselect-tree-1.3.5.tgz", - "integrity": "sha512-h/iXrz7wGBidwMmNFu5L1z0sDvqU6SAdJ2TKr5IIsyGKeyXQchi0gXbfbIJJfGWD8VGcDYjzGAbhy1KaGD4FWQ==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "esdoc": "^1.0.4", - "json-pointer": "^0.6.1", - "reselect": "^4.0.0", - "source-map-support": "^0.5.3" - } - }, - "node_modules/reselect-tree/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/reset": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/reset/-/reset-0.1.0.tgz", - "integrity": "sha1-n8cxQXGZWubLC35YsGznUir0uvs=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true, - "optional": true - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "optional": true, - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/retimer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", - "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==", - "dev": true, - "optional": true - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.1" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/rollup": { - "version": "2.67.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.67.2.tgz", - "integrity": "sha512-hoEiBWwZtf1QdK3jZIq59L0FJj4Fiv4RplCO4pvCRC86qsoFurWB4hKQIjoRf3WvJmk5UZ9b0y5ton+62fC7Tw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" - } - }, - "node_modules/rollup-plugin-inject/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", - "dev": true, - "dependencies": { - "rollup-plugin-inject": "^3.0.0" - } - }, - "node_modules/rollup-plugin-peer-deps-external": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz", - "integrity": "sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==", - "dev": true - }, - "node_modules/rollup-plugin-typescript2": { - "version": "0.31.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz", - "integrity": "sha512-hRwEYR1C8xDGVVMFJQdEVnNAeWRvpaY97g5mp3IeLnzhNXzSVq78Ye/BJ9PAaUfN4DXa/uDnqerifMOaMFY54Q==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.1.2", - "@yarn-tool/resolve-package": "^1.0.40", - "find-cache-dir": "^3.3.2", - "fs-extra": "^10.0.0", - "resolve": "^1.20.0", - "tslib": "^2.3.1" - }, - "peerDependencies": { - "rollup": ">=1.26.3", - "typescript": ">=2.4.0" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/@rollup/pluginutils": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.2.tgz", - "integrity": "sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/rollup-plugin-typescript2/node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/rpc-websockets": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-5.3.1.tgz", - "integrity": "sha512-rIxEl1BbXRlIA9ON7EmY/2GUM7RLMy8zrUPTiLPFiYnYOz0I3PXfCmDDrge5vt4pW4oIcAXBDvgZuJ1jlY5+VA==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/runtime": "^7.8.7", - "assert-args": "^1.2.1", - "babel-runtime": "^6.26.0", - "circular-json": "^0.5.9", - "eventemitter3": "^3.1.2", - "uuid": "^3.4.0", - "ws": "^5.2.2" - } - }, - "node_modules/rpc-websockets/node_modules/eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true, - "optional": true - }, - "node_modules/rpc-websockets/node_modules/ws": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", - "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", - "dev": true, - "optional": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/run": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/run/-/run-1.4.0.tgz", - "integrity": "sha1-4X2ekEOrL+F3dsspnhI3848LT/o=", - "dev": true, - "optional": true, - "dependencies": { - "minimatch": "*" - }, - "bin": { - "runjs": "cli.js" - }, - "engines": { - "node": ">=v0.9.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true, - "optional": true - }, - "node_modules/sc-istanbul": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", - "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", - "dev": true, - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/sc-istanbul/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sc-istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/sc-istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sc-istanbul/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "node_modules/sc-istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/scrypt-async": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/scrypt-async/-/scrypt-async-2.0.1.tgz", - "integrity": "sha512-wHR032jldwZNy7Tzrfu7RccOgGf8r5hyDMSP2uV6DpLiBUsR8JsDcx/in73o2UGVVrH5ivRFdNsFPcjtl3LErQ==", - "dev": true, - "optional": true - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true - }, - "node_modules/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dev": true, - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "dev": true, - "optional": true - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "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.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/sentence-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz", - "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case-first": "^1.1.2" - } - }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "dev": true, - "dependencies": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz", - "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==", - "dev": true - }, - "node_modules/signed-varint": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/signed-varint/-/signed-varint-2.0.1.tgz", - "integrity": "sha1-UKmYnafJjCxh2tEZvJdHDvhSgSk=", - "dev": true, - "optional": true, - "dependencies": { - "varint": "~5.0.0" - } - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true - }, - "node_modules/simple-get": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", - "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", - "dev": true, - "dependencies": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz", - "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/solidity-coverage": { - "version": "0.7.20", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.20.tgz", - "integrity": "sha512-edOXTugUYdqxrtEnIn4vgrGjLPxdexcL0WD8LzAvVA3d1dwgcfRO3k8xQR02ZQnOnWMBi8Cqs0F+kAQQp3JW8g==", - "dev": true, - "license": "ISC", - "dependencies": { - "@solidity-parser/parser": "^0.14.0", - "@truffle/provider": "^0.2.24", - "chalk": "^2.4.2", - "death": "^1.1.0", - "detect-port": "^1.3.0", - "fs-extra": "^8.1.0", - "ghost-testrpc": "^0.0.2", - "global-modules": "^2.0.0", - "globby": "^10.0.1", - "jsonschema": "^1.2.4", - "lodash": "^4.17.15", - "node-emoji": "^1.10.0", - "pify": "^4.0.1", - "recursive-readdir": "^2.2.2", - "sc-istanbul": "^0.4.5", - "semver": "^7.3.4", - "shelljs": "^0.8.3", - "web3-utils": "^1.3.0" - }, - "bin": { - "solidity-coverage": "plugins/bin.js" - } - }, - "node_modules/solidity-coverage/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "optional": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true, - "optional": true - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/spark-md5": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.0.tgz", - "integrity": "sha1-NyIifFTi+vJLHcbZM8wUTm9xv+8=", - "dev": true, - "optional": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "node_modules/spinnies": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/spinnies/-/spinnies-0.5.1.tgz", - "integrity": "sha512-WpjSXv9NQz0nU3yCT9TFEOfpFrXADY9C5fG6eAJqixLhvTX1jP3w92Y8IE5oafIe42nlF9otjhllnXN/QCaB3A==", - "dev": true, - "optional": true, - "dependencies": { - "chalk": "^2.4.2", - "cli-cursor": "^3.0.0", - "strip-ansi": "^5.2.0" - } - }, - "node_modules/spinnies/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "optional": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spinnies/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/spinnies/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "optional": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/spinnies/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "optional": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sqlite3": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", - "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", - "dev": true, - "optional": true, - "dependencies": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true, - "optional": true - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4", - "npm": ">=6" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true, - "optional": true - }, - "node_modules/stream-to-it": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/stream-to-it/-/stream-to-it-0.2.4.tgz", - "integrity": "sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==", - "dev": true, - "optional": true, - "dependencies": { - "get-iterator": "^1.0.2" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/string-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "optional": true, - "dependencies": { - "first-chunk-stream": "^1.0.0", - "strip-bom": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "dev": true, - "dependencies": { - "is-hex-prefixed": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sublevel-pouchdb": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/sublevel-pouchdb/-/sublevel-pouchdb-7.2.2.tgz", - "integrity": "sha512-y5uYgwKDgXVyPZceTDGWsSFAhpSddY29l9PJbXqMJLfREdPmQTY8InpatohlEfCXX7s1LGcrfYAhxPFZaJOLnQ==", - "dev": true, - "optional": true, - "dependencies": { - "inherits": "2.0.4", - "level-codec": "9.0.2", - "ltgt": "2.2.1", - "readable-stream": "1.1.14" - } - }, - "node_modules/sublevel-pouchdb/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true - }, - "node_modules/sublevel-pouchdb/node_modules/level-codec": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", - "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", - "dev": true, - "optional": true, - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sublevel-pouchdb/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/sublevel-pouchdb/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true - }, - "node_modules/subscriptions-transport-ws": { - "version": "0.9.19", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz", - "integrity": "sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==", - "dev": true, - "optional": true, - "dependencies": { - "backo2": "^1.0.2", - "eventemitter3": "^3.1.0", - "iterall": "^1.2.1", - "symbol-observable": "^1.0.4", - "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/subscriptions-transport-ws/node_modules/eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true, - "optional": true - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-hyperlinks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", - "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", - "dev": true, - "dependencies": { - "has-flag": "^2.0.0", - "supports-color": "^5.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/swap-case": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz", - "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=", - "dev": true, - "dependencies": { - "lower-case": "^1.1.1", - "upper-case": "^1.1.1" - } - }, - "node_modules/swarm-js": { - "version": "0.1.40", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", - "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "eth-lib": "^0.1.26", - "fs-extra": "^4.0.2", - "got": "^7.1.0", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar": "^4.0.2", - "xhr-request": "^1.0.1" - } - }, - "node_modules/swarm-js/node_modules/fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/swarm-js/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, - "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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/swarm-js/node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/swarm-js/node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/swarm-js/node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/symbol": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz", - "integrity": "sha1-O5hzuKkB5Hxu/iFSajrDcu8ou8c=", - "dev": true - }, - "node_modules/symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, - "optional": true - }, - "node_modules/table-layout": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", - "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", - "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/taffydb": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", - "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=", - "dev": true - }, - "node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dev": true, - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/tar/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "optional": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/through2/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true, - "optional": true, - "dependencies": { - "os-homedir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/timeout-abort-controller": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", - "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==", - "dev": true, - "optional": true, - "dependencies": { - "abort-controller": "^3.0.0", - "retimer": "^2.0.0" - } - }, - "node_modules/tiny-queue": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz", - "integrity": "sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=", - "dev": true, - "optional": true - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "dev": true, - "optional": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/title-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz", - "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.0.3" - } - }, - "node_modules/to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "optional": true, - "dependencies": { - "extend-shallow": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-data-view": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz", - "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", - "dev": true, - "optional": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-json-schema": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/to-json-schema/-/to-json-schema-0.2.5.tgz", - "integrity": "sha512-jP1ievOee8pec3tV9ncxLSS48Bnw7DIybgy112rhMCEhf3K4uyVNZZHr03iQQBzbV5v5Hos+dlZRRyk6YSMNDw==", - "dev": true, - "optional": true, - "dependencies": { - "lodash.isequal": "^4.5.0", - "lodash.keys": "^4.2.0", - "lodash.merge": "^4.6.2", - "lodash.omit": "^4.5.0", - "lodash.without": "^4.4.0", - "lodash.xor": "^4.5.0" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true, - "optional": true - }, - "node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/truffle": { - "version": "5.4.32", - "resolved": "https://registry.npmjs.org/truffle/-/truffle-5.4.32.tgz", - "integrity": "sha512-HZLoLZqXZkid3aUL06WSPxSxf60mlT0g8RXBKEGjiZBjqIEIx5DmpwdiLADYIlh2+NPqklEMQDFIVWQZHXVFdA==", - "dev": true, - "dependencies": { - "@truffle/db-loader": "^0.1.0", - "@truffle/debugger": "^9.2.14", - "app-module-path": "^2.2.0", - "ganache": "7.0.1", - "mocha": "8.1.2", - "original-require": "^1.0.1" - }, - "bin": { - "truffle": "build/cli.bundled.js" - }, - "optionalDependencies": { - "@truffle/db": "^0.5.50", - "@truffle/preserve-fs": "^0.2.6", - "@truffle/preserve-to-buckets": "^0.2.6", - "@truffle/preserve-to-filecoin": "^0.2.7", - "@truffle/preserve-to-ipfs": "^0.2.7" - } - }, - "node_modules/truffle-assertions": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/truffle-assertions/-/truffle-assertions-0.9.2.tgz", - "integrity": "sha512-9g2RhaxU2F8DeWhqoGQvL/bV8QVoSnQ6PY+ZPvYRP5eF7+/8LExb4mjLx/FeliLTjc3Tv1SABG05Gu5qQ/ErmA==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "lodash.isequal": "^4.5.0" - } - }, - "node_modules/truffle/node_modules/ganache": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ganache/-/ganache-7.0.1.tgz", - "integrity": "sha512-P3mw+O23fD7BuWTdhr0WweOrTJCBRBFX22nMpmQDZgb1vmcYEv7PzNiKIfsI6PGOLh7PO8GuoRiMYBF+SlFikg==", - "dev": true, - "dependencies": { - "@trufflesuite/bigint-buffer": "1.1.9", - "emittery": "0.10.0", - "keccak": "3.0.1", - "leveldown": "6.1.0", - "secp256k1": "4.0.2" - }, - "bin": { - "ganache": "dist/node/cli.js", - "ganache-cli": "dist/node/cli.js" - }, - "optionalDependencies": { - "bufferutil": "4.0.5", - "utf-8-validate": "5.0.7" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/@trufflesuite/bigint-buffer": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@trufflesuite/bigint-buffer/-/bigint-buffer-1.1.9.tgz", - "integrity": "sha512-bdM5cEGCOhDSwminryHJbRmXc1x7dPKg6Pqns3qyTwFlxsqUgxE29lsERS3PlIW1HTjoIGMUqsk1zQQwST1Yxw==", - "dev": true, - "dependencies": { - "node-gyp-build": "4.3.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/bufferutil": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", - "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", - "dev": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/catering": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.0.tgz", - "integrity": "sha512-M5imwzQn6y+ODBfgi+cfgZv2hIUI6oYU/0f35Mdb1ujGeqeoI5tOnl9Q13DTH7LW+7er+NYq8stNOKZD/Z3U/A==", - "dev": true, - "dependencies": { - "queue-tick": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/emittery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.0.tgz", - "integrity": "sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, - "dependencies": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/leveldown": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.0.tgz", - "integrity": "sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w==", - "dev": true, - "dependencies": { - "abstract-leveldown": "^7.2.0", - "napi-macros": "~2.0.0", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/leveldown/node_modules/abstract-leveldown": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", - "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/leveldown/node_modules/level-concat-iterator": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", - "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", - "dev": true, - "dependencies": { - "catering": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/leveldown/node_modules/level-supports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", - "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/napi-macros": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", - "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/node-gyp-build": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", - "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/queue-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.0.tgz", - "integrity": "sha512-ULWhjjE8BmiICGn3G8+1L9wFpERNxkf8ysxkAer4+TFdRefDaXOCV5m92aMB9FtBVmn/8sETXLXY6BfW7hyaWQ==", - "dev": true - }, - "node_modules/truffle/node_modules/ganache/node_modules/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dev": true, - "dependencies": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/truffle/node_modules/ganache/node_modules/utf-8-validate": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", - "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", - "dev": true, - "optional": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, - "node_modules/ts-command-line-args": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.2.1.tgz", - "integrity": "sha512-mnK68QA86FYzQYTSA/rxIjT/8EpKsvQw9QkawPic8I8t0gjAOw3Oa509NIRoaY1FmH7hdrncMp7t7o+vYoceNQ==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "command-line-args": "^5.1.1", - "command-line-usage": "^6.1.0", - "string-format": "^2.0.0" - }, - "bin": { - "write-markdown": "dist/write-markdown.js" - } - }, - "node_modules/ts-command-line-args/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-command-line-args/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ts-command-line-args/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-command-line-args/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-essentials": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz", - "integrity": "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==", - "dev": true - }, - "node_modules/ts-invariant": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", - "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "^1.9.3" - } - }, - "node_modules/ts-invariant/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - }, - "node_modules/ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ts-toolbelt": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true, - "peer": true - }, - "node_modules/ts-type": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-2.1.4.tgz", - "integrity": "sha512-wnajiiIMhn/RHJ1oPld95siKmMJrOgaT6+rMmC8vO1LORgDFEzKP2nBmEFM5b4XVe7Q0J5KcU9oRJFzju7UzrA==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1", - "typedarray-dts": "^1.0.0" - }, - "peerDependencies": { - "@types/bluebird": "*", - "@types/node": "*", - "ts-toolbelt": "^9.6.0" - } - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true, - "optional": true, - "engines": { - "node": "*" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typechain": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-7.0.0.tgz", - "integrity": "sha512-ILfvBBFJ7j9aIk0crX03+N2GmzoDN1gtk32G1+XrasjuvXS0XAw2XxwQeQMMgKwlnxViJjIkG87sTMYXPkXA9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prettier": "^2.1.1", - "debug": "^4.1.1", - "fs-extra": "^7.0.0", - "glob": "^7.1.6", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.4", - "prettier": "^2.1.2", - "ts-command-line-args": "^2.2.0", - "ts-essentials": "^7.0.1" - }, - "bin": { - "typechain": "dist/cli/cli.js" - }, - "peerDependencies": { - "typescript": ">=4.1.0" - } - }, - "node_modules/typechain/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/typechain/node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true - }, - "node_modules/typechain/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typechain/node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true, - "optional": true - }, - "node_modules/typedarray-dts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typedarray-dts/-/typedarray-dts-1.0.0.tgz", - "integrity": "sha512-Ka0DBegjuV9IPYFT1h0Qqk5U4pccebNIJCGl8C5uU7xtOs+jpJvKGAY4fHGK25hTmXZOEUl9Cnsg5cS6K/b5DA==", - "dev": true - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==", - "dev": true, - "optional": true - }, - "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typescript-compare": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz", - "integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==", - "dev": true, - "dependencies": { - "typescript-logic": "^0.0.0" - } - }, - "node_modules/typescript-logic": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz", - "integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==", - "dev": true - }, - "node_modules/typescript-tuple": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz", - "integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==", - "dev": true, - "dependencies": { - "typescript-compare": "^0.0.2" - } - }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/uglify-js": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", - "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uint8arrays": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz", - "integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==", - "dev": true, - "optional": true, - "dependencies": { - "multibase": "^3.0.0", - "web-encoding": "^1.0.2" - } - }, - "node_modules/uint8arrays/node_modules/multibase": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz", - "integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==", - "dev": true, - "optional": true, - "dependencies": { - "@multiformats/base-x": "^4.0.1", - "web-encoding": "^1.0.6" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "node_modules/unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "optional": true, - "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "node_modules/unique-stream/node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "optional": true, - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/upath2": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/upath2/-/upath2-3.1.12.tgz", - "integrity": "sha512-yC3eZeCyCXFWjy7Nu4pgjLhXNYjuzuUmJiRgSSw6TJp8Emc+E4951HGPJf+bldFC5SL7oBLeNbtm1fGzXn2gxw==", - "dev": true, - "dependencies": { - "path-is-network-drive": "^1.0.13", - "path-strip-sep": "^1.0.10", - "tslib": "^2.3.1" - }, - "peerDependencies": { - "@types/node": "*" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "node_modules/upper-case-first": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz", - "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=", - "dev": true, - "dependencies": { - "upper-case": "^1.1.1" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true, - "optional": true - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=", - "dev": true - }, - "node_modules/url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ursa-optional": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/ursa-optional/-/ursa-optional-0.10.2.tgz", - "integrity": "sha512-TKdwuLboBn7M34RcvVTuQyhvrA8gYKapuVdm0nBP0mnBc7oECOfUQZrY91cefL3/nm64ZyrejSRrhTVdX7NG/A==", - "dev": true, - "optional": true, - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.14.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/utf-8-validate": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", - "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", - "dev": true, - "dependencies": { - "node-gyp-build": "^4.2.0" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/util.promisify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", - "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", - "dev": true, - "optional": true, - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "for-each": "^0.3.3", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.1" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-promise": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", - "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "optional": true, - "dependencies": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "node_modules/vinyl-fs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.3.tgz", - "integrity": "sha1-PZflYuv91LZpId6nBia4S96dLQc=", - "dev": true, - "optional": true, - "dependencies": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", - "gulp-sourcemaps": "^1.5.2", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/vinyl-fs/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/vinyl-fs/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "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" - } - }, - "node_modules/vinyl-fs/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/vuvuzela": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/vuvuzela/-/vuvuzela-1.0.3.tgz", - "integrity": "sha1-O+FF5YJxxzylUnndhR8SpoIRSws=", - "dev": true, - "optional": true - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "optional": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-encoding": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", - "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", - "dev": true, - "optional": true, - "dependencies": { - "@zxing/text-encoding": "0.9.0", - "util": "^0.12.3" - } - }, - "node_modules/web3": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.5.2.tgz", - "integrity": "sha512-aapKLdO8t7Cos6tZLeeQUtCJvTiPMlLcHsHHDLSBZ/VaJEucSTxzun32M8sp3BmF4waDEmhY+iyUM1BKvtAcVQ==", - "dev": true, - "dependencies": { - "web3-bzz": "1.5.2", - "web3-core": "1.5.2", - "web3-eth": "1.5.2", - "web3-eth-personal": "1.5.2", - "web3-net": "1.5.2", - "web3-shh": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.5.2.tgz", - "integrity": "sha512-W/sPCdA+XQ9duUYKHAwf/g69cbbV8gTCRsa1MpZwU7spXECiyJ2EvD/QzAZ+UpJk3GELXFF/fUByeZ3VRQKF2g==", - "dev": true, - "dependencies": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-bzz/node_modules/@types/node": { - "version": "12.20.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.25.tgz", - "integrity": "sha512-hcTWqk7DR/HrN9Xe7AlJwuCaL13Vcd9/g/T54YrJz4Q3ESM5mr33YCzW2bOfzSIc3aZMeGBvbLGvgN6mIJ0I5Q==", - "dev": true - }, - "node_modules/web3-core": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.5.2.tgz", - "integrity": "sha512-sebMpQbg3kbh3vHUbHrlKGKOxDWqjgt8KatmTBsTAWj/HwWYVDzeX+2Q84+swNYsm2DrTBVFlqTErFUwPBvyaA==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.5.2", - "web3-core-method": "1.5.2", - "web3-core-requestmanager": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-helpers": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.5.2.tgz", - "integrity": "sha512-U7LJoeUdQ3aY9t5gU7t/1XpcApsWm+4AcW5qKl/44ZxD44w0Dmsq1c5zJm3GuLr/a9MwQfXK4lpmvxVQWHHQRg==", - "dev": true, - "dependencies": { - "web3-eth-iban": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-method": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.5.2.tgz", - "integrity": "sha512-/mC5t9UjjJoQmJJqO5nWK41YHo+tMzFaT7Tp7jDCQsBkinE68KsUJkt0jzygpheW84Zra0DVp6q19gf96+cugg==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.4.0", - "@ethersproject/transactions": "^5.0.0-beta.135", - "web3-core-helpers": "1.5.2", - "web3-core-promievent": "1.5.2", - "web3-core-subscriptions": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-promievent": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.5.2.tgz", - "integrity": "sha512-5DacbJXe98ozSor7JlkTNCy6G8945VunRRkPxMk98rUrg60ECVEM/vuefk1atACzjQsKx6tmLZuHxbJQ64TQeQ==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-requestmanager": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.5.2.tgz", - "integrity": "sha512-oRVW9OrAsXN2JIZt68OEg1Mb1A9a/L3JAGMv15zLEFEnJEGw0KQsGK1ET2kvZBzvpFd5G0EVkYCnx7WDe4HSNw==", - "dev": true, - "dependencies": { - "util": "^0.12.0", - "web3-core-helpers": "1.5.2", - "web3-providers-http": "1.5.2", - "web3-providers-ipc": "1.5.2", - "web3-providers-ws": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core-subscriptions": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.5.2.tgz", - "integrity": "sha512-hapI4rKFk22yurtIv0BYvkraHsM7epA4iI8Np+HuH6P9DD0zj/llaps6TXLM9HyacLBRwmOLZmr+pHBsPopUnQ==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-core/node_modules/@types/node": { - "version": "12.20.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.25.tgz", - "integrity": "sha512-hcTWqk7DR/HrN9Xe7AlJwuCaL13Vcd9/g/T54YrJz4Q3ESM5mr33YCzW2bOfzSIc3aZMeGBvbLGvgN6mIJ0I5Q==", - "dev": true - }, - "node_modules/web3-eth": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.5.2.tgz", - "integrity": "sha512-DwWQ6TCOUqvYyo7T20S7HpQDPveNHNqOn2Q2F3E8ZFyEjmqT4XsGiwvm08kB/VgQ4e/ANyq/i8PPFSYMT8JKHg==", - "dev": true, - "dependencies": { - "web3-core": "1.5.2", - "web3-core-helpers": "1.5.2", - "web3-core-method": "1.5.2", - "web3-core-subscriptions": "1.5.2", - "web3-eth-abi": "1.5.2", - "web3-eth-accounts": "1.5.2", - "web3-eth-contract": "1.5.2", - "web3-eth-ens": "1.5.2", - "web3-eth-iban": "1.5.2", - "web3-eth-personal": "1.5.2", - "web3-net": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.5.2.tgz", - "integrity": "sha512-P3bJbDR5wib4kWGfVeBKBVi27T+AiHy4EJxYM6SMNbpm3DboLDdisu9YBd6INMs8rzxgnprBbGmmyn4jKIDKAA==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "5.0.7", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-abi/node_modules/@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "dev": true, - "dependencies": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "node_modules/web3-eth-accounts": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.5.2.tgz", - "integrity": "sha512-F8mtzxgEhxfLc66vPi0Gqd6mpscvvk7Ua575bsJ1p9J2X/VtuKgDgpWcU4e4LKeROQ+ouCpAG9//0j9jQuij3A==", - "dev": true, - "dependencies": { - "@ethereumjs/common": "^2.3.0", - "@ethereumjs/tx": "^3.2.1", - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-util": "^7.0.10", - "scrypt-js": "^3.0.1", - "uuid": "3.3.2", - "web3-core": "1.5.2", - "web3-core-helpers": "1.5.2", - "web3-core-method": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-accounts/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/web3-eth-accounts/node_modules/uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/web3-eth-contract": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.5.2.tgz", - "integrity": "sha512-4B8X/IPFxZCTmtENpdWXtyw5fskf2muyc3Jm5brBQRb4H3lVh1/ZyQy7vOIkdphyaXu4m8hBLHzeyKkd37mOUg==", - "dev": true, - "dependencies": { - "@types/bn.js": "^4.11.5", - "web3-core": "1.5.2", - "web3-core-helpers": "1.5.2", - "web3-core-method": "1.5.2", - "web3-core-promievent": "1.5.2", - "web3-core-subscriptions": "1.5.2", - "web3-eth-abi": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-ens": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.5.2.tgz", - "integrity": "sha512-/UrLL42ZOCYge+BpFBdzG8ICugaRS4f6X7PxJKO+zAt+TwNgBpjuWfW/ZYNcuqJun/ZyfcTuj03TXqA1RlNhZQ==", - "dev": true, - "dependencies": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "web3-core": "1.5.2", - "web3-core-helpers": "1.5.2", - "web3-core-promievent": "1.5.2", - "web3-eth-abi": "1.5.2", - "web3-eth-contract": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-iban": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.5.2.tgz", - "integrity": "sha512-C04YDXuSG/aDwOHSX+HySBGb0KraiAVt+/l1Mw7y/fCUrKC/K0yYzMYqY/uYOcvLtepBPsC4ZfUYWUBZ2PO8Vg==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-personal": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.5.2.tgz", - "integrity": "sha512-nH5N2GiVC0C5XeMEKU16PeFP3Hb3hkPvlR6Tf9WQ+pE+jw1c8eaXBO1CJQLr15ikhUF3s94ICyHcfjzkDsmRbA==", - "dev": true, - "dependencies": { - "@types/node": "^12.12.6", - "web3-core": "1.5.2", - "web3-core-helpers": "1.5.2", - "web3-core-method": "1.5.2", - "web3-net": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-eth-personal/node_modules/@types/node": { - "version": "12.20.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.25.tgz", - "integrity": "sha512-hcTWqk7DR/HrN9Xe7AlJwuCaL13Vcd9/g/T54YrJz4Q3ESM5mr33YCzW2bOfzSIc3aZMeGBvbLGvgN6mIJ0I5Q==", - "dev": true - }, - "node_modules/web3-net": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.5.2.tgz", - "integrity": "sha512-VEc9c+jfoERhbJIxnx0VPlQDot8Lm4JW/tOWFU+ekHgIiu2zFKj5YxhURIth7RAbsaRsqCb79aE+M0eI8maxVQ==", - "dev": true, - "dependencies": { - "web3-core": "1.5.2", - "web3-core-method": "1.5.2", - "web3-utils": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-http": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.2.tgz", - "integrity": "sha512-dUNFJc9IMYDLZnkoQX3H4ZjvHjGO6VRVCqrBrdh84wPX/0da9dOA7DwIWnG0Gv3n9ybWwu5JHQxK4MNQ444lyA==", - "dev": true, - "dependencies": { - "web3-core-helpers": "1.5.2", - "xhr2-cookies": "1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ipc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.5.2.tgz", - "integrity": "sha512-SJC4Sivt4g9LHKlRy7cs1jkJgp7bjrQeUndE6BKs0zNALKguxu6QYnzbmuHCTFW85GfMDjhvi24jyyZHMnBNXQ==", - "dev": true, - "dependencies": { - "oboe": "2.1.5", - "web3-core-helpers": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-providers-ws": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.5.2.tgz", - "integrity": "sha512-xy9RGlyO8MbJDuKv2vAMDkg+en+OvXG0CGTCM2BTl6l1vIdHpCa+6A/9KV2rK8aU9OBZ7/Pf+Y19517kHVl9RA==", - "dev": true, - "dependencies": { - "eventemitter3": "4.0.4", - "web3-core-helpers": "1.5.2", - "websocket": "^1.0.32" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-shh": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.5.2.tgz", - "integrity": "sha512-wOxOcYt4Sa0AHAI8gG7RulCwVuVjSRS/M/AbFsea3XfJdN6sU13/syY7OdZNjNYuKjYTzxKYrd3dU/K2iqffVw==", - "dev": true, - "dependencies": { - "web3-core": "1.5.2", - "web3-core-method": "1.5.2", - "web3-core-subscriptions": "1.5.2", - "web3-net": "1.5.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.2.tgz", - "integrity": "sha512-quTtTeQJHYSxAwIBOCGEcQtqdVcFWX6mCFNoqnp+mRbq+Hxbs8CGgO/6oqfBx4OvxIOfCpgJWYVHswRXnbEu9Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/web3-utils/node_modules/eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true, - "optional": true - }, - "node_modules/websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "dev": true, - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/websocket/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/websql": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/websql/-/websql-1.0.0.tgz", - "integrity": "sha512-7iZ+u28Ljw5hCnMiq0BCOeSYf0vCFQe/ORY0HgscTiKjQed8WqugpBUggJ2NTnB9fahn1kEnPRX2jf8Px5PhJw==", - "dev": true, - "optional": true, - "dependencies": { - "argsarray": "^0.0.1", - "immediate": "^3.2.2", - "noop-fn": "^1.0.0", - "sqlite3": "^4.0.0", - "tiny-queue": "^0.2.1" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dev": true, - "optional": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/whatwg-url-compat": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", - "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", - "dev": true, - "optional": true, - "dependencies": { - "tr46": "~0.0.1" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", - "dev": true, - "optional": true, - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true, - "bin": { - "window-size": "cli.js" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/wordwrapjs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", - "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", - "dev": true, - "dependencies": { - "reduce-flatten": "^2.0.0", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/write-stream": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/write-stream/-/write-stream-0.4.3.tgz", - "integrity": "sha1-g8yMA0fQr2BXqThitOOuAd5cgcE=", - "dev": true, - "optional": true, - "dependencies": { - "readable-stream": "~0.0.2" - } - }, - "node_modules/write-stream/node_modules/readable-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-0.0.4.tgz", - "integrity": "sha1-8y124/uGM0SlSNeZIwBxc2ZbO40=", - "dev": true, - "optional": true - }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "dev": true, - "dependencies": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "dev": true, - "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" - } - }, - "node_modules/xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "dev": true, - "dependencies": { - "xhr-request": "^1.1.0" - } - }, - "node_modules/xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "dev": true, - "dependencies": { - "cookiejar": "^2.1.1" - } - }, - "node_modules/xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", - "dev": true, - "optional": true - }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xss": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.10.tgz", - "integrity": "sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==", - "dev": true, - "optional": true, - "dependencies": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "bin": { - "xss": "bin/xss" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/xss/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "optional": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true, - "engines": { - "node": ">=0.10.32" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.6.0.tgz", - "integrity": "sha1-y0BQwBWb+2u2ScD0r1UFJqhGGdw=", - "dev": true, - "dependencies": { - "camelcase": "^2.0.1", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "lodash.assign": "^4.0.3", - "os-locale": "^1.4.0", - "pkg-conf": "^1.1.2", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1", - "string-width": "^1.0.1", - "window-size": "^0.2.0", - "y18n": "^3.2.1", - "yargs-parser": "^2.4.0" - } - }, - "node_modules/yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "dev": true, - "dependencies": { - "camelcase": "^3.0.0", - "lodash.assign": "^4.0.6" - } - }, - "node_modules/yargs-parser/node_modules/camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/yargs-unparser/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "node_modules/yargs-unparser/node_modules/yargs-parser": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", - "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", - "dev": true, - "optional": true - }, - "node_modules/zen-observable-ts": { - "version": "0.8.21", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", - "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", - "dev": true, - "optional": true, - "dependencies": { - "tslib": "^1.9.3", - "zen-observable": "^0.8.0" - } - }, - "node_modules/zen-observable-ts/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "optional": true - } - }, "dependencies": { "101": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/101/-/101-1.6.3.tgz", "integrity": "sha512-4dmQ45yY0Dx24Qxp+zAsNLlMF6tteCyfVzgbulvSyC7tCyd3V8sW76sS0tHq8NpcbXfWTKasfyfzU1Kd86oKzw==", "dev": true, - "optional": true, "requires": { "clone": "^1.0.2", "deep-eql": "^0.1.3", @@ -24776,8 +3207,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -24786,18 +3216,10 @@ "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", "dev": true, - "optional": true, "requires": { "@types/node": "*" } }, - "@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true, - "peer": true - }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -24812,7 +3234,6 @@ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, - "optional": true, "requires": { "@types/connect": "*", "@types/node": "*" @@ -24823,7 +3244,6 @@ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, - "optional": true, "requires": { "@types/node": "*" } @@ -24832,15 +3252,13 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==", - "dev": true, - "optional": true + "dev": true }, "@types/cookies": { "version": "0.7.7", "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", "dev": true, - "optional": true, "requires": { "@types/connect": "*", "@types/express": "*", @@ -24885,7 +3303,6 @@ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "dev": true, - "optional": true, "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -24898,7 +3315,6 @@ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "dev": true, - "optional": true, "requires": { "@types/node": "*", "@types/qs": "*", @@ -24936,15 +3352,13 @@ "version": "1.5.3", "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", - "dev": true, - "optional": true + "dev": true }, "@types/http-errors": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", - "dev": true, - "optional": true + "dev": true }, "@types/json-schema": { "version": "7.0.9", @@ -24957,15 +3371,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", - "dev": true, - "optional": true + "dev": true }, "@types/koa": { "version": "2.13.4", "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", "dev": true, - "optional": true, "requires": { "@types/accepts": "*", "@types/content-disposition": "*", @@ -24982,7 +3394,6 @@ "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", "dev": true, - "optional": true, "requires": { "@types/koa": "*" } @@ -24998,8 +3409,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", - "dev": true, - "optional": true + "dev": true }, "@types/minimatch": { "version": "3.0.5", @@ -25032,15 +3442,13 @@ "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true, - "optional": true + "dev": true }, "@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true, - "optional": true + "dev": true }, "@types/resolve": { "version": "1.17.1", @@ -25071,7 +3479,6 @@ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", "dev": true, - "optional": true, "requires": { "@types/mime": "^1", "@types/node": "*" @@ -25178,8 +3585,8 @@ }, "@zondax/filecoin-signing-tools": { "version": "git+ssh://git@github.com/Digital-MOB-Filecoin/filecoin-signing-tools-js.git#8f8e92157cac2556d35cab866779e9a8ea8a4e25", - "dev": true, "from": "@zondax/filecoin-signing-tools@github:Digital-MOB-Filecoin/filecoin-signing-tools-js", + "dev": true, "optional": true, "requires": { "axios": "^0.20.0", @@ -26786,7 +5193,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true + "dev": true, + "optional": true }, "caniuse-lite": { "version": "1.0.30001312", @@ -26987,6 +5395,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", @@ -26997,13 +5406,15 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -27014,8 +5425,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true, - "optional": true + "dev": true }, "clone-buffer": { "version": "1.0.0", @@ -27636,7 +6046,6 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, - "optional": true, "requires": { "type-detect": "0.1.1" } @@ -28187,6 +6596,7 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "optional": true, "requires": { "is-arrayish": "^0.2.1" } @@ -29198,7 +7608,7 @@ "@ledgerhq/hw-transport-webusb": "^5.22.0", "@nodefactory/filsnap-adapter": "^0.2.1", "@nodefactory/filsnap-types": "^0.2.1", - "@zondax/filecoin-signing-tools": "github:Digital-MOB-Filecoin/filecoin-signing-tools-js", + "@zondax/filecoin-signing-tools": "@zondax/filecoin-signing-tools@github:Digital-MOB-Filecoin/filecoin-signing-tools-js", "bignumber.js": "^9.0.0", "bitcore-lib": "^8.22.2", "bitcore-mnemonic": "^8.22.2", @@ -30116,14 +8526,6 @@ "source-map": "^0.6.0" } }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, "string-width": { "version": "3.1.0", "bundled": true, @@ -30134,6 +8536,14 @@ "strip-ansi": "^5.1.0" } }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "5.2.0", "bundled": true, @@ -30905,7 +9315,8 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "optional": true }, "htmlparser2": { "version": "3.10.1", @@ -31158,7 +9569,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "dev": true, + "optional": true }, "ip-regex": { "version": "4.3.0", @@ -32108,7 +10520,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "dev": true, + "optional": true }, "is-bigint": { "version": "1.0.4", @@ -32450,7 +10863,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "dev": true, + "optional": true }, "is-valid-glob": { "version": "0.3.0", @@ -32950,7 +11364,6 @@ "resolved": "https://registry.npmjs.org/keypather/-/keypather-1.10.2.tgz", "integrity": "sha1-4ESWMtSz5RbyHMAUznxWRP3c5hQ=", "dev": true, - "optional": true, "requires": { "101": "^1.0.0" } @@ -33027,6 +11440,7 @@ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, + "optional": true, "requires": { "invert-kv": "^1.0.0" } @@ -33311,6 +11725,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -33323,7 +11738,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -33358,7 +11774,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", - "dev": true + "dev": true, + "optional": true }, "lodash.assignin": { "version": "4.2.0", @@ -34833,6 +13250,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "optional": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -34844,7 +13262,8 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "dev": true, + "optional": true } } }, @@ -35189,6 +13608,7 @@ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, + "optional": true, "requires": { "lcid": "^1.0.0" } @@ -35356,6 +13776,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, + "optional": true, "requires": { "error-ex": "^1.2.0" } @@ -35630,13 +14051,15 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "dev": true, + "optional": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, + "optional": true, "requires": { "pinkie": "^2.0.0" } @@ -35646,6 +14069,7 @@ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz", "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=", "dev": true, + "optional": true, "requires": { "find-up": "^1.0.0", "load-json-file": "^1.1.0", @@ -35658,6 +14082,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, + "optional": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -35668,6 +14093,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "optional": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -36688,6 +15114,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, + "optional": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -36699,6 +15126,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -36709,7 +15137,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -36718,6 +15147,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, + "optional": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -36728,6 +15158,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, + "optional": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -36738,6 +15169,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "optional": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -36947,7 +15379,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "dev": true, + "optional": true }, "reselect": { "version": "4.1.5", @@ -37692,6 +16125,7 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, + "optional": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -37701,13 +16135,15 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "dev": true, + "optional": true }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "optional": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -37717,7 +16153,8 @@ "version": "3.0.11", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true + "dev": true, + "optional": true }, "spinnies": { "version": "0.5.1", @@ -37861,23 +16298,6 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "dev": true }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, "string-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", @@ -37932,6 +16352,23 @@ "define-properties": "^1.1.3" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -37946,6 +16383,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, + "optional": true, "requires": { "is-utf8": "^0.2.0" } @@ -38186,7 +16624,8 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz", "integrity": "sha1-O5hzuKkB5Hxu/iFSajrDcu8ou8c=", - "dev": true + "dev": true, + "optional": true }, "symbol-observable": { "version": "1.2.0", @@ -38833,13 +17272,6 @@ "yn": "3.1.1" } }, - "ts-toolbelt": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", - "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", - "dev": true, - "peer": true - }, "ts-type": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/ts-type/-/ts-type-2.1.4.tgz", @@ -38896,8 +17328,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true, - "optional": true + "dev": true }, "type-is": { "version": "1.6.18", @@ -38954,8 +17385,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -39269,6 +17699,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "optional": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -39890,7 +18321,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true + "dev": true, + "optional": true }, "word-wrap": { "version": "1.2.3", @@ -39933,6 +18365,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -39942,13 +18375,15 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -40074,7 +18509,8 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true + "dev": true, + "optional": true }, "yaeti": { "version": "0.0.6", @@ -40093,6 +18529,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.6.0.tgz", "integrity": "sha1-y0BQwBWb+2u2ScD0r1UFJqhGGdw=", "dev": true, + "optional": true, "requires": { "camelcase": "^2.0.1", "cliui": "^3.2.0", @@ -40113,6 +18550,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", "dev": true, + "optional": true, "requires": { "camelcase": "^3.0.0", "lodash.assign": "^4.0.6" @@ -40122,7 +18560,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true + "dev": true, + "optional": true } } }, diff --git a/test/contractBridge/admin.js b/test/contractBridge/admin.js index 3e2e321b..0df9e4c7 100644 --- a/test/contractBridge/admin.js +++ b/test/contractBridge/admin.js @@ -34,7 +34,7 @@ contract('Bridge - [admin]', async accounts => { }; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, 0, 100); + BridgeInstance = await BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, 100); ADMIN_ROLE = await BridgeInstance.DEFAULT_ADMIN_ROLE() }); @@ -168,25 +168,6 @@ contract('Bridge - [admin]', async accounts => { await assertOnlyAdmin(BridgeInstance.adminSetBurnable, someAddress, someAddress); }); - // Set fee - - it('Should set fee', async () => { - assert.equal(await BridgeInstance._fee.call(), 0); - - const fee = Ethers.utils.parseEther("0.05"); - await BridgeInstance.adminChangeFee(fee); - const newFee = await BridgeInstance._fee.call() - assert.equal(web3.utils.fromWei(newFee, "ether"), "0.05") - }); - - it('Should not set the same fee', async () => { - await TruffleAssert.reverts(BridgeInstance.adminChangeFee(0), "Current fee is equal to new fee"); - }); - - it('Should require admin role to set fee', async () => { - await assertOnlyAdmin(BridgeInstance.adminChangeFee, 0); - }); - // Withdraw it('Should withdraw funds', async () => { diff --git a/test/contractBridge/cancelDepositProposal.js b/test/contractBridge/cancelDepositProposal.js index cda87c41..cce13163 100644 --- a/test/contractBridge/cancelDepositProposal.js +++ b/test/contractBridge/cancelDepositProposal.js @@ -44,7 +44,6 @@ contract('Bridge - [voteProposal with relayerThreshold == 3]', async (accounts) relayer3Address, relayer4Address], relayerThreshold, - 0, 10,).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); diff --git a/test/contractBridge/constructor.js b/test/contractBridge/constructor.js index 762e72a2..4796507f 100644 --- a/test/contractBridge/constructor.js +++ b/test/contractBridge/constructor.js @@ -20,15 +20,10 @@ contract('Bridge - [constructor]', async accounts => { }; it('Bridge should not allow to set initialRelayerThreshold above 255', async () => { - return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, 256, 0, 100), "value does not fit in 8 bits"); - }); - - it('Bridge should not allow to set fee above 2**128 - 1', async () => { - return TruffleAssert.fails(BridgeContract.new( - domainID, initialRelayers, initialRelayerThreshold, BN(2).pow(BN(128)), 100), "value does not fit in 128 bits"); + return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, 256, 100), "value does not fit in 8 bits"); }); it('Bridge should not allow to set expiry above 2**40 - 1', async () => { - return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, 0, BN(2).pow(BN(40))), "value does not fit in 40 bits"); + return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, BN(2).pow(BN(40))), "value does not fit in 40 bits"); }); }); diff --git a/test/contractBridge/createDepositProposal.js b/test/contractBridge/createDepositProposal.js index 0022254f..5b0cf3b7 100644 --- a/test/contractBridge/createDepositProposal.js +++ b/test/contractBridge/createDepositProposal.js @@ -33,7 +33,7 @@ contract('Bridge - [create a deposit proposal (voteProposal) with relayerThresho beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance), - BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance) + BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 100).then(instance => BridgeInstance = instance) ]); resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, destinationDomainID); @@ -168,7 +168,7 @@ contract('Bridge - [create a deposit proposal (voteProposal) with relayerThresho beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance), - BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance) + BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 100).then(instance => BridgeInstance = instance) ]); resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, destinationDomainID); diff --git a/test/contractBridge/depositERC1155.js b/test/contractBridge/depositERC1155.js index bbb55875..d72a0a98 100644 --- a/test/contractBridge/depositERC1155.js +++ b/test/contractBridge/depositERC1155.js @@ -20,6 +20,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { const originChainInitialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let OriginERC1155MintableInstance; @@ -29,7 +30,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 0, 100) + BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 100) ]); @@ -61,6 +62,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } )); }); @@ -70,6 +72,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -82,6 +85,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -97,6 +101,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -110,6 +115,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -121,6 +127,6 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { }); it('deposit requires resourceID that is mapped to a handler', async () => { - await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, { from: depositerAddress }), "resourceID not mapped to handler"); + await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "resourceID not mapped to handler"); }); }); diff --git a/test/contractBridge/depositERC20.js b/test/contractBridge/depositERC20.js index ed8251d1..33ff5a03 100644 --- a/test/contractBridge/depositERC20.js +++ b/test/contractBridge/depositERC20.js @@ -20,6 +20,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { const originChainInitialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let OriginERC20MintableInstance; @@ -29,10 +30,9 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 0, 100) + BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 100), ]); - - + resourceID = Helpers.createResourceID(OriginERC20MintableInstance.address, originDomainID); OriginERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); @@ -64,6 +64,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } )); }); @@ -73,6 +74,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -85,6 +87,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -100,6 +103,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -113,6 +117,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { destinationDomainID, resourceID, depositData, + feeData, { from: depositerAddress } ); @@ -124,6 +129,6 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { }); it('deposit requires resourceID that is mapped to a handler', async () => { - await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, { from: depositerAddress }), "resourceID not mapped to handler"); + await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "resourceID not mapped to handler"); }); }); diff --git a/test/contractBridge/depositERC721.js b/test/contractBridge/depositERC721.js index e7d26ef2..cfc062d7 100644 --- a/test/contractBridge/depositERC721.js +++ b/test/contractBridge/depositERC721.js @@ -19,6 +19,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { const originChainTokenID = 42; const expectedDepositNonce = 1; const genericBytes = '0x736f796c656e745f677265656e5f69735f70656f706c65'; + const feeData = '0x'; let BridgeInstance; let OriginERC721MintableInstance; @@ -30,7 +31,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), - BridgeContract.new(originDomainID, [], 0, 0, 100).then(instance => BridgeInstance = instance) + BridgeContract.new(originDomainID, [], 0, 100).then(instance => BridgeInstance = instance) ]); originResourceID = Helpers.createResourceID(OriginERC721MintableInstance.address, originDomainID); @@ -73,6 +74,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { destinationDomainID, originResourceID, depositData, + feeData, { from: depositerAddress } ) }); @@ -82,6 +84,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { destinationDomainID, originResourceID, depositData, + feeData, { from: depositerAddress } ); @@ -94,6 +97,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { destinationDomainID, originResourceID, depositData, + feeData, { from: depositerAddress } ); @@ -112,6 +116,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { destinationDomainID, originResourceID, depositData, + feeData, { from: depositerAddress } ); diff --git a/test/contractBridge/depositGeneric.js b/test/contractBridge/depositGeneric.js index 3f537e9b..38f91ca8 100644 --- a/test/contractBridge/depositGeneric.js +++ b/test/contractBridge/depositGeneric.js @@ -15,6 +15,7 @@ contract('Bridge - [deposit - Generic]', async () => { const originDomainID = 1; const destinationDomainID = 2; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let GenericHandlerInstance; @@ -28,7 +29,7 @@ contract('Bridge - [deposit - Generic]', async () => { beforeEach(async () => { await Promise.all([ CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), - BridgeInstance = BridgeContract.new(originDomainID, [], 0, 0, 100).then(instance => BridgeInstance = instance) + BridgeInstance = BridgeContract.new(originDomainID, [], 0, 100).then(instance => BridgeInstance = instance) ]); resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID) @@ -50,7 +51,8 @@ contract('Bridge - [deposit - Generic]', async () => { await TruffleAssert.passes(BridgeInstance.deposit( destinationDomainID, resourceID, - depositData + depositData, + feeData )); }); @@ -58,7 +60,8 @@ contract('Bridge - [deposit - Generic]', async () => { await BridgeInstance.deposit( destinationDomainID, resourceID, - depositData + depositData, + feeData ); const depositCount = await BridgeInstance._depositCounts.call(destinationDomainID); @@ -69,7 +72,8 @@ contract('Bridge - [deposit - Generic]', async () => { const depositTx = await BridgeInstance.deposit( destinationDomainID, resourceID, - depositData + depositData, + feeData ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index 40de7435..19eeb24c 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -38,7 +38,7 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/contractBridge/fee.js b/test/contractBridge/fee.js deleted file mode 100644 index 9c5b779c..00000000 --- a/test/contractBridge/fee.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); -const GenericHandlerContract = artifacts.require("GenericHandler"); - -contract('Bridge - [fee]', async (accounts) => { - const originDomainID = 1; - const destinationDomainID = 2; - const blankFunctionSig = '0x00000000'; - const blankFunctionDepositerOffset = 0; - const relayer = accounts[0]; - - let BridgeInstance; - let GenericHandlerInstance; - let resourceID; - let depositData; - let initialResourceIDs; - let initialContractAddresses; - let initialDepositFunctionSignatures; - let initialDepositFunctionDepositerOffsets; - let initialExecuteFunctionSignatures; - - beforeEach(async () => { - await Promise.all([ - CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), - BridgeInstance = BridgeContract.new(originDomainID, [relayer], 0, 0, 100).then(instance => BridgeInstance = instance) - ]); - - resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID) - initialResourceIDs = [resourceID]; - initialContractAddresses = [CentrifugeAssetInstance.address]; - initialDepositFunctionSignatures = [blankFunctionSig]; - initialDepositFunctionDepositerOffsets = [blankFunctionDepositerOffset]; - initialExecuteFunctionSignatures = [blankFunctionSig]; - - GenericHandlerInstance = await GenericHandlerContract.new( - BridgeInstance.address); - - await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialDepositFunctionDepositerOffsets[0], initialExecuteFunctionSignatures[0]); - - depositData = Helpers.createGenericDepositData('0xdeadbeef'); - }); - - it('[sanity] Generic deposit can be made', async () => { - await TruffleAssert.passes(BridgeInstance.deposit( - destinationDomainID, - resourceID, - depositData - )); - }); - - it('deposit reverts if invalid amount supplied', async () => { - // current fee is set to 0 - assert.equal(await BridgeInstance._fee.call(), 0) - - await TruffleAssert.reverts( - BridgeInstance.deposit( - destinationDomainID, - resourceID, - depositData, - { - value: Ethers.utils.parseEther("1.0") - } - ) - ) - }); - - it('deposit passes if valid amount supplied', async () => { - // current fee is set to 0 - assert.equal(await BridgeInstance._fee.call(), 0) - // Change fee to 0.5 ether - await BridgeInstance.adminChangeFee(Ethers.utils.parseEther("0.5"), { from: relayer }) - assert.equal(web3.utils.fromWei((await BridgeInstance._fee.call()), "ether"), "0.5"); - - await TruffleAssert.passes( - BridgeInstance.deposit( - destinationDomainID, - resourceID, - depositData, - { - value: Ethers.utils.parseEther("0.5") - } - ) - ) - }); - - it('distribute fees', async () => { - await BridgeInstance.adminChangeFee(Ethers.utils.parseEther("1"), { from: relayer }); - assert.equal(web3.utils.fromWei((await BridgeInstance._fee.call()), "ether"), "1"); - - // check the balance is 0 - assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "0"); - await BridgeInstance.deposit(destinationDomainID, resourceID, depositData, {value: Ethers.utils.parseEther("1")}) - assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "1"); - - let b1Before = await web3.eth.getBalance(accounts[1]); - let b2Before = await web3.eth.getBalance(accounts[2]); - - let payout = Ethers.utils.parseEther("0.5") - // Transfer the funds - TruffleAssert.passes( - await BridgeInstance.transferFunds( - [accounts[1], accounts[2]], - [payout, payout] - ) - ) - b1 = await web3.eth.getBalance(accounts[1]); - b2 = await web3.eth.getBalance(accounts[2]); - assert.equal(b1, Ethers.BigNumber.from(b1Before).add(payout)); - assert.equal(b2, Ethers.BigNumber.from(b2Before).add(payout)); - }) -}); \ No newline at end of file diff --git a/test/contractBridge/voteDepositProposal.js b/test/contractBridge/voteDepositProposal.js index b0b6d258..99f28a48 100644 --- a/test/contractBridge/voteDepositProposal.js +++ b/test/contractBridge/voteDepositProposal.js @@ -58,7 +58,6 @@ contract('Bridge - [voteProposal with relayerThreshold == 3]', async (accounts) relayer3Address, relayer4Address], relayerThreshold, - 0, 100,).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); diff --git a/test/contractBridge/voteDepositProposalWithRealForwarder.js b/test/contractBridge/voteDepositProposalWithRealForwarder.js index b33862cf..28a4a47e 100644 --- a/test/contractBridge/voteDepositProposalWithRealForwarder.js +++ b/test/contractBridge/voteDepositProposalWithRealForwarder.js @@ -89,7 +89,6 @@ contract('Bridge - [voteProposal through forwarder]', async (accounts) => { relayer3Address, relayer4Address], relayerThreshold, - 0, 100,).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); diff --git a/test/contractBridge/voteDepositProposalWithTestForwarder.js b/test/contractBridge/voteDepositProposalWithTestForwarder.js index f90b514c..44f6a1dc 100644 --- a/test/contractBridge/voteDepositProposalWithTestForwarder.js +++ b/test/contractBridge/voteDepositProposalWithTestForwarder.js @@ -59,7 +59,6 @@ contract('Bridge - [voteProposal through forwarder]', async (accounts) => { relayer3Address, relayer4Address], relayerThreshold, - 0, 100,).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); diff --git a/test/e2e/erc1155/differentChainsMock.js b/test/e2e/erc1155/differentChainsMock.js index efe4db9f..5dac2290 100644 --- a/test/e2e/erc1155/differentChainsMock.js +++ b/test/e2e/erc1155/differentChainsMock.js @@ -24,6 +24,7 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let OriginBridgeInstance; let OriginERC1155MintableInstance; @@ -43,8 +44,8 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 0, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 0, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => DestinationERC1155MintableInstance = instance) ]); @@ -104,6 +105,7 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { destinationDomainID, originResourceID, originDepositData, + feeData, { from: depositerAddress } )); @@ -144,6 +146,7 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { originDomainID, destinationResourceID, destinationDepositData, + feeData, { from: recipientAddress } )); diff --git a/test/e2e/erc1155/sameChain.js b/test/e2e/erc1155/sameChain.js index 379760cd..71b03a34 100644 --- a/test/e2e/erc1155/sameChain.js +++ b/test/e2e/erc1155/sameChain.js @@ -20,6 +20,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let ERC1155MintableInstance; @@ -34,7 +35,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]); @@ -67,6 +68,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { domainID, resourceID, depositData, + feeData, { from: depositerAddress } )); diff --git a/test/e2e/erc20/differentChainsMock.js b/test/e2e/erc20/differentChainsMock.js index 9597a617..fcf4a7cd 100644 --- a/test/e2e/erc20/differentChainsMock.js +++ b/test/e2e/erc20/differentChainsMock.js @@ -23,6 +23,7 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let OriginBridgeInstance; let OriginERC20MintableInstance; @@ -48,8 +49,8 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 0, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 0, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); @@ -114,6 +115,7 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { destinationDomainID, originResourceID, originDepositData, + feeData, { from: depositerAddress } )); @@ -160,6 +162,7 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { originDomainID, destinationResourceID, destinationDepositData, + feeData, { from: recipientAddress } )); diff --git a/test/e2e/erc20/sameChain.js b/test/e2e/erc20/sameChain.js index 829de8b4..0d828996 100644 --- a/test/e2e/erc20/sameChain.js +++ b/test/e2e/erc20/sameChain.js @@ -19,6 +19,7 @@ contract('E2E ERC20 - Same Chain', async accounts => { const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance; @@ -34,7 +35,7 @@ contract('E2E ERC20 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); @@ -74,6 +75,7 @@ contract('E2E ERC20 - Same Chain', async accounts => { domainID, resourceID, depositData, + feeData, { from: depositerAddress } )); diff --git a/test/e2e/erc721/differentChainsMock.js b/test/e2e/erc721/differentChainsMock.js index 7de5d441..1a38ea04 100644 --- a/test/e2e/erc721/differentChainsMock.js +++ b/test/e2e/erc721/differentChainsMock.js @@ -22,6 +22,7 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { const recipientAddress = accounts[2]; const tokenID = 1; const expectedDepositNonce = 1; + const feeData = '0x'; let OriginBridgeInstance; let OriginERC721MintableInstance; @@ -42,8 +43,8 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 0, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 0, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => DestinationERC721MintableInstance = instance) ]); @@ -106,6 +107,7 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { destinationDomainID, originResourceID, originDepositData, + feeData, { from: depositerAddress } )); @@ -153,6 +155,7 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { originDomainID, destinationResourceID, destinationDepositData, + feeData, { from: recipientAddress } )); diff --git a/test/e2e/erc721/sameChain.js b/test/e2e/erc721/sameChain.js index c7509701..48402ede 100644 --- a/test/e2e/erc721/sameChain.js +++ b/test/e2e/erc721/sameChain.js @@ -19,6 +19,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { const tokenID = 1; const depositMetadata = "0xc0ff33"; const expectedDepositNonce = 1; + const feeData = '0x'; let BridgeInstance; let ERC721MintableInstance; @@ -34,7 +35,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]); @@ -73,6 +74,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { domainID, resourceID, depositData, + feeData, { from: depositerAddress } )); diff --git a/test/gasBenchmarks/deployments.js b/test/gasBenchmarks/deployments.js index 44db8d3d..de2492b5 100644 --- a/test/gasBenchmarks/deployments.js +++ b/test/gasBenchmarks/deployments.js @@ -22,7 +22,7 @@ contract('Gas Benchmark - [contract deployments]', async () => { let BridgeInstance; it('Should deploy all contracts and print benchmarks', async () => { - let contractInstances = [await BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance)]; + let contractInstances = [await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance)]; contractInstances = contractInstances.concat( await Promise.all([ ERC20HandlerContract.new(BridgeInstance.address), diff --git a/test/gasBenchmarks/deposits.js b/test/gasBenchmarks/deposits.js index 167c1fc8..188d3948 100644 --- a/test/gasBenchmarks/deposits.js +++ b/test/gasBenchmarks/deposits.js @@ -30,6 +30,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { const erc721TokenID = 1; const erc1155TokenID = 1; const erc1155TokenAmount = 100; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance; @@ -55,7 +56,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { before(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), @@ -139,6 +140,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { erc20TokenAmount, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress }); gasBenchmarks.push({ @@ -155,6 +157,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { erc721TokenID, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress }); gasBenchmarks.push({ @@ -170,6 +173,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { Helpers.createERC1155DepositData( [erc1155TokenID], [erc1155TokenAmount]), + feeData, { from: depositerAddress }); gasBenchmarks.push({ @@ -183,6 +187,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { domainID, centrifugeAssetResourceID, Helpers.createGenericDepositData('0xc0ff33'), + feeData, { from: depositerAddress } ); @@ -197,6 +202,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { domainID, noArgumentResourceID, Helpers.createGenericDepositData(null), + feeData, { from: depositerAddress } ); @@ -211,6 +217,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { domainID, oneArgumentResourceID, Helpers.createGenericDepositData(Helpers.toHex(42, 32)), + feeData, { from: depositerAddress } ); @@ -228,6 +235,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { domainID, twoArgumentsResourceID, Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); @@ -246,6 +254,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { domainID, threeArgumentsResourceID, Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); diff --git a/test/gasBenchmarks/executeProposal.js b/test/gasBenchmarks/executeProposal.js index 39e6179d..37d078bf 100644 --- a/test/gasBenchmarks/executeProposal.js +++ b/test/gasBenchmarks/executeProposal.js @@ -34,6 +34,7 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const erc721TokenID = 1; const erc1155TokenID = 1; const erc1155TokenAmount = 100; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance; @@ -56,13 +57,13 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { let twoArgumentsResourceID; let threeArgumentsResourceID; - const deposit = (resourceID, depositData) => BridgeInstance.deposit(domainID, resourceID, depositData, { from: depositerAddress }); + const deposit = (resourceID, depositData) => BridgeInstance.deposit(domainID, resourceID, depositData, feeData, { from: depositerAddress }); const vote = (resourceID, depositNonce, depositData) => BridgeInstance.voteProposal(domainID, depositNonce, resourceID, depositData, { from: relayerAddress }); const execute = (depositNonce, depositData, resourceID) => BridgeInstance.executeProposal(domainID, depositNonce, depositData, resourceID, true); before(async () => { await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), diff --git a/test/gasBenchmarks/voteProposal.js b/test/gasBenchmarks/voteProposal.js index 1de9d22c..12986084 100644 --- a/test/gasBenchmarks/voteProposal.js +++ b/test/gasBenchmarks/voteProposal.js @@ -34,7 +34,7 @@ contract('Gas Benchmark - [Vote Proposal]', async (accounts) => { before(async () => { await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ]); diff --git a/test/handlers/erc1155/burnList.js b/test/handlers/erc1155/burnList.js index da8fad1f..1574cbeb 100644 --- a/test/handlers/erc1155/burnList.js +++ b/test/handlers/erc1155/burnList.js @@ -25,7 +25,7 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]); diff --git a/test/handlers/erc1155/deposit.js b/test/handlers/erc1155/deposit.js index 8a4d85d3..42354bd1 100644 --- a/test/handlers/erc1155/deposit.js +++ b/test/handlers/erc1155/deposit.js @@ -18,6 +18,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { const depositerAddress = accounts[1]; const tokenID = 1; const tokenAmount = 100; + const feeData = '0x'; let BridgeInstance; let ERC1155MintableInstance; @@ -31,7 +32,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]) @@ -63,6 +64,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { domainID, resourceID, depositData, + feeData, {from: depositerAddress} ); diff --git a/test/handlers/erc1155/depositBurn.js b/test/handlers/erc1155/depositBurn.js index 37824d2d..c98589ca 100644 --- a/test/handlers/erc1155/depositBurn.js +++ b/test/handlers/erc1155/depositBurn.js @@ -20,6 +20,8 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { const tokenID = 1; const tokenAmount = 100; + const feeData = '0x'; + let BridgeInstance; let ERC1155MintableInstance1; let ERC1155MintableInstance2; @@ -33,7 +35,7 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]) @@ -71,6 +73,7 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { domainID, resourceID1, depositData, + feeData, { from: depositerAddress } ); diff --git a/test/handlers/erc20/burnList.js b/test/handlers/erc20/burnList.js index ef325672..9ca93def 100644 --- a/test/handlers/erc20/burnList.js +++ b/test/handlers/erc20/burnList.js @@ -26,7 +26,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]); diff --git a/test/handlers/erc20/constructor.js b/test/handlers/erc20/constructor.js index 0fbc206c..c1797697 100644 --- a/test/handlers/erc20/constructor.js +++ b/test/handlers/erc20/constructor.js @@ -24,7 +24,7 @@ contract('ERC20Handler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance3 = instance) diff --git a/test/handlers/erc20/deposit.js b/test/handlers/erc20/deposit.js index 33b83b51..079a3f3c 100644 --- a/test/handlers/erc20/deposit.js +++ b/test/handlers/erc20/deposit.js @@ -17,6 +17,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { const expectedDepositNonce = 1; const depositerAddress = accounts[1]; const tokenAmount = 100; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance; @@ -29,7 +30,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); @@ -70,6 +71,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { tokenAmount, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ); @@ -97,6 +99,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { tokenAmount, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ); @@ -131,6 +134,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { tokenAmount, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ), "ERC20: not a contract"); @@ -141,6 +145,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { tokenAmount, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ), "ERC20: not a contract"); }); diff --git a/test/handlers/erc20/depositBurn.js b/test/handlers/erc20/depositBurn.js index 9cfd3d42..6360d725 100644 --- a/test/handlers/erc20/depositBurn.js +++ b/test/handlers/erc20/depositBurn.js @@ -20,6 +20,7 @@ contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { const initialTokenAmount = 100; const depositAmount = 10; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance1; @@ -34,7 +35,7 @@ contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) diff --git a/test/handlers/erc20/isWhitelisted.js b/test/handlers/erc20/isWhitelisted.js index 044a0339..e326a51d 100644 --- a/test/handlers/erc20/isWhitelisted.js +++ b/test/handlers/erc20/isWhitelisted.js @@ -25,7 +25,7 @@ contract('ERC20Handler - [isWhitelisted]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) diff --git a/test/handlers/erc20/setResourceIDAndContractAddress.js b/test/handlers/erc20/setResourceIDAndContractAddress.js index 4f52c38f..6d520236 100644 --- a/test/handlers/erc20/setResourceIDAndContractAddress.js +++ b/test/handlers/erc20/setResourceIDAndContractAddress.js @@ -24,7 +24,7 @@ contract('ERC20Handler - [setResourceIDAndContractAddress]', async () => { let burnableContractAddresses; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 0, 100); + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100); ERC20MintableInstance1 = await ERC20MintableContract.new("token", "TOK"); initialResourceIDs = [Ethers.utils.hexZeroPad((ERC20MintableInstance1.address + Ethers.utils.hexlify(domainID).substr(2)), 32)]; diff --git a/test/handlers/erc721/burnList.js b/test/handlers/erc721/burnList.js index 68714d0a..8362d73c 100644 --- a/test/handlers/erc721/burnList.js +++ b/test/handlers/erc721/burnList.js @@ -27,7 +27,7 @@ contract('ERC721Handler - [Burn ERC721]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) diff --git a/test/handlers/erc721/deposit.js b/test/handlers/erc721/deposit.js index 6ff85d2d..28f4aade 100644 --- a/test/handlers/erc721/deposit.js +++ b/test/handlers/erc721/deposit.js @@ -17,6 +17,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { const expectedDepositNonce = 1; const depositerAddress = accounts[1]; const tokenID = 1; + const feeData = '0x'; let BridgeInstance; let ERC721MintableInstance; @@ -29,7 +30,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]) @@ -70,6 +71,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { tokenID, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ); @@ -97,6 +99,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { tokenID, lenRecipientAddress, recipientAddress), + feeData, { from: depositerAddress } ); diff --git a/test/handlers/erc721/depositBurn.js b/test/handlers/erc721/depositBurn.js index 7d64c0c5..9b521d38 100644 --- a/test/handlers/erc721/depositBurn.js +++ b/test/handlers/erc721/depositBurn.js @@ -20,6 +20,8 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { const tokenID = 1; + const feeData = '0x'; + let BridgeInstance; let ERC721MintableInstance1; let ERC721MintableInstance2; @@ -33,7 +35,7 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) @@ -76,6 +78,7 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { domainID, resourceID1, depositData, + feeData, { from: depositerAddress } ); diff --git a/test/handlers/fee/basic/calculateFee.js b/test/handlers/fee/basic/calculateFee.js new file mode 100644 index 00000000..40c0c009 --- /dev/null +++ b/test/handlers/fee/basic/calculateFee.js @@ -0,0 +1,75 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); + +const Helpers = require("../../../helpers"); + +const BridgeContract = artifacts.require("Bridge"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + +contract("BasicFeeHandler - [calculateFee]", async (accounts) => { + const originDomainID = 1; + const destinationDomainID = 2; + const relayer = accounts[0]; + const recipientAddress = accounts[1]; + const feeData = "0x0"; + + let BridgeInstance; + let BasicFeeHandlerInstance; + let resourceID; + let depositData; + let initialResourceIDs; + let initialContractAddresses; + let ERC20MintableInstance; + + beforeEach(async () => { + await Promise.all([ + ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), + BridgeInstance = BridgeContract.new(originDomainID, [relayer], 0, 100).then(instance => BridgeInstance = instance) + ]); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + initialResourceIDs = [resourceID]; + initialContractAddresses = [ERC20MintableInstance.address]; + burnableContractAddresses = []; + + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + + depositData = Helpers.createERCDepositData(100, 20, recipientAddress); + }); + + it("should return amount of fee", async () => { + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + // current fee is set to 0 + let res = await BasicFeeHandlerInstance.calculateFee.call( + relayer, + originDomainID, + destinationDomainID, + resourceID, + depositData, + feeData + ); + assert.equal(web3.utils.fromWei(res[0], "ether"), "0"); + // Change fee to 0.5 ether + await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("0.5")); + res = await BasicFeeHandlerInstance.calculateFee.call( + relayer, + originDomainID, + destinationDomainID, + resourceID, + depositData, + feeData + ); + assert.equal(web3.utils.fromWei(res[0], "ether"), "0.5"); + }); +}); \ No newline at end of file diff --git a/test/handlers/fee/basic/changeFee.js b/test/handlers/fee/basic/changeFee.js new file mode 100644 index 00000000..4aa68bd6 --- /dev/null +++ b/test/handlers/fee/basic/changeFee.js @@ -0,0 +1,53 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); + +const BridgeContract = artifacts.require("Bridge"); +const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + +contract("BasicFeeHandler - [changeFee]", async accounts => { + const relayerThreshold = 0; + const domainID = 1; + const initialRelayers = accounts.slice(0, 3); + const relayer = accounts[0]; + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + }); + + it("[sanity] contract should be deployed successfully", async () => { + TruffleAssert.passes( + await BasicFeeHandlerContract.new(BridgeInstance.address)); + }); + + it("should set fee", async () => { + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + const fee = Ethers.utils.parseEther("0.05"); + const tx = await BasicFeeHandlerInstance.changeFee(fee); + TruffleAssert.eventEmitted(tx, "FeeChanged", (event) => + web3.utils.fromWei(event.newFee, "ether") === "0.05" + ); + const newFee = await BasicFeeHandlerInstance._fee.call(); + assert.equal(web3.utils.fromWei(newFee, "ether"), "0.05"); + }); + + it("should not set the same fee", async () => { + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + await TruffleAssert.reverts(BasicFeeHandlerInstance.changeFee(0), "Current fee is equal to new fee"); + }); + + it("should require admin role to change fee", async () => { + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + await assertOnlyAdmin(BasicFeeHandlerInstance.changeFee, 1); + }); +}); diff --git a/test/handlers/fee/basic/collectFee.js b/test/handlers/fee/basic/collectFee.js new file mode 100644 index 00000000..c448b452 --- /dev/null +++ b/test/handlers/fee/basic/collectFee.js @@ -0,0 +1,153 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); + +const Helpers = require("../../../helpers"); + +const BridgeContract = artifacts.require("Bridge"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + +contract("BasicFeeHandler - [collectFee]", async (accounts) => { + + const relayerThreshold = 1; + const domainID = 1; + + const depositerAddress = accounts[1]; + const recipientAddress = accounts[2]; + + const depositAmount = 10; + const feeData = "0x0"; + + let BridgeInstance; + let ERC20MintableInstance; + let ERC20HandlerInstance; + let BasicFeeHandlerInstance; + + let resourceID; + let depositData; + + beforeEach(async () => { + await Promise.all([ + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ]); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await Promise.all([ + ERC20MintableInstance.mint(depositerAddress, depositAmount), + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + ]); + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); + + depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); + + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + }); + + it("[sanity] Generic deposit can be made", async () => { + await TruffleAssert.passes(BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + )); + }); + + it("deposit should revert if invalid fee amount supplied", async () => { + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + // current fee is set to 0 + assert.equal(await BasicFeeHandlerInstance._fee.call(), 0); + + await TruffleAssert.reverts( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("1.0") + } + ), + "Incorrect fee supplied" + ) + }); + + it("deposit should pass if valid fee amount supplied", async () => { + const fee = Ethers.utils.parseEther("0.5"); + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + // current fee is set to 0 + assert.equal(await BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.5 ether + await BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + + const balanceBefore = await web3.eth.getBalance(BasicFeeHandlerInstance.address); + + const depositTx = await BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: fee + } + ); + + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === domainID && + event.resourceID === resourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(BasicFeeHandlerInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === domainID && + event.destinationDomainID.toNumber() === domainID && + event.resourceID === resourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === "0x0000000000000000000000000000000000000000"; + }); + const balanceAfter = await web3.eth.getBalance(BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, fee.add(balanceBefore)); + }); + + it("deposit should revert if fee handler not set and fee supplied", async () => { + await TruffleAssert.reverts( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("1.0") + } + ), + "no FeeHandler, msg.value != 0" + ) + }); + + it("deposit should pass if fee handler not set and fee not supplied", async () => { + await TruffleAssert.passes( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + ) + ) + }); +}); \ No newline at end of file diff --git a/test/handlers/fee/basic/distributeFee.js b/test/handlers/fee/basic/distributeFee.js new file mode 100644 index 00000000..874783b2 --- /dev/null +++ b/test/handlers/fee/basic/distributeFee.js @@ -0,0 +1,121 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require("truffle-assertions"); + const Ethers = require("ethers"); + + const Helpers = require("../../../helpers"); + + const BridgeContract = artifacts.require("Bridge"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + +contract("BasicFeeHandler - [distributeFee]", async (accounts) => { + + const relayerThreshold = 1; + const domainID = 1; + + const depositerAddress = accounts[1]; + const recipientAddress = accounts[2]; + + const depositAmount = 10; + const feeData = "0x0"; + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: accounts[1]}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + let ERC20MintableInstance; + let ERC20HandlerInstance; + let BasicFeeHandlerInstance; + + let resourceID; + let depositData; + + beforeEach(async () => { + await Promise.all([ + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ]); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await Promise.all([ + ERC20MintableInstance.mint(depositerAddress, depositAmount), + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + ]); + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); + + depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); + + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + }); + + it("should distribute fees", async () => { + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); + assert.equal(web3.utils.fromWei((await BasicFeeHandlerInstance._fee.call()), "ether"), "1"); + + // check the balance is 0 + assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "0"); + await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}) + assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "0"); + assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); + + let b1Before = await web3.eth.getBalance(accounts[1]); + let b2Before = await web3.eth.getBalance(accounts[2]); + + let payout = Ethers.utils.parseEther("0.5") + // Transfer the funds + const tx = await BasicFeeHandlerInstance.transferFee( + [accounts[1], accounts[2]], + [payout, payout] + ); + TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { + return event.tokenAddress === '0x0000000000000000000000000000000000000000' && + event.recipient === accounts[1] && + event.amount.toString() === payout.toString() + }); + TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { + return event.tokenAddress === '0x0000000000000000000000000000000000000000' && + event.recipient === accounts[2] && + event.amount.toString() === payout.toString() + }); + b1 = await web3.eth.getBalance(accounts[1]); + b2 = await web3.eth.getBalance(accounts[2]); + assert.equal(b1, Ethers.BigNumber.from(b1Before).add(payout)); + assert.equal(b2, Ethers.BigNumber.from(b2Before).add(payout)); + }); + + it("should require admin role to distribute fee", async () => { + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); + + await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); + + assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + await assertOnlyAdmin(BasicFeeHandlerInstance.transferFee, [accounts[3], accounts[4]], [payout, payout]); + }); + + it("should revert if addrs and amounts arrays have different length", async () => { + await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); + await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); + + await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); + + assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + await TruffleAssert.reverts(BasicFeeHandlerInstance.transferFee([accounts[3], accounts[4]], [payout, payout, payout]), + "addrs[], amounts[]: diff length"); + }); + }); \ No newline at end of file diff --git a/test/handlers/fee/withOracle/admin.js b/test/handlers/fee/withOracle/admin.js new file mode 100644 index 00000000..071fdf90 --- /dev/null +++ b/test/handlers/fee/withOracle/admin.js @@ -0,0 +1,57 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require("truffle-assertions"); + + const BridgeContract = artifacts.require("Bridge"); + const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); + + contract("FeeHandlerWithOracle - [admin]", async accounts => { + const relayerThreshold = 0; + const domainID = 1; + const initialRelayers = accounts.slice(0, 3); + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + }); + + it("should set fee oracle", async () => { + const oracleAddress = accounts[1]; + assert.equal(await FeeHandlerWithOracleInstance._oracleAddress.call(), "0x0000000000000000000000000000000000000000"); + await FeeHandlerWithOracleInstance.setFeeOracle(oracleAddress); + const newOracle = await FeeHandlerWithOracleInstance._oracleAddress.call(); + assert.equal(newOracle, oracleAddress); + }); + + it("should require admin role to change fee oracle", async () => { + const oracleAddress = accounts[1]; + await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeOracle, oracleAddress); + }); + + it("should set fee properties", async () => { + const gasUsed = 100000; + const feePercent = 5; + assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), "0"); + assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), "0"); + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), gasUsed); + assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), feePercent); + }); + + it("should require admin role to change fee properties", async () => { + const gasUsed = 100000; + const feePercent = 5; + await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeProperties, gasUsed, feePercent); + }); + }); + \ No newline at end of file diff --git a/test/handlers/fee/withOracle/calculateFee.js b/test/handlers/fee/withOracle/calculateFee.js new file mode 100644 index 00000000..9c791f78 --- /dev/null +++ b/test/handlers/fee/withOracle/calculateFee.js @@ -0,0 +1,201 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); + +const Helpers = require("../../../helpers"); + +const BridgeContract = artifacts.require("Bridge"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); + +contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { + const relayerThreshold = 0; + const domainID = 1; + const oracle = new Ethers.Wallet.createRandom(); + const sender = accounts[0]; + const recipientAddress = accounts[1]; + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + let resourceID; + + /* + feeData structure: + ber*10^18: uint256 + ter*10^18: uint256 + dstGasPrice: uint256 + expiresAt: uint256 + fromDomainID: uint8 encoded as uint256 + toDomainID: uint8 encoded as uint256 + resourceID: bytes32 + sig: bytes(65 bytes) + + total in bytes: + message: + 32 * 7 = 224 + message + sig: + 224 + 65 = 289 + + amount: uint256 + total feeData length: 321 + */ + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); + + const gasUsed = 100000; + const feePercent = 500; + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + + ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); + }); + + it("should calculate amount of fee and return token address", async () => { + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + assert.equal(Ethers.utils.formatEther(res.fee.toString()), "0.00491802"); + assert.equal(res.tokenAddress, ERC20MintableInstance.address); + }); + + it("should return percent fee", async () => { + const tokenAmount = Ethers.utils.parseEther("1"); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + assert.equal(web3.utils.fromWei(res.fee, "ether"), "0.05"); + assert.equal(res.tokenAddress, ERC20MintableInstance.address); + }); + + it("should return fee to cover tx cost if percent fee does not cover tx cost", async () => { + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.0005"), + ter: Ethers.utils.parseEther("1.5"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + assert.equal(Ethers.utils.formatEther(res.fee.toString()), "0.0045"); + assert.equal(res.tokenAddress, ERC20MintableInstance.address); + }); + + it("should not calculate fee if fee data is misformed", async () => { + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.0005"), + ter: Ethers.utils.parseEther("1.5"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount) + "11"; + await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Incorrect feeData length"); + }); + + it("should not calculate fee if deposit data differ from fee data", async () => { + const otherDomainId = 2; + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.0005"), + ter: Ethers.utils.parseEther("1.5"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, otherDomainId, resourceID, depositData, feeData), "Incorrect deposit params"); + }); + + it("should not calculate fee if oracle signature is incorrect", async () => { + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.0005"), + ter: Ethers.utils.parseEther("1.5"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const oracle2 = new Ethers.Wallet.createRandom(); + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle2.privateKey, tokenAmount); + await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Invalid signature"); + }); + + it("should not calculate fee if oracle data are outdated", async () => { + const gasUsed = 100000; + const feePercent = 500; + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + + const tokenAmount = Ethers.utils.parseEther("1"); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) - 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Obsolete oracle data"); + }); + }); + \ No newline at end of file diff --git a/test/handlers/fee/withOracle/collectFee.js b/test/handlers/fee/withOracle/collectFee.js new file mode 100644 index 00000000..2c46547c --- /dev/null +++ b/test/handlers/fee/withOracle/collectFee.js @@ -0,0 +1,203 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require("truffle-assertions"); + const Ethers = require("ethers"); + + const Helpers = require("../../../helpers"); + + const BridgeContract = artifacts.require("Bridge"); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); + const ERC20HandlerContract = artifacts.require("ERC20Handler"); + const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); + + contract("FeeHandlerWithOracle - [collectFee]", async accounts => { + const relayerThreshold = 0; + const domainID = 1; + const oracle = new Ethers.Wallet.createRandom(); + const recipientAddress = accounts[2]; + const tokenAmount = Ethers.utils.parseEther("1"); + const feeAmount =Ethers.utils.parseEther("0.05"); + const depositerAddress = accounts[1]; + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + let resourceID; + + /* + feeData structure: + ber*10^18: uint256 + ter*10^18: uint256 + dstGasPrice: uint256 + expiresAt: uint256 + fromDomainID: uint8 encoded as uint256 + toDomainID: uint8 encoded as uint256 + resourceID: bytes32 + sig: bytes(65 bytes) + + total in bytes: + message: + 32 * 7 = 224 + message + sig: + 224 + 65 = 289 + + amount: uint256 + total feeData length: 321 + */ + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); + + const gasUsed = 100000; + const feePercent = 500; + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + + ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); + + await ERC20MintableInstance.mint(depositerAddress, tokenAmount + feeAmount), + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); + await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, feeAmount, { from: depositerAddress }); + await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); + }); + + it("should collect fee in tokens", async () => { + const fee = Ethers.utils.parseEther("0.05"); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + + const balanceBefore = (await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address)).toString(); + + const depositTx = await BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ); + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === domainID && + event.resourceID === resourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(FeeHandlerWithOracleInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === domainID && + event.destinationDomainID.toNumber() === domainID && + event.resourceID === resourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === ERC20MintableInstance.address; + }); + const balanceAfter = (await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address)).toString(); + assert.equal(balanceAfter, fee.add(balanceBefore).toString()); + }); + + it("deposit should revert if msg.value != 0", async () => { + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await TruffleAssert.reverts( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ), + "msg.value != 0" + ); + }); + + it("deposit should revert if fee collection fails", async () => { + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, 0, { from: depositerAddress }); + await TruffleAssert.reverts( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ) + ); + }); + + it("deposit should revert if called not by bridge", async () => { + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, 0, { from: depositerAddress }); + await TruffleAssert.reverts( + FeeHandlerWithOracleInstance.collectFee( + depositerAddress, + domainID, + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ), + "sender must be bridge contract" + ); + }); + }); + \ No newline at end of file diff --git a/test/handlers/fee/withOracle/distributeFee.js b/test/handlers/fee/withOracle/distributeFee.js new file mode 100644 index 00000000..6533ac0d --- /dev/null +++ b/test/handlers/fee/withOracle/distributeFee.js @@ -0,0 +1,182 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require("truffle-assertions"); + const Ethers = require("ethers"); + + const Helpers = require("../../../helpers"); + + const BridgeContract = artifacts.require("Bridge"); + const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); + const ERC20HandlerContract = artifacts.require("ERC20Handler"); + + contract("FeeHandlerWithOracle - [distributeFee]", async accounts => { + const relayerThreshold = 0; + const domainID = 1; + const oracle = new Ethers.Wallet.createRandom(); + const recipientAddress = accounts[2]; + const depositerAddress = accounts[1]; + const tokenAmount = feeAmount = Ethers.utils.parseEther("1"); + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + let resourceID; + let depositData; + let feeData; + let oracleResponse; + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: accounts[1]}), "sender doesn't have admin role"); + }; + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); + + const gasUsed = 100000; + const feePercent = 10000; + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + + ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); + + await ERC20MintableInstance.mint(depositerAddress, tokenAmount.add(feeAmount)), + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); + await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, tokenAmount, { from: depositerAddress }); + await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); + + depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: domainID, + toDomainID: domainID, + resourceID + }; + + feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + }); + + it("should distribute fees", async () => { + // check the balance is 0 + let b1Before = (await ERC20MintableInstance.balanceOf(accounts[3])).toString(); + let b2Before = (await ERC20MintableInstance.balanceOf(accounts[4])).toString(); + + await TruffleAssert.passes( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ) + ); + const balance = await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address); + assert.equal(web3.utils.fromWei(balance, "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + + // Transfer the funds + const tx = await FeeHandlerWithOracleInstance.transferFee( + resourceID, + [accounts[3], accounts[4]], + [payout, payout] + ); + TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { + return event.tokenAddress === ERC20MintableInstance.address && + event.recipient === accounts[3] && + event.amount.toString() === payout.toString() + }); + TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { + return event.tokenAddress === ERC20MintableInstance.address && + event.recipient === accounts[4] && + event.amount.toString() === payout.toString() + }); + b1 = await ERC20MintableInstance.balanceOf(accounts[3]); + b2 = await ERC20MintableInstance.balanceOf(accounts[4]); + assert.equal(b1.toString(), payout.add(b1Before).toString()); + assert.equal(b2.toString(), payout.add(b2Before).toString()); + }); + + it("should not distribute fees with other resourceID", async () => { + await TruffleAssert.passes( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ) + ); + const balance = await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address); + assert.equal(web3.utils.fromWei(balance, "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + + // Incorrect resourceID + resourceID = Helpers.createResourceID(FeeHandlerWithOracleInstance.address, domainID); + + // Transfer the funds: fails + await TruffleAssert.reverts( + FeeHandlerWithOracleInstance.transferFee( + resourceID, + [accounts[3], accounts[4]], + [payout, payout] + ) + ); + }); + + it("should require admin role to distribute fee", async () => { + await TruffleAssert.passes( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ) + ); + const balance = await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address); + assert.equal(web3.utils.fromWei(balance, "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + await assertOnlyAdmin(FeeHandlerWithOracleInstance.transferFee, resourceID, [accounts[3], accounts[4]], [payout, payout]); + }); + + it("should revert if addrs and amounts arrays have different length", async () => { + await TruffleAssert.passes( + BridgeInstance.deposit( + domainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ) + ); + const balance = await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address); + assert.equal(web3.utils.fromWei(balance, "ether"), "1"); + + let payout = Ethers.utils.parseEther("0.5"); + await TruffleAssert.reverts(FeeHandlerWithOracleInstance.transferFee(resourceID, [accounts[3], accounts[4]], [payout, payout, payout]), + "addrs[], amounts[]: diff length"); + }); + }); \ No newline at end of file diff --git a/test/handlers/generic/constructor.js b/test/handlers/generic/constructor.js index 3a29dd56..1a7e760d 100644 --- a/test/handlers/generic/constructor.js +++ b/test/handlers/generic/constructor.js @@ -32,7 +32,7 @@ contract('GenericHandler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance1 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance2 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance3 = instance) @@ -53,8 +53,8 @@ contract('GenericHandler - [constructor]', async () => { }); it('[sanity] contract should be deployed successfully', async () => { - TruffleAssert.passes( - await GenericHandlerContract.new( + await TruffleAssert.passes( + GenericHandlerContract.new( BridgeInstance.address)); }); diff --git a/test/handlers/generic/deposit.js b/test/handlers/generic/deposit.js index 0b7dba59..b3a83a2d 100644 --- a/test/handlers/generic/deposit.js +++ b/test/handlers/generic/deposit.js @@ -23,6 +23,8 @@ contract('GenericHandler - [deposit]', async (accounts) => { const depositerAddress = accounts[1]; + const feeData = '0x'; + let BridgeInstance; let CentrifugeAssetInstance; let NoArgumentInstance; @@ -42,7 +44,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), NoArgumentContract.new().then(instance => NoArgumentInstance = instance), OneArgumentContract.new().then(instance => OneArgumentInstance = instance), @@ -118,6 +120,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[0], depositData, + feeData, { from: depositerAddress } )); }); @@ -127,6 +130,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[0], depositData, + feeData, { from: depositerAddress } ); @@ -145,6 +149,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[1], Helpers.createGenericDepositData(null), + feeData, { from: depositerAddress } ); @@ -168,6 +173,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[2], Helpers.createGenericDepositData(Helpers.toHex(argumentOne, 32)), + feeData, { from: depositerAddress } ); @@ -193,6 +199,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[3], Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); @@ -222,6 +229,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[4], Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); @@ -250,6 +258,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[5], Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); @@ -278,6 +287,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[5], Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ), 'incorrect depositer in the data'); }); @@ -290,6 +300,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { domainID, initialResourceIDs[6], Helpers.createGenericDepositData(encodedMetaData), + feeData, { from: depositerAddress } ); diff --git a/test/handlers/generic/executeProposal.js b/test/handlers/generic/executeProposal.js index 65fa165b..1eab00b9 100644 --- a/test/handlers/generic/executeProposal.js +++ b/test/handlers/generic/executeProposal.js @@ -25,6 +25,7 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { const centrifugeAssetMinCount = 10; const hashOfCentrifugeAsset = Ethers.utils.keccak256('0xc0ffee'); + const feeData = '0x'; let BridgeInstance; let CentrifugeAssetInstance; @@ -39,7 +40,7 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 0, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance = instance) ]); @@ -66,6 +67,7 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { domainID, resourceID, depositData, + feeData, { from: depositerAddress } )); @@ -99,6 +101,7 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { domainID, resourceID, depositData, + feeData, { from: depositerAddress } )); diff --git a/test/helpers.js b/test/helpers.js index a7ba9f70..5f1406b3 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -70,6 +70,12 @@ const advanceBlock = () => { return provider.send("evm_mine", [time]); } +const advanceTime = (seconds) => { + let provider = new Ethers.providers.JsonRpcProvider(); + const time = Math.floor(Date.now() / 1000) + seconds; + return provider.send("evm_mine", [time]); +} + const createGenericDepositData = (hexMetaData) => { if (hexMetaData === null) { return '0x' + @@ -122,8 +128,48 @@ const nonceAndId = (nonce, id) => { return Ethers.utils.hexZeroPad(Ethers.utils.hexlify(nonce), 8) + Ethers.utils.hexZeroPad(Ethers.utils.hexlify(id), 1).substr(2) } +const createOracleFeeData = (oracleResponse, privateKey, amount) => { + /* + feeData structure: + ber*10^18: uint256 + ter*10^18: uint256 + dstGasPrice: uint256 + timestamp: uint256 + fromDomainID: uint8 encoded as uint256 + toDomainID: uint8 encoded as uint256 + resourceID: bytes32 + sig: bytes(65 bytes) + + total in bytes: + message: + 32 * 7 = 224 + message + sig: + 224 + 65 = 289 + + amount: uint256 + total feeData length: 321 + */ + + const oracleMessage = '0x' + + toHex(oracleResponse.ber, 32).substr(2) + // ber*10^18: uint256 (32 bytes) + toHex(oracleResponse.ter, 32).substr(2) + // ter*10^18: uint256 (32 bytes) + toHex(oracleResponse.dstGasPrice, 32).substr(2) + // dstGasPrice: uint256 (32 bytes) + toHex(oracleResponse.expiresAt, 32).substr(2) + // expiresAt: uint256 + toHex(oracleResponse.fromDomainID, 32).substr(2) + // fromDomainID: uint256 + toHex(oracleResponse.toDomainID, 32).substr(2) + // toDomainID: uint256 + oracleResponse.resourceID.substr(2); // resourceID: bytes32 + + const messageHash = Ethers.utils.keccak256(oracleMessage); + const signingKey = new Ethers.utils.SigningKey(privateKey); + const messageHashBytes = Ethers.utils.arrayify(messageHash); + const signature = signingKey.signDigest(messageHashBytes); + const rawSignature = Ethers.utils.joinSignature(signature); + return oracleMessage + rawSignature.substr(2) + toHex(amount, 32).substr(2); +} + module.exports = { advanceBlock, + advanceTime, blankFunctionSig, blankFunctionDepositerOffset, toHex, @@ -139,5 +185,6 @@ module.exports = { createERC721DepositProposalData, createResourceID, assertObjectsMatch, - nonceAndId + nonceAndId, + createOracleFeeData }; From 65dc0bb4c55fa76c78488e283007f0cd45e9786d Mon Sep 17 00:00:00 2001 From: Jon Roethke Date: Fri, 13 May 2022 05:59:36 -0700 Subject: [PATCH 03/20] use updated geth flags (#511) Co-authored-by: Kirill --- scripts/geth/start_geth.sh | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/geth/start_geth.sh b/scripts/geth/start_geth.sh index 2d5233a9..5b1d5dbb 100755 --- a/scripts/geth/start_geth.sh +++ b/scripts/geth/start_geth.sh @@ -22,13 +22,12 @@ if [[ $QUIET ]]; then --unlock "0xff93B45308FD417dF303D6515aB04D9e89a750Ca","0x8e0a907331554AF72563Bd8D43051C2E64Be5d35","0x24962717f8fA5BA3b931bACaF9ac03924EB475a0","0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7","0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485" \ --password ./scripts/geth/password.txt \ --ws \ - --wsport 8545 \ + --ws.port 8545 \ --networkid 5 \ - --wsorigins="*" \ - --rpc \ - --rpcport 8545 \ - --rpccorsdomain="*" \ - --targetgaslimit 8000000 \ + --ws.origins="*" \ + --port 8545 \ + --http.corsdomain="*" \ + --miner.gaslimit 8000000 \ --allow-insecure-unlock \ --mine else @@ -37,13 +36,12 @@ else --unlock "0xff93B45308FD417dF303D6515aB04D9e89a750Ca","0x8e0a907331554AF72563Bd8D43051C2E64Be5d35","0x24962717f8fA5BA3b931bACaF9ac03924EB475a0","0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7","0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485" \ --password ./scripts/geth/password.txt \ --ws \ - --wsport 8545 \ + --ws.port 8545 \ --networkid 5 \ - --wsorigins="*" \ - --rpc \ - --rpcport 8545 \ - --rpccorsdomain="*" \ - --targetgaslimit 8000000 \ + --ws.origins="*" \ + --port 8545 \ + --http.corsdomain="*" \ + --miner.gaslimit 8000000 \ --allow-insecure-unlock \ --mine fi From 6bcfdb19aaac0bc62bf3134f3fc26c854265e401 Mon Sep 17 00:00:00 2001 From: Neuti Yoo <103201346+neutiyoo@users.noreply.github.com> Date: Tue, 24 May 2022 00:36:31 +0900 Subject: [PATCH 04/20] Remove ignored visibility for constructor (#552) --- contracts/ERC721MinterBurnerPauser.sol | 2 +- contracts/handlers/ERC1155Handler.sol | 2 +- contracts/handlers/ERC20Handler.sol | 2 +- contracts/handlers/ERC721Handler.sol | 2 +- contracts/handlers/HandlerHelpers.sol | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/ERC721MinterBurnerPauser.sol b/contracts/ERC721MinterBurnerPauser.sol index 6dfc03de..16fdae0f 100644 --- a/contracts/ERC721MinterBurnerPauser.sol +++ b/contracts/ERC721MinterBurnerPauser.sol @@ -23,7 +23,7 @@ contract ERC721MinterBurnerPauser is Context, AccessControl, ERC721Burnable, ERC * Token URIs will be autogenerated based on `baseURI` and their token IDs. * See {ERC721-tokenURI}. */ - constructor(string memory name, string memory symbol, string memory baseURI) public ERC721(name, symbol) { + constructor(string memory name, string memory symbol, string memory baseURI) ERC721(name, symbol) { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, _msgSender()); diff --git a/contracts/handlers/ERC1155Handler.sol b/contracts/handlers/ERC1155Handler.sol index f39de918..268726f4 100644 --- a/contracts/handlers/ERC1155Handler.sol +++ b/contracts/handlers/ERC1155Handler.sol @@ -19,7 +19,7 @@ contract ERC1155Handler is IDepositExecute, HandlerHelpers, ERC1155Safe, ERC1155 */ constructor( address bridgeAddress - ) public HandlerHelpers(bridgeAddress) { + ) HandlerHelpers(bridgeAddress) { } /** diff --git a/contracts/handlers/ERC20Handler.sol b/contracts/handlers/ERC20Handler.sol index 45a1751f..6ad65bc5 100644 --- a/contracts/handlers/ERC20Handler.sol +++ b/contracts/handlers/ERC20Handler.sol @@ -16,7 +16,7 @@ contract ERC20Handler is IDepositExecute, HandlerHelpers, ERC20Safe { */ constructor( address bridgeAddress - ) public HandlerHelpers(bridgeAddress) { + ) HandlerHelpers(bridgeAddress) { } /** diff --git a/contracts/handlers/ERC721Handler.sol b/contracts/handlers/ERC721Handler.sol index 71e25548..ebbae7cb 100644 --- a/contracts/handlers/ERC721Handler.sol +++ b/contracts/handlers/ERC721Handler.sol @@ -23,7 +23,7 @@ contract ERC721Handler is IDepositExecute, HandlerHelpers, ERC721Safe { */ constructor( address bridgeAddress - ) public HandlerHelpers(bridgeAddress) { + ) HandlerHelpers(bridgeAddress) { } /** diff --git a/contracts/handlers/HandlerHelpers.sol b/contracts/handlers/HandlerHelpers.sol index 15a93a7d..cc1d22b1 100644 --- a/contracts/handlers/HandlerHelpers.sol +++ b/contracts/handlers/HandlerHelpers.sol @@ -33,7 +33,7 @@ contract HandlerHelpers is IERCHandler { */ constructor( address bridgeAddress - ) public { + ) { _bridgeAddress = bridgeAddress; } From 1da71c42228987444a290ea0f240123ddf8e6d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Thu, 2 Jun 2022 11:57:22 +0200 Subject: [PATCH 05/20] Remove voting logic + add logic for MPC (#544) * Remove voting logic + add mpc logic * Update tests for new MPC Bridge contract logic * Add 'executeWithFailedHandler' tests * Remove transferFunds, refactor helper func * Remove unneeded SafeCast & SafeMath * Remove unneeded depositNonce, rename domainID to originDomainID and lint * Remove unneeded depositNonce from tests, clean up code and lint * Remove SafeCast from TestContract * Remove destination domain id from proposal execution event * Restrict deposits to current domain * Update tests with new same domain deposit restriction * Fix typo Co-authored-by: viatrix Co-authored-by: Kirill Co-authored-by: Oleksii Matiiasevych --- contracts/Bridge.sol | 331 ++++----------- contracts/TestContracts.sol | 8 - contracts/utils/SafeCast.sol | 26 -- contracts/utils/SafeMath.sol | 43 -- test/contractBridge/admin.js | 103 +++-- test/contractBridge/cancelDepositProposal.js | 185 --------- test/contractBridge/constructor.js | 29 -- test/contractBridge/createDepositProposal.js | 274 ------------- test/contractBridge/depositERC1155.js | 18 +- test/contractBridge/depositERC20.js | 14 +- test/contractBridge/depositERC721.js | 24 +- test/contractBridge/depositGeneric.js | 20 +- test/contractBridge/executeProposal.js | 179 ++++++++ .../executeWithFailedHandler.js | 158 ++----- test/contractBridge/voteDepositProposal.js | 240 ----------- .../voteDepositProposalWithRealForwarder.js | 387 ------------------ .../voteDepositProposalWithTestForwarder.js | 234 ----------- test/e2e/erc1155/differentChainsMock.js | 69 ++-- test/e2e/erc1155/sameChain.js | 46 +-- test/e2e/erc20/differentChainsMock.js | 75 ++-- test/e2e/erc20/sameChain.js | 49 +-- test/e2e/erc721/differentChainsMock.js | 65 ++- test/e2e/erc721/sameChain.js | 39 +- test/forwarder/forwarder.js | 36 +- test/gasBenchmarks/deployments.js | 3 +- test/gasBenchmarks/deposits.js | 44 +- test/gasBenchmarks/executeProposal.js | 74 ++-- test/gasBenchmarks/voteProposal.js | 96 ----- test/handlers/erc1155/burnList.js | 11 +- test/handlers/erc1155/deposit.js | 20 +- test/handlers/erc1155/depositBurn.js | 19 +- test/handlers/erc20/burnList.js | 9 +- test/handlers/erc20/constructor.js | 17 +- test/handlers/erc20/deposit.js | 35 +- test/handlers/erc20/depositBurn.js | 7 +- test/handlers/erc20/isWhitelisted.js | 7 +- .../erc20/setResourceIDAndContractAddress.js | 5 +- test/handlers/erc721/burnList.js | 3 +- test/handlers/erc721/deposit.js | 25 +- test/handlers/erc721/depositBurn.js | 19 +- test/handlers/fee/basic/calculateFee.js | 8 +- test/handlers/fee/basic/changeFee.js | 10 +- test/handlers/fee/basic/collectFee.js | 39 +- test/handlers/fee/basic/distributeFee.js | 39 +- test/handlers/fee/withOracle/admin.js | 64 ++- test/handlers/fee/withOracle/calculateFee.js | 32 +- test/handlers/fee/withOracle/collectFee.js | 60 +-- test/handlers/fee/withOracle/distributeFee.js | 50 +-- test/handlers/generic/constructor.js | 7 +- test/handlers/generic/deposit.js | 69 ++-- test/handlers/generic/executeProposal.js | 69 ++-- test/helpers.js | 49 ++- test/safeCast.js | 21 - 53 files changed, 957 insertions(+), 2606 deletions(-) delete mode 100644 contracts/utils/SafeCast.sol delete mode 100644 contracts/utils/SafeMath.sol delete mode 100644 test/contractBridge/cancelDepositProposal.js delete mode 100644 test/contractBridge/constructor.js delete mode 100644 test/contractBridge/createDepositProposal.js create mode 100644 test/contractBridge/executeProposal.js delete mode 100644 test/contractBridge/voteDepositProposal.js delete mode 100644 test/contractBridge/voteDepositProposalWithRealForwarder.js delete mode 100644 test/contractBridge/voteDepositProposalWithTestForwarder.js delete mode 100644 test/gasBenchmarks/voteProposal.js delete mode 100644 test/safeCast.js diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 0a225766..cea8fcda 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -1,39 +1,29 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./utils/AccessControl.sol"; import "./utils/Pausable.sol"; -import "./utils/SafeMath.sol"; -import "./utils/SafeCast.sol"; + import "./interfaces/IDepositExecute.sol"; import "./interfaces/IERCHandler.sol"; import "./interfaces/IGenericHandler.sol"; import "./interfaces/IFeeHandler.sol"; /** - @title Facilitates deposits, creation and voting of deposit proposals, and deposit executions. + @title Facilitates deposits and creation of deposit proposals, and deposit executions. @author ChainSafe Systems. */ -contract Bridge is Pausable, AccessControl, SafeMath { - using SafeCast for *; +contract Bridge is Pausable, AccessControl { + using ECDSA for bytes32; - // Limit relayers number because proposal can fit only so much votes - uint256 constant public MAX_RELAYERS = 200; - uint8 public _domainID; - uint8 public _relayerThreshold; - uint40 public _expiry; - IFeeHandler public _feeHandler; - enum ProposalStatus {Inactive, Active, Passed, Executed, Cancelled} + uint8 public _domainID; + address public _MPCAddress; - struct Proposal { - ProposalStatus _status; - uint200 _yesVotes; // bitmap, 200 maximum votes - uint8 _yesVotesTotal; - uint40 _proposedBlock; // 1099511627775 maximum block - } + IFeeHandler public _feeHandler; // destinationDomainID => number of deposits mapping(uint8 => uint64) public _depositCounts; @@ -41,76 +31,42 @@ contract Bridge is Pausable, AccessControl, SafeMath { mapping(bytes32 => address) public _resourceIDToHandlerAddress; // forwarder address => is Valid mapping(address => bool) public isValidForwarder; - // destinationDomainID + depositNonce => dataHash => Proposal - mapping(uint72 => mapping(bytes32 => Proposal)) private _proposals; + // origin domainID => nonces set => used deposit nonces + mapping(uint8 => mapping(uint256 => uint256)) public usedNonces; - event RelayerThresholdChanged(uint256 newThreshold); - event RelayerAdded(address relayer); - event RelayerRemoved(address relayer); event FeeHandlerChanged(address newFeeHandler); event Deposit( uint8 destinationDomainID, bytes32 resourceID, uint64 depositNonce, address indexed user, - bytes data, - bytes handlerResponse + bytes data, + bytes handlerResponse ); - event ProposalEvent( - uint8 originDomainID, - uint64 depositNonce, - ProposalStatus status, - bytes32 dataHash - ); - event ProposalVote( + event ProposalExecution( uint8 originDomainID, uint64 depositNonce, - ProposalStatus status, bytes32 dataHash ); event FailedHandlerExecution( bytes lowLevelData ); - bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE"); + event StartKeygen(); - modifier onlyAdmin() { - _onlyAdmin(); - _; - } + event EndKeygen(); - modifier onlyAdminOrRelayer() { - _onlyAdminOrRelayer(); - _; - } + event KeyRefresh(); - modifier onlyRelayers() { - _onlyRelayers(); + modifier onlyAdmin() { + _onlyAdmin(); _; } - function _onlyAdminOrRelayer() private view { - address sender = _msgSender(); - require(hasRole(DEFAULT_ADMIN_ROLE, sender) || hasRole(RELAYER_ROLE, sender), - "sender is not relayer or admin"); - } - function _onlyAdmin() private view { require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "sender doesn't have admin role"); } - function _onlyRelayers() private view { - require(hasRole(RELAYER_ROLE, _msgSender()), "sender doesn't have relayer role"); - } - - function _relayerBit(address relayer) private view returns(uint) { - return uint(1) << sub(AccessControl.getRoleMemberIndex(RELAYER_ROLE, relayer), 1); - } - - function _hasVoted(Proposal memory proposal, address relayer) private view returns(bool) { - return (_relayerBit(relayer) & uint(proposal._yesVotes)) > 0; - } - function _msgSender() internal override view returns (address) { address signer = msg.sender; if (msg.data.length >= 20 && isValidForwarder[signer]) { @@ -122,41 +78,15 @@ contract Bridge is Pausable, AccessControl, SafeMath { } /** - @notice Initializes Bridge, creates and grants {_msgSender()} the admin role, - creates and grants {initialRelayers} the relayer role. + @notice Initializes Bridge, creates and grants {_msgSender()} the admin role and + sets the inital state of the Bridge to paused. @param domainID ID of chain the Bridge contract exists on. - @param initialRelayers Addresses that should be initially granted the relayer role. - @param initialRelayerThreshold Number of votes needed for a deposit proposal to be considered passed. */ - constructor (uint8 domainID, address[] memory initialRelayers, uint256 initialRelayerThreshold, uint256 expiry) public { + constructor (uint8 domainID) public { _domainID = domainID; - _relayerThreshold = initialRelayerThreshold.toUint8(); - _expiry = expiry.toUint40(); _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); - - for (uint256 i; i < initialRelayers.length; i++) { - grantRole(RELAYER_ROLE, initialRelayers[i]); - } - } - - /** - @notice Returns true if {relayer} has voted on {destNonce} {dataHash} proposal. - @notice Naming left unchanged for backward compatibility. - @param destNonce destinationDomainID + depositNonce of the proposal. - @param dataHash Hash of data to be provided when deposit proposal is executed. - @param relayer Address to check. - */ - function _hasVotedOnProposal(uint72 destNonce, bytes32 dataHash, address relayer) public view returns(bool) { - return _hasVoted(_proposals[destNonce][dataHash], relayer); - } - - /** - @notice Returns true if {relayer} has the relayer role. - @param relayer Address to check. - */ - function isRelayer(address relayer) external view returns (bool) { - return hasRole(RELAYER_ROLE, relayer); + _pause(_msgSender()); } /** @@ -182,49 +112,13 @@ contract Bridge is Pausable, AccessControl, SafeMath { /** @notice Unpauses deposits, proposal creation and voting, and deposit executions. @notice Only callable by an address that currently has the admin role. + @notice MPC address has to be set before Bridge can be unpaused */ function adminUnpauseTransfers() external onlyAdmin { + require(_MPCAddress != address(0), "MPC address not set"); _unpause(_msgSender()); } - /** - @notice Modifies the number of votes required for a proposal to be considered passed. - @notice Only callable by an address that currently has the admin role. - @param newThreshold Value {_relayerThreshold} will be changed to. - @notice Emits {RelayerThresholdChanged} event. - */ - function adminChangeRelayerThreshold(uint256 newThreshold) external onlyAdmin { - _relayerThreshold = newThreshold.toUint8(); - emit RelayerThresholdChanged(newThreshold); - } - - /** - @notice Grants {relayerAddress} the relayer role. - @notice Only callable by an address that currently has the admin role, which is - checked in grantRole(). - @param relayerAddress Address of relayer to be added. - @notice Emits {RelayerAdded} event. - */ - function adminAddRelayer(address relayerAddress) external { - require(!hasRole(RELAYER_ROLE, relayerAddress), "addr already has relayer role!"); - require(_totalRelayers() < MAX_RELAYERS, "relayers limit reached"); - grantRole(RELAYER_ROLE, relayerAddress); - emit RelayerAdded(relayerAddress); - } - - /** - @notice Removes relayer role for {relayerAddress}. - @notice Only callable by an address that currently has the admin role, which is - checked in revokeRole(). - @param relayerAddress Address of relayer to be removed. - @notice Emits {RelayerRemoved} event. - */ - function adminRemoveRelayer(address relayerAddress) external { - require(hasRole(RELAYER_ROLE, relayerAddress), "addr doesn't have relayer role!"); - revokeRole(RELAYER_ROLE, relayerAddress); - emit RelayerRemoved(relayerAddress); - } - /** @notice Sets a new resource for handler contracts that use the IERCHandler interface, and maps the {handlerAddress} to {resourceID} in {_resourceIDToHandlerAddress}. @@ -292,30 +186,6 @@ contract Bridge is Pausable, AccessControl, SafeMath { isValidForwarder[forwarder] = valid; } - /** - @notice Returns a proposal. - @param originDomainID Chain ID deposit originated from. - @param depositNonce ID of proposal generated by proposal's origin Bridge contract. - @param dataHash Hash of data to be provided when deposit proposal is executed. - @return Proposal which consists of: - - _dataHash Hash of data to be provided when deposit proposal is executed. - - _yesVotes Number of votes in favor of proposal. - - _noVotes Number of votes against proposal. - - _status Current status of proposal. - */ - function getProposal(uint8 originDomainID, uint64 depositNonce, bytes32 dataHash) external view returns (Proposal memory) { - uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(originDomainID); - return _proposals[nonceAndID][dataHash]; - } - - /** - @notice Returns total relayers number. - @notice Added for backwards compatibility. - */ - function _totalRelayers() public view returns (uint) { - return AccessControl.getRoleMemberCount(RELAYER_ROLE); - } - /** @notice Changes deposit fee handler contract address. @notice Only callable by admin. @@ -352,6 +222,8 @@ contract Bridge is Pausable, AccessControl, SafeMath { - GenericHandler: responds with the raw bytes returned from the call to the target contract. */ function deposit(uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external payable whenNotPaused { + require(destinationDomainID != _domainID, "Can't deposit to current domain"); + address sender = _msgSender(); if (address(_feeHandler) == address(0)) { require(msg.value == 0, "no FeeHandler, msg.value != 0"); @@ -372,129 +244,70 @@ contract Bridge is Pausable, AccessControl, SafeMath { } /** - @notice When called, {_msgSender()} will be marked as voting in favor of proposal. - @notice Only callable by relayers when Bridge is not paused. - @param domainID ID of chain deposit originated from. - @param depositNonce ID of deposited generated by origin Bridge contract. + @notice Executes a deposit proposal using a specified handler contract (only if signature is signed by MPC). + @param originDomainID ID of chain deposit originated from. + @param resourceID ResourceID to be used when making deposits. + @param depositNonce ID of deposit generated by origin Bridge contract. @param data Data originally provided when deposit was made. - @notice Proposal must not have already been passed or executed. - @notice {_msgSender()} must not have already voted on proposal. - @notice Emits {ProposalEvent} event with status indicating the proposal status. - @notice Emits {ProposalVote} event. + @param signature bytes memory signature composed of MPC key shares + @notice Emits {ProposalExecution} event. */ - function voteProposal(uint8 domainID, uint64 depositNonce, bytes32 resourceID, bytes calldata data) external onlyRelayers whenNotPaused { - address handler = _resourceIDToHandlerAddress[resourceID]; - uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); - bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); - Proposal memory proposal = _proposals[nonceAndID][dataHash]; + function executeProposal(uint8 originDomainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID, bytes calldata signature) public whenNotPaused { + require(isProposalExecuted(originDomainID, depositNonce) != true, "Deposit with provided nonce already executed"); - require(_resourceIDToHandlerAddress[resourceID] != address(0), "no handler for resourceID"); + address signer = keccak256(abi.encodePacked(originDomainID, _domainID, depositNonce, data, resourceID)).recover(signature); + require(signer == _MPCAddress, "Invalid message signer"); - if (proposal._status == ProposalStatus.Passed) { - executeProposal(domainID, depositNonce, data, resourceID, true); - return; - } + address handler = _resourceIDToHandlerAddress[resourceID]; + bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); - address sender = _msgSender(); - - require(uint(proposal._status) <= 1, "proposal already executed/cancelled"); - require(!_hasVoted(proposal, sender), "relayer already voted"); - - if (proposal._status == ProposalStatus.Inactive) { - proposal = Proposal({ - _status : ProposalStatus.Active, - _yesVotes : 0, - _yesVotesTotal : 0, - _proposedBlock : uint40(block.number) // Overflow is desired. - }); - - emit ProposalEvent(domainID, depositNonce, ProposalStatus.Active, dataHash); - } else if (uint40(sub(block.number, proposal._proposedBlock)) > _expiry) { - // if the number of blocks that has passed since this proposal was - // submitted exceeds the expiry threshold set, cancel the proposal - proposal._status = ProposalStatus.Cancelled; - - emit ProposalEvent(domainID, depositNonce, ProposalStatus.Cancelled, dataHash); - } + IDepositExecute depositHandler = IDepositExecute(handler); - if (proposal._status != ProposalStatus.Cancelled) { - proposal._yesVotes = (proposal._yesVotes | _relayerBit(sender)).toUint200(); - proposal._yesVotesTotal++; // TODO: check if bit counting is cheaper. + usedNonces[originDomainID][depositNonce / 256] |= 1 << (depositNonce % 256); - emit ProposalVote(domainID, depositNonce, proposal._status, dataHash); + // Reverts on failure + depositHandler.executeProposal(resourceID, data); - // Finalize if _relayerThreshold has been reached - if (proposal._yesVotesTotal >= _relayerThreshold) { - proposal._status = ProposalStatus.Passed; - emit ProposalEvent(domainID, depositNonce, ProposalStatus.Passed, dataHash); - } - } - _proposals[nonceAndID][dataHash] = proposal; - - if (proposal._status == ProposalStatus.Passed) { - executeProposal(domainID, depositNonce, data, resourceID, false); - } + emit ProposalExecution(originDomainID, depositNonce, dataHash); } /** - @notice Cancels a deposit proposal that has not been executed yet. - @notice Only callable by relayers when Bridge is not paused. - @param domainID ID of chain deposit originated from. - @param depositNonce ID of deposited generated by origin Bridge contract. - @param dataHash Hash of data originally provided when deposit was made. - @notice Proposal must be past expiry threshold. - @notice Emits {ProposalEvent} event with status {Cancelled}. + @notice Once MPC address is set, this method can't be invoked anymore. + It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. */ - function cancelProposal(uint8 domainID, uint64 depositNonce, bytes32 dataHash) public onlyAdminOrRelayer { - uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); - Proposal memory proposal = _proposals[nonceAndID][dataHash]; - ProposalStatus currentStatus = proposal._status; - - require(currentStatus == ProposalStatus.Active || currentStatus == ProposalStatus.Passed, - "Proposal cannot be cancelled"); - require(uint40(sub(block.number, proposal._proposedBlock)) > _expiry, "Proposal not at expiry threshold"); + function startKeygen() external onlyAdmin { + require(_MPCAddress == address(0), "MPC address is already set"); + emit StartKeygen(); + } - proposal._status = ProposalStatus.Cancelled; - _proposals[nonceAndID][dataHash] = proposal; + /** + @notice This method can be called only once, after the MPC address is set Bridge is unpaused. + It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. + @param MPCAddress Address that will be set as MPC address. + */ + function endKeygen(address MPCAddress) external onlyAdmin { + require(MPCAddress != address(0), "MPC address can't be null-address"); + require(_MPCAddress == address(0), "MPC address can't be updated"); + _MPCAddress = MPCAddress; + _unpause(_msgSender()); + emit EndKeygen(); + } - emit ProposalEvent(domainID, depositNonce, ProposalStatus.Cancelled, dataHash); + /** + @notice It's used to trigger the belonging process on the MPC side. + It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. + */ + function refreshKey() external onlyAdmin { + emit KeyRefresh(); } /** - @notice Executes a deposit proposal that is considered passed using a specified handler contract. - @notice Only callable by relayers when Bridge is not paused. + @notice Returns a boolean value. @param domainID ID of chain deposit originated from. - @param resourceID ResourceID to be used when making deposits. - @param depositNonce ID of deposited generated by origin Bridge contract. - @param data Data originally provided when deposit was made. - @param revertOnFail Decision if the transaction should be reverted in case of handler's executeProposal is reverted or not. - @notice Proposal must have Passed status. - @notice Hash of {data} must equal proposal's {dataHash}. - @notice Emits {ProposalEvent} event with status {Executed}. - @notice Emits {FailedExecution} event with the failed reason. + @param depositNonce ID of deposit generated by origin Bridge contract. + @return Boolean value depending if deposit nonce has already been used or not. */ - function executeProposal(uint8 domainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID, bool revertOnFail) public onlyRelayers whenNotPaused { - address handler = _resourceIDToHandlerAddress[resourceID]; - uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); - bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); - Proposal storage proposal = _proposals[nonceAndID][dataHash]; - - require(proposal._status == ProposalStatus.Passed, "Proposal must have Passed status"); - - proposal._status = ProposalStatus.Executed; - IDepositExecute depositHandler = IDepositExecute(handler); - - if (revertOnFail) { - depositHandler.executeProposal(resourceID, data); - } else { - try depositHandler.executeProposal(resourceID, data) { - } catch (bytes memory lowLevelData) { - proposal._status = ProposalStatus.Passed; - emit FailedHandlerExecution(lowLevelData); - return; - } - } - - emit ProposalEvent(domainID, depositNonce, ProposalStatus.Executed, dataHash); + function isProposalExecuted(uint8 domainID, uint256 depositNonce) public view returns (bool) { + return usedNonces[domainID][depositNonce / 256] & (1 << (depositNonce % 256)) != 0; } } diff --git a/contracts/TestContracts.sol b/contracts/TestContracts.sol index 6aeb1342..0dd66e7c 100644 --- a/contracts/TestContracts.sol +++ b/contracts/TestContracts.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -import "./utils/SafeCast.sol"; import "./handlers/HandlerHelpers.sol"; contract NoArgument { @@ -44,13 +43,6 @@ contract WithDepositer { } } -contract SafeCaster { - using SafeCast for *; - - function toUint200(uint input) external pure returns(uint200) { - return input.toUint200(); - } -} contract ReturnData { function returnData(string memory argument) external pure returns(bytes32 response) { diff --git a/contracts/utils/SafeCast.sol b/contracts/utils/SafeCast.sol deleted file mode 100644 index 553c3e1c..00000000 --- a/contracts/utils/SafeCast.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.11; - - -library SafeCast { - function toUint200(uint256 value) internal pure returns (uint200) { - require(value < 2**200, "value does not fit in 200 bits"); - return uint200(value); - } - - function toUint128(uint256 value) internal pure returns (uint128) { - require(value < 2**128, "value does not fit in 128 bits"); - return uint128(value); - } - - function toUint40(uint256 value) internal pure returns (uint40) { - require(value < 2**40, "value does not fit in 40 bits"); - return uint40(value); - } - - function toUint8(uint256 value) internal pure returns (uint8) { - require(value < 2**8, "value does not fit in 8 bits"); - return uint8(value); - } -} diff --git a/contracts/utils/SafeMath.sol b/contracts/utils/SafeMath.sol deleted file mode 100644 index 3bcbb0fb..00000000 --- a/contracts/utils/SafeMath.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.11; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * note that this is a stripped down version of open zeppelin's safemath - * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol - */ - -contract SafeMath { - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return _sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function _sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } -} \ No newline at end of file diff --git a/test/contractBridge/admin.js b/test/contractBridge/admin.js index 0df9e4c7..6e3170a6 100644 --- a/test/contractBridge/admin.js +++ b/test/contractBridge/admin.js @@ -13,87 +13,108 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); const GenericHandlerContract = artifacts.require('GenericHandler'); const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); -// This test does NOT include all getter methods, just +// This test does NOT include all getter methods, just // getters that should work with only the constructor called -contract('Bridge - [admin]', async accounts => { +contract('Bridge - [admin]', async (accounts) => { const domainID = 1; - const initialRelayers = accounts.slice(0, 3); - const initialRelayerThreshold = 2; + const nonAdminAddress = accounts[1]; const expectedBridgeAdmin = accounts[0]; const someAddress = "0xcafecafecafecafecafecafecafecafecafecafe"; + const nullAddress = "0x0000000000000000000000000000000000000000"; + const bytes32 = "0x0"; let ADMIN_ROLE; - + let BridgeInstance; let withdrawData = ''; const assertOnlyAdmin = (method, ...params) => { - return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + return TruffleAssert.reverts(method(...params, {from: nonAdminAddress}), "sender doesn't have admin role"); }; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, 100); - ADMIN_ROLE = await BridgeInstance.DEFAULT_ADMIN_ROLE() + BridgeInstance = await BridgeContract.new(domainID); + ADMIN_ROLE = await BridgeInstance.DEFAULT_ADMIN_ROLE(); }); - // Testing pausable methods + // Testing pauseable methods - it('Bridge should not be paused', async () => { + it('Bridge should not be paused after MPC address is set', async () => { + await BridgeInstance.endKeygen(Helpers.mpcAddress); assert.isFalse(await BridgeInstance.paused()); }); - it('Bridge should be paused', async () => { + it('Bridge should be paused after being paused by admin', async () => { + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); + await TruffleAssert.passes(BridgeInstance.adminPauseTransfers()); assert.isTrue(await BridgeInstance.paused()); }); - it('Bridge should be unpaused after being paused', async () => { + it('Bridge should be unpaused after being paused by admin', async () => { + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); + await TruffleAssert.passes(BridgeInstance.adminPauseTransfers()); assert.isTrue(await BridgeInstance.paused()); await TruffleAssert.passes(BridgeInstance.adminUnpauseTransfers()); assert.isFalse(await BridgeInstance.paused()); }); - // Testing relayer methods + // Testing starKeygen, endKeygen and refreshKey methods + + it('Should successfully emit "StartKeygen" event if called by admin', async () => { + const startKeygenTx = await BridgeInstance.startKeygen(); - it('_relayerThreshold should be initialRelayerThreshold', async () => { - assert.equal(await BridgeInstance._relayerThreshold.call(), initialRelayerThreshold); + TruffleAssert.eventEmitted(startKeygenTx, 'StartKeygen'); }); - it('_relayerThreshold should be initialRelayerThreshold', async () => { - const newRelayerThreshold = 1; - await TruffleAssert.passes(BridgeInstance.adminChangeRelayerThreshold(newRelayerThreshold)); - assert.equal(await BridgeInstance._relayerThreshold.call(), newRelayerThreshold); + it('Should fail if "StartKeygen" is called by non admin', async () => { + await assertOnlyAdmin(BridgeInstance.startKeygen); }); - it('newRelayer should be added as a relayer', async () => { - const newRelayer = accounts[4]; - await TruffleAssert.passes(BridgeInstance.adminAddRelayer(newRelayer)); - assert.isTrue(await BridgeInstance.isRelayer(newRelayer)); + it('Should fail if "StartKeygen" is called after MPC address is set', async () => { + await BridgeInstance.endKeygen(Helpers.mpcAddress); + + await TruffleAssert.reverts(BridgeInstance.startKeygen(), "MPC address is already set"); }); - it('newRelayer should be removed as a relayer after being added', async () => { - const newRelayer = accounts[4]; - await TruffleAssert.passes(BridgeInstance.adminAddRelayer(newRelayer)); - assert.isTrue(await BridgeInstance.isRelayer(newRelayer)) - await TruffleAssert.passes(BridgeInstance.adminRemoveRelayer(newRelayer)); - assert.isFalse(await BridgeInstance.isRelayer(newRelayer)); + it('Should successfully set MPC address and emit "EndKeygen" event if called by admin', async () => { + const startKeygenTx = await BridgeInstance.endKeygen(Helpers.mpcAddress); + + assert.equal(await BridgeInstance._MPCAddress(), Helpers.mpcAddress); + + TruffleAssert.eventEmitted(startKeygenTx, 'EndKeygen'); }); - it('existingRelayer should not be able to be added as a relayer', async () => { - const existingRelayer = accounts[1]; - await TruffleAssert.reverts(BridgeInstance.adminAddRelayer(existingRelayer)); - assert.isTrue(await BridgeInstance.isRelayer(existingRelayer)); - }); + it('Should fail if "endKeygen" is called by non admin', async () => { + await assertOnlyAdmin(BridgeInstance.endKeygen, someAddress); + }); - it('nonRelayerAddr should not be able to be added as a relayer', async () => { - const nonRelayerAddr = accounts[4]; - await TruffleAssert.reverts(BridgeInstance.adminRemoveRelayer(nonRelayerAddr)); - assert.isFalse(await BridgeInstance.isRelayer(nonRelayerAddr)); + it('Should fail if null address is passed as MPC address', async () => { + await TruffleAssert.reverts(BridgeInstance.endKeygen(nullAddress), "MPC address can't be null-address"); }); + it('Should fail if admin tries to updated MPC address', async () => { + await BridgeInstance.endKeygen(Helpers.mpcAddress); + + await TruffleAssert.reverts(BridgeInstance.endKeygen(someAddress), "MPC address can't be updated"); + }); + + it('Should successfully emit "KeyRefresh" event if called by admin', async () => { + const startKeygenTx = await BridgeInstance.refreshKey(); + + TruffleAssert.eventEmitted(startKeygenTx, 'KeyRefresh'); + }); + + it('Should fail if "refreshKey" is called by non admin', async () => { + await assertOnlyAdmin(BridgeInstance.refreshKey); + }); + + // Testing ownership methods it('Bridge admin should be expectedBridgeAdmin', async () => { @@ -173,7 +194,7 @@ contract('Bridge - [admin]', async accounts => { it('Should withdraw funds', async () => { const numTokens = 10; const tokenOwner = accounts[0]; - + let ownerBalance; let handlerBalance; @@ -186,7 +207,7 @@ contract('Bridge - [admin]', async accounts => { await ERC20MintableInstance.mint(tokenOwner, numTokens); ownerBalance = await ERC20MintableInstance.balanceOf(tokenOwner); assert.equal(ownerBalance, numTokens); - + await ERC20MintableInstance.transfer(ERC20HandlerInstance.address, numTokens); ownerBalance = await ERC20MintableInstance.balanceOf(tokenOwner); @@ -195,7 +216,7 @@ contract('Bridge - [admin]', async accounts => { assert.equal(handlerBalance, numTokens); withdrawData = Helpers.createERCWithdrawData(ERC20MintableInstance.address, tokenOwner, numTokens); - + await BridgeInstance.adminWithdraw(ERC20HandlerInstance.address, withdrawData); ownerBalance = await ERC20MintableInstance.balanceOf(tokenOwner); assert.equal(ownerBalance, numTokens); diff --git a/test/contractBridge/cancelDepositProposal.js b/test/contractBridge/cancelDepositProposal.js deleted file mode 100644 index cce13163..00000000 --- a/test/contractBridge/cancelDepositProposal.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); - -contract('Bridge - [voteProposal with relayerThreshold == 3]', async (accounts) => { - const originDomainID = 1; - const destinationDomainID = 2; - const relayer1Address = accounts[0]; - const relayer2Address = accounts[1]; - const relayer3Address = accounts[2]; - const relayer4Address = accounts[3]; - const relayer1Bit = 1 << 0; - const relayer2Bit = 1 << 1; - const relayer3Bit = 1 << 2; - const destinationChainRecipientAddress = accounts[4]; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 3; - - let BridgeInstance; - let DestinationERC20MintableInstance; - let DestinationERC20HandlerInstance; - let depositData = ''; - let depositDataHash = ''; - let resourceID = ''; - - let vote, executeProposal; - - beforeEach(async () => { - await Promise.all([ - BridgeContract.new(destinationDomainID, [ - relayer1Address, - relayer2Address, - relayer3Address, - relayer4Address], - relayerThreshold, - 10,).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, originDomainID); - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - await TruffleAssert.passes(BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address)); - await TruffleAssert.passes(BridgeInstance.adminSetBurnable(DestinationERC20HandlerInstance.address, DestinationERC20MintableInstance.address)); - - depositData = Helpers.createERCDepositData(depositAmount, 20, destinationChainRecipientAddress); - depositDataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + depositData.substr(2)); - - await Promise.all([ - DestinationERC20MintableInstance.grantRole(await DestinationERC20MintableInstance.MINTER_ROLE(), DestinationERC20HandlerInstance.address), - BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address) - ]); - - vote = (relayer) => BridgeInstance.voteProposal(originDomainID, expectedDepositNonce, resourceID, depositData, { from: relayer }); - executeProposal = (relayer) => BridgeInstance.executeProposal(originDomainID, expectedDepositNonce, depositData, { from: relayer }); - }); - - it ('[sanity] bridge configured with threshold, relayers, and expiry', async () => { - assert.equal(await BridgeInstance._domainID(), destinationDomainID) - - assert.equal(await BridgeInstance._relayerThreshold(), relayerThreshold) - - assert.equal((await BridgeInstance._totalRelayers()).toString(), '4') - - assert.equal(await BridgeInstance._expiry(), 10) - }) - - it('[sanity] depositProposal should be created with expected values', async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - const expectedDepositProposal = { - _yesVotes: relayer1Bit.toString(), - _yesVotesTotal: '1', - _status: '1' // Active - }; - - const depositProposal = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - }); - - - it("voting on depositProposal after threshold results in cancelled proposal", async () => { - - - await TruffleAssert.passes(vote(relayer1Address)); - - for (i=0; i<10; i++) { - await Helpers.advanceBlock(); - } - - await TruffleAssert.passes(vote(relayer2Address)); - - const expectedDepositProposal = { - _yesVotes: relayer1Bit.toString(), - _yesVotesTotal: '1', - _status: '4' // Cancelled - }; - - const depositProposal = await BridgeInstance.getProposal(originDomainID, expectedDepositNonce, depositDataHash); - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - await TruffleAssert.reverts(vote(relayer3Address), "proposal already executed/cancelled.") - }); - - - it("relayer can cancel proposal after threshold blocks have passed", async () => { - await TruffleAssert.passes(vote(relayer2Address)); - - for (i=0; i<10; i++) { - await Helpers.advanceBlock(); - } - - const expectedDepositProposal = { - _yesVotes: relayer2Bit.toString(), - _yesVotesTotal: '1', - _status: '4' // Cancelled - }; - - await TruffleAssert.passes(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash)) - const depositProposal = await BridgeInstance.getProposal(originDomainID, expectedDepositNonce, depositDataHash); - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - await TruffleAssert.reverts(vote(relayer4Address), "proposal already executed/cancelled.") - }); - - it("relayer cannot cancel proposal before threshold blocks have passed", async () => { - await TruffleAssert.passes(vote(relayer2Address)); - - await TruffleAssert.reverts(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash), "Proposal not at expiry threshold") - }); - - it("admin can cancel proposal after threshold blocks have passed", async () => { - await TruffleAssert.passes(vote(relayer3Address)); - - for (i=0; i<10; i++) { - await Helpers.advanceBlock(); - } - - const expectedDepositProposal = { - _yesVotes: relayer3Bit.toString(), - _yesVotesTotal: '1', - _status: '4' // Cancelled - }; - - await TruffleAssert.passes(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash)) - const depositProposal = await BridgeInstance.getProposal(originDomainID, expectedDepositNonce, depositDataHash); - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - await TruffleAssert.reverts(vote(relayer2Address), "proposal already executed/cancelled.") - }); - - it("proposal cannot be cancelled twice", async () => { - await TruffleAssert.passes(vote(relayer3Address)); - - for (i=0; i<10; i++) { - await Helpers.advanceBlock(); - } - - await TruffleAssert.passes(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash)) - await TruffleAssert.reverts(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash), "Proposal cannot be cancelled") - }); - - it("inactive proposal cannot be cancelled", async () => { - await TruffleAssert.reverts(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash), "Proposal cannot be cancelled") - }); - - it("executed proposal cannot be cancelled", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - await TruffleAssert.passes(vote(relayer2Address)); - await TruffleAssert.passes(vote(relayer3Address)); // After this vote, automatically executes the proposal. - - await TruffleAssert.reverts(BridgeInstance.cancelProposal(originDomainID, expectedDepositNonce, depositDataHash), "Proposal cannot be cancelled") - }); - -}); diff --git a/test/contractBridge/constructor.js b/test/contractBridge/constructor.js deleted file mode 100644 index 4796507f..00000000 --- a/test/contractBridge/constructor.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ -const TruffleAssert = require('truffle-assertions'); - -const BridgeContract = artifacts.require("Bridge"); - -contract('Bridge - [constructor]', async accounts => { - const domainID = 1; - const initialRelayers = accounts.slice(0, 3); - const initialRelayerThreshold = 2; - - const expectedBridgeAdmin = accounts[0]; - const someAddress = "0xcafecafecafecafecafecafecafecafecafecafe"; - const bytes32 = "0x0"; - - const BN = (num) => { - return web3.utils.toBN(num); - }; - - it('Bridge should not allow to set initialRelayerThreshold above 255', async () => { - return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, 256, 100), "value does not fit in 8 bits"); - }); - - it('Bridge should not allow to set expiry above 2**40 - 1', async () => { - return TruffleAssert.fails(BridgeContract.new(domainID, initialRelayers, initialRelayerThreshold, BN(2).pow(BN(40))), "value does not fit in 40 bits"); - }); -}); diff --git a/test/contractBridge/createDepositProposal.js b/test/contractBridge/createDepositProposal.js deleted file mode 100644 index 5b0cf3b7..00000000 --- a/test/contractBridge/createDepositProposal.js +++ /dev/null @@ -1,274 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); - -contract('Bridge - [create a deposit proposal (voteProposal) with relayerThreshold = 1]', async (accounts) => { - const originChainRelayerAddress = accounts[1]; - const originChainRelayerBit = 1 << 0; - const depositerAddress = accounts[2]; - const destinationRecipientAddress = accounts[3]; - const originDomainID = 1; - const destinationDomainID = 2; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 1; - const expectedCreateEventStatus = 1; - - let BridgeInstance; - let DestinationERC20MintableInstance; - let resourceID; - let data = ''; - let dataHash = ''; - - beforeEach(async () => { - await Promise.all([ - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance), - BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 100).then(instance => BridgeInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, destinationDomainID); - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - - await BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address); - - data = Helpers.createERCDepositData( - depositAmount, - 20, - destinationRecipientAddress); - dataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + data.substr(2)); - }); - - it('should create depositProposal successfully', async () => { - await TruffleAssert.passes(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - }); - - it('should revert because depositerAddress is not a relayer', async () => { - await TruffleAssert.reverts(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: depositerAddress } - )); - }); - - it("depositProposal shouldn't be created if it has an Active status", async () => { - await TruffleAssert.passes(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - - await TruffleAssert.reverts(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - }); - - it("getProposal should be called successfully", async () => { - await TruffleAssert.passes(BridgeInstance.getProposal( - destinationDomainID, expectedDepositNonce, dataHash - )); - }); - - it('depositProposal should be created with expected values', async () => { - const expectedDepositProposal = { - _yesVotes: originChainRelayerBit.toString(), - _yesVotesTotal: '1', - _status: '2' // passed - }; - - await BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - - const depositProposal = await BridgeInstance.getProposal( - destinationDomainID, expectedDepositNonce, dataHash); - Helpers.assertObjectsMatch(expectedDepositProposal, Object.assign({}, depositProposal)); - }); - - it('originChainRelayerAddress should be marked as voted for proposal', async () => { - await BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - const hasVoted = await BridgeInstance._hasVotedOnProposal.call( - Helpers.nonceAndId(expectedDepositNonce, destinationDomainID), dataHash, originChainRelayerAddress); - assert.isTrue(hasVoted); - }); - - it('DepositProposalCreated event should be emitted with expected values', async () => { - const proposalTx = await BridgeInstance.voteProposal( - originDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - - TruffleAssert.eventEmitted(proposalTx, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedCreateEventStatus && - event.dataHash === dataHash - }); - }); -}); - -contract('Bridge - [create a deposit proposal (voteProposal) with relayerThreshold > 1]', async (accounts) => { - // const minterAndRelayer = accounts[0]; - const originChainRelayerAddress = accounts[1]; - const originChainRelayerBit = 1 << 0; - const depositerAddress = accounts[2]; - const destinationRecipientAddress = accounts[3]; - const originDomainID = 1; - const destinationDomainID = 2; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 2; - const expectedCreateEventStatus = 1; - - - let BridgeInstance; - let DestinationERC20MintableInstance; - let DestinationERC20HandlerInstance; - let resourceID; - let data = ''; - let dataHash = ''; - - beforeEach(async () => { - await Promise.all([ - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance), - BridgeContract.new(originDomainID, [originChainRelayerAddress], relayerThreshold, 100).then(instance => BridgeInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, destinationDomainID); - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - - await BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address); - - data = Helpers.createERCDepositData( - depositAmount, - 20, - destinationRecipientAddress); - dataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + data.substr(2)); - }); - - it('should create depositProposal successfully', async () => { - await TruffleAssert.passes(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - }); - - it('should revert because depositerAddress is not a relayer', async () => { - await TruffleAssert.reverts(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: depositerAddress } - )); - }); - - it("depositProposal shouldn't be created if it has an Active status", async () => { - await TruffleAssert.passes(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - - await TruffleAssert.reverts(BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - )); - }); - - it('depositProposal should be created with expected values', async () => { - const expectedDepositProposal = { - _yesVotes: originChainRelayerBit.toString(), - _yesVotesTotal: '1', - _status: '1' // active - }; - - await BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - - const depositProposal = await BridgeInstance.getProposal( - destinationDomainID, expectedDepositNonce, dataHash); - Helpers.assertObjectsMatch(expectedDepositProposal, Object.assign({}, depositProposal)); - }); - - it('originChainRelayerAddress should be marked as voted for proposal', async () => { - await BridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - const hasVoted = await BridgeInstance._hasVotedOnProposal.call( - Helpers.nonceAndId(expectedDepositNonce, destinationDomainID), dataHash, originChainRelayerAddress); - assert.isTrue(hasVoted); - }); - - it('DepositProposalCreated event should be emitted with expected values', async () => { - const proposalTx = await BridgeInstance.voteProposal( - originDomainID, - expectedDepositNonce, - resourceID, - data, - { from: originChainRelayerAddress } - ); - - TruffleAssert.eventEmitted(proposalTx, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedCreateEventStatus && - event.dataHash === dataHash - }); - }); -}); \ No newline at end of file diff --git a/test/contractBridge/depositERC1155.js b/test/contractBridge/depositERC1155.js index d72a0a98..c68afd0a 100644 --- a/test/contractBridge/depositERC1155.js +++ b/test/contractBridge/depositERC1155.js @@ -14,14 +14,14 @@ const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('Bridge - [deposit - ERC1155]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; - const relayerThreshold = 0; const depositerAddress = accounts[1]; + const originChainTokenID = 42; const originChainInitialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; const feeData = '0x'; - + let BridgeInstance; let OriginERC1155MintableInstance; let OriginERC1155HandlerInstance; @@ -30,10 +30,10 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 100) + BridgeInstance = await BridgeContract.new(originDomainID) ]); - - + + resourceID = Helpers.createResourceID(OriginERC1155MintableInstance.address, originDomainID); OriginERC1155HandlerInstance = await ERC1155HandlerContract.new(BridgeInstance.address); @@ -45,6 +45,10 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { await OriginERC1155MintableInstance.setApprovalForAll(OriginERC1155HandlerInstance.address, true, { from: depositerAddress }); depositData = Helpers.createERC1155DepositData([originChainTokenID], [depositAmount]); + + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] test depositerAddress' balance", async () => { @@ -129,4 +133,8 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { it('deposit requires resourceID that is mapped to a handler', async () => { await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "resourceID not mapped to handler"); }); + + it('Deposit destination domain can not be current bridge domain ', async () => { + await TruffleAssert.reverts(BridgeInstance.deposit(originDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "Can't deposit to current domain"); + }); }); diff --git a/test/contractBridge/depositERC20.js b/test/contractBridge/depositERC20.js index 33ff5a03..bc8dc9ca 100644 --- a/test/contractBridge/depositERC20.js +++ b/test/contractBridge/depositERC20.js @@ -14,14 +14,14 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('Bridge - [deposit - ERC20]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; - const relayerThreshold = 0; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const originChainInitialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; const feeData = '0x'; - + let BridgeInstance; let OriginERC20MintableInstance; let OriginERC20HandlerInstance; @@ -30,7 +30,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID, [], relayerThreshold, 100), + BridgeInstance = await BridgeContract.new(originDomainID) ]); resourceID = Helpers.createResourceID(OriginERC20MintableInstance.address, originDomainID); @@ -47,6 +47,10 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { depositAmount, 20, recipientAddress); + + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] test depositerAddress' balance", async () => { @@ -131,4 +135,8 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { it('deposit requires resourceID that is mapped to a handler', async () => { await TruffleAssert.reverts(BridgeInstance.deposit(destinationDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "resourceID not mapped to handler"); }); + + it('Deposit destination domain can not be current bridge domain ', async () => { + await TruffleAssert.reverts(BridgeInstance.deposit(originDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "Can't deposit to current domain"); + }); }); diff --git a/test/contractBridge/depositERC721.js b/test/contractBridge/depositERC721.js index cfc062d7..9724c26a 100644 --- a/test/contractBridge/depositERC721.js +++ b/test/contractBridge/depositERC721.js @@ -16,11 +16,12 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const originChainTokenID = 42; const expectedDepositNonce = 1; const genericBytes = '0x736f796c656e745f677265656e5f69735f70656f706c65'; const feeData = '0x'; - + let BridgeInstance; let OriginERC721MintableInstance; let OriginERC721HandlerInstance; @@ -31,9 +32,9 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), - BridgeContract.new(originDomainID, [], 0, 100).then(instance => BridgeInstance = instance) + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance) ]); - + originResourceID = Helpers.createResourceID(OriginERC721MintableInstance.address, originDomainID); await Promise.all([ @@ -45,13 +46,16 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { BridgeInstance.adminSetResource(OriginERC721HandlerInstance.address, originResourceID, OriginERC721MintableInstance.address), OriginERC721MintableInstance.mint(depositerAddress, originChainTokenID, genericBytes) ]); - + await OriginERC721MintableInstance.approve(OriginERC721HandlerInstance.address, originChainTokenID, { from: depositerAddress }); depositData = Helpers.createERCDepositData( originChainTokenID, 20, recipientAddress); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] test depositerAddress' balance", async () => { @@ -119,17 +123,21 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { feeData, { from: depositerAddress } ); - + let expectedMetaData = Ethers.utils.hexlify(Ethers.utils.toUtf8Bytes(genericBytes)); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === originResourceID.toLowerCase() && - event.depositNonce.toNumber() === expectedDepositNonce && + event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && event.data === depositData.toLowerCase() && event.handlerResponse === expectedMetaData }); }); -}); \ No newline at end of file + + it('Deposit destination domain can not be current bridge domain ', async () => { + await TruffleAssert.reverts(BridgeInstance.deposit(originDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "Can't deposit to current domain"); + }); +}); diff --git a/test/contractBridge/depositGeneric.js b/test/contractBridge/depositGeneric.js index 38f91ca8..cc5e18bd 100644 --- a/test/contractBridge/depositGeneric.js +++ b/test/contractBridge/depositGeneric.js @@ -11,12 +11,13 @@ const BridgeContract = artifacts.require("Bridge"); const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); const GenericHandlerContract = artifacts.require("GenericHandler"); -contract('Bridge - [deposit - Generic]', async () => { +contract('Bridge - [deposit - Generic]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; const expectedDepositNonce = 1; const feeData = '0x'; - + const depositerAddress = accounts[1]; + let BridgeInstance; let GenericHandlerInstance; let depositData; @@ -29,9 +30,9 @@ contract('Bridge - [deposit - Generic]', async () => { beforeEach(async () => { await Promise.all([ CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), - BridgeInstance = BridgeContract.new(originDomainID, [], 0, 100).then(instance => BridgeInstance = instance) + BridgeInstance = BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance) ]); - + resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID) initialResourceIDs = [resourceID]; initialContractAddresses = [CentrifugeAssetInstance.address]; @@ -41,10 +42,13 @@ contract('Bridge - [deposit - Generic]', async () => { GenericHandlerInstance = await GenericHandlerContract.new( BridgeInstance.address); - + await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialDepositFunctionDepositerOffsets[0], initialExecuteFunctionSignatures[0]); depositData = Helpers.createGenericDepositData('0xdeadbeef'); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('Generic deposit can be made', async () => { @@ -82,4 +86,8 @@ contract('Bridge - [deposit - Generic]', async () => { event.depositNonce.toNumber() === expectedDepositNonce }); }); -}); \ No newline at end of file + + it('Deposit destination domain can not be current bridge domain ', async () => { + await TruffleAssert.reverts(BridgeInstance.deposit(originDomainID, '0x0', depositData, feeData, { from: depositerAddress }), "Can't deposit to current domain"); + }); +}); diff --git a/test/contractBridge/executeProposal.js b/test/contractBridge/executeProposal.js new file mode 100644 index 00000000..f2ddadd0 --- /dev/null +++ b/test/contractBridge/executeProposal.js @@ -0,0 +1,179 @@ +/** + * Copyright 2020 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require('truffle-assertions'); +const Ethers = require('ethers'); + +const Helpers = require('../helpers'); + +const BridgeContract = artifacts.require("Bridge"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); + +contract('Bridge - [execute proposal]', async (accounts) => { + const originDomainID = 1; + const destinationDomainID = 2; + + const depositerAddress = accounts[1]; + const recipientAddress = accounts[2]; + const relayer1Address = accounts[3]; + + + const initialTokenAmount = 100; + const depositAmount = 10; + const expectedDepositNonce = 1; + const feeData = '0x'; + + let BridgeInstance; + let ERC20MintableInstance; + let ERC20HandlerInstance; + + let resourceID; + let depositData; + let depositProposalData; + let depositProposalDataHash; + + let data = ''; + let dataHash = ''; + + beforeEach(async () => { + await Promise.all([ + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ]); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, destinationDomainID); + + initialResourceIDs = [resourceID]; + initialContractAddresses = [ERC20MintableInstance.address]; + burnableContractAddresses = []; + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + + await Promise.all([ + ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + ]); + + data = Helpers.createERCDepositData( + depositAmount, + 20, + recipientAddress); + dataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + data.substr(2)); + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); + + depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); + depositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) + depositProposalDataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + depositProposalData.substr(2)); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); + }); + + it("isProposalExecuted returns false if depositNonce is not used", async () => { + const destinationDomainID = await BridgeInstance._domainID(); + + assert.isFalse(await BridgeInstance.isProposalExecuted(destinationDomainID, expectedDepositNonce)); + }); + + it('should create and execute executeProposal successfully', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + depositProposalData, + resourceID, + proposalSignedData, + { from: relayer1Address } + )); + + // check that deposit nonce has been marked as used in bitmap + assert.isTrue(await BridgeInstance.isProposalExecuted(originDomainID, expectedDepositNonce)); + + // check that tokens are transferred to recipient address + const recipientBalance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientBalance.toNumber(), depositAmount); + }); + + it('should fail to executeProposal if deposit nonce is already used', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + depositProposalData, + resourceID, + proposalSignedData, + { from: relayer1Address } + )); + + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + depositProposalData, + resourceID, + proposalSignedData, + { from: relayer1Address } + ), "Deposit with provided nonce already executed"); + }); + + it('executeProposal event should be emitted with expected values', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + )); + + const proposalTx = await BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + depositProposalData, + resourceID, + proposalSignedData, + { from: relayer1Address } + ); + + TruffleAssert.eventEmitted(proposalTx, 'ProposalExecution', (event) => { + return event.originDomainID.toNumber() === originDomainID && + event.depositNonce.toNumber() === expectedDepositNonce && + event.dataHash === dataHash + }); + + // check that deposit nonce has been marked as used in bitmap + assert.isTrue(await BridgeInstance.isProposalExecuted(originDomainID, expectedDepositNonce)); + + // check that tokens are transferred to recipient address + const recipientBalance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientBalance.toNumber(), depositAmount); + }); +}); diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index 19eeb24c..256293be 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -8,8 +8,8 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("HandlerRevert"); contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -28,165 +28,55 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { let depositProposalData; let depositProposalDataHash; - const STATUS = { - Inactive : '0', - Active : '1', - Passed : '2', - Executed : '3', - Cancelled : '4' - } - beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); - + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); await Promise.all([ ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) ]); - - await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); + + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, 5000, { from: depositerAddress }); depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) depositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) depositProposalDataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + depositProposalData.substr(2)); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("Should revert if handler execute is reverted", async () => { - const revertOnFail = true; - - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer1Address } - )); + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - )); + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); - const depositProposalBeforeFailedExecute = await BridgeInstance.getProposal( - domainID, expectedDepositNonce, depositProposalDataHash); + const proposalSignedData = await Helpers.signDataWithMpc( + originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID + ); await TruffleAssert.reverts(BridgeInstance.executeProposal( - domainID, + originDomainID, expectedDepositNonce, depositProposalData, resourceID, - revertOnFail, + proposalSignedData, { from: relayer2Address } )); - const depositProposalAfterFailedExecute = await BridgeInstance.getProposal( - domainID, expectedDepositNonce, depositProposalDataHash); - - assert.deepInclude(Object.assign({}, depositProposalBeforeFailedExecute), depositProposalAfterFailedExecute); - }); - - it("Should not revert even though handler execute is reverted if the proposal's status is changed to Passed during voting. FailedHandlerExecution event should be emitted with expected values. Proposal status still stays on Passed", async () => { - - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer1Address } - )); - - const voteWithExecuteTx = await BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - ); - - TruffleAssert.eventEmitted(voteWithExecuteTx, 'FailedHandlerExecution', (event) => { - return Ethers.utils.parseBytes32String('0x' + event.lowLevelData.slice(-64)) === 'Something bad happened' - }); - - const depositProposalAfterFailedExecute = await BridgeInstance.getProposal( - domainID, expectedDepositNonce, depositProposalDataHash); - - assert.strictEqual(depositProposalAfterFailedExecute._status, STATUS.Passed); - }); - - it("Vote proposal should be reverted if handler execution is reverted and proposal status was on Passed for vote", async () => { - - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer1Address } - )); - - // After this vote, automatically executes the proposqal but handler execute is reverted. So proposal still stays on Passed after this vote. - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - )); + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); - await TruffleAssert.reverts(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - ), 'Something bad happened'); + // depositNonce is not used + assert.isFalse(depositProposalAfterFailedExecute); }); - - it("Should execute the proposal successfully if the handler has enough amount after the last execution is reverted", async () => { - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer1Address } - )); - - // After this vote, automatically executes the proposal but the execution is reverted. - // But the whole transaction is not reverted and proposal still be on Passed status. - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - )); - - // Some virtual operation so that the handler can have enough conditions to be executed. - await ERC20HandlerInstance.virtualIncreaseBalance(1); - - // Should execute directly in this vote. - const voteWithExecuteTx = await BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositProposalData, - { from: relayer2Address } - ); - - TruffleAssert.eventEmitted(voteWithExecuteTx, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === domainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toString() === STATUS.Executed && - event.dataHash === depositProposalDataHash - }); - }) }); diff --git a/test/contractBridge/voteDepositProposal.js b/test/contractBridge/voteDepositProposal.js deleted file mode 100644 index 99f28a48..00000000 --- a/test/contractBridge/voteDepositProposal.js +++ /dev/null @@ -1,240 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); - -contract('Bridge - [voteProposal with relayerThreshold == 3]', async (accounts) => { - const originDomainID = 1; - const destinationDomainID = 2; - const relayer1Address = accounts[0]; - const relayer2Address = accounts[1]; - const relayer3Address = accounts[2]; - const relayer4Address = accounts[3]; - const relayer1Bit = 1 << 0; - const relayer2Bit = 1 << 1; - const relayer3Bit = 1 << 2; - const depositerAddress = accounts[4]; - const destinationChainRecipientAddress = accounts[4]; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 3; - const expectedFinalizedEventStatus = 2; - const expectedExecutedEventStatus = 3; - - const STATUS = { - Inactive : '0', - Active : '1', - Passed : '2', - Executed : '3', - Cancelled : '4' - } - - let BridgeInstance; - let DestinationERC20MintableInstance; - let DestinationERC20HandlerInstance; - let depositData = ''; - let depositDataHash = ''; - let resourceID = ''; - let initialResourceIDs; - let initialContractAddresses; - let burnableContractAddresses; - - let vote, executeProposal; - - beforeEach(async () => { - await Promise.all([ - BridgeContract.new(destinationDomainID, [ - relayer1Address, - relayer2Address, - relayer3Address, - relayer4Address], - relayerThreshold, - 100,).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, originDomainID); - initialResourceIDs = [resourceID]; - initialContractAddresses = [DestinationERC20MintableInstance.address]; - burnableContractAddresses = [DestinationERC20MintableInstance.address]; - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - - await TruffleAssert.passes(BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, initialContractAddresses[0])); - await TruffleAssert.passes(BridgeInstance.adminSetBurnable(DestinationERC20HandlerInstance.address, burnableContractAddresses[0])); - - depositData = Helpers.createERCDepositData(depositAmount, 20, destinationChainRecipientAddress); - depositDataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + depositData.substr(2)); - - await Promise.all([ - DestinationERC20MintableInstance.grantRole(await DestinationERC20MintableInstance.MINTER_ROLE(), DestinationERC20HandlerInstance.address), - BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address) - ]); - - vote = (relayer) => BridgeInstance.voteProposal(originDomainID, expectedDepositNonce, resourceID, depositData, { from: relayer }); - executeProposal = (relayer) => BridgeInstance.executeProposal(originDomainID, expectedDepositNonce, depositData, resourceID, { from: relayer }); - }); - - it ('[sanity] bridge configured with threshold and relayers', async () => { - assert.equal(await BridgeInstance._domainID(), destinationDomainID) - - assert.equal(await BridgeInstance._relayerThreshold(), relayerThreshold) - - assert.equal((await BridgeInstance._totalRelayers()).toString(), '4') - }) - - it('[sanity] depositProposal should be created with expected values', async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - const expectedDepositProposal = { - _yesVotes: relayer1Bit.toString(), - _yesVotesTotal: '1', - _status: '1' // Active - }; - - const depositProposal = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - }); - - it("depositProposal should be automatically executed after the vote if proposal status is changed to Passed during the vote", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - await TruffleAssert.passes(vote(relayer2Address)); - - await TruffleAssert.passes(vote(relayer3Address)); // After this vote, automatically executes the proposal. - - const depositProposalAfterThirdVoteWithExecute = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.strictEqual(depositProposalAfterThirdVoteWithExecute._status, STATUS.Executed); // Executed - }); - - it('should revert because depositerAddress is not a relayer', async () => { - await TruffleAssert.reverts(vote(depositerAddress)); - }); - - it("depositProposal shouldn't be voted on if it has a Passed status", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - await TruffleAssert.passes(vote(relayer2Address)); - - await TruffleAssert.passes(vote(relayer3Address)); - - await TruffleAssert.reverts(vote(relayer4Address), 'proposal already executed/cancelled.'); - }); - - it("relayer shouldn't be able to vote on a depositProposal more than once", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - await TruffleAssert.reverts(vote(relayer1Address), 'relayer already voted'); - }); - - it("Should be able to create a proposal with a different hash", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - await TruffleAssert.passes( - BridgeInstance.voteProposal( - originDomainID, expectedDepositNonce, - resourceID, Ethers.utils.keccak256(depositDataHash), - { from: relayer2Address })); - }); - - it("Relayer's vote should be recorded correctly - yes vote", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - const depositProposalAfterFirstVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterFirstVote._yesVotesTotal, 1); - assert.equal(depositProposalAfterFirstVote._yesVotes, relayer1Bit); - assert.strictEqual(depositProposalAfterFirstVote._status, STATUS.Active); - - await TruffleAssert.passes(vote(relayer2Address)); - - const depositProposalAfterSecondVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterSecondVote._yesVotesTotal, 2); - assert.equal(depositProposalAfterSecondVote._yesVotes, relayer1Bit + relayer2Bit); - assert.strictEqual(depositProposalAfterSecondVote._status, STATUS.Active); - - await TruffleAssert.passes(vote(relayer3Address)); // After this vote, automatically executes the proposal. - - const depositProposalAfterThirdVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterThirdVote._yesVotesTotal, 3); - assert.equal(depositProposalAfterThirdVote._yesVotes, relayer1Bit + relayer2Bit + relayer3Bit); - assert.strictEqual(depositProposalAfterThirdVote._status, STATUS.Executed); // Executed - }); - - it("Relayer's address should be marked as voted for proposal", async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - const hasVoted = await BridgeInstance._hasVotedOnProposal.call( - Helpers.nonceAndId(expectedDepositNonce, originDomainID), depositDataHash, relayer1Address); - assert.isTrue(hasVoted); - }); - - it('DepositProposalFinalized event should be emitted when proposal status updated to passed after numYes >= relayerThreshold', async () => { - await TruffleAssert.passes(vote(relayer1Address)); - await TruffleAssert.passes(vote(relayer2Address)); - - const voteTx = await vote(relayer3Address); - - TruffleAssert.eventEmitted(voteTx, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedFinalizedEventStatus && - event.dataHash === depositDataHash - }); - }); - - it('DepositProposalVote event fired when proposal vote made', async () => { - const voteTx = await vote(relayer1Address); - - TruffleAssert.eventEmitted(voteTx, 'ProposalVote', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === 1 - }); - }); - - it('Execution successful', async () => { - await TruffleAssert.passes(vote(relayer1Address)); - - await TruffleAssert.passes(vote(relayer2Address)); - - const voteWithExecuteTx = await vote(relayer3Address); // After this vote, automatically executes the proposal. - - TruffleAssert.eventEmitted(voteWithExecuteTx, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedFinalizedEventStatus && - event.dataHash === depositDataHash - }); - }); - - it('Proposal cannot be executed twice', async () => { - await vote(relayer1Address); - await vote(relayer2Address); - await vote(relayer3Address); // After this vote, automatically executes the proposal. - await TruffleAssert.reverts(executeProposal(relayer1Address), "Proposal must have Passed status"); - }); - - it('Execution requires active proposal', async () => { - await TruffleAssert.reverts(BridgeInstance.executeProposal(originDomainID, expectedDepositNonce, depositData, '0x0', { from: relayer1Address }), "Proposal must have Passed status"); - }); - - it('Voting requires resourceID that is mapped to a handler', async () => { - await TruffleAssert.reverts(BridgeInstance.voteProposal(originDomainID, expectedDepositNonce, '0x0', depositDataHash, { from: relayer1Address }), "no handler for resourceID"); - }); -}); diff --git a/test/contractBridge/voteDepositProposalWithRealForwarder.js b/test/contractBridge/voteDepositProposalWithRealForwarder.js deleted file mode 100644 index 28a4a47e..00000000 --- a/test/contractBridge/voteDepositProposalWithRealForwarder.js +++ /dev/null @@ -1,387 +0,0 @@ -/** - * Copyright 2021 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); -const Wallet = require('ethereumjs-wallet').default; -const ethSigUtil = require('eth-sig-util'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); -const ForwarderContract = artifacts.require("Forwarder"); - -contract('Bridge - [voteProposal through forwarder]', async (accounts) => { - const originDomainID = 1; - const destinationDomainID = 2; - const relayer1 = Wallet.generate(); - const relayer2 = Wallet.generate(); - const relayer3 = Wallet.generate(); - const relayer4 = Wallet.generate(); - const relayer1Address = relayer1.getAddressString(); - const relayer2Address = relayer2.getAddressString(); - const relayer3Address = relayer3.getAddressString(); - const relayer4Address = relayer4.getAddressString(); - const relayer1Bit = 1 << 0; - const relayer2Bit = 1 << 1; - const relayer3Bit = 1 << 2; - const depositer = Wallet.generate(); - const depositerAddress = depositer.getAddressString(); - const destinationChainRecipientAddress = accounts[4]; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 3; - const expectedFinalizedEventStatus = 2; - - const STATUS = { - Inactive : '0', - Active : '1', - Passed : '2', - Executed : '3', - Cancelled : '4' - } - - const name = 'Forwarder'; - const version = '0.0.1'; - - const EIP712Domain = [ - { name: 'name', type: 'string' }, - { name: 'version', type: 'string' }, - { name: 'chainId', type: 'uint256' }, - { name: 'verifyingContract', type: 'address' }, - ]; - - let domain; - const types = { - EIP712Domain, - ForwardRequest: [ - { name: 'from', type: 'address' }, - { name: 'to', type: 'address' }, - { name: 'value', type: 'uint256' }, - { name: 'gas', type: 'uint256' }, - { name: 'nonce', type: 'uint256' }, - { name: 'data', type: 'bytes' }, - ], - } - - let BridgeInstance; - let DestinationERC20MintableInstance; - let DestinationERC20HandlerInstance; - let ForwarderInstance; - let depositData = ''; - let depositDataHash = ''; - let resourceID = ''; - let initialResourceIDs; - let initialContractAddresses; - let burnableContractAddresses; - - let voteCallData, executeCallData; - - beforeEach(async () => { - await Promise.all([ - BridgeContract.new(destinationDomainID, [ - relayer1Address, - relayer2Address, - relayer3Address, - relayer4Address], - relayerThreshold, - 100,).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, originDomainID); - initialResourceIDs = [resourceID]; - initialContractAddresses = [DestinationERC20MintableInstance.address]; - burnableContractAddresses = [DestinationERC20MintableInstance.address]; - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - ForwarderInstance = await ForwarderContract.new(); - - await TruffleAssert.passes(BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, initialContractAddresses[0])); - await TruffleAssert.passes(BridgeInstance.adminSetBurnable(DestinationERC20HandlerInstance.address, burnableContractAddresses[0])); - - depositData = Helpers.createERCDepositData(depositAmount, 20, destinationChainRecipientAddress); - depositDataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + depositData.substr(2)); - - await Promise.all([ - DestinationERC20MintableInstance.grantRole(await DestinationERC20MintableInstance.MINTER_ROLE(), DestinationERC20HandlerInstance.address), - BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address) - ]); - - voteCallData = Helpers.createCallData(BridgeInstance, 'voteProposal', ["uint8", "uint64", "bytes32", "bytes"], [originDomainID, expectedDepositNonce, resourceID, depositData]); - executeCallData = Helpers.createCallData(BridgeInstance, 'executeProposal', ["uint8", "uint64", "bytes", "bytes32", "bool"], [originDomainID, expectedDepositNonce, depositData, resourceID, true]); - await BridgeInstance.adminSetForwarder(ForwarderInstance.address, true); - - const provider = new Ethers.providers.JsonRpcProvider(); - const signer = provider.getSigner(); - - await signer.sendTransaction({to: relayer1Address, value: Ethers.utils.parseEther("0.1")}); - await signer.sendTransaction({to: relayer2Address, value: Ethers.utils.parseEther("0.1")}); - await signer.sendTransaction({to: relayer3Address, value: Ethers.utils.parseEther("0.1")}); - await signer.sendTransaction({to: relayer4Address, value: Ethers.utils.parseEther("0.1")}); - await signer.sendTransaction({to: depositerAddress, value: Ethers.utils.parseEther("0.1")}); - - domain = { - name, - version, - chainId: 1, - verifyingContract: ForwarderInstance.address, - }; - }); - - it ('[sanity] bridge configured with threshold and relayers', async () => { - assert.equal(await BridgeInstance._domainID(), destinationDomainID) - - assert.equal(await BridgeInstance._relayerThreshold(), relayerThreshold) - - assert.equal((await BridgeInstance._totalRelayers()).toString(), '4') - }) - - it('[sanity] depositProposal should be created with expected values after the vote through forwarder', async () => { - const request = { - from: relayer1Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: 0, - data: voteCallData - } - - const sign = ethSigUtil.signTypedMessage( - relayer1.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request - } - } - ) - - await ForwarderInstance.execute(request, sign); - const expectedDepositProposal = { - _yesVotes: relayer1Bit.toString(), - _yesVotesTotal: '1', - _status: '1' // Active - }; - - const depositProposal = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - }); - - it("depositProposal should be automatically executed after the vote if proposal status is changed to Passed during the vote", async () => { - const request1 = { - from: relayer1Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: 0, - data: voteCallData - } - const sign1 = ethSigUtil.signTypedMessage( - relayer1.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request1 - } - } - ) - await ForwarderInstance.execute(request1, sign1); - - const request2 = { - from: relayer2Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: 0, - data: voteCallData - } - const sign2 = ethSigUtil.signTypedMessage( - relayer2.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request2 - } - } - ) - await ForwarderInstance.execute(request2, sign2); - - const request3 = { - from: relayer3Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: 0, - data: voteCallData - } - const sign3 = ethSigUtil.signTypedMessage( - relayer3.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request3 - } - } - ) - await ForwarderInstance.execute(request3, sign3); // After this vote, automatically executes the proposal. - - const depositProposalAfterThirdVoteWithExecute = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.strictEqual(depositProposalAfterThirdVoteWithExecute._status, STATUS.Executed); // Executed - }); - - it('should not create proposal because depositerAddress is not a relayer', async () => { - const request = { - from: depositerAddress, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: 0, - data: voteCallData - } - const sign = ethSigUtil.signTypedMessage( - depositer.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request - } - } - ) - - await ForwarderInstance.execute(request, sign); - - const expectedDepositProposal = { - _yesVotes: '0', - _yesVotesTotal: '0', - _status: '0' - }; - - const depositProposal = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - }); - - it("Relayer's address that used forwarder should be marked as voted for proposal", async () => { - const relayer1_forwarder_nonce = await ForwarderInstance.getNonce(relayer1Address); - const request1 = { - from: relayer1Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: relayer1_forwarder_nonce, - data: voteCallData - } - const sign1 = ethSigUtil.signTypedMessage( - relayer1.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request1 - } - } - ) - await ForwarderInstance.execute(request1, sign1); - - const hasVoted = await BridgeInstance._hasVotedOnProposal.call( - Helpers.nonceAndId(expectedDepositNonce, originDomainID), depositDataHash, relayer1Address); - assert.isTrue(hasVoted); - }); - - it('Execution successful', async () => { - const relayer1_forwarder_nonce = await ForwarderInstance.getNonce(relayer1Address); - const request1 = { - from: relayer1Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: relayer1_forwarder_nonce, - data: voteCallData - } - const sign1 = ethSigUtil.signTypedMessage( - relayer1.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request1 - } - } - ) - await ForwarderInstance.execute(request1, sign1); - - const relayer2_forwarder_nonce = await ForwarderInstance.getNonce(relayer2Address); - const request2 = { - from: relayer2Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: relayer2_forwarder_nonce, - data: voteCallData - } - const sign2 = ethSigUtil.signTypedMessage( - relayer2.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request2 - } - } - ) - await ForwarderInstance.execute(request2, sign2); - - const relayer3_forwarder_nonce = await ForwarderInstance.getNonce(relayer3Address); - const request3 = { - from: relayer3Address, - to: BridgeInstance.address, - value: '0', - gas: '300000', - nonce: relayer3_forwarder_nonce, - data: voteCallData - } - const sign3 = ethSigUtil.signTypedMessage( - relayer3.getPrivateKey(), - { - data: { - types: types, - domain: domain, - primaryType: 'ForwardRequest', - message: request3 - } - } - ) - - const voteWithExecuteTx_Forwarder = await ForwarderInstance.execute(request3, sign3); - const voteWithExecuteTx_Bridge = await TruffleAssert.createTransactionResult(BridgeInstance, voteWithExecuteTx_Forwarder.tx); - - TruffleAssert.eventEmitted(voteWithExecuteTx_Bridge, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedFinalizedEventStatus && - event.dataHash === depositDataHash - }); - }); -}); diff --git a/test/contractBridge/voteDepositProposalWithTestForwarder.js b/test/contractBridge/voteDepositProposalWithTestForwarder.js deleted file mode 100644 index 44f6a1dc..00000000 --- a/test/contractBridge/voteDepositProposalWithTestForwarder.js +++ /dev/null @@ -1,234 +0,0 @@ -/** - * Copyright 2021 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ - -const TruffleAssert = require('truffle-assertions'); -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); -const ForwarderContract = artifacts.require("TestForwarder"); - -contract('Bridge - [voteProposal through forwarder]', async (accounts) => { - const originDomainID = 1; - const destinationDomainID = 2; - const relayer1Address = accounts[0]; - const relayer2Address = accounts[1]; - const relayer3Address = accounts[2]; - const relayer4Address = accounts[3]; - const relayer1Bit = 1 << 0; - const relayer2Bit = 1 << 1; - const relayer3Bit = 1 << 2; - const depositerAddress = accounts[4]; - const destinationChainRecipientAddress = accounts[4]; - const depositAmount = 10; - const expectedDepositNonce = 1; - const relayerThreshold = 3; - const expectedFinalizedEventStatus = 2; - - const STATUS = { - Inactive : '0', - Active : '1', - Passed : '2', - Executed : '3', - Cancelled : '4' - } - - let BridgeInstance; - let DestinationERC20MintableInstance; - let DestinationERC20HandlerInstance; - let ForwarderInstance; - let depositData = ''; - let depositDataHash = ''; - let resourceID = ''; - let initialResourceIDs; - let initialContractAddresses; - let burnableContractAddresses; - - let voteCallData, executeCallData; - - beforeEach(async () => { - await Promise.all([ - BridgeContract.new(destinationDomainID, [ - relayer1Address, - relayer2Address, - relayer3Address, - relayer4Address], - relayerThreshold, - 100,).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) - ]); - - resourceID = Helpers.createResourceID(DestinationERC20MintableInstance.address, originDomainID); - initialResourceIDs = [resourceID]; - initialContractAddresses = [DestinationERC20MintableInstance.address]; - burnableContractAddresses = [DestinationERC20MintableInstance.address]; - - DestinationERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - ForwarderInstance = await ForwarderContract.new(); - - await TruffleAssert.passes(BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, initialContractAddresses[0])); - await TruffleAssert.passes(BridgeInstance.adminSetBurnable(DestinationERC20HandlerInstance.address, burnableContractAddresses[0])); - - depositData = Helpers.createERCDepositData(depositAmount, 20, destinationChainRecipientAddress); - depositDataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + depositData.substr(2)); - - await Promise.all([ - DestinationERC20MintableInstance.grantRole(await DestinationERC20MintableInstance.MINTER_ROLE(), DestinationERC20HandlerInstance.address), - BridgeInstance.adminSetResource(DestinationERC20HandlerInstance.address, resourceID, DestinationERC20MintableInstance.address) - ]); - - voteCallData = Helpers.createCallData(BridgeInstance, 'voteProposal', ["uint8", "uint64", "bytes32", "bytes"], [originDomainID, expectedDepositNonce, resourceID, depositData]); - executeCallData = Helpers.createCallData(BridgeInstance, 'executeProposal', ["uint8", "uint64", "bytes", "bytes32", "bool"], [originDomainID, expectedDepositNonce, depositData, resourceID, true]); - await BridgeInstance.adminSetForwarder(ForwarderInstance.address, true); - }); - - it ('[sanity] bridge configured with threshold and relayers', async () => { - assert.equal(await BridgeInstance._domainID(), destinationDomainID) - - assert.equal(await BridgeInstance._relayerThreshold(), relayerThreshold) - - assert.equal((await BridgeInstance._totalRelayers()).toString(), '4') - }) - - it('[sanity] depositProposal should be created with expected values after the vote through forwarder', async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - const expectedDepositProposal = { - _yesVotes: relayer1Bit.toString(), - _yesVotesTotal: '1', - _status: '1' // Active - }; - - const depositProposal = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.deepInclude(Object.assign({}, depositProposal), expectedDepositProposal); - }); - - it('Calling through invalid forwarder should be reverted', async () => { - let ForwarderInstance2 = await ForwarderContract.new(); - await TruffleAssert.reverts(ForwarderInstance2.execute(voteCallData, BridgeInstance.address, relayer1Address)); - }); - - it("depositProposal should be automatically executed after the vote if proposal status is changed to Passed during the vote", async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); // After this vote, automatically executes the proposal. - - const depositProposalAfterThirdVoteWithExecute = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - - assert.strictEqual(depositProposalAfterThirdVoteWithExecute._status, STATUS.Executed); // Executed - }); - - it('should revert because depositerAddress is not a relayer', async () => { - await TruffleAssert.reverts(ForwarderInstance.execute(voteCallData, BridgeInstance.address, depositerAddress)); - }); - - it("depositProposal shouldn't be voted on if it has a Passed status", async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); - - await TruffleAssert.reverts(ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer4Address)); - }); - - it("relayer shouldn't be able to vote on a depositProposal more than once", async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - await TruffleAssert.reverts(ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address)); - }); - - it("Relayer's vote using forwarder should be recorded correctly - yes vote", async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - - const depositProposalAfterFirstVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterFirstVote._yesVotesTotal, 1); - assert.equal(depositProposalAfterFirstVote._yesVotes, relayer1Bit); - assert.strictEqual(depositProposalAfterFirstVote._status, STATUS.Active); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - - const depositProposalAfterSecondVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterSecondVote._yesVotesTotal, 2); - assert.equal(depositProposalAfterSecondVote._yesVotes, relayer1Bit + relayer2Bit); - assert.strictEqual(depositProposalAfterSecondVote._status, STATUS.Active); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); // After this vote, automatically executes the proposal. - - const depositProposalAfterThirdVote = await BridgeInstance.getProposal( - originDomainID, expectedDepositNonce, depositDataHash); - assert.equal(depositProposalAfterThirdVote._yesVotesTotal, 3); - assert.equal(depositProposalAfterThirdVote._yesVotes, relayer1Bit + relayer2Bit + relayer3Bit); - assert.strictEqual(depositProposalAfterThirdVote._status, STATUS.Executed); // Executed - }); - - it("Relayer's address that used forwarder should be marked as voted for proposal", async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - - const hasVoted = await BridgeInstance._hasVotedOnProposal.call( - Helpers.nonceAndId(expectedDepositNonce, originDomainID), depositDataHash, relayer1Address); - assert.isTrue(hasVoted); - }); - - it('DepositProposalFinalized event should be emitted when proposal status updated to passed after numYes >= relayerThreshold', async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - - const voteTx_Forwarder = await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); - const voteTx_Bridge = await TruffleAssert.createTransactionResult(BridgeInstance, voteTx_Forwarder.tx); - - TruffleAssert.eventEmitted(voteTx_Bridge, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedFinalizedEventStatus && - event.dataHash === depositDataHash - }); - }); - - it('DepositProposalVote event fired when proposal vote made', async () => { - const voteTx_Forwarder = await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - const voteTx_Bridge = await TruffleAssert.createTransactionResult(BridgeInstance, voteTx_Forwarder.tx); - TruffleAssert.eventEmitted(voteTx_Bridge, 'ProposalVote', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === 1 - }); - }); - - it('Execution successful', async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - - const voteWithExecuteTx_Forwarder = await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); - const voteWithExecuteTx_Bridge = await TruffleAssert.createTransactionResult(BridgeInstance, voteWithExecuteTx_Forwarder.tx); - - TruffleAssert.eventEmitted(voteWithExecuteTx_Bridge, 'ProposalEvent', (event) => { - return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.status.toNumber() === expectedFinalizedEventStatus && - event.dataHash === depositDataHash - }); - }); - - it('Proposal cannot be executed twice', async () => { - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer1Address); - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer2Address); - await ForwarderInstance.execute(voteCallData, BridgeInstance.address, relayer3Address); // After this vote, automatically executes the proposal. - await TruffleAssert.reverts(ForwarderInstance.execute(executeCallData, BridgeInstance.address, relayer1Address)); - }); - - it('Execution requires active proposal', async () => { - await TruffleAssert.reverts(ForwarderInstance.execute(executeCallData, BridgeInstance.address, relayer1Address)); - }); -}); diff --git a/test/e2e/erc1155/differentChainsMock.js b/test/e2e/erc1155/differentChainsMock.js index 5dac2290..d099c51b 100644 --- a/test/e2e/erc1155/differentChainsMock.js +++ b/test/e2e/erc1155/differentChainsMock.js @@ -8,21 +8,17 @@ const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('E2E ERC1155 - Two EVM Chains', async accounts => { - const originRelayerThreshold = 2; const originDomainID = 1; - const originRelayer1Address = accounts[3]; - const originRelayer2Address = accounts[4]; - - const destinationRelayerThreshold = 2; const destinationDomainID = 2; - const destinationRelayer1Address = accounts[3]; - const destinationRelayer2Address = accounts[4]; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const originRelayer2Address = accounts[3]; + const destinationRelayer1Address = accounts[4]; + const tokenID = 1; const initialTokenAmount = 100; - const depositAmount = 10; + const depositAmount = 10; const expectedDepositNonce = 1; const feeData = '0x'; @@ -44,17 +40,17 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => DestinationERC1155MintableInstance = instance) ]); - + originResourceID = Helpers.createResourceID(OriginERC1155MintableInstance.address, originDomainID); originInitialResourceIDs = [originResourceID]; originInitialContractAddresses = [OriginERC1155MintableInstance.address]; originBurnableContractAddresses = []; - + destinationResourceID = Helpers.createResourceID(DestinationERC1155MintableInstance.address, originDomainID) destinationInitialResourceIDs = [destinationResourceID]; destinationInitialContractAddresses = [DestinationERC1155MintableInstance.address]; @@ -76,12 +72,16 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { DestinationBridgeInstance.adminSetResource(DestinationERC1155HandlerInstance.address, destinationResourceID, DestinationERC1155MintableInstance.address), DestinationBridgeInstance.adminSetBurnable(DestinationERC1155HandlerInstance.address, destinationBurnableContractAddresses[0]) ]); - + originDepositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); originDepositProposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], recipientAddress, "0x"); destinationDepositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); destinationDepositProposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], depositerAddress, "0x"); + + // set MPC address to unpause the Bridge + await OriginBridgeInstance.endKeygen(Helpers.mpcAddress); + await DestinationBridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] depositerAddress' balance of tokenID should be equal to initialTokenAmount", async () => { @@ -95,6 +95,10 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { }); it("E2E: tokenID of Origin ERC1155 owned by depositAddress to Destination ERC1155 owned by recipientAddress and back again", async () => { + // when signing data, first param is domain from where deposit originated and second is destination + const originProposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, originDepositProposalData, destinationResourceID); + const destinationProposalSignedData = await Helpers.signDataWithMpc(destinationDomainID, originDomainID, expectedDepositNonce, destinationDepositProposalData, originResourceID); + let tokenOwner; let depositerBalance; @@ -112,25 +116,14 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { depositerBalance = await OriginERC1155MintableInstance.balanceOf(depositerAddress, tokenID); assert.strictEqual(depositerBalance.toNumber(), initialTokenAmount - depositAmount); - // // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( + // destinationRelayer1 executes the proposal + await TruffleAssert.passes(DestinationBridgeInstance.executeProposal( originDomainID, expectedDepositNonce, - destinationResourceID, originDepositProposalData, - { from: destinationRelayer1Address } - )); - - // // destinationRelayer2 votes in favor of the deposit proposal - // // because the destinationRelayerThreshold is 2, the deposit proposal will go - // // into a finalized state - // // and then automatically executes the proposal - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( - originDomainID, - expectedDepositNonce, destinationResourceID, - originDepositProposalData, - { from: destinationRelayer2Address } + originProposalSignedData, + { from: destinationRelayer1Address } )); depositerBalance = await OriginERC1155MintableInstance.balanceOf(depositerAddress, tokenID); @@ -154,30 +147,18 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { recipientBalance = await DestinationERC1155MintableInstance.balanceOf(recipientAddress, tokenID); assert.strictEqual(recipientBalance.toNumber(), 0); - // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( + // originRelayer2 executes the proposal + await TruffleAssert.passes(OriginBridgeInstance.executeProposal( destinationDomainID, expectedDepositNonce, - originResourceID, destinationDepositProposalData, - { from: originRelayer1Address } - )); - - // destinationRelayer2 votes in favor of the deposit proposal - // because the destinationRelayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, originResourceID, - destinationDepositProposalData, + destinationProposalSignedData, { from: originRelayer2Address } )); - recipientBalance = await DestinationERC1155MintableInstance.balanceOf(recipientAddress, tokenID); assert.strictEqual(recipientBalance.toNumber(), 0); - + depositerBalance = await OriginERC1155MintableInstance.balanceOf(depositerAddress, tokenID); assert.strictEqual(depositerBalance.toNumber(), initialTokenAmount); }); diff --git a/test/e2e/erc1155/sameChain.js b/test/e2e/erc1155/sameChain.js index 71b03a34..7c4d9abe 100644 --- a/test/e2e/erc1155/sameChain.js +++ b/test/e2e/erc1155/sameChain.js @@ -8,20 +8,20 @@ const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('E2E ERC1155 - Same Chain', async accounts => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; - const relayer2Address = accounts[4]; + const tokenID = 1; const initialTokenAmount = 100; - const depositAmount = 10; + const depositAmount = 10; const expectedDepositNonce = 1; const feeData = '0x'; - + let BridgeInstance; let ERC1155MintableInstance; let ERC1155HandlerInstance; @@ -35,11 +35,11 @@ contract('E2E ERC1155 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC1155MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC1155MintableInstance.address]; burnableContractAddresses = []; @@ -55,6 +55,9 @@ contract('E2E ERC1155 - Same Chain', async accounts => { depositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); proposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], recipientAddress, "0x"); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] depositerAddress' balance should be equal to initialTokenAmount", async () => { @@ -63,9 +66,11 @@ contract('E2E ERC1155 - Same Chain', async accounts => { }); it("depositAmount of Destination ERC1155 should be transferred to recipientAddress", async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, proposalData, resourceID); + // depositerAddress makes initial deposit of depositAmount await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + originDomainID, resourceID, depositData, feeData, @@ -76,25 +81,14 @@ contract('E2E ERC1155 - Same Chain', async accounts => { const handlerBalance = await ERC1155MintableInstance.balanceOf(ERC1155HandlerInstance.address, tokenID); assert.strictEqual(handlerBalance.toNumber(), depositAmount); - // relayer1 creates the deposit proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, + // relayer1 executes the proposal + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, expectedDepositNonce, - resourceID, proposalData, - { from: relayer1Address } - )); - - // relayer2 votes in favor of the deposit proposal - // because the relayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, resourceID, - proposalData, - { from: relayer2Address } + proposalSignedData, + { from: relayer1Address } )); // Assert ERC1155 balance was transferred from depositerAddress @@ -121,7 +115,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { await TruffleAssert.reverts(ERC1155HandlerInstance.withdraw(withdrawData, { from: depositerAddress }), "sender must be bridge contract"); }); - it("Should withdraw funds", async () => { + it("Should withdraw funds", async () => { let depositerBalance; let handlerBalance; let withdrawData; diff --git a/test/e2e/erc20/differentChainsMock.js b/test/e2e/erc20/differentChainsMock.js index fcf4a7cd..2c864ace 100644 --- a/test/e2e/erc20/differentChainsMock.js +++ b/test/e2e/erc20/differentChainsMock.js @@ -8,23 +8,19 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('E2E ERC20 - Two EVM Chains', async accounts => { - const originRelayerThreshold = 2; const originDomainID = 1; const originRelayer1Address = accounts[3]; - const originRelayer2Address = accounts[4]; - - const destinationRelayerThreshold = 2; + const destinationDomainID = 2; const destinationRelayer1Address = accounts[3]; - const destinationRelayer2Address = accounts[4]; - + const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; const feeData = '0x'; - + let OriginBridgeInstance; let OriginERC20MintableInstance; let OriginERC20HandlerInstance; @@ -35,7 +31,7 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { let originInitialResourceIDs; let originInitialContractAddresses; let originBurnableContractAddresses; - + let DestinationBridgeInstance; let DestinationERC20MintableInstance; let DestinationERC20HandlerInstance; @@ -49,8 +45,8 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); @@ -85,12 +81,16 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { originDepositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); originDepositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); originDepositProposalDataHash = Ethers.utils.keccak256(DestinationERC20HandlerInstance.address + originDepositProposalData.substr(2)); - + destinationDepositData = Helpers.createERCDepositData(depositAmount, 20, depositerAddress); destinationDepositProposalData = Helpers.createERCDepositData(depositAmount, 20, depositerAddress); destinationDepositProposalDataHash = Ethers.utils.keccak256(OriginERC20HandlerInstance.address + destinationDepositProposalData.substr(2)); + + // set MPC address to unpause the Bridge + await OriginBridgeInstance.endKeygen(Helpers.mpcAddress); + await DestinationBridgeInstance.endKeygen(Helpers.mpcAddress); }); - + it("[sanity] depositerAddress' balance should be equal to initialTokenAmount", async () => { const depositerBalance = await OriginERC20MintableInstance.balanceOf(depositerAddress); assert.strictEqual(depositerBalance.toNumber(), initialTokenAmount); @@ -101,12 +101,16 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { assert.strictEqual(handlerAllowance.toNumber(), depositAmount); }); - it("[sanity] DestinationERC20HandlerInstance.address should have minterRole for DestinationERC20MintableInstance", async () => { + it("[sanity] DestinationERC20HandlerInstance.address should have minterRole for DestinationERC20MintableInstance", async () => { const isMinter = await DestinationERC20MintableInstance.hasRole(await DestinationERC20MintableInstance.MINTER_ROLE(), DestinationERC20HandlerInstance.address); assert.isTrue(isMinter); }); it("E2E: depositAmount of Origin ERC20 owned by depositAddress to Destination ERC20 owned by recipientAddress and back again", async () => { + // when signing data, first param is domain from where deposit originated and second is destination + const originProposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, originDepositProposalData, destinationResourceID); + const destinationProposalSignedData = await Helpers.signDataWithMpc(destinationDomainID, originDomainID, expectedDepositNonce, destinationDepositProposalData, originResourceID); + let depositerBalance; let recipientBalance; @@ -119,33 +123,21 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { { from: depositerAddress } )); - // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( + // destinationRelayer1 executes the proposal + await TruffleAssert.passes(DestinationBridgeInstance.executeProposal( originDomainID, expectedDepositNonce, - destinationResourceID, originDepositProposalData, - { from: destinationRelayer1Address } - )); - - - // destinationRelayer2 votes in favor of the deposit proposal - // because the destinationRelayerThreshold is 2, the deposit proposal will go - // into a finalized state - // And then automatically executes the proposal. - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( - originDomainID, - expectedDepositNonce, destinationResourceID, - originDepositProposalData, - { from: destinationRelayer2Address } + originProposalSignedData, + { from: destinationRelayer1Address } )); // Assert ERC20 balance was transferred from depositerAddress depositerBalance = await OriginERC20MintableInstance.balanceOf(depositerAddress); assert.strictEqual(depositerBalance.toNumber(), initialTokenAmount - depositAmount, "depositAmount wasn't transferred from depositerAddress"); - + // Assert ERC20 balance was transferred to recipientAddress recipientBalance = await DestinationERC20MintableInstance.balanceOf(recipientAddress); assert.strictEqual(recipientBalance.toNumber(), depositAmount, "depositAmount wasn't transferred to recipientAddress"); @@ -166,35 +158,24 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { { from: recipientAddress } )); - // Recipient should have a balance of 0 (deposit amount - deposit amount) + // Recipient should have a balance of 0 (deposit amount - deposit amount) recipientBalance = await DestinationERC20MintableInstance.balanceOf(recipientAddress); assert.strictEqual(recipientBalance.toNumber(), 0); - // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( + // destinationRelayer1 executes the proposal + await TruffleAssert.passes(OriginBridgeInstance.executeProposal( destinationDomainID, expectedDepositNonce, - originResourceID, destinationDepositProposalData, - { from: originRelayer1Address } - )); - - // destinationRelayer2 votes in favor of the deposit proposal - // because the destinationRelayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, originResourceID, - destinationDepositProposalData, - { from: originRelayer2Address } + destinationProposalSignedData, + { from: originRelayer1Address } )); // Assert ERC20 balance was transferred from recipientAddress recipientBalance = await DestinationERC20MintableInstance.balanceOf(recipientAddress); assert.strictEqual(recipientBalance.toNumber(), 0); - + // Assert ERC20 balance was transferred to recipientAddress depositerBalance = await OriginERC20MintableInstance.balanceOf(depositerAddress); assert.strictEqual(depositerBalance.toNumber(), initialTokenAmount); diff --git a/test/e2e/erc20/sameChain.js b/test/e2e/erc20/sameChain.js index 0d828996..3ba69579 100644 --- a/test/e2e/erc20/sameChain.js +++ b/test/e2e/erc20/sameChain.js @@ -8,13 +8,12 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('E2E ERC20 - Same Chain', async accounts => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; - const relayer2Address = accounts[4]; const initialTokenAmount = 100; const depositAmount = 10; @@ -29,21 +28,14 @@ contract('E2E ERC20 - Same Chain', async accounts => { let depositData; let depositProposalData; let depositProposalDataHash; - let initialResourceIDs; - let initialContractAddresses; - let burnableContractAddresses; beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); - - initialResourceIDs = [resourceID]; - initialContractAddresses = [ERC20MintableInstance.address]; - burnableContractAddresses = []; + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); @@ -51,12 +43,15 @@ contract('E2E ERC20 - Same Chain', async accounts => { ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) ]); - + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) depositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) depositProposalDataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + depositProposalData.substr(2)); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] depositerAddress' balance should be equal to initialTokenAmount", async () => { @@ -70,9 +65,12 @@ contract('E2E ERC20 - Same Chain', async accounts => { }); it("depositAmount of Destination ERC20 should be transferred to recipientAddress", async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID); + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + originDomainID, resourceID, depositData, feeData, @@ -83,25 +81,14 @@ contract('E2E ERC20 - Same Chain', async accounts => { const handlerBalance = await ERC20MintableInstance.balanceOf(ERC20HandlerInstance.address); assert.strictEqual(handlerBalance.toNumber(), depositAmount); - // relayer1 creates the deposit proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, + // relayer2 executes the proposal + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, expectedDepositNonce, - resourceID, depositProposalData, - { from: relayer1Address } - )); - - // relayer2 votes in favor of the deposit proposal - // because the relayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, resourceID, - depositProposalData, - { from: relayer2Address } + proposalSignedData, + { from: relayer1Address } )); // Assert ERC20 balance was transferred from depositerAddress diff --git a/test/e2e/erc721/differentChainsMock.js b/test/e2e/erc721/differentChainsMock.js index 1a38ea04..030c93e1 100644 --- a/test/e2e/erc721/differentChainsMock.js +++ b/test/e2e/erc721/differentChainsMock.js @@ -8,18 +8,14 @@ const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('E2E ERC721 - Two EVM Chains', async accounts => { - const originRelayerThreshold = 2; const originDomainID = 1; - const originRelayer1Address = accounts[3]; - const originRelayer2Address = accounts[4]; - - const destinationRelayerThreshold = 2; const destinationDomainID = 2; - const destinationRelayer1Address = accounts[3]; - const destinationRelayer2Address = accounts[4]; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const originRelayer1Address = accounts[3]; + const destinationRelayer1Address = accounts[4]; + const tokenID = 1; const expectedDepositNonce = 1; const feeData = '0x'; @@ -43,17 +39,17 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID, [originRelayer1Address, originRelayer2Address], originRelayerThreshold, 100).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID, [destinationRelayer1Address, destinationRelayer2Address], destinationRelayerThreshold, 100).then(instance => DestinationBridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => DestinationERC721MintableInstance = instance) ]); - + originResourceID = Helpers.createResourceID(OriginERC721MintableInstance.address, originDomainID); originInitialResourceIDs = [originResourceID]; originInitialContractAddresses = [OriginERC721MintableInstance.address]; originBurnableContractAddresses = []; - + destinationResourceID = Helpers.createResourceID(DestinationERC721MintableInstance.address, originDomainID) destinationInitialResourceIDs = [destinationResourceID]; destinationInitialContractAddresses = [DestinationERC721MintableInstance.address]; @@ -82,6 +78,10 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { destinationDepositData = Helpers.createERCDepositData(tokenID, 20, depositerAddress); destinationDepositProposalData = Helpers.createERC721DepositProposalData(tokenID, 20, depositerAddress, 32, 0) destinationDepositProposalDataHash = Ethers.utils.keccak256(OriginERC721HandlerInstance.address + destinationDepositProposalData.substr(2)); + + // set MPC address to unpause the Bridge + await OriginBridgeInstance.endKeygen(Helpers.mpcAddress); + await DestinationBridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] depositerAddress' should own tokenID", async () => { @@ -100,6 +100,10 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { }); it("E2E: tokenID of Origin ERC721 owned by depositAddress to Destination ERC721 owned by recipientAddress and back again", async () => { + // when signing data, first param is domain from where deposit originated and second is destination + const originProposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, originDepositProposalData, destinationResourceID); + const destinationProposalSignedData = await Helpers.signDataWithMpc(destinationDomainID, originDomainID, expectedDepositNonce, destinationDepositProposalData, originResourceID); + let tokenOwner; // depositerAddress makes initial deposit of tokenID @@ -115,25 +119,14 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { tokenOwner = await OriginERC721MintableInstance.ownerOf(tokenID); assert.strictEqual(OriginERC721HandlerInstance.address, tokenOwner, "OriginERC721HandlerInstance.address does not own tokenID"); - // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( + // destinationRelayer2 executes the proposal + await TruffleAssert.passes(DestinationBridgeInstance.executeProposal( originDomainID, expectedDepositNonce, - destinationResourceID, originDepositProposalData, - { from: destinationRelayer1Address } - )); - - // destinationRelayer2 votes in favor of the deposit proposal - // because the destinationRelayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(DestinationBridgeInstance.voteProposal( - originDomainID, - expectedDepositNonce, destinationResourceID, - originDepositProposalData, - { from: destinationRelayer2Address } + originProposalSignedData, + { from: destinationRelayer1Address } )); // Handler should still own tokenID of OriginERC721MintableInstance @@ -162,25 +155,15 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { // Token should no longer exist TruffleAssert.reverts(DestinationERC721MintableInstance.ownerOf(tokenID), "ERC721: owner query for nonexistent token") - // destinationRelayer1 creates the deposit proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( - destinationDomainID, - expectedDepositNonce, - originResourceID, - destinationDepositProposalData, - { from: originRelayer1Address } - )); - // destinationRelayer2 votes in favor of the deposit proposal - // because the destinationRelayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(OriginBridgeInstance.voteProposal( + // originRelayer executes the proposal + await TruffleAssert.passes(OriginBridgeInstance.executeProposal( destinationDomainID, expectedDepositNonce, - originResourceID, destinationDepositProposalData, - { from: originRelayer2Address } + originResourceID, + destinationProposalSignedData, + { from: originRelayer1Address } )); // Assert Destination tokenID no longer exists diff --git a/test/e2e/erc721/sameChain.js b/test/e2e/erc721/sameChain.js index 48402ede..67bdca0f 100644 --- a/test/e2e/erc721/sameChain.js +++ b/test/e2e/erc721/sameChain.js @@ -8,19 +8,18 @@ const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('E2E ERC721 - Same Chain', async accounts => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; - const relayer2Address = accounts[4]; const tokenID = 1; const depositMetadata = "0xc0ff33"; const expectedDepositNonce = 1; const feeData = '0x'; - + let BridgeInstance; let ERC721MintableInstance; let ERC721HandlerInstance; @@ -35,11 +34,11 @@ contract('E2E ERC721 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [relayer1Address, relayer2Address], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC721MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC721MintableInstance.address]; burnableContractAddresses = []; @@ -56,6 +55,9 @@ contract('E2E ERC721 - Same Chain', async accounts => { depositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); proposalData = Helpers.createERC721DepositProposalData(tokenID, 20, recipientAddress, depositMetadata.length, depositMetadata); depositProposalDataHash = Ethers.utils.keccak256(ERC721HandlerInstance.address + proposalData.substr(2)); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] depositerAddress' should own tokenID", async () => { @@ -71,7 +73,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { it("depositAmount of Destination ERC721 should be transferred to recipientAddress", async () => { // depositerAddress makes initial deposit of depositAmount await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + originDomainID, resourceID, depositData, feeData, @@ -82,25 +84,16 @@ contract('E2E ERC721 - Same Chain', async accounts => { const tokenOwner = await ERC721MintableInstance.ownerOf(tokenID); assert.strictEqual(ERC721HandlerInstance.address, tokenOwner); + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, proposalData, resourceID); + // relayer1 creates the deposit proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, expectedDepositNonce, - resourceID, proposalData, - { from: relayer1Address } - )); - - // relayer2 votes in favor of the deposit proposal - // because the relayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, resourceID, - proposalData, - { from: relayer2Address } + proposalSignedData, + { from: relayer1Address } )); // Assert ERC721 balance was transferred from depositerAddress diff --git a/test/forwarder/forwarder.js b/test/forwarder/forwarder.js index 485061e0..99c4ab60 100644 --- a/test/forwarder/forwarder.js +++ b/test/forwarder/forwarder.js @@ -51,7 +51,7 @@ contract('Forwarder', async (accounts) => { beforeEach(async () => { ForwarderInstance = await ForwarderContract.new(); TestTargetInstance = await TestTargetContract.new(); - + const signer = provider.getSigner(); await signer.sendTransaction({to: relayer1Address, value: Ethers.utils.parseEther("0.1")}); @@ -87,7 +87,7 @@ contract('Forwarder', async (accounts) => { ) }); - it ('In case of invalid request(from), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(from), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer2Address, to: TestTargetInstance.address, @@ -101,7 +101,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('In case of invalid request(to), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(to), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer1Address, to: relayer2Address, @@ -115,7 +115,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('In case of invalid request(value), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(value), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer1Address, to: TestTargetInstance.address, @@ -129,7 +129,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('In case of invalid request(gas), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(gas), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer1Address, to: TestTargetInstance.address, @@ -143,7 +143,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('In case of invalid request(nonce), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(nonce), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer1Address, to: TestTargetInstance.address, @@ -157,7 +157,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('In case of invalid request(data), it should not be verified and should be reverted in executing of the forwarder contract', async () => { + it('In case of invalid request(data), it should not be verified and should be reverted in executing of the forwarder contract', async () => { const request_other = { from: relayer1Address, to: TestTargetInstance.address, @@ -171,7 +171,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign), "MinimalForwarder: signature does not match request"); }); - it ('If signature is valid, but req.from != signer, it should be reverted and should not be verified', async () => { + it('If signature is valid, but req.from != signer, it should be reverted and should not be verified', async () => { const sign_other = ethSigUtil.signTypedMessage( relayer2.getPrivateKey(), { @@ -188,7 +188,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request, sign_other), "MinimalForwarder: signature does not match request"); }); - it ('If signature is valid, but req.nonce != nonce[signer], it should be reverted and should not be verified', async () => { + it('If signature is valid, but req.nonce != nonce[signer], it should be reverted and should not be verified', async () => { const request_other = { from: relayer1Address, to: TestTargetInstance.address, @@ -214,7 +214,7 @@ contract('Forwarder', async (accounts) => { return TruffleAssert.reverts(ForwarderInstance.execute(request_other, sign_other), "MinimalForwarder: signature does not match request"); }); - it ('Execute should succeed even if the call to the target failed', async () => { + it('Execute should succeed even if the call to the target failed', async () => { const new_request = { from: relayer1Address, to: ForwarderInstance.address, @@ -240,7 +240,7 @@ contract('Forwarder', async (accounts) => { assert.equal(result[0], false); }); - it ('Should be failed in case of execute is called with less gas than req.gas', async () => { + it('Should be failed in case of execute is called with less gas than req.gas', async () => { const new_request = { from: relayer3Address, to: TestTargetInstance.address, @@ -266,7 +266,7 @@ contract('Forwarder', async (accounts) => { await TruffleAssert.fails(ForwarderInstance.execute(new_request, new_sign, {gas: 100000})); }); - it ('req.gas should be passed to the target contract', async () => { + it('req.gas should be passed to the target contract', async () => { const requestGas = 100000; const new_request = { from: relayer3Address, @@ -295,7 +295,7 @@ contract('Forwarder', async (accounts) => { assert(availableGas < requestGas); }); - it ('req.data should be passed to the target contract along with the req.from at the end', async () => { + it('req.data should be passed to the target contract along with the req.from at the end', async () => { const requestData = '0x1234'; const new_request = { from: relayer3Address, @@ -323,7 +323,7 @@ contract('Forwarder', async (accounts) => { assert.equal(callData, expectedData); }); - it ('req.value should be passed to the target contract', async () => { + it('req.value should be passed to the target contract', async () => { const request_value = Ethers.utils.parseEther('0.1'); const new_request = { from: relayer3Address, @@ -350,22 +350,22 @@ contract('Forwarder', async (accounts) => { assert.equal((await targetContract_balance).toString(), request_value.toString()); }); - it ('The successful execute can not be replayed again', async () => { + it('The successful execute can not be replayed again', async () => { await ForwarderInstance.execute(request, sign); return TruffleAssert.reverts(ForwarderInstance.execute(request, sign), "MinimalForwarder: signature does not match request"); }); - it ('Only a single call to the target is performed during the execution', async () => { + it('Only a single call to the target is performed during the execution', async () => { await ForwarderInstance.execute(request, sign); const calls = await TestTargetInstance.calls(); assert.equal(calls.toNumber(), 1); }); - it ('In case of request is matched with signature, it should be verified', async () => { + it('In case of request is matched with signature, it should be verified', async () => { assert.equal((await ForwarderInstance.verify(request, sign)), true); }); - it ('In case of request is matched with signature, it should not be reverted and nonce should be increased', async () => { + it('In case of request is matched with signature, it should not be reverted and nonce should be increased', async () => { const nonce_before_execute = await ForwarderInstance.getNonce(relayer1Address); await ForwarderInstance.execute(request, sign); const nonce_after_execute = await ForwarderInstance.getNonce(relayer1Address); diff --git a/test/gasBenchmarks/deployments.js b/test/gasBenchmarks/deployments.js index de2492b5..3f8e071f 100644 --- a/test/gasBenchmarks/deployments.js +++ b/test/gasBenchmarks/deployments.js @@ -15,14 +15,13 @@ const ERC1155SafeContract = artifacts.require("ERC1155Safe"); contract('Gas Benchmark - [contract deployments]', async () => { const domainID = 1; - const relayerThreshold = 1; const centrifugeAssetMinCount = 1; const gasBenchmarks = []; let BridgeInstance; it('Should deploy all contracts and print benchmarks', async () => { - let contractInstances = [await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance)]; + let contractInstances = [await BridgeContract.new(domainID).then(instance => BridgeInstance = instance)]; contractInstances = contractInstances.concat( await Promise.all([ ERC20HandlerContract.new(BridgeInstance.address), diff --git a/test/gasBenchmarks/deposits.js b/test/gasBenchmarks/deposits.js index 188d3948..9fa5bde4 100644 --- a/test/gasBenchmarks/deposits.js +++ b/test/gasBenchmarks/deposits.js @@ -19,10 +19,11 @@ const ThreeArgumentsContract = artifacts.require("ThreeArguments"); const Helpers = require('../helpers'); contract('Gas Benchmark - [Deposits]', async (accounts) => { - const domainID = 1; - const relayerThreshold = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const lenRecipientAddress = 20; const gasBenchmarks = []; @@ -56,7 +57,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { before(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), @@ -67,15 +68,15 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { ThreeArgumentsContract.new().then(instance => ThreeArgumentsInstance = instance) ]); - erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); - erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, domainID); - erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, domainID); - centrifugeAssetResourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, domainID); - noArgumentResourceID = Helpers.createResourceID(NoArgumentInstance.address, domainID); - oneArgumentResourceID = Helpers.createResourceID(OneArgumentInstance.address, domainID); - twoArgumentsResourceID = Helpers.createResourceID(TwoArgumentsInstance.address, domainID); - threeArgumentsResourceID = Helpers.createResourceID(ThreeArgumentsInstance.address, domainID); - + erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); + erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); + centrifugeAssetResourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID); + noArgumentResourceID = Helpers.createResourceID(NoArgumentInstance.address, originDomainID); + oneArgumentResourceID = Helpers.createResourceID(OneArgumentInstance.address, originDomainID); + twoArgumentsResourceID = Helpers.createResourceID(TwoArgumentsInstance.address, originDomainID); + threeArgumentsResourceID = Helpers.createResourceID(ThreeArgumentsInstance.address, originDomainID); + const genericInitialResourceIDs = [ centrifugeAssetResourceID, noArgumentResourceID, @@ -130,11 +131,14 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, twoArgumentsResourceID, genericInitialContractAddresses[3], genericInitialDepositFunctionSignatures[3], genericInitialDepositFunctionDepositerOffsets[3], genericInitialExecuteFunctionSignatures[3]), BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, threeArgumentsResourceID, genericInitialContractAddresses[4], genericInitialDepositFunctionSignatures[4], genericInitialDepositFunctionDepositerOffsets[4], genericInitialExecuteFunctionSignatures[4]) ]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('Should make ERC20 deposit', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, erc20ResourceID, Helpers.createERCDepositData( erc20TokenAmount, @@ -151,7 +155,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { it('Should make ERC721 deposit', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, erc721ResourceID, Helpers.createERCDepositData( erc721TokenID, @@ -168,7 +172,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { it('Should make ERC1155 deposit', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, erc1155ResourceID, Helpers.createERC1155DepositData( [erc1155TokenID], @@ -184,7 +188,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { it('Should make Generic deposit - Centrifuge asset', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, centrifugeAssetResourceID, Helpers.createGenericDepositData('0xc0ff33'), feeData, @@ -199,7 +203,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { it('Should make Generic deposit - No Argument', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, noArgumentResourceID, Helpers.createGenericDepositData(null), feeData, @@ -214,7 +218,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { it('Should make Generic deposit - One Argument', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, oneArgumentResourceID, Helpers.createGenericDepositData(Helpers.toHex(42, 32)), feeData, @@ -232,7 +236,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { const argumentTwo = Helpers.getFunctionSignature(CentrifugeAssetInstance, 'store'); const encodedMetaData = Helpers.abiEncode(['address[]','bytes4'], [argumentOne, argumentTwo]); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, twoArgumentsResourceID, Helpers.createGenericDepositData(encodedMetaData), feeData, @@ -251,7 +255,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { const argumentThree = true; const encodedMetaData = Helpers.abiEncode(['string','int8','bool'], [argumentOne, argumentTwo, argumentThree]); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, threeArgumentsResourceID, Helpers.createGenericDepositData(encodedMetaData), feeData, diff --git a/test/gasBenchmarks/executeProposal.js b/test/gasBenchmarks/executeProposal.js index 37d078bf..f95fd39d 100644 --- a/test/gasBenchmarks/executeProposal.js +++ b/test/gasBenchmarks/executeProposal.js @@ -21,15 +21,14 @@ const TwoArgumentsContract = artifacts.require("TwoArguments"); const ThreeArgumentsContract = artifacts.require("ThreeArguments"); contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { - const domainID = 1; - const relayerThreshold = 1; - const relayerAddress = accounts[0]; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const lenRecipientAddress = 20; const gasBenchmarks = []; - const initialRelayers = [relayerAddress]; const erc20TokenAmount = 100; const erc721TokenID = 1; const erc1155TokenID = 1; @@ -57,13 +56,15 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { let twoArgumentsResourceID; let threeArgumentsResourceID; - const deposit = (resourceID, depositData) => BridgeInstance.deposit(domainID, resourceID, depositData, feeData, { from: depositerAddress }); - const vote = (resourceID, depositNonce, depositData) => BridgeInstance.voteProposal(domainID, depositNonce, resourceID, depositData, { from: relayerAddress }); - const execute = (depositNonce, depositData, resourceID) => BridgeInstance.executeProposal(domainID, depositNonce, depositData, resourceID, true); + const deposit = (resourceID, depositData) => BridgeInstance.deposit(originDomainID, resourceID, depositData, feeData, { from: depositerAddress }); + const execute = async (originDomainID, depositNonce, depositData, resourceID) => { + const signature = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, depositNonce, depositData, resourceID); + return BridgeInstance.executeProposal(originDomainID, depositNonce, depositData, resourceID, signature); + }; before(async () => { await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), @@ -74,14 +75,14 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { ThreeArgumentsContract.new().then(instance => ThreeArgumentsInstance = instance) ]); - erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); - erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, domainID); - erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, domainID); - centrifugeAssetResourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, domainID); - noArgumentResourceID = Helpers.createResourceID(NoArgumentInstance.address, domainID); - oneArgumentResourceID = Helpers.createResourceID(OneArgumentInstance.address, domainID); - twoArgumentsResourceID = Helpers.createResourceID(TwoArgumentsInstance.address, domainID); - threeArgumentsResourceID = Helpers.createResourceID(ThreeArgumentsInstance.address, domainID); + erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); + erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); + centrifugeAssetResourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID); + noArgumentResourceID = Helpers.createResourceID(NoArgumentInstance.address, originDomainID); + oneArgumentResourceID = Helpers.createResourceID(OneArgumentInstance.address, originDomainID); + twoArgumentsResourceID = Helpers.createResourceID(TwoArgumentsInstance.address, originDomainID); + threeArgumentsResourceID = Helpers.createResourceID(ThreeArgumentsInstance.address, originDomainID); const genericInitialResourceIDs = [ centrifugeAssetResourceID, @@ -137,6 +138,9 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, twoArgumentsResourceID, genericInitialContractAddresses[3], genericInitialDepositFunctionSignatures[3], genericInitialDepositFunctionDepositerOffsets[3], genericInitialExecuteFunctionSignatures[3]), BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, threeArgumentsResourceID, genericInitialContractAddresses[4], genericInitialDepositFunctionSignatures[4], genericInitialDepositFunctionDepositerOffsets[4], genericInitialExecuteFunctionSignatures[4]) ]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('Should execute ERC20 deposit proposal', async () => { @@ -147,11 +151,11 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { recipientAddress); await deposit(erc20ResourceID, depositData); - const voteWithExecuteTx = await vote(erc20ResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, erc20ResourceID); gasBenchmarks.push({ type: 'ERC20', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -167,25 +171,25 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { metaData); await deposit(erc721ResourceID, depositData); - const voteWithExecuteTx = await vote(erc721ResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, erc721ResourceID); gasBenchmarks.push({ type: 'ERC721', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); it('Should execute ERC1155 deposit proposal', async () => { const depositNonce = 3; - - const depositData = Helpers.createERC1155DepositData([erc1155TokenID], [erc1155TokenAmount]); + const metaData = "0x"; + const depositData = Helpers.createERC1155DepositProposalData([erc1155TokenID], [erc1155TokenAmount], recipientAddress, metaData); await deposit(erc1155ResourceID, depositData); - const voteWithExecuteTx = await vote(erc1155ResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, erc1155ResourceID); gasBenchmarks.push({ type: 'ERC1155', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -195,11 +199,11 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const depositData = Helpers.createGenericDepositData(hashOfCentrifugeAsset); await deposit(centrifugeAssetResourceID, depositData); - const voteWithExecuteTx = await vote(centrifugeAssetResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, centrifugeAssetResourceID); gasBenchmarks.push({ type: 'Generic - Centrifuge Asset', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -208,11 +212,11 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const depositData = Helpers.createGenericDepositData(null); await deposit(noArgumentResourceID, depositData); - const voteWithExecuteTx = await vote(noArgumentResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, noArgumentResourceID,); gasBenchmarks.push({ type: 'Generic - No Argument', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -221,11 +225,11 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const depositData = Helpers.createGenericDepositData(Helpers.toHex(42, 32)); await deposit(oneArgumentResourceID, depositData); - const voteWithExecuteTx = await vote(oneArgumentResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, oneArgumentResourceID); gasBenchmarks.push({ type: 'Generic - One Argument', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -237,11 +241,11 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const depositData = Helpers.createGenericDepositData(encodedMetaData); await deposit(twoArgumentsResourceID, depositData); - const voteWithExecuteTx = await vote(twoArgumentsResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, twoArgumentsResourceID); gasBenchmarks.push({ type: 'Generic - Two Argument', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); @@ -254,13 +258,13 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const depositData = Helpers.createGenericDepositData(encodedMetaData); await deposit(threeArgumentsResourceID, depositData); - const voteWithExecuteTx = await vote(threeArgumentsResourceID, depositNonce, depositData, relayerAddress); + const executeTx = await execute(originDomainID, depositNonce, depositData, threeArgumentsResourceID); gasBenchmarks.push({ type: 'Generic - Three Argument', - gasUsed: voteWithExecuteTx.receipt.gasUsed + gasUsed: executeTx.receipt.gasUsed }); }); - + it('Should print out benchmarks', () => console.table(gasBenchmarks)); }); diff --git a/test/gasBenchmarks/voteProposal.js b/test/gasBenchmarks/voteProposal.js deleted file mode 100644 index 12986084..00000000 --- a/test/gasBenchmarks/voteProposal.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ -const Ethers = require('ethers'); - -const Helpers = require('../helpers'); - -const BridgeContract = artifacts.require("Bridge"); -const ERC20HandlerContract = artifacts.require("ERC20Handler"); -const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); - -contract('Gas Benchmark - [Vote Proposal]', async (accounts) => { - const domainID = 1; - const relayerThreshold = 2; - const relayer1Address = accounts[0]; - const relayer2Address = accounts[1] - const depositerAddress = accounts[2]; - const recipientAddress = accounts[3]; - const lenRecipientAddress = 20; - const depositNonce = 1; - const gasBenchmarks = []; - - const initialRelayers = [relayer1Address, relayer2Address]; - const erc20TokenAmount = 100; - - let BridgeInstance; - let ERC20MintableInstance; - let ERC20HandlerInstance; - - let erc20ResourceID; - - const vote = (resourceID, depositNonce, depositData, relayer) => BridgeInstance.voteProposal(domainID, depositNonce, resourceID, depositData, { from: relayer }); - - before(async () => { - await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), - ]); - - erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); - - await ERC20HandlerContract.new(BridgeInstance.address).then(instance => ERC20HandlerInstance = instance); - - await Promise.all([ - ERC20MintableInstance.approve(ERC20HandlerInstance.address, erc20TokenAmount, { from: depositerAddress }), - BridgeInstance.adminSetResource(ERC20HandlerInstance.address, erc20ResourceID, ERC20MintableInstance.address), - ]); - }); - - it('Should create proposal - relayerThreshold = 2, not finalized', async () => { - const depositData = Helpers.createERCDepositData( - erc20TokenAmount, - lenRecipientAddress, - recipientAddress); - - const voteTx = await vote(erc20ResourceID, depositNonce, depositData, relayer1Address); - - gasBenchmarks.push({ - type: 'Vote Proposal - relayerThreshold = 2, Not Finalized', - gasUsed: voteTx.receipt.gasUsed - }); - }); - - it('Should vote proposal - relayerThreshold = 2, finalized', async () => { - const depositData = Helpers.createERCDepositData( - erc20TokenAmount, - lenRecipientAddress, - recipientAddress); - - const voteTx = await vote(erc20ResourceID, depositNonce, depositData, relayer2Address); - - gasBenchmarks.push({ - type: 'Vote Proposal - relayerThreshold = 2, Finalized', - gasUsed: voteTx.receipt.gasUsed - }); - }); - - it('Should vote proposal - relayerThreshold = 1, finalized', async () => { - const newDepositNonce = 2; - await BridgeInstance.adminChangeRelayerThreshold(1); - - const depositData = Helpers.createERCDepositData( - erc20TokenAmount, - lenRecipientAddress, - recipientAddress); - const voteTx = await vote(erc20ResourceID, newDepositNonce, depositData, relayer2Address); - - gasBenchmarks.push({ - type: 'Vote Proposal - relayerThreshold = 1, Finalized', - gasUsed: voteTx.receipt.gasUsed - }); - }); - - it('Should print out benchmarks', () => console.table(gasBenchmarks)); -}); diff --git a/test/handlers/erc1155/burnList.js b/test/handlers/erc1155/burnList.js index 1574cbeb..f5deceb9 100644 --- a/test/handlers/erc1155/burnList.js +++ b/test/handlers/erc1155/burnList.js @@ -11,7 +11,6 @@ const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('ERC1155Handler - [Burn ERC1155]', async () => { - const relayerThreshold = 2; const domainID = 1; let BridgeInstance; @@ -25,7 +24,7 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]); @@ -43,7 +42,7 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { it('burnableContractAddresses should be marked true in _burnList', async () => { const ERC1155HandlerInstance = await ERC1155HandlerContract.new(BridgeInstance.address); - + for (i = 0; i < initialResourceIDs.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetResource(ERC1155HandlerInstance.address, initialResourceIDs[i], initialContractAddresses[i])); } @@ -51,7 +50,7 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { for (i = 0; i < burnableContractAddresses.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetBurnable(ERC1155HandlerInstance.address, burnableContractAddresses[i])); } - + for (const burnableAddress of burnableContractAddresses) { const isBurnable = await ERC1155HandlerInstance._burnList.call(burnableAddress); assert.isTrue(isBurnable, "Contract wasn't successfully marked burnable"); @@ -83,9 +82,9 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { for (i = 0; i < burnableContractAddresses.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetBurnable(ERC1155HandlerInstance.address, burnableContractAddresses[i])); } - + await BridgeInstance.adminSetBurnable(ERC1155HandlerInstance.address, ERC1155MintableInstance2.address); const isBurnable = await ERC1155HandlerInstance._burnList.call(ERC1155MintableInstance2.address); assert.isTrue(isBurnable, "Contract wasn't successfully marked burnable"); }); -}); \ No newline at end of file +}); diff --git a/test/handlers/erc1155/deposit.js b/test/handlers/erc1155/deposit.js index 42354bd1..d8278252 100644 --- a/test/handlers/erc1155/deposit.js +++ b/test/handlers/erc1155/deposit.js @@ -12,10 +12,11 @@ const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const expectedDepositNonce = 1; const depositerAddress = accounts[1]; + const tokenID = 1; const tokenAmount = 100; const feeData = '0x'; @@ -32,11 +33,11 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]) - - resourceID = Helpers.createResourceID(ERC1155MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC1155MintableInstance.address]; burnableContractAddresses = [] @@ -50,8 +51,11 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { ERC1155MintableInstance.setApprovalForAll(ERC1155HandlerInstance.address, true, { from: depositerAddress }), BridgeInstance.adminSetResource(ERC1155HandlerInstance.address, resourceID, ERC1155MintableInstance.address) ]); - + depositData = Helpers.createERC1155DepositData([tokenID], [tokenAmount]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] depositer owns tokenAmount of tokenID', async () => { @@ -61,7 +65,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { it('Deposit event is emitted with expected values', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -69,7 +73,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.data === Helpers.createERC1155DepositData([tokenID], [tokenAmount]).toLowerCase() && diff --git a/test/handlers/erc1155/depositBurn.js b/test/handlers/erc1155/depositBurn.js index c98589ca..6ddf9333 100644 --- a/test/handlers/erc1155/depositBurn.js +++ b/test/handlers/erc1155/depositBurn.js @@ -2,7 +2,7 @@ * Copyright 2021 ChainSafe Systems * SPDX-License-Identifier: LGPL-3.0-only */ - + const TruffleAssert = require('truffle-assertions'); const Helpers = require('../../helpers'); @@ -12,8 +12,8 @@ const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; @@ -35,13 +35,13 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]) - resourceID1 = Helpers.createResourceID(ERC1155MintableInstance1.address, domainID); - resourceID2 = Helpers.createResourceID(ERC1155MintableInstance2.address, domainID); + resourceID1 = Helpers.createResourceID(ERC1155MintableInstance1.address, originDomainID); + resourceID2 = Helpers.createResourceID(ERC1155MintableInstance2.address, originDomainID); initialResourceIDs = [resourceID1, resourceID2]; initialContractAddresses = [ERC1155MintableInstance1.address, ERC1155MintableInstance2.address]; burnableContractAddresses = [ERC1155MintableInstance1.address] @@ -50,7 +50,7 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { ERC1155HandlerContract.new(BridgeInstance.address).then(instance => ERC1155HandlerInstance = instance), ERC1155MintableInstance1.mintBatch(depositerAddress, [tokenID], [tokenAmount], "0x0") ]); - + await Promise.all([ ERC1155MintableInstance1.setApprovalForAll(ERC1155HandlerInstance.address, true, { from: depositerAddress }), BridgeInstance.adminSetResource(ERC1155HandlerInstance.address, resourceID1, ERC1155MintableInstance1.address), @@ -59,6 +59,9 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { ]); depositData = Helpers.createERC1155DepositData([tokenID], [tokenAmount]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] burnableContractAddresses should be marked true in _burnList', async () => { @@ -70,7 +73,7 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { it('depositAmount of ERC1155MintableInstance1 tokens should have been burned', async () => { await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID1, depositData, feeData, diff --git a/test/handlers/erc20/burnList.js b/test/handlers/erc20/burnList.js index 9ca93def..b4e8f7c9 100644 --- a/test/handlers/erc20/burnList.js +++ b/test/handlers/erc20/burnList.js @@ -11,7 +11,6 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [Burn ERC20]', async () => { - const relayerThreshold = 2; const domainID = 1; let RelayerInstance; @@ -26,7 +25,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]); @@ -44,7 +43,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { it('burnableContractAddresses should be marked true in _burnList', async () => { const ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - + for (i = 0; i < initialResourceIDs.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetResource(ERC20HandlerInstance.address, initialResourceIDs[i], initialContractAddresses[i])); } @@ -52,7 +51,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { for (i = 0; i < burnableContractAddresses.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetBurnable(ERC20HandlerInstance.address, burnableContractAddresses[i])); } - + for (const burnableAddress of burnableContractAddresses) { const isBurnable = await ERC20HandlerInstance._burnList.call(burnableAddress); assert.isTrue(isBurnable, "Contract wasn't successfully marked burnable"); @@ -84,7 +83,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { for (i = 0; i < burnableContractAddresses.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetBurnable(ERC20HandlerInstance.address, burnableContractAddresses[i])); } - + await BridgeInstance.adminSetBurnable(ERC20HandlerInstance.address, ERC20MintableInstance2.address); const isBurnable = await ERC20HandlerInstance._burnList.call(ERC20MintableInstance2.address); assert.isTrue(isBurnable, "Contract wasn't successfully marked burnable"); diff --git a/test/handlers/erc20/constructor.js b/test/handlers/erc20/constructor.js index c1797697..ec4c72ca 100644 --- a/test/handlers/erc20/constructor.js +++ b/test/handlers/erc20/constructor.js @@ -11,7 +11,6 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [constructor]', async () => { - const relayerThreshold = 2; const domainID = 1; let BridgeInstance; @@ -24,7 +23,7 @@ contract('ERC20Handler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance3 = instance) @@ -44,16 +43,24 @@ contract('ERC20Handler - [constructor]', async () => { await TruffleAssert.passes(ERC20HandlerContract.new(BridgeInstance.address)); }); + it('[sanity] bridge configured on domain', async () => { + assert.equal(await BridgeInstance._domainID(), domainID) + }); + + it('[sanity] bridge should be initially paused', async () => { + assert.isTrue(await BridgeInstance.paused()); + }); + it('initialResourceIDs should be parsed correctly and corresponding resourceID mappings should have expected values', async () => { const ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); for (i = 0; i < initialResourceIDs.length; i++) { await TruffleAssert.passes(BridgeInstance.adminSetResource(ERC20HandlerInstance.address, initialResourceIDs[i], initialContractAddresses[i])); } - + for (const resourceID of initialResourceIDs) { const tokenAddress = `0x` + resourceID.substr(24,40); - + const retrievedTokenAddress = await ERC20HandlerInstance._resourceIDToTokenContractAddress.call(resourceID); assert.strictEqual(Ethers.utils.getAddress(tokenAddress).toLowerCase(), retrievedTokenAddress.toLowerCase()); @@ -61,4 +68,4 @@ contract('ERC20Handler - [constructor]', async () => { assert.strictEqual(resourceID.toLowerCase(), retrievedResourceID.toLowerCase()); } }); -}); + }); diff --git a/test/handlers/erc20/deposit.js b/test/handlers/erc20/deposit.js index 079a3f3c..ca5117b7 100644 --- a/test/handlers/erc20/deposit.js +++ b/test/handlers/erc20/deposit.js @@ -12,10 +12,11 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const expectedDepositNonce = 1; const depositerAddress = accounts[1]; + const tokenAmount = 100; const feeData = '0x'; @@ -30,11 +31,11 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC20MintableInstance.address]; burnableContractAddresses = [] @@ -48,6 +49,9 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) ]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] depositer owns tokenAmount of ERC20', async () => { @@ -63,20 +67,20 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { it('Varied recipient address with length 40', async () => { const recipientAddress = accounts[0] + accounts[1].substr(2); const lenRecipientAddress = 40; - + const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, Helpers.createERCDepositData( tokenAmount, lenRecipientAddress, recipientAddress), - feeData, + feeData, { from: depositerAddress } ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -93,7 +97,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { const lenRecipientAddress = 32; const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, Helpers.createERCDepositData( tokenAmount, @@ -104,7 +108,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -119,8 +123,8 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { it("When non-contract addresses are whitelisted in the handler, deposits which the addresses are set as a token address will be failed", async () => { const ZERO_Address = "0x0000000000000000000000000000000000000000"; const EOA_Address = accounts[1]; - const resourceID_ZERO_Address = Helpers.createResourceID(ZERO_Address, domainID); - const resourceID_EOA_Address = Helpers.createResourceID(EOA_Address, domainID); + const resourceID_ZERO_Address = Helpers.createResourceID(ZERO_Address, originDomainID); + const resourceID_EOA_Address = Helpers.createResourceID(EOA_Address, originDomainID); await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID_ZERO_Address, ZERO_Address); await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID_EOA_Address, EOA_Address); @@ -128,7 +132,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { const lenRecipientAddress = 40; await TruffleAssert.reverts(BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID_ZERO_Address, Helpers.createERCDepositData( tokenAmount, @@ -139,7 +143,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { ), "ERC20: not a contract"); await TruffleAssert.reverts(BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID_EOA_Address, Helpers.createERCDepositData( tokenAmount, @@ -150,4 +154,3 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { ), "ERC20: not a contract"); }); }); - diff --git a/test/handlers/erc20/depositBurn.js b/test/handlers/erc20/depositBurn.js index 6360d725..f54fa889 100644 --- a/test/handlers/erc20/depositBurn.js +++ b/test/handlers/erc20/depositBurn.js @@ -12,7 +12,6 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { - const relayerThreshold = 2; const domainID = 1; const depositerAddress = accounts[1]; @@ -35,7 +34,7 @@ contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) @@ -59,7 +58,9 @@ contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { ]); depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); - + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] burnableContractAddresses should be marked true in _burnList', async () => { diff --git a/test/handlers/erc20/isWhitelisted.js b/test/handlers/erc20/isWhitelisted.js index e326a51d..4d73da90 100644 --- a/test/handlers/erc20/isWhitelisted.js +++ b/test/handlers/erc20/isWhitelisted.js @@ -12,8 +12,7 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [isWhitelisted]', async () => { const AbiCoder = new Ethers.utils.AbiCoder(); - - const relayerThreshold = 2; + const domainID = 1; let BridgeInstance; @@ -25,7 +24,7 @@ contract('ERC20Handler - [isWhitelisted]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) @@ -50,7 +49,7 @@ contract('ERC20Handler - [isWhitelisted]', async () => { // as we are working with a mandatory whitelist, these tests are currently not necessary - + // it('initialContractAddress should not be whitelisted', async () => { // const ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address, initialResourceIDs, initialContractAddresses); // const isWhitelisted = await ERC20HandlerInstance._contractWhitelist.call(ERC20MintableInstance1.address); diff --git a/test/handlers/erc20/setResourceIDAndContractAddress.js b/test/handlers/erc20/setResourceIDAndContractAddress.js index 6d520236..98b396ad 100644 --- a/test/handlers/erc20/setResourceIDAndContractAddress.js +++ b/test/handlers/erc20/setResourceIDAndContractAddress.js @@ -12,8 +12,7 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('ERC20Handler - [setResourceIDAndContractAddress]', async () => { const AbiCoder = new Ethers.utils.AbiCoder(); - - const relayerThreshold = 2; + const domainID = 1; let BridgeInstance; @@ -24,7 +23,7 @@ contract('ERC20Handler - [setResourceIDAndContractAddress]', async () => { let burnableContractAddresses; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100); + BridgeInstance = await BridgeContract.new(domainID); ERC20MintableInstance1 = await ERC20MintableContract.new("token", "TOK"); initialResourceIDs = [Ethers.utils.hexZeroPad((ERC20MintableInstance1.address + Ethers.utils.hexlify(domainID).substr(2)), 32)]; diff --git a/test/handlers/erc721/burnList.js b/test/handlers/erc721/burnList.js index 8362d73c..19ad31f6 100644 --- a/test/handlers/erc721/burnList.js +++ b/test/handlers/erc721/burnList.js @@ -13,7 +13,6 @@ const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('ERC721Handler - [Burn ERC721]', async () => { - const relayerThreshold = 2; const domainID = 1; let BridgeInstance; @@ -27,7 +26,7 @@ contract('ERC721Handler - [Burn ERC721]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) diff --git a/test/handlers/erc721/deposit.js b/test/handlers/erc721/deposit.js index 28f4aade..c78b016e 100644 --- a/test/handlers/erc721/deposit.js +++ b/test/handlers/erc721/deposit.js @@ -12,10 +12,12 @@ const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; + const expectedDepositNonce = 1; const depositerAddress = accounts[1]; + const tokenID = 1; const feeData = '0x'; @@ -30,11 +32,11 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]) - - resourceID = Helpers.createResourceID(ERC721MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC721MintableInstance.address]; burnableContractAddresses = [] @@ -48,6 +50,9 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { ERC721MintableInstance.approve(ERC721HandlerInstance.address, tokenID, { from: depositerAddress }), BridgeInstance.adminSetResource(ERC721HandlerInstance.address, resourceID, ERC721MintableInstance.address) ]); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] depositer owns ERC721 with tokenID', async () => { @@ -63,9 +68,9 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { it('Varied recipient address with length 40', async () => { const recipientAddress = accounts[0] + accounts[1].substr(2); const lenRecipientAddress = 40; - + const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, Helpers.createERCDepositData( tokenID, @@ -76,7 +81,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -93,7 +98,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { const lenRecipientAddress = 32; const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, Helpers.createERCDepositData( tokenID, @@ -104,7 +109,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && diff --git a/test/handlers/erc721/depositBurn.js b/test/handlers/erc721/depositBurn.js index 9b521d38..0cd88e31 100644 --- a/test/handlers/erc721/depositBurn.js +++ b/test/handlers/erc721/depositBurn.js @@ -2,7 +2,7 @@ * Copyright 2020 ChainSafe Systems * SPDX-License-Identifier: LGPL-3.0-only */ - + const TruffleAssert = require('truffle-assertions'); const Helpers = require('../../helpers'); @@ -12,8 +12,8 @@ const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -35,13 +35,13 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) - resourceID1 = Helpers.createResourceID(ERC721MintableInstance1.address, domainID); - resourceID2 = Helpers.createResourceID(ERC721MintableInstance2.address, domainID); + resourceID1 = Helpers.createResourceID(ERC721MintableInstance1.address, originDomainID); + resourceID2 = Helpers.createResourceID(ERC721MintableInstance2.address, originDomainID); initialResourceIDs = [resourceID1, resourceID2]; initialContractAddresses = [ERC721MintableInstance1.address, ERC721MintableInstance2.address]; burnableContractAddresses = [ERC721MintableInstance1.address] @@ -50,7 +50,7 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { ERC721HandlerContract.new(BridgeInstance.address).then(instance => ERC721HandlerInstance = instance), ERC721MintableInstance1.mint(depositerAddress, tokenID, "") ]); - + await Promise.all([ ERC721MintableInstance1.approve(ERC721HandlerInstance.address, tokenID, { from: depositerAddress }), BridgeInstance.adminSetResource(ERC721HandlerInstance.address, resourceID1, ERC721MintableInstance1.address), @@ -59,6 +59,9 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { ]); depositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('[sanity] burnableContractAddresses should be marked true in _burnList', async () => { @@ -75,7 +78,7 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { it('depositAmount of ERC721MintableInstance1 tokens should have been burned', async () => { await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID1, depositData, feeData, diff --git a/test/handlers/fee/basic/calculateFee.js b/test/handlers/fee/basic/calculateFee.js index 40c0c009..fea9a8f6 100644 --- a/test/handlers/fee/basic/calculateFee.js +++ b/test/handlers/fee/basic/calculateFee.js @@ -31,7 +31,7 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), - BridgeInstance = BridgeContract.new(originDomainID, [relayer], 0, 100).then(instance => BridgeInstance = instance) + BridgeInstance = BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance) ]); resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); @@ -52,7 +52,7 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); // current fee is set to 0 let res = await BasicFeeHandlerInstance.calculateFee.call( - relayer, + relayer, originDomainID, destinationDomainID, resourceID, @@ -63,7 +63,7 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { // Change fee to 0.5 ether await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("0.5")); res = await BasicFeeHandlerInstance.calculateFee.call( - relayer, + relayer, originDomainID, destinationDomainID, resourceID, @@ -72,4 +72,4 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { ); assert.equal(web3.utils.fromWei(res[0], "ether"), "0.5"); }); -}); \ No newline at end of file +}); diff --git a/test/handlers/fee/basic/changeFee.js b/test/handlers/fee/basic/changeFee.js index 4aa68bd6..363e9d39 100644 --- a/test/handlers/fee/basic/changeFee.js +++ b/test/handlers/fee/basic/changeFee.js @@ -10,19 +10,17 @@ const BridgeContract = artifacts.require("Bridge"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); contract("BasicFeeHandler - [changeFee]", async accounts => { - const relayerThreshold = 0; const domainID = 1; - const initialRelayers = accounts.slice(0, 3); - const relayer = accounts[0]; + const nonAdmin = accounts[1]; const assertOnlyAdmin = (method, ...params) => { - return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + return TruffleAssert.reverts(method(...params, {from: nonAdmin}), "sender doesn't have admin role"); }; let BridgeInstance; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); }); it("[sanity] contract should be deployed successfully", async () => { @@ -34,7 +32,7 @@ contract("BasicFeeHandler - [changeFee]", async accounts => { const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); const fee = Ethers.utils.parseEther("0.05"); const tx = await BasicFeeHandlerInstance.changeFee(fee); - TruffleAssert.eventEmitted(tx, "FeeChanged", (event) => + TruffleAssert.eventEmitted(tx, "FeeChanged", (event) => web3.utils.fromWei(event.newFee, "ether") === "0.05" ); const newFee = await BasicFeeHandlerInstance._fee.call(); diff --git a/test/handlers/fee/basic/collectFee.js b/test/handlers/fee/basic/collectFee.js index c448b452..7e9eb604 100644 --- a/test/handlers/fee/basic/collectFee.js +++ b/test/handlers/fee/basic/collectFee.js @@ -14,9 +14,9 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); contract("BasicFeeHandler - [collectFee]", async (accounts) => { - - const relayerThreshold = 1; - const domainID = 1; + + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -34,11 +34,11 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); @@ -46,17 +46,20 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { ERC20MintableInstance.mint(depositerAddress, depositAmount), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) ]); - + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("[sanity] Generic deposit can be made", async () => { await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -68,10 +71,10 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); // current fee is set to 0 assert.equal(await BasicFeeHandlerInstance._fee.call(), 0); - + await TruffleAssert.reverts( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -96,7 +99,7 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { const balanceBefore = await web3.eth.getBalance(BasicFeeHandlerInstance.address); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -107,14 +110,14 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase(); }); const internalTx = await TruffleAssert.createTransactionResult(BasicFeeHandlerInstance, depositTx.tx); TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { return event.sender === depositerAddress && - event.fromDomainID.toNumber() === domainID && - event.destinationDomainID.toNumber() === domainID && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.fee.toString() === fee.toString() && event.tokenAddress === "0x0000000000000000000000000000000000000000"; @@ -123,10 +126,10 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { assert.equal(balanceAfter, fee.add(balanceBefore)); }); - it("deposit should revert if fee handler not set and fee supplied", async () => { + it("deposit should revert if fee handler not set and fee supplied", async () => { await TruffleAssert.reverts( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -142,7 +145,7 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { it("deposit should pass if fee handler not set and fee not supplied", async () => { await TruffleAssert.passes( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -150,4 +153,4 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { ) ) }); -}); \ No newline at end of file +}); diff --git a/test/handlers/fee/basic/distributeFee.js b/test/handlers/fee/basic/distributeFee.js index 874783b2..9e8ffa7d 100644 --- a/test/handlers/fee/basic/distributeFee.js +++ b/test/handlers/fee/basic/distributeFee.js @@ -5,18 +5,18 @@ const TruffleAssert = require("truffle-assertions"); const Ethers = require("ethers"); - + const Helpers = require("../../../helpers"); - + const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); contract("BasicFeeHandler - [distributeFee]", async (accounts) => { - - const relayerThreshold = 1; - const domainID = 1; + + const originDomainID = 1; + const destinationDomainID = 2; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -38,11 +38,11 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); - - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); @@ -50,32 +50,35 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { ERC20MintableInstance.mint(depositerAddress, depositAmount), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) ]); - + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); - + it("should distribute fees", async () => { await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); assert.equal(web3.utils.fromWei((await BasicFeeHandlerInstance._fee.call()), "ether"), "1"); - + // check the balance is 0 assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "0"); - await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}) + await BridgeInstance.deposit(destinationDomainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}) assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BridgeInstance.address)), "ether"), "0"); assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); - + let b1Before = await web3.eth.getBalance(accounts[1]); let b2Before = await web3.eth.getBalance(accounts[2]); - + let payout = Ethers.utils.parseEther("0.5") // Transfer the funds const tx = await BasicFeeHandlerInstance.transferFee( - [accounts[1], accounts[2]], + [accounts[1], accounts[2]], [payout, payout] ); TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { @@ -98,7 +101,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); - await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); + await BridgeInstance.deposit(destinationDomainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); @@ -110,7 +113,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("1")); - await BridgeInstance.deposit(domainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); + await BridgeInstance.deposit(destinationDomainID, resourceID, depositData, feeData, {from: depositerAddress, value: Ethers.utils.parseEther("1")}); assert.equal(web3.utils.fromWei((await web3.eth.getBalance(BasicFeeHandlerInstance.address)), "ether"), "1"); @@ -118,4 +121,4 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { await TruffleAssert.reverts(BasicFeeHandlerInstance.transferFee([accounts[3], accounts[4]], [payout, payout, payout]), "addrs[], amounts[]: diff length"); }); - }); \ No newline at end of file + }); diff --git a/test/handlers/fee/withOracle/admin.js b/test/handlers/fee/withOracle/admin.js index 071fdf90..0130a943 100644 --- a/test/handlers/fee/withOracle/admin.js +++ b/test/handlers/fee/withOracle/admin.js @@ -4,54 +4,52 @@ */ const TruffleAssert = require("truffle-assertions"); - + const BridgeContract = artifacts.require("Bridge"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); - + contract("FeeHandlerWithOracle - [admin]", async accounts => { - const relayerThreshold = 0; - const domainID = 1; - const initialRelayers = accounts.slice(0, 3); - - const assertOnlyAdmin = (method, ...params) => { - return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); - }; - - let BridgeInstance; - let FeeHandlerWithOracleInstance; - - beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); - FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); - }); - - it("should set fee oracle", async () => { + const domainID = 1; + const initialRelayers = accounts.slice(0, 3); + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + }); + + it("should set fee oracle", async () => { const oracleAddress = accounts[1]; assert.equal(await FeeHandlerWithOracleInstance._oracleAddress.call(), "0x0000000000000000000000000000000000000000"); await FeeHandlerWithOracleInstance.setFeeOracle(oracleAddress); const newOracle = await FeeHandlerWithOracleInstance._oracleAddress.call(); assert.equal(newOracle, oracleAddress); - }); + }); it("should require admin role to change fee oracle", async () => { const oracleAddress = accounts[1]; await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeOracle, oracleAddress); - }); - - it("should set fee properties", async () => { - const gasUsed = 100000; - const feePercent = 5; - assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), "0"); - assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), "0"); - await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); - assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), gasUsed); - assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), feePercent); + }); + + it("should set fee properties", async () => { + const gasUsed = 100000; + const feePercent = 5; + assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), "0"); + assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), "0"); + await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); + assert.equal(await FeeHandlerWithOracleInstance._gasUsed.call(), gasUsed); + assert.equal(await FeeHandlerWithOracleInstance._feePercent.call(), feePercent); }); it("should require admin role to change fee properties", async () => { const gasUsed = 100000; const feePercent = 5; await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeProperties, gasUsed, feePercent); - }); - }); - \ No newline at end of file + }); +}); diff --git a/test/handlers/fee/withOracle/calculateFee.js b/test/handlers/fee/withOracle/calculateFee.js index 9c791f78..b18abd2d 100644 --- a/test/handlers/fee/withOracle/calculateFee.js +++ b/test/handlers/fee/withOracle/calculateFee.js @@ -12,9 +12,8 @@ const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); - + contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { - const relayerThreshold = 0; const domainID = 1; const oracle = new Ethers.Wallet.createRandom(); const sender = accounts[0]; @@ -46,7 +45,7 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { */ beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); @@ -63,8 +62,8 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { }); it("should calculate amount of fee and return token address", async () => { - const tokenAmount = 100; - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), @@ -84,7 +83,7 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { it("should return percent fee", async () => { const tokenAmount = Ethers.utils.parseEther("1"); - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), @@ -102,8 +101,8 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { }); it("should return fee to cover tx cost if percent fee does not cover tx cost", async () => { - const tokenAmount = 100; - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.0005"), @@ -122,8 +121,8 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { }); it("should not calculate fee if fee data is misformed", async () => { - const tokenAmount = 100; - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.0005"), @@ -141,8 +140,8 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { it("should not calculate fee if deposit data differ from fee data", async () => { const otherDomainId = 2; - const tokenAmount = 100; - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.0005"), @@ -157,10 +156,10 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, otherDomainId, resourceID, depositData, feeData), "Incorrect deposit params"); }); - + it("should not calculate fee if oracle signature is incorrect", async () => { - const tokenAmount = 100; - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const tokenAmount = 100; + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.0005"), @@ -184,7 +183,7 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); const tokenAmount = Ethers.utils.parseEther("1"); - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), @@ -198,4 +197,3 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Obsolete oracle data"); }); }); - \ No newline at end of file diff --git a/test/handlers/fee/withOracle/collectFee.js b/test/handlers/fee/withOracle/collectFee.js index 2c46547c..41b9f620 100644 --- a/test/handlers/fee/withOracle/collectFee.js +++ b/test/handlers/fee/withOracle/collectFee.js @@ -5,17 +5,17 @@ const TruffleAssert = require("truffle-assertions"); const Ethers = require("ethers"); - + const Helpers = require("../../../helpers"); - + const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); - + contract("FeeHandlerWithOracle - [collectFee]", async accounts => { - const relayerThreshold = 0; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const oracle = new Ethers.Wallet.createRandom(); const recipientAddress = accounts[2]; const tokenAmount = Ethers.utils.parseEther("1"); @@ -48,7 +48,7 @@ */ beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + BridgeInstance = await BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); @@ -57,29 +57,32 @@ await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); await ERC20MintableInstance.mint(depositerAddress, tokenAmount + feeAmount), - + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, feeAmount, { from: depositerAddress }); await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("should collect fee in tokens", async () => { const fee = Ethers.utils.parseEther("0.05"); - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; @@ -88,7 +91,7 @@ const balanceBefore = (await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address)).toString(); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -97,14 +100,14 @@ } ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase(); }); const internalTx = await TruffleAssert.createTransactionResult(FeeHandlerWithOracleInstance, depositTx.tx); TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { return event.sender === depositerAddress && - event.fromDomainID.toNumber() === domainID && - event.destinationDomainID.toNumber() === domainID && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === resourceID.toLowerCase() && event.fee.toString() === fee.toString() && event.tokenAddress === ERC20MintableInstance.address; @@ -114,21 +117,21 @@ }); it("deposit should revert if msg.value != 0", async () => { - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); await TruffleAssert.reverts( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -142,14 +145,14 @@ }); it("deposit should revert if fee collection fails", async () => { - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: originDomainID, resourceID }; @@ -157,7 +160,7 @@ await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, 0, { from: depositerAddress }); await TruffleAssert.reverts( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -170,14 +173,14 @@ }); it("deposit should revert if called not by bridge", async () => { - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; @@ -186,8 +189,8 @@ await TruffleAssert.reverts( FeeHandlerWithOracleInstance.collectFee( depositerAddress, - domainID, - domainID, + originDomainID, + destinationDomainID, resourceID, depositData, feeData, @@ -200,4 +203,3 @@ ); }); }); - \ No newline at end of file diff --git a/test/handlers/fee/withOracle/distributeFee.js b/test/handlers/fee/withOracle/distributeFee.js index 6533ac0d..4cd09db7 100644 --- a/test/handlers/fee/withOracle/distributeFee.js +++ b/test/handlers/fee/withOracle/distributeFee.js @@ -7,18 +7,19 @@ const Ethers = require("ethers"); const Helpers = require("../../../helpers"); - + const BridgeContract = artifacts.require("Bridge"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); - + contract("FeeHandlerWithOracle - [distributeFee]", async accounts => { - const relayerThreshold = 0; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const oracle = new Ethers.Wallet.createRandom(); const recipientAddress = accounts[2]; const depositerAddress = accounts[1]; + const tokenAmount = feeAmount = Ethers.utils.parseEther("1"); let BridgeInstance; @@ -27,13 +28,13 @@ let depositData; let feeData; let oracleResponse; - + const assertOnlyAdmin = (method, ...params) => { return TruffleAssert.reverts(method(...params, {from: accounts[1]}), "sender doesn't have admin role"); }; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance); + BridgeInstance = await BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); @@ -42,32 +43,35 @@ await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); await ERC20MintableInstance.mint(depositerAddress, tokenAmount.add(feeAmount)), - + await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, tokenAmount, { from: depositerAddress }); await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); - depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); - + it("should distribute fees", async () => { // check the balance is 0 let b1Before = (await ERC20MintableInstance.balanceOf(accounts[3])).toString(); @@ -75,7 +79,7 @@ await TruffleAssert.passes( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -92,7 +96,7 @@ // Transfer the funds const tx = await FeeHandlerWithOracleInstance.transferFee( resourceID, - [accounts[3], accounts[4]], + [accounts[3], accounts[4]], [payout, payout] ); TruffleAssert.eventEmitted(tx, 'FeeDistributed', (event) => { @@ -114,7 +118,7 @@ it("should not distribute fees with other resourceID", async () => { await TruffleAssert.passes( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -129,13 +133,13 @@ let payout = Ethers.utils.parseEther("0.5"); // Incorrect resourceID - resourceID = Helpers.createResourceID(FeeHandlerWithOracleInstance.address, domainID); + resourceID = Helpers.createResourceID(FeeHandlerWithOracleInstance.address, originDomainID); // Transfer the funds: fails await TruffleAssert.reverts( FeeHandlerWithOracleInstance.transferFee( resourceID, - [accounts[3], accounts[4]], + [accounts[3], accounts[4]], [payout, payout] ) ); @@ -144,7 +148,7 @@ it("should require admin role to distribute fee", async () => { await TruffleAssert.passes( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -158,12 +162,12 @@ let payout = Ethers.utils.parseEther("0.5"); await assertOnlyAdmin(FeeHandlerWithOracleInstance.transferFee, resourceID, [accounts[3], accounts[4]], [payout, payout]); - }); + }); - it("should revert if addrs and amounts arrays have different length", async () => { + it("should revert if addrs and amounts arrays have different length", async () => { await TruffleAssert.passes( BridgeInstance.deposit( - domainID, + destinationDomainID, resourceID, depositData, feeData, @@ -178,5 +182,5 @@ let payout = Ethers.utils.parseEther("0.5"); await TruffleAssert.reverts(FeeHandlerWithOracleInstance.transferFee(resourceID, [accounts[3], accounts[4]], [payout, payout, payout]), "addrs[], amounts[]: diff length"); - }); - }); \ No newline at end of file + }); +}); diff --git a/test/handlers/generic/constructor.js b/test/handlers/generic/constructor.js index 1a7e760d..7a54269c 100644 --- a/test/handlers/generic/constructor.js +++ b/test/handlers/generic/constructor.js @@ -13,7 +13,6 @@ const GenericHandlerContract = artifacts.require("GenericHandler"); const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); contract('GenericHandler - [constructor]', async () => { - const relayerThreshold = 2; const domainID = 1; const centrifugeAssetMinCount = 1; const blankFunctionSig = '0x00000000'; @@ -32,7 +31,7 @@ contract('GenericHandler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(domainID).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance1 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance2 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance3 = instance) @@ -44,7 +43,7 @@ contract('GenericHandler - [constructor]', async () => { Helpers.createResourceID(CentrifugeAssetInstance3.address, domainID) ]; initialContractAddresses = [CentrifugeAssetInstance1.address, CentrifugeAssetInstance2.address, CentrifugeAssetInstance3.address]; - + const executeProposalFuncSig = Ethers.utils.keccak256(Ethers.utils.hexlify(Ethers.utils.toUtf8Bytes(centrifugeAssetStoreFuncSig))).substr(0, 10); initialDepositFunctionSignatures = [blankFunctionSig, blankFunctionSig, blankFunctionSig]; @@ -65,7 +64,7 @@ contract('GenericHandler - [constructor]', async () => { for (let i = 0; i < initialResourceIDs.length; i++) { await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, initialResourceIDs[i], initialContractAddresses[i], initialDepositFunctionSignatures[i], initialDepositFunctionDepositerOffsets[i], initialExecuteFunctionSignatures[i]); } - + for (let i = 0; i < initialResourceIDs.length; i++) { const retrievedTokenAddress = await GenericHandlerInstance._resourceIDToContractAddress.call(initialResourceIDs[i]); assert.strictEqual(initialContractAddresses[i].toLowerCase(), retrievedTokenAddress.toLowerCase()); diff --git a/test/handlers/generic/deposit.js b/test/handlers/generic/deposit.js index b3a83a2d..9b9c40ce 100644 --- a/test/handlers/generic/deposit.js +++ b/test/handlers/generic/deposit.js @@ -17,8 +17,8 @@ const ThreeArgumentsContract = artifacts.require("ThreeArguments"); const WithDepositerContract = artifacts.require("WithDepositer"); const ReturnDataContract = artifacts.require("ReturnData"); contract('GenericHandler - [deposit]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const expectedDepositNonce = 1; const depositerAddress = accounts[1]; @@ -44,7 +44,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, [], relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), NoArgumentContract.new().then(instance => NoArgumentInstance = instance), OneArgumentContract.new().then(instance => OneArgumentInstance = instance), @@ -54,13 +54,13 @@ contract('GenericHandler - [deposit]', async (accounts) => { ReturnDataContract.new().then(instance => ReturnDataInstance = instance), ]); initialResourceIDs = [ - Helpers.createResourceID(CentrifugeAssetInstance.address, domainID), - Helpers.createResourceID(NoArgumentInstance.address, domainID), - Helpers.createResourceID(OneArgumentInstance.address, domainID), - Helpers.createResourceID(TwoArgumentsInstance.address, domainID), - Helpers.createResourceID(ThreeArgumentsInstance.address, domainID), - Helpers.createResourceID(WithDepositerInstance.address, domainID), - Helpers.createResourceID(ReturnDataInstance.address, domainID), + Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID), + Helpers.createResourceID(NoArgumentInstance.address, originDomainID), + Helpers.createResourceID(OneArgumentInstance.address, originDomainID), + Helpers.createResourceID(TwoArgumentsInstance.address, originDomainID), + Helpers.createResourceID(ThreeArgumentsInstance.address, originDomainID), + Helpers.createResourceID(WithDepositerInstance.address, originDomainID), + Helpers.createResourceID(ReturnDataInstance.address, originDomainID), ]; initialContractAddresses = [ CentrifugeAssetInstance.address, @@ -101,7 +101,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { GenericHandlerInstance = await GenericHandlerContract.new( BridgeInstance.address); - + await Promise.all([ BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, initialResourceIDs[0], initialContractAddresses[0], initialDepositFunctionSignatures[0], initialDepositFunctionDepositerOffsets[0], initialExecuteFunctionSignatures[0]), BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, initialResourceIDs[1], initialContractAddresses[1], initialDepositFunctionSignatures[1], initialDepositFunctionDepositerOffsets[1], initialExecuteFunctionSignatures[1]), @@ -111,13 +111,16 @@ contract('GenericHandler - [deposit]', async (accounts) => { BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, initialResourceIDs[5], initialContractAddresses[5], initialDepositFunctionSignatures[5], initialDepositFunctionDepositerOffsets[5], initialExecuteFunctionSignatures[5]), BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, initialResourceIDs[6], initialContractAddresses[6], initialDepositFunctionSignatures[6], initialDepositFunctionDepositerOffsets[6], initialExecuteFunctionSignatures[6]) ]); - + depositData = Helpers.createGenericDepositData('0xdeadbeef'); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('deposit can be made successfully', async () => { await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[0], depositData, feeData, @@ -127,7 +130,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { it('depositEvent is emitted with expected values', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[0], depositData, feeData, @@ -135,7 +138,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[0].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -146,7 +149,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { it('noArgument can be called successfully and deposit event is emitted with expected values', async () => { const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[1], Helpers.createGenericDepositData(null), feeData, @@ -154,7 +157,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[1].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -168,9 +171,9 @@ contract('GenericHandler - [deposit]', async (accounts) => { it('oneArgument can be called successfully and deposit event is emitted with expected values', async () => { const argumentOne = 42; - + const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[2], Helpers.createGenericDepositData(Helpers.toHex(argumentOne, 32)), feeData, @@ -178,7 +181,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[2].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -194,9 +197,9 @@ contract('GenericHandler - [deposit]', async (accounts) => { const argumentOne = [NoArgumentInstance.address, OneArgumentInstance.address, TwoArgumentsInstance.address]; const argumentTwo = initialDepositFunctionSignatures[3]; const encodedMetaData = Helpers.abiEncode(['address[]','bytes4'], [argumentOne, argumentTwo]); - + const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[3], Helpers.createGenericDepositData(encodedMetaData), feeData, @@ -204,7 +207,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[3].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -224,9 +227,9 @@ contract('GenericHandler - [deposit]', async (accounts) => { const argumentTwo = -42; const argumentThree = true; const encodedMetaData = Helpers.abiEncode(['string','int8','bool'], [argumentOne, argumentTwo, argumentThree]); - + const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[4], Helpers.createGenericDepositData(encodedMetaData), feeData, @@ -234,7 +237,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[4].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -255,7 +258,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { const encodedMetaData = Helpers.abiEncode(['address','uint256'], [argumentOne, argumentTwo]); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[5], Helpers.createGenericDepositData(encodedMetaData), feeData, @@ -263,7 +266,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { ); TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[5].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && @@ -284,7 +287,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { const encodedMetaData = Helpers.abiEncode(['address','uint256'], [argumentOne, argumentTwo]); await TruffleAssert.reverts(BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[5], Helpers.createGenericDepositData(encodedMetaData), feeData, @@ -297,17 +300,17 @@ contract('GenericHandler - [deposit]', async (accounts) => { const encodedMetaData = Helpers.abiEncode(['string'], [argument]); const depositTx = await BridgeInstance.deposit( - domainID, + destinationDomainID, initialResourceIDs[6], Helpers.createGenericDepositData(encodedMetaData), feeData, { from: depositerAddress } ); - + const expectedMetaData = Ethers.utils.formatBytes32String(argument); - TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { - return event.destinationDomainID.toNumber() === domainID && + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === destinationDomainID && event.resourceID === initialResourceIDs[6].toLowerCase() && event.depositNonce.toNumber() === expectedDepositNonce && event.user === depositerAddress && diff --git a/test/handlers/generic/executeProposal.js b/test/handlers/generic/executeProposal.js index 1eab00b9..f1e1e04c 100644 --- a/test/handlers/generic/executeProposal.js +++ b/test/handlers/generic/executeProposal.js @@ -13,15 +13,13 @@ const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); const GenericHandlerContract = artifacts.require("GenericHandler"); contract('GenericHandler - [Execute Proposal]', async (accounts) => { - const relayerThreshold = 2; - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 2; const expectedDepositNonce = 1; - - const depositerAddress = accounts[1]; const relayer1Address = accounts[2]; const relayer2Address = accounts[3]; - const initialRelayers = [relayer1Address, relayer2Address]; + const depositerAddress = accounts[1]; const centrifugeAssetMinCount = 10; const hashOfCentrifugeAsset = Ethers.utils.keccak256('0xc0ffee'); @@ -40,13 +38,13 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID, initialRelayers, relayerThreshold, 100).then(instance => BridgeInstance = instance), + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance = instance) ]); const centrifugeAssetFuncSig = Helpers.getFunctionSignature(CentrifugeAssetInstance, 'store'); - resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, domainID); + resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [CentrifugeAssetInstance.address]; initialDepositFunctionSignatures = [Helpers.blankFunctionSig]; @@ -60,75 +58,60 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { depositData = Helpers.createGenericDepositData(hashOfCentrifugeAsset); depositProposalDataHash = Ethers.utils.keccak256(GenericHandlerInstance.address + depositData.substr(2)); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it('deposit can be executed successfully', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositData, resourceID); + await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + originDomainID, resourceID, depositData, feeData, { from: depositerAddress } )); - // relayer1 creates the deposit proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, + // relayer1 executes the proposal + await TruffleAssert.passes(BridgeInstance.executeProposal( + originDomainID, expectedDepositNonce, - resourceID, depositData, + resourceID, + proposalSignedData, { from: relayer1Address } )); - // relayer2 votes in favor of the deposit proposal - // because the relayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, - resourceID, - depositData, - { from: relayer2Address } - )); - // Verifying asset was marked as stored in CentrifugeAssetInstance assert.isTrue(await CentrifugeAssetInstance._assetsStored.call(hashOfCentrifugeAsset)); }); it('AssetStored event should be emitted', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, depositData, resourceID); + + await TruffleAssert.passes(BridgeInstance.deposit( - domainID, + originDomainID, resourceID, depositData, feeData, { from: depositerAddress } )); - // relayer1 creates the deposit proposal - await TruffleAssert.passes(BridgeInstance.voteProposal( - domainID, + // relayer1 executes the proposal + const executeTx = await BridgeInstance.executeProposal( + originDomainID, expectedDepositNonce, - resourceID, depositData, - { from: relayer1Address } - )); - - // relayer2 votes in favor of the deposit proposal - // because the relayerThreshold is 2, the deposit proposal will go - // into a finalized state - // and then automatically executes the proposal - const voteWithExecuteTx = await BridgeInstance.voteProposal( - domainID, - expectedDepositNonce, resourceID, - depositData, + proposalSignedData, { from: relayer2Address } ); - - const internalTx = await TruffleAssert.createTransactionResult(CentrifugeAssetInstance, voteWithExecuteTx.tx); + const internalTx = await TruffleAssert.createTransactionResult(CentrifugeAssetInstance, executeTx.tx); TruffleAssert.eventEmitted(internalTx, 'AssetStored', event => { - return event.asset === hashOfCentrifugeAsset; + return event.asset === hashOfCentrifugeAsset; }); assert.isTrue(await CentrifugeAssetInstance._assetsStored.call(hashOfCentrifugeAsset), diff --git a/test/helpers.js b/test/helpers.js index 5f1406b3..3a9b70ef 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -8,7 +8,8 @@ const blankFunctionSig = '0x00000000'; const blankFunctionDepositerOffset = 0; const AbiCoder = new Ethers.utils.AbiCoder; - + const mpcAddress = "0x1Ad4b1efE3Bc6FEE085e995FCF48219430e615C3"; + const mpcPrivateKey= "0x497b6ae580cb1b0238f8b6b543fada697bc6f8768a983281e5e52a1a5bca4d58" const toHex = (covertThis, padding) => { return Ethers.utils.hexZeroPad(Ethers.utils.hexlify(covertThis), padding); }; @@ -80,7 +81,7 @@ const createGenericDepositData = (hexMetaData) => { if (hexMetaData === null) { return '0x' + toHex(0, 32).substr(2) // len(metaData) (32 bytes) - } + } const hexMetaDataLength = (hexMetaData.substr(2)).length / 2; return '0x' + toHex(hexMetaDataLength, 32).substr(2) + @@ -119,8 +120,8 @@ const assertObjectsMatch = (expectedObj, actualObj) => { actualValue = parseInt(actualValue); } } - - assert.deepEqual(expectedValue, actualValue, `expectedValue: ${expectedValue} does not match actualValue: ${actualValue}`); + + assert.deepEqual(expectedValue, actualValue, `expectedValue: ${expectedValue} does not match actualValue: ${actualValue}`); } }; //uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); @@ -150,15 +151,18 @@ const createOracleFeeData = (oracleResponse, privateKey, amount) => { total feeData length: 321 */ - const oracleMessage = '0x' + - toHex(oracleResponse.ber, 32).substr(2) + // ber*10^18: uint256 (32 bytes) - toHex(oracleResponse.ter, 32).substr(2) + // ter*10^18: uint256 (32 bytes) - toHex(oracleResponse.dstGasPrice, 32).substr(2) + // dstGasPrice: uint256 (32 bytes) - toHex(oracleResponse.expiresAt, 32).substr(2) + // expiresAt: uint256 - toHex(oracleResponse.fromDomainID, 32).substr(2) + // fromDomainID: uint256 - toHex(oracleResponse.toDomainID, 32).substr(2) + // toDomainID: uint256 - oracleResponse.resourceID.substr(2); // resourceID: bytes32 - + const oracleMessage = Ethers.utils.solidityPack( + ['uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes32'], + [ + oracleResponse.ber, + oracleResponse.ter, + oracleResponse.dstGasPrice, + oracleResponse.expiresAt, + oracleResponse.fromDomainID, + oracleResponse.toDomainID, + oracleResponse.resourceID + ] + ); const messageHash = Ethers.utils.keccak256(oracleMessage); const signingKey = new Ethers.utils.SigningKey(privateKey); const messageHashBytes = Ethers.utils.arrayify(messageHash); @@ -167,11 +171,27 @@ const createOracleFeeData = (oracleResponse, privateKey, amount) => { return oracleMessage + rawSignature.substr(2) + toHex(amount, 32).substr(2); } + +const signDataWithMpc = async (originDomainID, destinationDomainID, depositNonce, depositData, resourceID) => { + const signingKey = new Ethers.utils.SigningKey(mpcPrivateKey) + + const messageHash = Ethers.utils.solidityKeccak256( + ['uint8', 'uint8', 'uint64', 'bytes', 'bytes32'], + [originDomainID, destinationDomainID, depositNonce, depositData, resourceID] + ); + + const signature = signingKey.signDigest(messageHash) + const rawSignature = Ethers.utils.joinSignature(signature) + return rawSignature +} + module.exports = { advanceBlock, advanceTime, blankFunctionSig, blankFunctionDepositerOffset, + mpcAddress, + mpcPrivateKey, toHex, abiEncode, getFunctionSignature, @@ -186,5 +206,6 @@ module.exports = { createResourceID, assertObjectsMatch, nonceAndId, - createOracleFeeData + createOracleFeeData, + signDataWithMpc }; diff --git a/test/safeCast.js b/test/safeCast.js deleted file mode 100644 index b840f11b..00000000 --- a/test/safeCast.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2020 ChainSafe Systems - * SPDX-License-Identifier: LGPL-3.0-only - */ -const TruffleAssert = require('truffle-assertions'); - -const SafeCaster = artifacts.require("SafeCaster"); - -contract('Utils - [SafeCast]', async accounts => { - let SafeCasterInstance; - - const BN = (num) => web3.utils.toBN(num); - - beforeEach(async () => { - SafeCasterInstance = await SafeCaster.new(); - }); - - it('toUint200 should revert if passed value greater than 2**200 - 1', async () => { - return TruffleAssert.reverts(SafeCasterInstance.toUint200(BN(2).pow(BN(200))), "value does not fit in 200 bits"); - }); -}); From 57648f9f0fa02f0906e91cb45395b404a047c7f2 Mon Sep 17 00:00:00 2001 From: Neuti Yoo <103201346+neutiyoo@users.noreply.github.com> Date: Fri, 3 Jun 2022 01:00:11 +0900 Subject: [PATCH 06/20] Remove SafeMath for uint256 (#555) Co-authored-by: Kirill --- contracts/ERC1155Safe.sol | 2 -- contracts/ERC20Safe.sol | 2 -- contracts/ERC721Safe.sol | 2 -- 3 files changed, 6 deletions(-) diff --git a/contracts/ERC1155Safe.sol b/contracts/ERC1155Safe.sol index b13237b0..69b83845 100644 --- a/contracts/ERC1155Safe.sol +++ b/contracts/ERC1155Safe.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import "@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser.sol"; @@ -12,7 +11,6 @@ import "@openzeppelin/contracts/token/ERC1155/presets/ERC1155PresetMinterPauser. @notice This contract is intended to be used with ERC1155Handler contract. */ contract ERC1155Safe { - using SafeMath for uint256; /** @notice Used to gain custoday of deposited token with batching. diff --git a/contracts/ERC20Safe.sol b/contracts/ERC20Safe.sol index 01f07c8e..9deac322 100644 --- a/contracts/ERC20Safe.sol +++ b/contracts/ERC20Safe.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; @@ -12,7 +11,6 @@ import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; @notice This contract is intended to be used with ERC20Handler contract. */ contract ERC20Safe { - using SafeMath for uint256; /** @notice Used to gain custody of deposited token. diff --git a/contracts/ERC721Safe.sol b/contracts/ERC721Safe.sol index 0670ac07..d9032335 100644 --- a/contracts/ERC721Safe.sol +++ b/contracts/ERC721Safe.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity 0.8.11; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "./ERC721MinterBurnerPauser.sol"; @@ -11,7 +10,6 @@ import "./ERC721MinterBurnerPauser.sol"; @notice This contract is intended to be used with ERC721Handler contract. */ contract ERC721Safe { - using SafeMath for uint256; /** @notice Used to gain custoday of deposited token. From f856f3a85ed70f548b56963213d6fac90b67b0ef Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 6 Jun 2022 17:08:19 +0300 Subject: [PATCH 07/20] Release v3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab3fe440..36037364 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/chainbridge-contracts", - "version": "2.1.3", + "version": "3.0.0", "description": "", "main": "dist/index.js", "repository": "https://github.com/ChainSafe/chainbridge-solidity.git", From 6100d61f8d0727a807ac0d24f7d98d9d0c1a0914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Tue, 7 Jun 2022 15:39:32 +0200 Subject: [PATCH 08/20] Fix which contract artifacts are published (#570) --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 36037364..ce114e3f 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,13 @@ "files": [ "dist", "build/contracts/Bridge.json", + "build/contracts/Forwarder.json", "build/contracts/ERC20Handler.json", "build/contracts/ERC721Handler.json", + "build/contracts/ERC1155Handler.json", "build/contracts/GenericHandler.json", - "build/contracts/HandlerHelpers.json" + "build/contracts/BasicFeeHandler.json", + "build/contracts/FeeHandlerWithOracle.json" ], "directories": { "test": "test" From 34cf568afaf4b821c2cabbbf0d5376a1b3f286f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Tue, 7 Jun 2022 15:51:16 +0200 Subject: [PATCH 09/20] Release v3.0.1 (#572) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce114e3f..bf2e8a9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/chainbridge-contracts", - "version": "3.0.0", + "version": "3.0.1", "description": "", "main": "dist/index.js", "repository": "https://github.com/ChainSafe/chainbridge-solidity.git", From b5c335fa4e549c623b2248797134f1eaf78bf93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Mon, 20 Jun 2022 15:42:43 +0200 Subject: [PATCH 10/20] Add `retry` function (#574) * Add retry method * Add retry method test --- contracts/Bridge.sol | 10 ++++++++ test/contractBridge/publicMethods.js | 38 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 test/contractBridge/publicMethods.js diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index cea8fcda..a9cc1e5d 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -58,6 +58,8 @@ contract Bridge is Pausable, AccessControl { event KeyRefresh(); + event Retry(string txHash); + modifier onlyAdmin() { _onlyAdmin(); _; @@ -301,6 +303,14 @@ contract Bridge is Pausable, AccessControl { emit KeyRefresh(); } + /** + @notice This method is used to trigger the process for retrying failed deposits on the MPC side. + @param txHash Transaction hash which contains deposit that should be retried + */ + function retry(string memory txHash) external { + emit Retry(txHash); + } + /** @notice Returns a boolean value. @param domainID ID of chain deposit originated from. diff --git a/test/contractBridge/publicMethods.js b/test/contractBridge/publicMethods.js new file mode 100644 index 00000000..a2fb914a --- /dev/null +++ b/test/contractBridge/publicMethods.js @@ -0,0 +1,38 @@ +/** + * Copyright 2020 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + const TruffleAssert = require('truffle-assertions'); + const Ethers = require('ethers'); + + const Helpers = require('../helpers'); + + const BridgeContract = artifacts.require("Bridge"); + + // This test does NOT include all getter methods, just + // getters that should work with only the constructor called + contract('Bridge - [public]', async (accounts) => { + const domainID = 1; + + const txHash = "0x59d881e01ca682130e550e3576b6de760951fb45b1d5dd81342132f57920bbfa"; + + let BridgeInstance; + + + beforeEach(async () => { + BridgeInstance = await BridgeContract.new(domainID); + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); + }); + + // Testing public methods + + it('Should successfully emit Retry event', async () => { + const eventTx = await BridgeInstance.retry(txHash); + + TruffleAssert.eventEmitted(eventTx, 'Retry', (event) => { + return event.txHash === txHash + }); + }); + }); From 3bcbce53f3781944ac50c6bd0434e4ae0040c2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Tue, 21 Jun 2022 07:57:23 +0200 Subject: [PATCH 11/20] Remove revert on fail for `GenericHandler` (#575) * Remove revert on fail for GenericHandler * Add tests for failed handlers execution * Fix indentation --- contracts/Bridge.sol | 2 +- contracts/handlers/GenericHandler.sol | 9 +- .../executeWithFailedHandler.js | 183 ++++++++++++++++-- 3 files changed, 173 insertions(+), 21 deletions(-) diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index a9cc1e5d..9dd929fd 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -267,7 +267,7 @@ contract Bridge is Pausable, AccessControl { usedNonces[originDomainID][depositNonce / 256] |= 1 << (depositNonce % 256); - // Reverts on failure + // Reverts for every handler except GenericHandler depositHandler.executeProposal(resourceID, data); emit ProposalExecution(originDomainID, depositNonce, dataHash); diff --git a/contracts/handlers/GenericHandler.sol b/contracts/handlers/GenericHandler.sol index fbce0b78..fffaa6e2 100644 --- a/contracts/handlers/GenericHandler.sol +++ b/contracts/handlers/GenericHandler.sol @@ -29,6 +29,8 @@ contract GenericHandler is IGenericHandler { // token contract address => is whitelisted mapping (address => bool) public _contractWhitelist; + event FailedHandlerExecution(); + modifier onlyBridge() { _onlyBridge(); _; @@ -140,8 +142,11 @@ contract GenericHandler is IGenericHandler { bytes4 sig = _contractAddressToExecuteFunctionSignature[contractAddress]; if (sig != bytes4(0)) { bytes memory callData = abi.encodePacked(sig, metaData); - (bool success,) = contractAddress.call(callData); - require(success, "delegatecall to contractAddress failed"); + (bool success, ) = contractAddress.call(callData); + + if (!success) { + emit FailedHandlerExecution(); + } } } diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index 256293be..0ff62374 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -2,10 +2,16 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); const Helpers = require('../helpers'); +const { convertCompilerOptionsFromJson } = require('typescript'); const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("HandlerRevert"); +const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); +const ERC721HandlerContract = artifacts.require("HandlerRevert"); +const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); +const ERC1155HandlerContract = artifacts.require("HandlerRevert"); +const GenericHandlerContract = artifacts.require("GenericHandler"); contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { const originDomainID = 1; @@ -13,47 +19,99 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; - const relayer2Address = accounts[4]; const initialTokenAmount = 100; const depositAmount = 10; const expectedDepositNonce = 1; + const tokenID = 1; + const erc721DepositMetadata = "0xf00d"; let BridgeInstance; let ERC20MintableInstance; let ERC20HandlerInstance; + let ERC721MintableInstance; + let ERC721HandlerInstance; + let ERC1155MintableInstance; + let ERC1155HandlerInstance; + let GenericHandlerInstance; + + let initialGenericContractAddress; + let initialGenericDepositFunctionSignature; + let initialGenericDepositFunctionDepositerOffset; + let initialGenericExecuteFunctionSignature; + + let erc20ResourceID; + let erc721ResourceID; + let erc1155ResourceID; + let erc20DepositData; + let erc20DepositProposalData; + let erc721DepositData; + let erc721DepositProposalData; + let erc1155DepositData; + let erc1155DepositProposalData; + let genericProposalData; + let genericDepositProposalDataHash; - let resourceID; - let depositData; - let depositProposalData; - let depositProposalDataHash; beforeEach(async () => { await Promise.all([ BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), - ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ERC20MintableContract.new("token721", "TOK20").then(instance => ERC20MintableInstance = instance), + ERC721MintableContract.new("token20", "TOK721", "").then(instance => ERC721MintableInstance = instance), + ERC1155MintableContract.new("TOK1155").then(instance => ERC1155MintableInstance = instance) ]); - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); - ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + ERC721HandlerInstance = await ERC721HandlerContract.new(BridgeInstance.address); + ERC1155HandlerInstance = await ERC1155HandlerContract.new(BridgeInstance.address); + GenericHandlerInstance = await GenericHandlerContract.new(BridgeInstance.address); + + erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); + erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); + genericResourceID = Helpers.createResourceID(GenericHandlerInstance.address, originDomainID); + + const mintFuncSig = Helpers.getFunctionSignature(ERC20MintableContract, 'mint'); + + initialGenericContractAddress = ERC20MintableInstance.address; + initialGenericDepositFunctionSignature = Helpers.blankFunctionSig; + initialGenericDepositFunctionDepositerOffset = Helpers.blankFunctionDepositerOffset; + initialGenericExecuteFunctionSignature = mintFuncSig; await Promise.all([ ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), - BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, erc20ResourceID, ERC20MintableInstance.address), + ERC721MintableInstance.mint(depositerAddress, tokenID, erc721DepositMetadata), + BridgeInstance.adminSetResource(ERC721HandlerInstance.address, erc721ResourceID, ERC721MintableInstance.address), + ERC1155MintableInstance.mintBatch(depositerAddress, [tokenID], [initialTokenAmount], "0x0"), + BridgeInstance.adminSetResource(ERC1155HandlerInstance.address, erc1155ResourceID, ERC1155MintableInstance.address), + BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, genericResourceID, initialGenericContractAddress, initialGenericDepositFunctionSignature, initialGenericDepositFunctionDepositerOffset, initialGenericExecuteFunctionSignature) ]); - await ERC20MintableInstance.approve(ERC20HandlerInstance.address, 5000, { from: depositerAddress }); + await Promise.all([ + ERC20MintableInstance.approve(ERC20HandlerInstance.address, 5000, { from: depositerAddress }), + ERC721MintableInstance.approve(ERC721HandlerInstance.address, tokenID, { from: depositerAddress }), + ERC1155MintableInstance.setApprovalForAll(ERC1155HandlerInstance.address, true, { from: depositerAddress }) + ]); + + + erc20DepositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) + erc20DepositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) - depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) - depositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) - depositProposalDataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + depositProposalData.substr(2)); + erc721DepositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); + erc721DepositProposalData = Helpers.createERC721DepositProposalData(tokenID, 20, recipientAddress, erc721DepositMetadata.length, erc721DepositMetadata); + + erc1155DepositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); + erc1155DepositProposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], recipientAddress, "0x"); + + genericProposalData = Helpers.createGenericDepositData(null); + genericDepositProposalDataHash = Ethers.utils.keccak256(GenericHandlerInstance.address + genericProposalData.substr(2)); // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); }); - it("Should revert if handler execute is reverted", async () => { + it("[ERC20] - Should revert if handler execute is reverted", async () => { const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( originDomainID, expectedDepositNonce); @@ -61,16 +119,16 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { assert.isFalse(depositProposalBeforeFailedExecute); const proposalSignedData = await Helpers.signDataWithMpc( - originDomainID, destinationDomainID, expectedDepositNonce, depositProposalData, resourceID + originDomainID, destinationDomainID, expectedDepositNonce, erc20DepositProposalData, erc20ResourceID ); await TruffleAssert.reverts(BridgeInstance.executeProposal( originDomainID, expectedDepositNonce, - depositProposalData, - resourceID, + erc20DepositProposalData, + erc20ResourceID, proposalSignedData, - { from: relayer2Address } + { from: relayer1Address } )); const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( @@ -79,4 +137,93 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { // depositNonce is not used assert.isFalse(depositProposalAfterFailedExecute); }); + + it("[ERC721] - Should revert if handler execute is reverted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); + + const proposalSignedData = await Helpers.signDataWithMpc( + originDomainID, destinationDomainID, expectedDepositNonce, erc721DepositProposalData, erc721ResourceID + ); + + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + erc721DepositProposalData, + erc721ResourceID, + proposalSignedData, + { from: relayer1Address } + )); + + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is not used + assert.isFalse(depositProposalAfterFailedExecute); + }); + + it("[ERC1155] - Should revert if handler execute is reverted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); + + const proposalSignedData = await Helpers.signDataWithMpc( + originDomainID, destinationDomainID, expectedDepositNonce, erc1155DepositProposalData, erc1155ResourceID + ); + + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + erc1155DepositProposalData, + erc1155ResourceID, + proposalSignedData, + { from: relayer1Address } + )); + + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is not used + assert.isFalse(depositProposalAfterFailedExecute); + }); + + it("[Generic] - Should not revert if handler execution failed. FailedHandlerExecution event should be emitted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); + + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, genericProposalData, genericResourceID); + + const executeTx = await BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + genericProposalData, + genericResourceID, + proposalSignedData, + { from: relayer1Address } + ); + + // check that "FailedHandlerExecution" event was emitted on the handler + const handlerPastEvents = await GenericHandlerInstance.getPastEvents('FailedHandlerExecution') + assert(handlerPastEvents[0].event === 'FailedHandlerExecution'); + + TruffleAssert.eventEmitted(executeTx, 'ProposalExecution', (event) => { + return event.originDomainID.toNumber() === originDomainID && + event.depositNonce.toNumber() === expectedDepositNonce && + event.dataHash === genericDepositProposalDataHash + }); + + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonce); + + // depositNonce is used + assert.isTrue(depositProposalAfterFailedExecute); + }); }); From 5811ad467c747d0606883489bb5e38ae030d3ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Fri, 1 Jul 2022 14:01:45 +0200 Subject: [PATCH 12/20] Add `executeProposals` function + switch to `abi.encode` (#578) * Use abi.encode for executeProposal * Add executeProposals function * Add helper function for signing batches of data * Add tests for executeProposals function * Add vcode to gitignore * Add Proposal struct + update executeProposals func * Fix indentation * Update helper func for executeProposals to accept an array of data * Update tests for executeProposals func * Fix unsetting nonce * Add convert decimal to padded binary helper function * Add checks for nonce bitmap before and after deposit --- .gitignore | 3 +- contracts/Bridge.sol | 73 +++- test/contractBridge/executeProposals.js | 323 ++++++++++++++++++ .../executeWithFailedHandler.js | 269 ++++++++++----- test/helpers.js | 40 ++- 5 files changed, 611 insertions(+), 97 deletions(-) create mode 100644 test/contractBridge/executeProposals.js diff --git a/.gitignore b/.gitignore index 03b5b50d..489e3638 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ coverage.json src/ethers src/web3 ganache-cli/ -dist/ \ No newline at end of file +dist/ +.vscode/ diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 9dd929fd..ab414593 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -25,6 +25,13 @@ contract Bridge is Pausable, AccessControl { IFeeHandler public _feeHandler; + struct Proposal { + uint8 originDomainID; + uint64 depositNonce; + bytes32 resourceID; + bytes data; + } + // destinationDomainID => number of deposits mapping(uint8 => uint64) public _depositCounts; // resourceID => handler address @@ -48,8 +55,11 @@ contract Bridge is Pausable, AccessControl { uint64 depositNonce, bytes32 dataHash ); + event FailedHandlerExecution( - bytes lowLevelData + bytes lowLevelData, + uint8 originDomainID, + uint64 depositNonce ); event StartKeygen(); @@ -257,7 +267,7 @@ contract Bridge is Pausable, AccessControl { function executeProposal(uint8 originDomainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID, bytes calldata signature) public whenNotPaused { require(isProposalExecuted(originDomainID, depositNonce) != true, "Deposit with provided nonce already executed"); - address signer = keccak256(abi.encodePacked(originDomainID, _domainID, depositNonce, data, resourceID)).recover(signature); + address signer = keccak256(abi.encode(originDomainID, _domainID, depositNonce, data, resourceID)).recover(signature); require(signer == _MPCAddress, "Invalid message signer"); address handler = _resourceIDToHandlerAddress[resourceID]; @@ -273,13 +283,52 @@ contract Bridge is Pausable, AccessControl { emit ProposalExecution(originDomainID, depositNonce, dataHash); } + /** + @notice Executes a batch of deposit proposals using a specified handler contract for each proposal (only if signature is signed by MPC). + @param proposals Array of Proposal which consists of: + - originDomainID ID of chain deposit originated from. + - resourceID ResourceID to be used when making deposits. + - depositNonce ID of deposit generated by origin Bridge contract. + - data Data originally provided when deposit was made. + @param signature bytes memory signature for the whole array composed of MPC key shares + @notice Emits {ProposalExecution} event for each proposal in the batch. + */ + function executeProposals(Proposal[] memory proposals, bytes memory signature) public whenNotPaused { + require(proposals.length > 0, "Proposals can't be an empty array"); + + address signer = keccak256(abi.encode(proposals)).recover(signature); + require(signer == _MPCAddress, "Invalid message signer"); + + for (uint256 i = 0; i < proposals.length; i++) { + if(isProposalExecuted(proposals[i].originDomainID, proposals[i].depositNonce)) { + continue; + } + + address handler = _resourceIDToHandlerAddress[proposals[i].resourceID]; + bytes32 dataHash = keccak256(abi.encodePacked(handler, proposals[i].data)); + + IDepositExecute depositHandler = IDepositExecute(handler); + + usedNonces[proposals[i].originDomainID][proposals[i].depositNonce / 256] |= 1 << (proposals[i].depositNonce % 256); + + try depositHandler.executeProposal(proposals[i].resourceID, proposals[i].data) { + } catch (bytes memory lowLevelData) { + emit FailedHandlerExecution(lowLevelData, proposals[i].originDomainID, proposals[i].depositNonce); + usedNonces[proposals[i].originDomainID][proposals[i].depositNonce / 256] &= ~(1 << (proposals[i].depositNonce % 256)); + continue; + } + + emit ProposalExecution(proposals[i].originDomainID, proposals[i].depositNonce, dataHash); + } + } + /** @notice Once MPC address is set, this method can't be invoked anymore. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. */ function startKeygen() external onlyAdmin { - require(_MPCAddress == address(0), "MPC address is already set"); - emit StartKeygen(); + require(_MPCAddress == address(0), "MPC address is already set"); + emit StartKeygen(); } /** @@ -288,11 +337,11 @@ contract Bridge is Pausable, AccessControl { @param MPCAddress Address that will be set as MPC address. */ function endKeygen(address MPCAddress) external onlyAdmin { - require(MPCAddress != address(0), "MPC address can't be null-address"); - require(_MPCAddress == address(0), "MPC address can't be updated"); - _MPCAddress = MPCAddress; - _unpause(_msgSender()); - emit EndKeygen(); + require(MPCAddress != address(0), "MPC address can't be null-address"); + require(_MPCAddress == address(0), "MPC address can't be updated"); + _MPCAddress = MPCAddress; + _unpause(_msgSender()); + emit EndKeygen(); } /** @@ -300,7 +349,7 @@ contract Bridge is Pausable, AccessControl { It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. */ function refreshKey() external onlyAdmin { - emit KeyRefresh(); + emit KeyRefresh(); } /** @@ -308,7 +357,7 @@ contract Bridge is Pausable, AccessControl { @param txHash Transaction hash which contains deposit that should be retried */ function retry(string memory txHash) external { - emit Retry(txHash); + emit Retry(txHash); } /** @@ -318,6 +367,6 @@ contract Bridge is Pausable, AccessControl { @return Boolean value depending if deposit nonce has already been used or not. */ function isProposalExecuted(uint8 domainID, uint256 depositNonce) public view returns (bool) { - return usedNonces[domainID][depositNonce / 256] & (1 << (depositNonce % 256)) != 0; + return usedNonces[domainID][depositNonce / 256] & (1 << (depositNonce % 256)) != 0; } } diff --git a/test/contractBridge/executeProposals.js b/test/contractBridge/executeProposals.js new file mode 100644 index 00000000..af6fdbb7 --- /dev/null +++ b/test/contractBridge/executeProposals.js @@ -0,0 +1,323 @@ +/** + * Copyright 2020 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require('truffle-assertions'); + const Ethers = require('ethers'); + + const Helpers = require('../helpers'); + + const BridgeContract = artifacts.require("Bridge"); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); + const ERC20HandlerContract = artifacts.require("ERC20Handler"); + const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); + const ERC721HandlerContract = artifacts.require("ERC721Handler"); + const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); + const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); + + contract('Bridge - [execute proposal]', async (accounts) => { + const destinationDomainID = 1; + const originDomainID = 2; + + const depositerAddress = accounts[1]; + const recipientAddress = accounts[2]; + const relayer1Address = accounts[3]; + + const tokenID = 1; + const erc721DepositMetadata = "0xf00d"; + const initialTokenAmount = 100; + const depositAmount = 10; + const expectedDepositNonces = [1,2,3]; + const feeData = '0x'; + + let BridgeInstance; + let ERC20MintableInstance; + let ERC20HandlerInstance; + let ERC721MintableInstance; + let ERC721HandlerInstance; + let ERC1155MintableInstance; + let ERC1155HandlerInstance; + + let erc20ResourceID; + let erc721ResourceID; + let erc1155ResourceID; + let resourceIDs; + let erc20DepositData; + let erc20DepositProposalData; + let erc20DataHash; + let erc721DepositData; + let erc721DepositProposalData; + let erc721DataHash; + let erc1155DepositData; + let erc1155DepositProposalData; + let erc1155DataHash; + + let proposalsForExecution; + + beforeEach(async () => { + await Promise.all([ + BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + ERC20MintableContract.new("ERC20token", "ERC20TOK").then(instance => ERC20MintableInstance = instance), + ERC721MintableContract.new("ERC721token", "ERC721TOK", "").then(instance => ERC721MintableInstance = instance), + ERC1155MintableContract.new("ERC1155TOK").then(instance => ERC1155MintableInstance = instance), + ]); + + erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, destinationDomainID), + erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, destinationDomainID), + erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, destinationDomainID); + resourceIDs = [erc20ResourceID, erc721ResourceID, erc1155ResourceID]; + contractAddresses = [ERC20MintableInstance.address, ERC721MintableInstance.address, ERC1155MintableInstance.address]; + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + ERC721HandlerInstance = await ERC721HandlerContract.new(BridgeInstance.address); + ERC1155HandlerInstance = await ERC1155HandlerContract.new(BridgeInstance.address); + + await Promise.all([ + ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, erc20ResourceID, ERC20MintableInstance.address), + ERC721MintableInstance.grantRole(await ERC721MintableInstance.MINTER_ROLE(), ERC721HandlerInstance.address), + ERC721MintableInstance.mint(depositerAddress, tokenID, ""), + BridgeInstance.adminSetResource(ERC721HandlerInstance.address, erc721ResourceID, ERC721MintableInstance.address), + BridgeInstance.adminSetResource(ERC1155HandlerInstance.address, erc1155ResourceID, ERC1155MintableInstance.address), + ERC1155MintableInstance.mintBatch(depositerAddress, [tokenID], [initialTokenAmount], "0x0"), + ]); + + await Promise.all([ + ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }), + ERC721MintableInstance.approve(ERC721HandlerInstance.address, tokenID, { from: depositerAddress }), + ERC1155MintableInstance.setApprovalForAll(ERC1155HandlerInstance.address, true, { from: depositerAddress }) + ]); + + erc20DepositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) + erc20DepositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) + erc20DataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + erc20DepositProposalData.substr(2)); + + erc721DepositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); + erc721DepositProposalData = Helpers.createERC721DepositProposalData(tokenID, 20, recipientAddress, erc721DepositMetadata.length, erc721DepositMetadata); + erc721DataHash = Ethers.utils.keccak256(ERC721HandlerInstance.address + erc721DepositProposalData.substr(2)); + + erc1155DepositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); + erc1155DepositProposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], recipientAddress, "0x"); + erc1155DataHash = Ethers.utils.keccak256(ERC1155HandlerInstance.address + erc1155DepositProposalData.substr(2)); + + proposalsForExecution = [{ + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[0], + resourceID: erc20ResourceID, + data: erc20DepositProposalData + }, + { + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[1], + resourceID: erc721ResourceID, + data: erc721DepositProposalData + }, + { + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[2], + resourceID: erc1155ResourceID, + data: erc1155DepositProposalData + }]; + + // set MPC address to unpause the Bridge + await BridgeInstance.endKeygen(Helpers.mpcAddress); + }); + + it('should create and execute executeProposal successfully', async () => { + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc20ResourceID, + erc20DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc721ResourceID, + erc721DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc1155ResourceID, + erc1155DepositData, + feeData, + { from: depositerAddress } + )); + + const executeTx = await BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ); + + await TruffleAssert.passes(executeTx); + + // check that deposit nonces had been marked as used in bitmap + expectedDepositNonces.forEach( + async (_,index) => { + assert.isTrue(await BridgeInstance.isProposalExecuted(originDomainID, expectedDepositNonces[index])); + }); + + // check that tokens are transferred to recipient address + const recipientERC20Balance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC20Balance.toNumber(), depositAmount); + + const recipientERC721Balance = await ERC721MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC721Balance.toNumber(), 1); + + const recipientERC1155Balance = await ERC1155MintableInstance.balanceOf(recipientAddress, destinationDomainID); + assert.strictEqual(recipientERC1155Balance.toNumber(), depositAmount); + }); + + it('should skip executing proposal if deposit nonce is already used', async () => { + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc20ResourceID, + erc20DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc721ResourceID, + erc721DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc1155ResourceID, + erc1155DepositData, + feeData, + { from: depositerAddress } + )); + + const executeTx = await BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ); + + + await TruffleAssert.passes(executeTx); + + // check that deposit nonces had been marked as used in bitmap + expectedDepositNonces.forEach( + async (_,index) => { + assert.isTrue(await BridgeInstance.isProposalExecuted(originDomainID, expectedDepositNonces[index])); + }); + + // check that tokens are transferred to recipient address + const recipientERC20Balance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC20Balance.toNumber(), depositAmount); + + const recipientERC721Balance = await ERC721MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC721Balance.toNumber(), 1); + + const recipientERC1155Balance = await ERC1155MintableInstance.balanceOf(recipientAddress, destinationDomainID); + assert.strictEqual(recipientERC1155Balance.toNumber(), depositAmount); + + + const skipExecuteTx = await BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ); + + // check that no ProposalExecution events are emitted + assert.equal(skipExecuteTx.logs.length, 0); + }); + + it('should fail executing proposals if empty array is passed for execution', async () => { + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + + await TruffleAssert.reverts(BridgeInstance.executeProposals( + [], + proposalSignedData, + { from: relayer1Address } + ), "Proposals can't be an empty array"); + }); + + it('executeProposal event should be emitted with expected values', async () => { + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc20ResourceID, + erc20DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc721ResourceID, + erc721DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc1155ResourceID, + erc1155DepositData, + feeData, + { from: depositerAddress } + )); + + const executeTx = await BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ); + + TruffleAssert.eventEmitted(executeTx, 'ProposalExecution', (event) => { + return event.originDomainID.toNumber() === originDomainID && + event.depositNonce.toNumber() === expectedDepositNonces[0] && + event.dataHash === erc20DataHash + }); + + // check that ProposalExecution has been emitted with expected values for ERC721 + assert.equal(executeTx.logs[1].args.originDomainID, originDomainID); + assert.equal(executeTx.logs[1].args.depositNonce, expectedDepositNonces[1]); + assert.equal(executeTx.logs[1].args.dataHash, erc721DataHash); + + // check that ProposalExecution has been emitted with expected values for ERC1155 + assert.equal(executeTx.logs[2].args.originDomainID, originDomainID); + assert.equal(executeTx.logs[2].args.depositNonce, expectedDepositNonces[2]); + assert.equal(executeTx.logs[2].args.dataHash, erc1155DataHash); + + // check that deposit nonces had been marked as used in bitmap + expectedDepositNonces.forEach( + async (_,index) => { + assert.isTrue(await BridgeInstance.isProposalExecuted(originDomainID, expectedDepositNonces[index])); + }); + + // check that tokens are transferred to recipient address + const recipientERC20Balance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC20Balance.toNumber(), depositAmount); + + const recipientERC721Balance = await ERC721MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC721Balance.toNumber(), 1); + + const recipientERC1155Balance = await ERC1155MintableInstance.balanceOf(recipientAddress, destinationDomainID); + assert.strictEqual(recipientERC1155Balance.toNumber(), depositAmount); + }); +}); diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index 0ff62374..df984ef4 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -8,9 +8,10 @@ const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("HandlerRevert"); const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); -const ERC721HandlerContract = artifacts.require("HandlerRevert"); +const ERC721HandlerContract = artifacts.require("ERC721Handler"); const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("HandlerRevert"); +const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); const GenericHandlerContract = artifacts.require("GenericHandler"); contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { @@ -20,11 +21,12 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; - const initialTokenAmount = 100; - const depositAmount = 10; - const expectedDepositNonce = 1; const tokenID = 1; const erc721DepositMetadata = "0xf00d"; + const initialTokenAmount = 100; + const depositAmount = 10; + const expectedDepositNonces = [1, 2, 3]; + const feeData = '0x'; let BridgeInstance; let ERC20MintableInstance; @@ -33,6 +35,8 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { let ERC721HandlerInstance; let ERC1155MintableInstance; let ERC1155HandlerInstance; + let CentrifugeAssetInstance; + let GenericHandlerInstance; let initialGenericContractAddress; @@ -52,13 +56,15 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { let genericProposalData; let genericDepositProposalDataHash; + let proposalsForExecution; beforeEach(async () => { await Promise.all([ BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), ERC20MintableContract.new("token721", "TOK20").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token20", "TOK721", "").then(instance => ERC721MintableInstance = instance), - ERC1155MintableContract.new("TOK1155").then(instance => ERC1155MintableInstance = instance) + ERC1155MintableContract.new("TOK1155").then(instance => ERC1155MintableInstance = instance), + CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance) ]); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); @@ -71,16 +77,15 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { erc1155ResourceID = Helpers.createResourceID(ERC1155MintableInstance.address, originDomainID); genericResourceID = Helpers.createResourceID(GenericHandlerInstance.address, originDomainID); - const mintFuncSig = Helpers.getFunctionSignature(ERC20MintableContract, 'mint'); - initialGenericContractAddress = ERC20MintableInstance.address; initialGenericDepositFunctionSignature = Helpers.blankFunctionSig; initialGenericDepositFunctionDepositerOffset = Helpers.blankFunctionDepositerOffset; - initialGenericExecuteFunctionSignature = mintFuncSig; + initialGenericExecuteFunctionSignature = Helpers.getFunctionSignature(ERC20MintableContract, 'mint');; await Promise.all([ ERC20MintableInstance.mint(depositerAddress, initialTokenAmount), BridgeInstance.adminSetResource(ERC20HandlerInstance.address, erc20ResourceID, ERC20MintableInstance.address), + ERC721MintableInstance.grantRole(await ERC721MintableInstance.MINTER_ROLE(), ERC721HandlerInstance.address), ERC721MintableInstance.mint(depositerAddress, tokenID, erc721DepositMetadata), BridgeInstance.adminSetResource(ERC721HandlerInstance.address, erc721ResourceID, ERC721MintableInstance.address), ERC1155MintableInstance.mintBatch(depositerAddress, [tokenID], [initialTokenAmount], "0x0"), @@ -94,12 +99,13 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { ERC1155MintableInstance.setApprovalForAll(ERC1155HandlerInstance.address, true, { from: depositerAddress }) ]); - erc20DepositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) erc20DepositProposalData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress) + erc20DepositProposalDataHash = Ethers.utils.keccak256(ERC20HandlerInstance.address + erc20DepositProposalData.substr(2)); erc721DepositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); erc721DepositProposalData = Helpers.createERC721DepositProposalData(tokenID, 20, recipientAddress, erc721DepositMetadata.length, erc721DepositMetadata); + erc721DepositProposalDataHash = Ethers.utils.keccak256(ERC721HandlerInstance.address + erc721DepositProposalData.substr(2)); erc1155DepositData = Helpers.createERC1155DepositData([tokenID], [depositAmount]); erc1155DepositProposalData = Helpers.createERC1155DepositProposalData([tokenID], [depositAmount], recipientAddress, "0x"); @@ -107,24 +113,43 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { genericProposalData = Helpers.createGenericDepositData(null); genericDepositProposalDataHash = Ethers.utils.keccak256(GenericHandlerInstance.address + genericProposalData.substr(2)); + proposalsForExecution = [{ + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[0], + resourceID: erc20ResourceID, + data: erc20DepositProposalData + }, + { + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[1], + resourceID: erc721ResourceID, + data: erc721DepositProposalData + }, + { + originDomainID: originDomainID, + depositNonce: expectedDepositNonces[2], + resourceID: genericResourceID, + data: genericProposalData + }]; + // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); }); - it("[ERC20] - Should revert if handler execute is reverted", async () => { + it("[executeProposal - ERC20] - Should revert if handler execute is reverted", async () => { const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + originDomainID, expectedDepositNonces[0]); // depositNonce is not used assert.isFalse(depositProposalBeforeFailedExecute); const proposalSignedData = await Helpers.signDataWithMpc( - originDomainID, destinationDomainID, expectedDepositNonce, erc20DepositProposalData, erc20ResourceID + originDomainID, destinationDomainID, expectedDepositNonces[0], erc20DepositProposalData, erc20ResourceID ); await TruffleAssert.reverts(BridgeInstance.executeProposal( originDomainID, - expectedDepositNonce, + expectedDepositNonces[0], erc20DepositProposalData, erc20ResourceID, proposalSignedData, @@ -132,98 +157,182 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { )); const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + originDomainID, expectedDepositNonces[0]); // depositNonce is not used assert.isFalse(depositProposalAfterFailedExecute); }); - it("[ERC721] - Should revert if handler execute is reverted", async () => { - const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + it("[executeProposal - ERC721] - Should revert if handler execute is reverted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); - // depositNonce is not used - assert.isFalse(depositProposalBeforeFailedExecute); + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); - const proposalSignedData = await Helpers.signDataWithMpc( - originDomainID, destinationDomainID, expectedDepositNonce, erc721DepositProposalData, erc721ResourceID - ); + const proposalSignedData = await Helpers.signDataWithMpc( + originDomainID, destinationDomainID, expectedDepositNonces[0], erc721DepositProposalData, erc721ResourceID + ); - await TruffleAssert.reverts(BridgeInstance.executeProposal( - originDomainID, - expectedDepositNonce, - erc721DepositProposalData, - erc721ResourceID, - proposalSignedData, - { from: relayer1Address } - )); + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonces[0], + erc721DepositProposalData, + erc721ResourceID, + proposalSignedData, + { from: relayer1Address } + )); - const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); - // depositNonce is not used - assert.isFalse(depositProposalAfterFailedExecute); + // depositNonce is not used + assert.isFalse(depositProposalAfterFailedExecute); }); - it("[ERC1155] - Should revert if handler execute is reverted", async () => { - const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + it("[executeProposal - ERC1155] - Should revert if handler execute is reverted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); - // depositNonce is not used - assert.isFalse(depositProposalBeforeFailedExecute); + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); - const proposalSignedData = await Helpers.signDataWithMpc( - originDomainID, destinationDomainID, expectedDepositNonce, erc1155DepositProposalData, erc1155ResourceID - ); + const proposalSignedData = await Helpers.signDataWithMpc( + originDomainID, destinationDomainID, expectedDepositNonces[0], erc1155DepositProposalData, erc1155ResourceID + ); - await TruffleAssert.reverts(BridgeInstance.executeProposal( - originDomainID, - expectedDepositNonce, - erc1155DepositProposalData, - erc1155ResourceID, - proposalSignedData, - { from: relayer1Address } - )); + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonces[0], + erc1155DepositProposalData, + erc1155ResourceID, + proposalSignedData, + { from: relayer1Address } + )); - const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); - // depositNonce is not used - assert.isFalse(depositProposalAfterFailedExecute); + // depositNonce is not used + assert.isFalse(depositProposalAfterFailedExecute); }); - it("[Generic] - Should not revert if handler execution failed. FailedHandlerExecution event should be emitted", async () => { - const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + it("[executeProposal - Generic] - Should not revert if handler execution failed. FailedHandlerExecution event should be emitted", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); - // depositNonce is not used - assert.isFalse(depositProposalBeforeFailedExecute); + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); - const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonce, genericProposalData, genericResourceID); + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, destinationDomainID, expectedDepositNonces[0], genericProposalData, genericResourceID); - const executeTx = await BridgeInstance.executeProposal( - originDomainID, - expectedDepositNonce, - genericProposalData, - genericResourceID, - proposalSignedData, - { from: relayer1Address } - ); + const executeTx = await BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonces[0], + genericProposalData, + genericResourceID, + proposalSignedData, + { from: relayer1Address } + ); + + // check that "FailedHandlerExecution" event was emitted on the handler + const handlerPastEvents = await GenericHandlerInstance.getPastEvents('FailedHandlerExecution') + assert(handlerPastEvents[0].event === 'FailedHandlerExecution'); + + TruffleAssert.eventEmitted(executeTx, 'ProposalExecution', (event) => { + return event.originDomainID.toNumber() === originDomainID && + event.depositNonce.toNumber() === expectedDepositNonces[0] && + event.dataHash === genericDepositProposalDataHash + }); + + const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); + + // depositNonce is used + assert.isTrue(depositProposalAfterFailedExecute); + }); + + it("[executeProposals] - Should not revert if handler execute is reverted and continue to process next execution. FailedHandlerExecution event should be emitted with expected values.", async () => { + const depositProposalBeforeFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0]); + + // depositNonce is not used + assert.isFalse(depositProposalBeforeFailedExecute); + + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + + // depositerAddress makes initial deposit of depositAmount + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc721ResourceID, + erc721DepositData, + feeData, + { from: depositerAddress } + )); - // check that "FailedHandlerExecution" event was emitted on the handler - const handlerPastEvents = await GenericHandlerInstance.getPastEvents('FailedHandlerExecution') - assert(handlerPastEvents[0].event === 'FailedHandlerExecution'); + // check that all nonces in nonce set are 0 + const noncesSetBeforeDeposit = await BridgeInstance.usedNonces(originDomainID, 0); + assert.equal( + Helpers.decimalToPaddedBinary(noncesSetBeforeDeposit.toNumber()), + // nonces: ...6543210 + "0000000000000000000000000000000000000000000000000000000000000000" + ); - TruffleAssert.eventEmitted(executeTx, 'ProposalExecution', (event) => { + const executeTx = await BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ); + + TruffleAssert.eventEmitted(executeTx, 'FailedHandlerExecution', (event) => { return event.originDomainID.toNumber() === originDomainID && - event.depositNonce.toNumber() === expectedDepositNonce && - event.dataHash === genericDepositProposalDataHash - }); + event.depositNonce.toNumber() === expectedDepositNonces[0] && + Ethers.utils.parseBytes32String('0x' + event.lowLevelData.slice(-64)) === 'Something bad happened' + }); + + const erc20depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[0] + ); + // depositNonce for failed ERC20 deposit is unset + assert.isFalse(erc20depositProposalAfterFailedExecute); + + const erc721depositProposal = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[1] + ); + // depositNonce for ERC721 deposit is used + assert.isTrue(erc721depositProposal); + + const genericDepositProposal = await BridgeInstance.isProposalExecuted( + originDomainID, expectedDepositNonces[2] + ); + // depositNonce for generic deposit is used + assert.isTrue(genericDepositProposal); + + + // recipient ERC20 token balances hasn't changed + const recipientERC20Balance = await ERC20MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC20Balance.toNumber(), 0); - const depositProposalAfterFailedExecute = await BridgeInstance.isProposalExecuted( - originDomainID, expectedDepositNonce); + // recipient ERC721 token balance has changed to 1 token + const recipientERC721Balance = await ERC721MintableInstance.balanceOf(recipientAddress); + assert.strictEqual(recipientERC721Balance.toNumber(), 1); - // depositNonce is used - assert.isTrue(depositProposalAfterFailedExecute); - }); + // check that other nonces in nonce set are not affected after failed deposit + const noncesSetAfterDeposit = await BridgeInstance.usedNonces(originDomainID, 0); + assert.equal( + Helpers.decimalToPaddedBinary(noncesSetAfterDeposit.toNumber()), + // nonces: ...6543210 + "0000000000000000000000000000000000000000000000000000000000001100" + ); + + // check that 'ProposalExecution' event has been emitted with proper values for ERC721 deposit + assert.equal(executeTx.logs[1].args.originDomainID, 1); + assert.equal(executeTx.logs[1].args.depositNonce, expectedDepositNonces[1]); + assert.equal(executeTx.logs[1].args.dataHash, erc721DepositProposalDataHash); + + // check that 'ProposalExecution' event has been emitted with proper values for generic deposit + assert.equal(executeTx.logs[2].args.originDomainID, 1); + assert.equal(executeTx.logs[2].args.depositNonce, expectedDepositNonces[2]); + assert.equal(executeTx.logs[2].args.dataHash, genericDepositProposalDataHash); + }); }); diff --git a/test/helpers.js b/test/helpers.js index 3a9b70ef..591168e7 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -175,9 +175,11 @@ const createOracleFeeData = (oracleResponse, privateKey, amount) => { const signDataWithMpc = async (originDomainID, destinationDomainID, depositNonce, depositData, resourceID) => { const signingKey = new Ethers.utils.SigningKey(mpcPrivateKey) - const messageHash = Ethers.utils.solidityKeccak256( - ['uint8', 'uint8', 'uint64', 'bytes', 'bytes32'], - [originDomainID, destinationDomainID, depositNonce, depositData, resourceID] + const messageHash = Ethers.utils.keccak256( + Ethers.utils.defaultAbiCoder.encode( + ['uint8', 'uint8', 'uint64', 'bytes', 'bytes32'], + [originDomainID, destinationDomainID, depositNonce, depositData, resourceID] + ) ); const signature = signingKey.signDigest(messageHash) @@ -185,6 +187,34 @@ const signDataWithMpc = async (originDomainID, destinationDomainID, depositNonce return rawSignature } +const signArrayOfDataWithMpc = async (proposals) => { + const signingKey = new Ethers.utils.SigningKey(mpcPrivateKey) + + const messageHash = Ethers.utils.keccak256( + Ethers.utils.defaultAbiCoder.encode( + [{ + type: "tuple[]", + name: "proposals", + components: [ + { name: "originDomainID", type: 'uint8' }, + { name: "depositNonce", type: 'uint64' }, + { name: "resourceID", type: 'bytes32'}, + { name: "data", type: 'bytes'} + ] + }], + [proposals] + ) + ); + + const signature = signingKey.signDigest(messageHash) + const rawSignature = Ethers.utils.joinSignature(signature) + return rawSignature +} + +const decimalToPaddedBinary = (decimal) => { + return decimal.toString(2).padStart(64,'0'); +} + module.exports = { advanceBlock, advanceTime, @@ -207,5 +237,7 @@ module.exports = { assertObjectsMatch, nonceAndId, createOracleFeeData, - signDataWithMpc + signDataWithMpc, + signArrayOfDataWithMpc, + decimalToPaddedBinary }; From 3be61a7198b560a8cf8fe0ed69ec4bc54d6ae878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Wed, 6 Jul 2022 10:01:18 +0200 Subject: [PATCH 13/20] Add `destinationDomainID` to signature in `executeProposals` function (#587) * Add destinationDomainID to executeProposals signature * Add destinationDomainID to signing data for executeProposals func * Add invalid destinationDomainID tests for executeProposals + update old tests * Make domainID immutable --- contracts/Bridge.sol | 7 +-- test/contractBridge/executeProposal.js | 24 ++++++++++ test/contractBridge/executeProposals.js | 45 +++++++++++++++++-- .../executeWithFailedHandler.js | 2 +- test/helpers.js | 8 ++-- 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index ab414593..4aa6ba25 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -17,10 +17,7 @@ import "./interfaces/IFeeHandler.sol"; contract Bridge is Pausable, AccessControl { using ECDSA for bytes32; - - - - uint8 public _domainID; + uint8 public immutable _domainID; address public _MPCAddress; IFeeHandler public _feeHandler; @@ -296,7 +293,7 @@ contract Bridge is Pausable, AccessControl { function executeProposals(Proposal[] memory proposals, bytes memory signature) public whenNotPaused { require(proposals.length > 0, "Proposals can't be an empty array"); - address signer = keccak256(abi.encode(proposals)).recover(signature); + address signer = keccak256(abi.encode(proposals, _domainID)).recover(signature); require(signer == _MPCAddress, "Invalid message signer"); for (uint256 i = 0; i < proposals.length; i++) { diff --git a/test/contractBridge/executeProposal.js b/test/contractBridge/executeProposal.js index f2ddadd0..825669f1 100644 --- a/test/contractBridge/executeProposal.js +++ b/test/contractBridge/executeProposal.js @@ -15,6 +15,7 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('Bridge - [execute proposal]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const invalidDestinationDomainID = 3; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -176,4 +177,27 @@ contract('Bridge - [execute proposal]', async (accounts) => { const recipientBalance = await ERC20MintableInstance.balanceOf(recipientAddress); assert.strictEqual(recipientBalance.toNumber(), depositAmount); }); + + it('should fail to executeProposal if signed destinationDomainID in not the domain on which proposal should be executed', async () => { + const proposalSignedData = await Helpers.signDataWithMpc(originDomainID, invalidDestinationDomainID, expectedDepositNonce, depositProposalData, resourceID); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + resourceID, + depositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.reverts(BridgeInstance.executeProposal( + originDomainID, + expectedDepositNonce, + depositProposalData, + resourceID, + proposalSignedData, + { from: relayer1Address } + ), "Invalid message signer"); + }); }); diff --git a/test/contractBridge/executeProposals.js b/test/contractBridge/executeProposals.js index af6fdbb7..39a00943 100644 --- a/test/contractBridge/executeProposals.js +++ b/test/contractBridge/executeProposals.js @@ -19,6 +19,7 @@ contract('Bridge - [execute proposal]', async (accounts) => { const destinationDomainID = 1; const originDomainID = 2; + const invalidDestinationDomainID = 3; const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -125,7 +126,7 @@ }); it('should create and execute executeProposal successfully', async () => { - const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, destinationDomainID); // depositerAddress makes initial deposit of depositAmount assert.isFalse(await BridgeInstance.paused()); @@ -179,7 +180,7 @@ }); it('should skip executing proposal if deposit nonce is already used', async () => { - const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, destinationDomainID); // depositerAddress makes initial deposit of depositAmount assert.isFalse(await BridgeInstance.paused()); @@ -244,7 +245,7 @@ }); it('should fail executing proposals if empty array is passed for execution', async () => { - const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, destinationDomainID); await TruffleAssert.reverts(BridgeInstance.executeProposals( [], @@ -254,7 +255,7 @@ }); it('executeProposal event should be emitted with expected values', async () => { - const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, destinationDomainID); // depositerAddress makes initial deposit of depositAmount assert.isFalse(await BridgeInstance.paused()); @@ -320,4 +321,40 @@ const recipientERC1155Balance = await ERC1155MintableInstance.balanceOf(recipientAddress, destinationDomainID); assert.strictEqual(recipientERC1155Balance.toNumber(), depositAmount); }); + + it('should fail to executeProposals if signed destinationDomainID in not the domain on which proposal should be executed', async () => { + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, invalidDestinationDomainID); + + // depositerAddress makes initial deposit of depositAmount + assert.isFalse(await BridgeInstance.paused()); + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc20ResourceID, + erc20DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc721ResourceID, + erc721DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.passes(BridgeInstance.deposit( + originDomainID, + erc1155ResourceID, + erc1155DepositData, + feeData, + { from: depositerAddress } + )); + + await TruffleAssert.reverts(BridgeInstance.executeProposals( + proposalsForExecution, + proposalSignedData, + { from: relayer1Address } + ), "Invalid message signer"); + }); }); diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index df984ef4..152f1567 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -259,7 +259,7 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { // depositNonce is not used assert.isFalse(depositProposalBeforeFailedExecute); - const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution); + const proposalSignedData = await Helpers.signArrayOfDataWithMpc(proposalsForExecution, destinationDomainID); // depositerAddress makes initial deposit of depositAmount await TruffleAssert.passes(BridgeInstance.deposit( diff --git a/test/helpers.js b/test/helpers.js index 591168e7..cd78b512 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -187,7 +187,7 @@ const signDataWithMpc = async (originDomainID, destinationDomainID, depositNonce return rawSignature } -const signArrayOfDataWithMpc = async (proposals) => { +const signArrayOfDataWithMpc = async (proposals, destinationDomainID) => { const signingKey = new Ethers.utils.SigningKey(mpcPrivateKey) const messageHash = Ethers.utils.keccak256( @@ -201,8 +201,10 @@ const signArrayOfDataWithMpc = async (proposals) => { { name: "resourceID", type: 'bytes32'}, { name: "data", type: 'bytes'} ] - }], - [proposals] + }, + 'uint8' + ], + [proposals, destinationDomainID] ) ); From 726c4767000bf41e4aabdf2a18ecafa5f7279d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20Petruni=C4=87?= Date: Wed, 6 Jul 2022 12:01:09 +0200 Subject: [PATCH 14/20] Bridge admin access segregator (#585) * Implement access control segregator * Add access control set functions * Fix solidity errors * Fix existing bridge deployments in tests * Add access control segregator tests * Remove TODO * Fix misaligned JS in tests * Replace functoin name with function signature * Fix typo * Fix tests * Remove prefix from function access --- contracts/Bridge.sol | 72 ++++++++++--------- .../interfaces/IAccessControlSegregator.sol | 16 +++++ contracts/utils/AccessControlSegregator.sol | 55 ++++++++++++++ test/contractBridge/admin.js | 27 +++---- test/contractBridge/depositERC1155.js | 3 +- test/contractBridge/depositERC20.js | 3 +- test/contractBridge/depositERC721.js | 3 +- test/contractBridge/depositGeneric.js | 3 +- test/contractBridge/executeProposal.js | 3 +- test/contractBridge/executeProposals.js | 2 +- .../executeWithFailedHandler.js | 3 +- test/contractBridge/publicMethods.js | 3 +- test/e2e/erc1155/differentChainsMock.js | 5 +- test/e2e/erc1155/sameChain.js | 3 +- test/e2e/erc20/differentChainsMock.js | 6 +- test/e2e/erc20/sameChain.js | 3 +- test/e2e/erc721/differentChainsMock.js | 5 +- test/e2e/erc721/sameChain.js | 3 +- test/gasBenchmarks/deployments.js | 14 +++- test/gasBenchmarks/deposits.js | 3 +- test/gasBenchmarks/executeProposal.js | 3 +- test/handlers/erc1155/burnList.js | 7 +- test/handlers/erc1155/deposit.js | 2 +- test/handlers/erc1155/depositBurn.js | 2 +- test/handlers/erc20/burnList.js | 8 +-- test/handlers/erc20/constructor.js | 7 +- test/handlers/erc20/deposit.js | 3 +- test/handlers/erc20/depositBurn.js | 2 +- test/handlers/erc20/isWhitelisted.js | 7 +- .../erc20/setResourceIDAndContractAddress.js | 7 +- test/handlers/erc721/burnList.js | 5 +- test/handlers/erc721/deposit.js | 3 +- test/handlers/erc721/depositBurn.js | 2 +- test/handlers/fee/basic/calculateFee.js | 2 +- test/handlers/fee/basic/changeFee.js | 5 +- test/handlers/fee/basic/collectFee.js | 2 +- test/handlers/fee/basic/distributeFee.js | 2 +- test/handlers/fee/withOracle/admin.js | 5 +- test/handlers/fee/withOracle/calculateFee.js | 3 +- test/handlers/fee/withOracle/collectFee.js | 2 +- test/handlers/fee/withOracle/distributeFee.js | 2 +- test/handlers/generic/constructor.js | 4 +- test/handlers/generic/deposit.js | 2 +- test/handlers/generic/executeProposal.js | 2 +- test/helpers.js | 29 +++++++- .../accessControlSegregator/constructor.js | 46 ++++++++++++ .../accessControlSegregator/grantAccess.js | 41 +++++++++++ 47 files changed, 325 insertions(+), 115 deletions(-) create mode 100644 contracts/interfaces/IAccessControlSegregator.sol create mode 100644 contracts/utils/AccessControlSegregator.sol create mode 100644 test/utils/accessControlSegregator/constructor.js create mode 100644 test/utils/accessControlSegregator/grantAccess.js diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 4aa6ba25..8838fc1a 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -2,26 +2,30 @@ pragma solidity 0.8.11; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "./utils/AccessControl.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; import "./utils/Pausable.sol"; import "./interfaces/IDepositExecute.sol"; import "./interfaces/IERCHandler.sol"; import "./interfaces/IGenericHandler.sol"; import "./interfaces/IFeeHandler.sol"; +import "./interfaces/IAccessControlSegregator.sol"; /** @title Facilitates deposits and creation of deposit proposals, and deposit executions. @author ChainSafe Systems. */ -contract Bridge is Pausable, AccessControl { +contract Bridge is Pausable, Context { using ECDSA for bytes32; + uint8 public immutable _domainID; address public _MPCAddress; IFeeHandler public _feeHandler; + IAccessControlSegregator public _accessControl; + struct Proposal { uint8 originDomainID; uint64 depositNonce; @@ -39,6 +43,7 @@ contract Bridge is Pausable, AccessControl { mapping(uint8 => mapping(uint256 => uint256)) public usedNonces; event FeeHandlerChanged(address newFeeHandler); + event AccessControlChanged(address newAccessControl); event Deposit( uint8 destinationDomainID, bytes32 resourceID, @@ -67,13 +72,13 @@ contract Bridge is Pausable, AccessControl { event Retry(string txHash); - modifier onlyAdmin() { - _onlyAdmin(); + modifier onlyAllowed() { + _onlyAllowed(msg.sig, _msgSender()); _; } - function _onlyAdmin() private view { - require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "sender doesn't have admin role"); + function _onlyAllowed(bytes4 sig, address sender) private view { + require(_accessControl.hasAccess(sig, sender), "sender doesn't have access to function"); } function _msgSender() internal override view returns (address) { @@ -87,34 +92,23 @@ contract Bridge is Pausable, AccessControl { } /** - @notice Initializes Bridge, creates and grants {_msgSender()} the admin role and - sets the inital state of the Bridge to paused. + @notice Initializes Bridge, creates and grants {_msgSender()} the admin role, sets access control + contract for bridge and sets the inital state of the Bridge to paused. @param domainID ID of chain the Bridge contract exists on. + @param accessControl Address of access control contract. */ - constructor (uint8 domainID) public { + constructor (uint8 domainID, address accessControl) public { _domainID = domainID; + _accessControl = IAccessControlSegregator(accessControl); - _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _pause(_msgSender()); } - /** - @notice Removes admin role from {_msgSender()} and grants it to {newAdmin}. - @notice Only callable by an address that currently has the admin role. - @param newAdmin Address that admin role will be granted to. - */ - function renounceAdmin(address newAdmin) external onlyAdmin { - address sender = _msgSender(); - require(sender != newAdmin, 'Cannot renounce oneself'); - grantRole(DEFAULT_ADMIN_ROLE, newAdmin); - renounceRole(DEFAULT_ADMIN_ROLE, sender); - } - /** @notice Pauses deposits, proposal creation and voting, and deposit executions. @notice Only callable by an address that currently has the admin role. */ - function adminPauseTransfers() external onlyAdmin { + function adminPauseTransfers() external onlyAllowed { _pause(_msgSender()); } @@ -123,7 +117,7 @@ contract Bridge is Pausable, AccessControl { @notice Only callable by an address that currently has the admin role. @notice MPC address has to be set before Bridge can be unpaused */ - function adminUnpauseTransfers() external onlyAdmin { + function adminUnpauseTransfers() external onlyAllowed { require(_MPCAddress != address(0), "MPC address not set"); _unpause(_msgSender()); } @@ -136,7 +130,7 @@ contract Bridge is Pausable, AccessControl { @param resourceID ResourceID to be used when making deposits. @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. */ - function adminSetResource(address handlerAddress, bytes32 resourceID, address tokenAddress) external onlyAdmin { + function adminSetResource(address handlerAddress, bytes32 resourceID, address tokenAddress) external onlyAllowed { _resourceIDToHandlerAddress[resourceID] = handlerAddress; IERCHandler handler = IERCHandler(handlerAddress); handler.setResource(resourceID, tokenAddress); @@ -157,7 +151,7 @@ contract Bridge is Pausable, AccessControl { bytes4 depositFunctionSig, uint256 depositFunctionDepositerOffset, bytes4 executeFunctionSig - ) external onlyAdmin { + ) external onlyAllowed { _resourceIDToHandlerAddress[resourceID] = handlerAddress; IGenericHandler handler = IGenericHandler(handlerAddress); handler.setResource(resourceID, contractAddress, depositFunctionSig, depositFunctionDepositerOffset, executeFunctionSig); @@ -169,7 +163,7 @@ contract Bridge is Pausable, AccessControl { @param handlerAddress Address of handler resource will be set for. @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. */ - function adminSetBurnable(address handlerAddress, address tokenAddress) external onlyAdmin { + function adminSetBurnable(address handlerAddress, address tokenAddress) external onlyAllowed { IERCHandler handler = IERCHandler(handlerAddress); handler.setBurnable(tokenAddress); } @@ -180,7 +174,7 @@ contract Bridge is Pausable, AccessControl { @param domainID Domain ID for increasing nonce. @param nonce The nonce value to be set. */ - function adminSetDepositNonce(uint8 domainID, uint64 nonce) external onlyAdmin { + function adminSetDepositNonce(uint8 domainID, uint64 nonce) external onlyAllowed { require(nonce > _depositCounts[domainID], "Does not allow decrements of the nonce"); _depositCounts[domainID] = nonce; } @@ -191,16 +185,26 @@ contract Bridge is Pausable, AccessControl { @param forwarder Forwarder address to be added. @param valid Decision for the specific forwarder. */ - function adminSetForwarder(address forwarder, bool valid) external onlyAdmin { + function adminSetForwarder(address forwarder, bool valid) external onlyAllowed { isValidForwarder[forwarder] = valid; } + /** + @notice Changes access control contract address. + @notice Only callable by admin. + @param newAccessControl Address {_accessControl} will be updated to. + */ + function adminChangeAccessControl(address newAccessControl) external onlyAllowed { + _accessControl = IAccessControlSegregator(newAccessControl); + emit AccessControlChanged(newAccessControl); + } + /** @notice Changes deposit fee handler contract address. @notice Only callable by admin. @param newFeeHandler Address {_feeHandler} will be updated to. */ - function adminChangeFeeHandler(address newFeeHandler) external onlyAdmin { + function adminChangeFeeHandler(address newFeeHandler) external onlyAllowed { _feeHandler = IFeeHandler(newFeeHandler); emit FeeHandlerChanged(newFeeHandler); } @@ -213,7 +217,7 @@ contract Bridge is Pausable, AccessControl { function adminWithdraw( address handlerAddress, bytes memory data - ) external onlyAdmin { + ) external onlyAllowed { IERCHandler handler = IERCHandler(handlerAddress); handler.withdraw(data); } @@ -323,7 +327,7 @@ contract Bridge is Pausable, AccessControl { @notice Once MPC address is set, this method can't be invoked anymore. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. */ - function startKeygen() external onlyAdmin { + function startKeygen() external onlyAllowed { require(_MPCAddress == address(0), "MPC address is already set"); emit StartKeygen(); } @@ -333,7 +337,7 @@ contract Bridge is Pausable, AccessControl { It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. @param MPCAddress Address that will be set as MPC address. */ - function endKeygen(address MPCAddress) external onlyAdmin { + function endKeygen(address MPCAddress) external onlyAllowed { require(MPCAddress != address(0), "MPC address can't be null-address"); require(_MPCAddress == address(0), "MPC address can't be updated"); _MPCAddress = MPCAddress; @@ -345,7 +349,7 @@ contract Bridge is Pausable, AccessControl { @notice It's used to trigger the belonging process on the MPC side. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. */ - function refreshKey() external onlyAdmin { + function refreshKey() external onlyAllowed { emit KeyRefresh(); } diff --git a/contracts/interfaces/IAccessControlSegregator.sol b/contracts/interfaces/IAccessControlSegregator.sol new file mode 100644 index 00000000..bf70b9e1 --- /dev/null +++ b/contracts/interfaces/IAccessControlSegregator.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; + +/** + @title Interface to be used with contracts that want per function access control. + @author ChainSafe Systems. + */ +interface IAccessControlSegregator { + /** + @notice Returns boolean value if account has access to function. + @param sig Function identifier. + @param account Address of account. + @return Boolean value depending if account has access. + */ + function hasAccess(bytes4 sig, address account) external view returns (bool); +} diff --git a/contracts/utils/AccessControlSegregator.sol b/contracts/utils/AccessControlSegregator.sol new file mode 100644 index 00000000..0390446a --- /dev/null +++ b/contracts/utils/AccessControlSegregator.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; + +/** + @title Handles access control per contract function. + @author ChainSafe Systems. + @notice This contract is intended to be used by the Bridge contract. + */ +contract AccessControlSegregator { + // function signature => address has access + mapping(bytes4 => address) public functionAccess; + + bytes4 public constant GRANT_ACCESS_SIG = AccessControlSegregator(address(0)).grantAccess.selector; + + /** + @notice Initializes access control to functions and sets initial + access to grantAccess function. + @param functions List of functions to be granted access to. + @param accounts List of accounts. + */ + constructor(bytes4[] memory functions, address[] memory accounts) public { + require(accounts.length == functions.length, "array length should be equal"); + + _grantAccess(GRANT_ACCESS_SIG, msg.sender); + for (uint i=0; i < accounts.length; i++) { + _grantAccess(functions[i], accounts[i]); + } + } + + /** + @notice Returns boolean value if account has access to function. + @param sig Function identifier. + @param account Address of account. + @return Boolean value depending if account has access. + */ + function hasAccess(bytes4 sig, address account) public view returns (bool) { + return functionAccess[sig] == account; + } + + /** + @notice Grants access to an account for a function. + @notice Set account to zero address to revoke access. + @param sig Function identifier. + @param account Address of account. + */ + function grantAccess(bytes4 sig, address account) public { + require(hasAccess(GRANT_ACCESS_SIG, msg.sender), "sender doesn't have grant access rights"); + + _grantAccess(sig, account); + } + + function _grantAccess(bytes4 sig, address account) private { + functionAccess[sig] = account; + } +} diff --git a/test/contractBridge/admin.js b/test/contractBridge/admin.js index 6e3170a6..76779ba8 100644 --- a/test/contractBridge/admin.js +++ b/test/contractBridge/admin.js @@ -31,12 +31,11 @@ contract('Bridge - [admin]', async (accounts) => { let withdrawData = ''; const assertOnlyAdmin = (method, ...params) => { - return TruffleAssert.reverts(method(...params, {from: nonAdminAddress}), "sender doesn't have admin role"); + return TruffleAssert.reverts(method(...params, {from: nonAdminAddress}), "sender doesn't have access to function"); }; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID); - ADMIN_ROLE = await BridgeInstance.DEFAULT_ADMIN_ROLE(); + BridgeInstance = await Helpers.deployBridge(domainID, expectedBridgeAdmin); }); // Testing pauseable methods @@ -98,7 +97,7 @@ contract('Bridge - [admin]', async (accounts) => { await TruffleAssert.reverts(BridgeInstance.endKeygen(nullAddress), "MPC address can't be null-address"); }); - it('Should fail if admin tries to updated MPC address', async () => { + it('Should fail if admin tries to update MPC address', async () => { await BridgeInstance.endKeygen(Helpers.mpcAddress); await TruffleAssert.reverts(BridgeInstance.endKeygen(someAddress), "MPC address can't be updated"); @@ -114,19 +113,6 @@ contract('Bridge - [admin]', async (accounts) => { await assertOnlyAdmin(BridgeInstance.refreshKey); }); - - // Testing ownership methods - - it('Bridge admin should be expectedBridgeAdmin', async () => { - assert.isTrue(await BridgeInstance.hasRole(ADMIN_ROLE, expectedBridgeAdmin)); - }); - - it('Bridge admin should be changed to expectedBridgeAdmin', async () => { - const expectedBridgeAdmin2 = accounts[1]; - await TruffleAssert.passes(BridgeInstance.renounceAdmin(expectedBridgeAdmin2)) - assert.isTrue(await BridgeInstance.hasRole(ADMIN_ROLE, expectedBridgeAdmin2)); - }); - // Set Handler Address it('Should set a Resource ID for handler address', async () => { @@ -245,4 +231,11 @@ contract('Bridge - [admin]', async (accounts) => { const newNonce = 2; await TruffleAssert.reverts(BridgeInstance.adminSetDepositNonce(domainID, newNonce), "Does not allow decrements of the nonce"); }); + + // Change access control contract + + it('Should require admin role to change access control contract', async () => { + await assertOnlyAdmin(BridgeInstance.adminChangeAccessControl, someAddress) + }) + }); diff --git a/test/contractBridge/depositERC1155.js b/test/contractBridge/depositERC1155.js index c68afd0a..3509ec62 100644 --- a/test/contractBridge/depositERC1155.js +++ b/test/contractBridge/depositERC1155.js @@ -14,6 +14,7 @@ const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); contract('Bridge - [deposit - ERC1155]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const originChainTokenID = 42; @@ -30,7 +31,7 @@ contract('Bridge - [deposit - ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID) + BridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress) ]); diff --git a/test/contractBridge/depositERC20.js b/test/contractBridge/depositERC20.js index bc8dc9ca..4b40d7a5 100644 --- a/test/contractBridge/depositERC20.js +++ b/test/contractBridge/depositERC20.js @@ -14,6 +14,7 @@ const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('Bridge - [deposit - ERC20]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -30,7 +31,7 @@ contract('Bridge - [deposit - ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), - BridgeInstance = await BridgeContract.new(originDomainID) + BridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress) ]); resourceID = Helpers.createResourceID(OriginERC20MintableInstance.address, originDomainID); diff --git a/test/contractBridge/depositERC721.js b/test/contractBridge/depositERC721.js index 9724c26a..30925480 100644 --- a/test/contractBridge/depositERC721.js +++ b/test/contractBridge/depositERC721.js @@ -14,6 +14,7 @@ const ERC721HandlerContract = artifacts.require("ERC721Handler"); contract('Bridge - [deposit - ERC721]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -32,7 +33,7 @@ contract('Bridge - [deposit - ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance) + BridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress) ]); originResourceID = Helpers.createResourceID(OriginERC721MintableInstance.address, originDomainID); diff --git a/test/contractBridge/depositGeneric.js b/test/contractBridge/depositGeneric.js index cc5e18bd..bee19f08 100644 --- a/test/contractBridge/depositGeneric.js +++ b/test/contractBridge/depositGeneric.js @@ -16,6 +16,7 @@ contract('Bridge - [deposit - Generic]', async (accounts) => { const destinationDomainID = 2; const expectedDepositNonce = 1; const feeData = '0x'; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; let BridgeInstance; @@ -30,7 +31,7 @@ contract('Bridge - [deposit - Generic]', async (accounts) => { beforeEach(async () => { await Promise.all([ CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), - BridgeInstance = BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance) + BridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress) ]); resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, originDomainID) diff --git a/test/contractBridge/executeProposal.js b/test/contractBridge/executeProposal.js index 825669f1..154e9fd2 100644 --- a/test/contractBridge/executeProposal.js +++ b/test/contractBridge/executeProposal.js @@ -17,6 +17,7 @@ contract('Bridge - [execute proposal]', async (accounts) => { const destinationDomainID = 2; const invalidDestinationDomainID = 3; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -41,7 +42,7 @@ contract('Bridge - [execute proposal]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/contractBridge/executeProposals.js b/test/contractBridge/executeProposals.js index 39a00943..f4b2128c 100644 --- a/test/contractBridge/executeProposals.js +++ b/test/contractBridge/executeProposals.js @@ -58,7 +58,7 @@ beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]), ERC20MintableContract.new("ERC20token", "ERC20TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("ERC721token", "ERC721TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("ERC1155TOK").then(instance => ERC1155MintableInstance = instance), diff --git a/test/contractBridge/executeWithFailedHandler.js b/test/contractBridge/executeWithFailedHandler.js index 152f1567..0c239095 100644 --- a/test/contractBridge/executeWithFailedHandler.js +++ b/test/contractBridge/executeWithFailedHandler.js @@ -17,6 +17,7 @@ const GenericHandlerContract = artifacts.require("GenericHandler"); contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -60,7 +61,7 @@ contract('Bridge - [execute - FailedHandlerExecution]', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC20MintableContract.new("token721", "TOK20").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token20", "TOK721", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK1155").then(instance => ERC1155MintableInstance = instance), diff --git a/test/contractBridge/publicMethods.js b/test/contractBridge/publicMethods.js index a2fb914a..34a44c15 100644 --- a/test/contractBridge/publicMethods.js +++ b/test/contractBridge/publicMethods.js @@ -15,12 +15,13 @@ const domainID = 1; const txHash = "0x59d881e01ca682130e550e3576b6de760951fb45b1d5dd81342132f57920bbfa"; + const adminAddress = accounts[0] let BridgeInstance; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID); + BridgeInstance = await Helpers.deployBridge(domainID, adminAddress), // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); diff --git a/test/e2e/erc1155/differentChainsMock.js b/test/e2e/erc1155/differentChainsMock.js index d099c51b..56d266a1 100644 --- a/test/e2e/erc1155/differentChainsMock.js +++ b/test/e2e/erc1155/differentChainsMock.js @@ -11,6 +11,7 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const originRelayer2Address = accounts[3]; @@ -40,8 +41,8 @@ contract('E2E ERC1155 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), + OriginBridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress), + DestinationBridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC1155MintableContract.new("TOK").then(instance => OriginERC1155MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => DestinationERC1155MintableInstance = instance) ]); diff --git a/test/e2e/erc1155/sameChain.js b/test/e2e/erc1155/sameChain.js index 7c4d9abe..993b33f6 100644 --- a/test/e2e/erc1155/sameChain.js +++ b/test/e2e/erc1155/sameChain.js @@ -11,6 +11,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -35,7 +36,7 @@ contract('E2E ERC1155 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]); diff --git a/test/e2e/erc20/differentChainsMock.js b/test/e2e/erc20/differentChainsMock.js index 2c864ace..64170b9c 100644 --- a/test/e2e/erc20/differentChainsMock.js +++ b/test/e2e/erc20/differentChainsMock.js @@ -8,6 +8,8 @@ const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); contract('E2E ERC20 - Two EVM Chains', async accounts => { + const adminAddress = accounts[0] + const originDomainID = 1; const originRelayer1Address = accounts[3]; @@ -45,8 +47,8 @@ contract('E2E ERC20 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), + OriginBridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress), + DestinationBridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC20MintableContract.new("token", "TOK").then(instance => OriginERC20MintableInstance = instance), ERC20MintableContract.new("token", "TOK").then(instance => DestinationERC20MintableInstance = instance) ]); diff --git a/test/e2e/erc20/sameChain.js b/test/e2e/erc20/sameChain.js index 3ba69579..b1d36b32 100644 --- a/test/e2e/erc20/sameChain.js +++ b/test/e2e/erc20/sameChain.js @@ -11,6 +11,7 @@ contract('E2E ERC20 - Same Chain', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -31,7 +32,7 @@ contract('E2E ERC20 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/e2e/erc721/differentChainsMock.js b/test/e2e/erc721/differentChainsMock.js index 030c93e1..1e6f0a1d 100644 --- a/test/e2e/erc721/differentChainsMock.js +++ b/test/e2e/erc721/differentChainsMock.js @@ -11,6 +11,7 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const originRelayer1Address = accounts[3]; @@ -39,8 +40,8 @@ contract('E2E ERC721 - Two EVM Chains', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => OriginBridgeInstance = instance), - BridgeContract.new(destinationDomainID).then(instance => DestinationBridgeInstance = instance), + OriginBridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress), + DestinationBridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC721MintableContract.new("token", "TOK", "").then(instance => OriginERC721MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => DestinationERC721MintableInstance = instance) ]); diff --git a/test/e2e/erc721/sameChain.js b/test/e2e/erc721/sameChain.js index 67bdca0f..69a5db01 100644 --- a/test/e2e/erc721/sameChain.js +++ b/test/e2e/erc721/sameChain.js @@ -11,6 +11,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; const relayer1Address = accounts[3]; @@ -34,7 +35,7 @@ contract('E2E ERC721 - Same Chain', async accounts => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]); diff --git a/test/gasBenchmarks/deployments.js b/test/gasBenchmarks/deployments.js index 3f8e071f..10447487 100644 --- a/test/gasBenchmarks/deployments.js +++ b/test/gasBenchmarks/deployments.js @@ -3,6 +3,7 @@ * SPDX-License-Identifier: LGPL-3.0-only */ const BridgeContract = artifacts.require("Bridge"); +const AccessControlSegregatorContract = artifacts.require("AccessControlSegregator"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); @@ -13,7 +14,7 @@ const ERC20SafeContract = artifacts.require("ERC20Safe"); const ERC721SafeContract = artifacts.require("ERC721Safe"); const ERC1155SafeContract = artifacts.require("ERC1155Safe"); -contract('Gas Benchmark - [contract deployments]', async () => { +contract('Gas Benchmark - [contract deployments]', async (accounts) => { const domainID = 1; const centrifugeAssetMinCount = 1; const gasBenchmarks = []; @@ -21,9 +22,18 @@ contract('Gas Benchmark - [contract deployments]', async () => { let BridgeInstance; it('Should deploy all contracts and print benchmarks', async () => { - let contractInstances = [await BridgeContract.new(domainID).then(instance => BridgeInstance = instance)]; + let accessControlInstance = await AccessControlSegregatorContract.new( + [ + "0x80ae1c28", "0xad71c7d2", "0xcb10f215", "0x5a1ad87c", "0x8c0c2631", + "0xedc20c3c", "0xd15ef64e", "0x9d33b6d4", "0x8b63aebf", "0xbd2a1820", + "0x6ba6db6b", "0xd2e5fae9", "0xf5f63b39", + ], + Array(13).fill(accounts[0]) + ); + let contractInstances = [accessControlInstance]; contractInstances = contractInstances.concat( await Promise.all([ + await BridgeContract.new(domainID, accessControlInstance.address).then(instance => BridgeInstance = instance), ERC20HandlerContract.new(BridgeInstance.address), ERC721HandlerContract.new(BridgeInstance.address), ERC1155HandlerContract.new(BridgeInstance.address), diff --git a/test/gasBenchmarks/deposits.js b/test/gasBenchmarks/deposits.js index 9fa5bde4..a2cee852 100644 --- a/test/gasBenchmarks/deposits.js +++ b/test/gasBenchmarks/deposits.js @@ -21,6 +21,7 @@ const Helpers = require('../helpers'); contract('Gas Benchmark - [Deposits]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -57,7 +58,7 @@ contract('Gas Benchmark - [Deposits]', async (accounts) => { before(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, adminAddress), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), diff --git a/test/gasBenchmarks/executeProposal.js b/test/gasBenchmarks/executeProposal.js index f95fd39d..1395eccd 100644 --- a/test/gasBenchmarks/executeProposal.js +++ b/test/gasBenchmarks/executeProposal.js @@ -23,6 +23,7 @@ const ThreeArgumentsContract = artifacts.require("ThreeArguments"); contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { const originDomainID = 1; const destinationDomainID = 2; + const adminAddress = accounts[0] const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; @@ -64,7 +65,7 @@ contract('Gas Benchmark - [Execute Proposal]', async (accounts) => { before(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, adminAddress), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance), diff --git a/test/handlers/erc1155/burnList.js b/test/handlers/erc1155/burnList.js index f5deceb9..3ddda03a 100644 --- a/test/handlers/erc1155/burnList.js +++ b/test/handlers/erc1155/burnList.js @@ -6,11 +6,12 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); -const BridgeContract = artifacts.require("Bridge"); +const Helpers =require('../../helpers'); + const ERC1155MintableContract = artifacts.require("ERC1155PresetMinterPauser"); const ERC1155HandlerContract = artifacts.require("ERC1155Handler"); -contract('ERC1155Handler - [Burn ERC1155]', async () => { +contract('ERC1155Handler - [Burn ERC1155]', async (accounts) => { const domainID = 1; let BridgeInstance; @@ -24,7 +25,7 @@ contract('ERC1155Handler - [Burn ERC1155]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]); diff --git a/test/handlers/erc1155/deposit.js b/test/handlers/erc1155/deposit.js index d8278252..fb96ff91 100644 --- a/test/handlers/erc1155/deposit.js +++ b/test/handlers/erc1155/deposit.js @@ -33,7 +33,7 @@ contract('ERC1155Handler - [Deposit ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance = instance) ]) diff --git a/test/handlers/erc1155/depositBurn.js b/test/handlers/erc1155/depositBurn.js index 6ddf9333..cb8c6d6e 100644 --- a/test/handlers/erc1155/depositBurn.js +++ b/test/handlers/erc1155/depositBurn.js @@ -35,7 +35,7 @@ contract('ERC1155Handler - [Deposit Burn ERC1155]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance1 = instance), ERC1155MintableContract.new("TOK").then(instance => ERC1155MintableInstance2 = instance) ]) diff --git a/test/handlers/erc20/burnList.js b/test/handlers/erc20/burnList.js index b4e8f7c9..2ca6d17f 100644 --- a/test/handlers/erc20/burnList.js +++ b/test/handlers/erc20/burnList.js @@ -6,14 +6,14 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); -const BridgeContract = artifacts.require("Bridge"); +const Helpers = require('../../helpers'); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); -contract('ERC20Handler - [Burn ERC20]', async () => { +contract('ERC20Handler - [Burn ERC20]', async (accounts) => { const domainID = 1; - let RelayerInstance; let BridgeInstance; let ERC20MintableInstance1; let ERC20MintableInstance2; @@ -25,7 +25,7 @@ contract('ERC20Handler - [Burn ERC20]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]); diff --git a/test/handlers/erc20/constructor.js b/test/handlers/erc20/constructor.js index ec4c72ca..85c64106 100644 --- a/test/handlers/erc20/constructor.js +++ b/test/handlers/erc20/constructor.js @@ -6,11 +6,12 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); -const BridgeContract = artifacts.require("Bridge"); +const Helpers = require('../../helpers'); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); -contract('ERC20Handler - [constructor]', async () => { +contract('ERC20Handler - [constructor]', async (accounts) => { const domainID = 1; let BridgeInstance; @@ -23,7 +24,7 @@ contract('ERC20Handler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance3 = instance) diff --git a/test/handlers/erc20/deposit.js b/test/handlers/erc20/deposit.js index ca5117b7..f68aba63 100644 --- a/test/handlers/erc20/deposit.js +++ b/test/handlers/erc20/deposit.js @@ -7,7 +7,6 @@ const Ethers = require('ethers'); const Helpers = require('../../helpers'); -const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); @@ -31,7 +30,7 @@ contract('ERC20Handler - [Deposit ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/handlers/erc20/depositBurn.js b/test/handlers/erc20/depositBurn.js index f54fa889..b40b457c 100644 --- a/test/handlers/erc20/depositBurn.js +++ b/test/handlers/erc20/depositBurn.js @@ -34,7 +34,7 @@ contract('ERC20Handler - [Deposit Burn ERC20]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) diff --git a/test/handlers/erc20/isWhitelisted.js b/test/handlers/erc20/isWhitelisted.js index 4d73da90..f05a623d 100644 --- a/test/handlers/erc20/isWhitelisted.js +++ b/test/handlers/erc20/isWhitelisted.js @@ -6,11 +6,12 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); -const BridgeContract = artifacts.require("Bridge"); +const Helpers = require('../../helpers'); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); -contract('ERC20Handler - [isWhitelisted]', async () => { +contract('ERC20Handler - [isWhitelisted]', async (accounts) => { const AbiCoder = new Ethers.utils.AbiCoder(); const domainID = 1; @@ -24,7 +25,7 @@ contract('ERC20Handler - [isWhitelisted]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance1 = instance), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance2 = instance) ]) diff --git a/test/handlers/erc20/setResourceIDAndContractAddress.js b/test/handlers/erc20/setResourceIDAndContractAddress.js index 98b396ad..ce3867b7 100644 --- a/test/handlers/erc20/setResourceIDAndContractAddress.js +++ b/test/handlers/erc20/setResourceIDAndContractAddress.js @@ -6,11 +6,12 @@ const TruffleAssert = require('truffle-assertions'); const Ethers = require('ethers'); -const BridgeContract = artifacts.require("Bridge"); +const Helpers = require('../../helpers'); + const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); -contract('ERC20Handler - [setResourceIDAndContractAddress]', async () => { +contract('ERC20Handler - [setResourceIDAndContractAddress]', async (accounts) => { const AbiCoder = new Ethers.utils.AbiCoder(); const domainID = 1; @@ -23,7 +24,7 @@ contract('ERC20Handler - [setResourceIDAndContractAddress]', async () => { let burnableContractAddresses; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID); + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC20MintableInstance1 = await ERC20MintableContract.new("token", "TOK"); initialResourceIDs = [Ethers.utils.hexZeroPad((ERC20MintableInstance1.address + Ethers.utils.hexlify(domainID).substr(2)), 32)]; diff --git a/test/handlers/erc721/burnList.js b/test/handlers/erc721/burnList.js index 19ad31f6..84687a61 100644 --- a/test/handlers/erc721/burnList.js +++ b/test/handlers/erc721/burnList.js @@ -8,11 +8,10 @@ const Ethers = require('ethers'); const Helpers =require('../../helpers'); -const BridgeContract = artifacts.require("Bridge"); const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); -contract('ERC721Handler - [Burn ERC721]', async () => { +contract('ERC721Handler - [Burn ERC721]', async (accounts) => { const domainID = 1; let BridgeInstance; @@ -26,7 +25,7 @@ contract('ERC721Handler - [Burn ERC721]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) diff --git a/test/handlers/erc721/deposit.js b/test/handlers/erc721/deposit.js index c78b016e..929840b8 100644 --- a/test/handlers/erc721/deposit.js +++ b/test/handlers/erc721/deposit.js @@ -7,7 +7,6 @@ const Ethers = require('ethers'); const Helpers = require('../../helpers'); -const BridgeContract = artifacts.require("Bridge"); const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); const ERC721HandlerContract = artifacts.require("ERC721Handler"); @@ -32,7 +31,7 @@ contract('ERC721Handler - [Deposit ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance = instance) ]) diff --git a/test/handlers/erc721/depositBurn.js b/test/handlers/erc721/depositBurn.js index 0cd88e31..c7c9a8eb 100644 --- a/test/handlers/erc721/depositBurn.js +++ b/test/handlers/erc721/depositBurn.js @@ -35,7 +35,7 @@ contract('ERC721Handler - [Deposit Burn ERC721]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance1 = instance), ERC721MintableContract.new("token", "TOK", "").then(instance => ERC721MintableInstance2 = instance) ]) diff --git a/test/handlers/fee/basic/calculateFee.js b/test/handlers/fee/basic/calculateFee.js index fea9a8f6..b4515303 100644 --- a/test/handlers/fee/basic/calculateFee.js +++ b/test/handlers/fee/basic/calculateFee.js @@ -31,7 +31,7 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), - BridgeInstance = BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance) + BridgeInstance = BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]) ]); resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); diff --git a/test/handlers/fee/basic/changeFee.js b/test/handlers/fee/basic/changeFee.js index 363e9d39..4b4abf3b 100644 --- a/test/handlers/fee/basic/changeFee.js +++ b/test/handlers/fee/basic/changeFee.js @@ -6,7 +6,8 @@ const TruffleAssert = require("truffle-assertions"); const Ethers = require("ethers"); -const BridgeContract = artifacts.require("Bridge"); +const Helpers = require('../../../helpers'); + const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); contract("BasicFeeHandler - [changeFee]", async accounts => { @@ -20,7 +21,7 @@ contract("BasicFeeHandler - [changeFee]", async accounts => { let BridgeInstance; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); }); it("[sanity] contract should be deployed successfully", async () => { diff --git a/test/handlers/fee/basic/collectFee.js b/test/handlers/fee/basic/collectFee.js index 7e9eb604..ea27b085 100644 --- a/test/handlers/fee/basic/collectFee.js +++ b/test/handlers/fee/basic/collectFee.js @@ -34,7 +34,7 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/handlers/fee/basic/distributeFee.js b/test/handlers/fee/basic/distributeFee.js index 9e8ffa7d..25593186 100644 --- a/test/handlers/fee/basic/distributeFee.js +++ b/test/handlers/fee/basic/distributeFee.js @@ -38,7 +38,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) ]); diff --git a/test/handlers/fee/withOracle/admin.js b/test/handlers/fee/withOracle/admin.js index 0130a943..67d26c05 100644 --- a/test/handlers/fee/withOracle/admin.js +++ b/test/handlers/fee/withOracle/admin.js @@ -5,7 +5,8 @@ const TruffleAssert = require("truffle-assertions"); - const BridgeContract = artifacts.require("Bridge"); + const Helpers = require("../../../helpers"); + const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); contract("FeeHandlerWithOracle - [admin]", async accounts => { @@ -20,7 +21,7 @@ let FeeHandlerWithOracleInstance; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); }); diff --git a/test/handlers/fee/withOracle/calculateFee.js b/test/handlers/fee/withOracle/calculateFee.js index b18abd2d..308bd2bd 100644 --- a/test/handlers/fee/withOracle/calculateFee.js +++ b/test/handlers/fee/withOracle/calculateFee.js @@ -8,7 +8,6 @@ const Ethers = require("ethers"); const Helpers = require("../../../helpers"); -const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); @@ -45,7 +44,7 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { */ beforeEach(async () => { - BridgeInstance = await BridgeContract.new(domainID).then(instance => BridgeInstance = instance); + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); diff --git a/test/handlers/fee/withOracle/collectFee.js b/test/handlers/fee/withOracle/collectFee.js index 41b9f620..c50f6d67 100644 --- a/test/handlers/fee/withOracle/collectFee.js +++ b/test/handlers/fee/withOracle/collectFee.js @@ -48,7 +48,7 @@ */ beforeEach(async () => { - BridgeInstance = await BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance); + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); diff --git a/test/handlers/fee/withOracle/distributeFee.js b/test/handlers/fee/withOracle/distributeFee.js index 4cd09db7..5e8c1226 100644 --- a/test/handlers/fee/withOracle/distributeFee.js +++ b/test/handlers/fee/withOracle/distributeFee.js @@ -34,7 +34,7 @@ }; beforeEach(async () => { - BridgeInstance = await BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance); + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); diff --git a/test/handlers/generic/constructor.js b/test/handlers/generic/constructor.js index 7a54269c..30b8b7cc 100644 --- a/test/handlers/generic/constructor.js +++ b/test/handlers/generic/constructor.js @@ -12,7 +12,7 @@ const BridgeContract = artifacts.require("Bridge"); const GenericHandlerContract = artifacts.require("GenericHandler"); const CentrifugeAssetContract = artifacts.require("CentrifugeAsset"); -contract('GenericHandler - [constructor]', async () => { +contract('GenericHandler - [constructor]', async (accounts) => { const domainID = 1; const centrifugeAssetMinCount = 1; const blankFunctionSig = '0x00000000'; @@ -31,7 +31,7 @@ contract('GenericHandler - [constructor]', async () => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(domainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance1 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance2 = instance), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance3 = instance) diff --git a/test/handlers/generic/deposit.js b/test/handlers/generic/deposit.js index 9b9c40ce..4ead650e 100644 --- a/test/handlers/generic/deposit.js +++ b/test/handlers/generic/deposit.js @@ -44,7 +44,7 @@ contract('GenericHandler - [deposit]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(originDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), CentrifugeAssetContract.new().then(instance => CentrifugeAssetInstance = instance), NoArgumentContract.new().then(instance => NoArgumentInstance = instance), OneArgumentContract.new().then(instance => OneArgumentInstance = instance), diff --git a/test/handlers/generic/executeProposal.js b/test/handlers/generic/executeProposal.js index f1e1e04c..14d1836a 100644 --- a/test/handlers/generic/executeProposal.js +++ b/test/handlers/generic/executeProposal.js @@ -38,7 +38,7 @@ contract('GenericHandler - [Execute Proposal]', async (accounts) => { beforeEach(async () => { await Promise.all([ - BridgeContract.new(destinationDomainID).then(instance => BridgeInstance = instance), + BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]), CentrifugeAssetContract.new(centrifugeAssetMinCount).then(instance => CentrifugeAssetInstance = instance) ]); diff --git a/test/helpers.js b/test/helpers.js index cd78b512..dc1f3b84 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -5,6 +5,9 @@ const Ethers = require('ethers'); + const AccessControlSegregatorContract = artifacts.require("AccessControlSegregator"); + const BridgeContract = artifacts.require("Bridge"); + const blankFunctionSig = '0x00000000'; const blankFunctionDepositerOffset = 0; const AbiCoder = new Ethers.utils.AbiCoder; @@ -217,6 +220,29 @@ const decimalToPaddedBinary = (decimal) => { return decimal.toString(2).padStart(64,'0'); } +const deployBridge = async (domainID, admin) => { + let accessControlInstance = await AccessControlSegregatorContract.new( + [ + "0x80ae1c28", // adminPauseTransfers + "0xffaac0eb", // adminUnpauseTransfers + "0xcb10f215", // adminSetResource + "0x5a1ad87c", // adminSetGenericResource + "0x8c0c2631", // adminSetBurnable + "0xedc20c3c", // adminSetDepositNonce + "0xd15ef64e", // adminSetForwarder + "0x9d33b6d4", // adminChangeAccessControl + "0x8b63aebf", // adminChangeFeeHandler + "0xbd2a1820", // adminWithdraw + "0x6ba6db6b", // startKeygen + "0xd2e5fae9", // endKeygen + "0xf5f63b39", // refreshKey + + ], + Array(13).fill(admin) + ) + return await BridgeContract.new(domainID, accessControlInstance.address); +} + module.exports = { advanceBlock, advanceTime, @@ -241,5 +267,6 @@ module.exports = { createOracleFeeData, signDataWithMpc, signArrayOfDataWithMpc, - decimalToPaddedBinary + decimalToPaddedBinary, + deployBridge }; diff --git a/test/utils/accessControlSegregator/constructor.js b/test/utils/accessControlSegregator/constructor.js new file mode 100644 index 00000000..99276eef --- /dev/null +++ b/test/utils/accessControlSegregator/constructor.js @@ -0,0 +1,46 @@ +/** + * Copyright 2020 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require('truffle-assertions'); +const Ethers = require('ethers'); + +const AccessControlSegregatorContract = artifacts.require("AccessControlSegregator"); + +contract('AccessControlSegregator - [constructor]', async (accounts) => { + let AccessControlSegregatorInstance; + let initialFunctions = ["0x29a71964", "0x78728c73", "0x2a64052b", "0x3a24555a"]; + let initialAccessHolders = [accounts[1], accounts[2], accounts[3], accounts[4]]; + + let grantAccessSig = "0xa973ec93" + + beforeEach(async () => { + AccessControlSegregatorInstance = await AccessControlSegregatorContract.new(initialFunctions, initialAccessHolders); + }); + + it('[sanity] should deploy contract successfully', async () => { + await TruffleAssert.passes(AccessControlSegregatorContract.new([], [])); + }); + + it('should revert if length of functions and accounts array is different', async () => { + await TruffleAssert.reverts(AccessControlSegregatorContract.new(["0xa973ec93", "0x78728c73"], [accounts[0]]), "array length should be equal"); + }); + + it('should grant deployer grant access rights', async () => { + assert.isTrue(await AccessControlSegregatorInstance.hasAccess(grantAccessSig, accounts[0])); + }); + + it('should grant function access specified in params', async () => { + for( let i = 0; i < initialFunctions.length; i++) { + assert.isTrue(await AccessControlSegregatorInstance.hasAccess(initialFunctions[i], initialAccessHolders[i])); + } + }); + + it('should replace grant access of deployer if specified in params', async () => { + let accessControlInstance = await AccessControlSegregatorContract.new([grantAccessSig], [accounts[1]]); + + assert.isFalse(await accessControlInstance.hasAccess(grantAccessSig, accounts[0])); + assert.isTrue(await accessControlInstance.hasAccess(grantAccessSig, accounts[1])); + }); + }); diff --git a/test/utils/accessControlSegregator/grantAccess.js b/test/utils/accessControlSegregator/grantAccess.js new file mode 100644 index 00000000..b64b675f --- /dev/null +++ b/test/utils/accessControlSegregator/grantAccess.js @@ -0,0 +1,41 @@ +/** + * Copyright 2020 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require('truffle-assertions'); +const Ethers = require('ethers'); + +const AccessControlSegregatorContract = artifacts.require("AccessControlSegregator"); + +contract('AccessControlSegregator - [grant access]', async (accounts) => { + let AccessControlSegregatorInstance; + + const functionSignature = "0x29a71964"; + + beforeEach(async () => { + AccessControlSegregatorInstance = await AccessControlSegregatorContract.new([], []); + }); + + it('hasAccess should return false if access not granted', async () => { + assert.isFalse(await AccessControlSegregatorInstance.hasAccess(functionSignature, accounts[2])); + }); + + it('should revert if sender doesn\'t have grant access rights', async () => { + await TruffleAssert.reverts(AccessControlSegregatorInstance.grantAccess(functionSignature, accounts[2], { from: accounts[1]}), "sender doesn't have grant access rights"); + }); + + it('should successfully grant access to a function', async () => { + await TruffleAssert.passes(AccessControlSegregatorInstance.grantAccess(functionSignature, accounts[2])); + + assert.isTrue(await AccessControlSegregatorInstance.hasAccess(functionSignature, accounts[2])); + }); + + it('should successfully regrant access', async () => { + await TruffleAssert.passes(AccessControlSegregatorInstance.grantAccess(functionSignature, accounts[2])); + assert.isTrue(await AccessControlSegregatorInstance.hasAccess(functionSignature, accounts[2])); + + await TruffleAssert.passes(AccessControlSegregatorInstance.grantAccess(functionSignature, accounts[3])); + assert.isTrue(await AccessControlSegregatorInstance.hasAccess(functionSignature, accounts[3])); + }); + }); From 9cd2120065d0abcdc7509e9321560ebe6e78904a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Tue, 12 Jul 2022 12:52:47 +0200 Subject: [PATCH 15/20] Fix Bridge descriptions after access segregation (#589) * Fix Bridge descriptions after access segregation * Improve onlyAllowed modifier descripion --- contracts/Bridge.sol | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 8838fc1a..9ec19d96 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -106,7 +106,8 @@ contract Bridge is Pausable, Context { /** @notice Pauses deposits, proposal creation and voting, and deposit executions. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. */ function adminPauseTransfers() external onlyAllowed { _pause(_msgSender()); @@ -114,7 +115,8 @@ contract Bridge is Pausable, Context { /** @notice Unpauses deposits, proposal creation and voting, and deposit executions. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @notice MPC address has to be set before Bridge can be unpaused */ function adminUnpauseTransfers() external onlyAllowed { @@ -125,7 +127,8 @@ contract Bridge is Pausable, Context { /** @notice Sets a new resource for handler contracts that use the IERCHandler interface, and maps the {handlerAddress} to {resourceID} in {_resourceIDToHandlerAddress}. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param handlerAddress Address of handler resource will be set for. @param resourceID ResourceID to be used when making deposits. @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. @@ -139,7 +142,8 @@ contract Bridge is Pausable, Context { /** @notice Sets a new resource for handler contracts that use the IGenericHandler interface, and maps the {handlerAddress} to {resourceID} in {_resourceIDToHandlerAddress}. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param handlerAddress Address of handler resource will be set for. @param resourceID ResourceID to be used when making deposits. @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. @@ -159,7 +163,8 @@ contract Bridge is Pausable, Context { /** @notice Sets a resource as burnable for handler contracts that use the IERCHandler interface. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param handlerAddress Address of handler resource will be set for. @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. */ @@ -170,7 +175,8 @@ contract Bridge is Pausable, Context { /** @notice Sets the nonce for the specific domainID. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param domainID Domain ID for increasing nonce. @param nonce The nonce value to be set. */ @@ -181,7 +187,8 @@ contract Bridge is Pausable, Context { /** @notice Set a forwarder to be used. - @notice Only callable by an address that currently has the admin role. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param forwarder Forwarder address to be added. @param valid Decision for the specific forwarder. */ @@ -191,7 +198,8 @@ contract Bridge is Pausable, Context { /** @notice Changes access control contract address. - @notice Only callable by admin. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param newAccessControl Address {_accessControl} will be updated to. */ function adminChangeAccessControl(address newAccessControl) external onlyAllowed { @@ -201,7 +209,8 @@ contract Bridge is Pausable, Context { /** @notice Changes deposit fee handler contract address. - @notice Only callable by admin. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param newFeeHandler Address {_feeHandler} will be updated to. */ function adminChangeFeeHandler(address newFeeHandler) external onlyAllowed { @@ -211,6 +220,8 @@ contract Bridge is Pausable, Context { /** @notice Used to manually withdraw funds from ERC safes. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param handlerAddress Address of handler to withdraw from. @param data ABI-encoded withdrawal params relevant to the specified handler. */ @@ -326,6 +337,8 @@ contract Bridge is Pausable, Context { /** @notice Once MPC address is set, this method can't be invoked anymore. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. */ function startKeygen() external onlyAllowed { require(_MPCAddress == address(0), "MPC address is already set"); @@ -335,6 +348,8 @@ contract Bridge is Pausable, Context { /** @notice This method can be called only once, after the MPC address is set Bridge is unpaused. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. @param MPCAddress Address that will be set as MPC address. */ function endKeygen(address MPCAddress) external onlyAllowed { @@ -348,6 +363,8 @@ contract Bridge is Pausable, Context { /** @notice It's used to trigger the belonging process on the MPC side. It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. + @notice Only callable by address that has the right to call the specific function, + which is mapped in {functionAccess} in AccessControlSegregator contract. */ function refreshKey() external onlyAllowed { emit KeyRefresh(); From d88949ece0fc32bae88cb2997c61b37c0b721cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Tue, 12 Jul 2022 14:09:50 +0200 Subject: [PATCH 16/20] Add `renouceAdmin` function (#592) * Add renounceAdmin function to FeeHandlers * Add tests for renounceAdmin functions * Fix indentation --- contracts/handlers/fee/BasicFeeHandler.sol | 12 ++++ .../handlers/fee/FeeHandlerWithOracle.sol | 28 +++++++--- test/handlers/fee/basic/admin.js | 56 +++++++++++++++++++ test/handlers/fee/withOracle/admin.js | 17 ++++++ 4 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 test/handlers/fee/basic/admin.js diff --git a/contracts/handlers/fee/BasicFeeHandler.sol b/contracts/handlers/fee/BasicFeeHandler.sol index 1b78f92a..6e0656ed 100644 --- a/contracts/handlers/fee/BasicFeeHandler.sol +++ b/contracts/handlers/fee/BasicFeeHandler.sol @@ -36,6 +36,18 @@ contract BasicFeeHandler is IFeeHandler, AccessControl { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } + /** + @notice Removes admin role from {_msgSender()} and grants it to {newAdmin}. + @notice Only callable by an address that currently has the admin role. + @param newAdmin Address that admin role will be granted to. + */ + function renounceAdmin(address newAdmin) external onlyAdmin { + address sender = _msgSender(); + require(sender != newAdmin, 'Cannot renounce oneself'); + grantRole(DEFAULT_ADMIN_ROLE, newAdmin); + renounceRole(DEFAULT_ADMIN_ROLE, sender); + } + /** @notice Collects fee for deposit. @param sender Sender of the deposit. diff --git a/contracts/handlers/fee/FeeHandlerWithOracle.sol b/contracts/handlers/fee/FeeHandlerWithOracle.sol index d51e75f0..6bd966f9 100644 --- a/contracts/handlers/fee/FeeHandlerWithOracle.sol +++ b/contracts/handlers/fee/FeeHandlerWithOracle.sol @@ -25,7 +25,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { struct OracleMessageType { // Base Effective Rate - effective rate between base currencies of source and dest networks (eg. MATIC/ETH) - uint256 ber; + uint256 ber; // Token Effective Rate - rate between base currency of destination network and token that is being trasferred (eg. MATIC/USDT) uint256 ter; uint256 dstGasPrice; @@ -51,6 +51,18 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { // Admin functions + /** + @notice Removes admin role from {_msgSender()} and grants it to {newAdmin}. + @notice Only callable by an address that currently has the admin role. + @param newAdmin Address that admin role will be granted to. + */ + function renounceAdmin(address newAdmin) external onlyAdmin { + address sender = _msgSender(); + require(sender != newAdmin, 'Cannot renounce oneself'); + grantRole(DEFAULT_ADMIN_ROLE, newAdmin); + renounceRole(DEFAULT_ADMIN_ROLE, sender); + } + /** @notice Sets the fee oracle address for signature verification. @param oracleAddress Fee oracle address. @@ -101,7 +113,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { } function _calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) internal view returns(uint256 fee, address tokenAddress) { - /** + /** Message: ber * 10^18: uint256 ter * 10^18: uint256 @@ -120,7 +132,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { amount: uint256 total: 321 - */ + */ require(feeData.length == 321, "Incorrect feeData length"); @@ -132,9 +144,9 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { OracleMessageType memory oracleMessage = abi.decode(feeDataDecoded.message, (OracleMessageType)); require(block.timestamp <= oracleMessage.expiresAt, "Obsolete oracle data"); - require((oracleMessage.fromDomainID == fromDomainID) - && (oracleMessage.toDomainID == destinationDomainID) - && (oracleMessage.resourceID == resourceID), + require((oracleMessage.fromDomainID == fromDomainID) + && (oracleMessage.toDomainID == destinationDomainID) + && (oracleMessage.resourceID == resourceID), "Incorrect deposit params" ); @@ -144,12 +156,12 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { address tokenHandler = IBridge(_bridgeAddress)._resourceIDToHandlerAddress(resourceID); address tokenAddress = IERCHandler(tokenHandler)._resourceIDToTokenContractAddress(resourceID); - + // txCost = dstGasPrice * _gasUsed * Token Effective Rate (rate of dest base currency to token) uint256 txCost = oracleMessage.dstGasPrice * _gasUsed * oracleMessage.ter / 1e18; fee = feeDataDecoded.amount * _feePercent / 1e4; // 100 for percent and 100 to avoid precision loss - + if (fee < txCost) { fee = txCost; } diff --git a/test/handlers/fee/basic/admin.js b/test/handlers/fee/basic/admin.js new file mode 100644 index 00000000..3d50a5be --- /dev/null +++ b/test/handlers/fee/basic/admin.js @@ -0,0 +1,56 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + + const TruffleAssert = require("truffle-assertions"); + + const Helpers = require("../../../helpers"); + + const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + + contract("BasicFeeHandler - [admin]", async accounts => { + const domainID = 1; + const initialRelayers = accounts.slice(0, 3); + const currentFeeHandlerAdmin = accounts[0]; + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + let BasicFeeHandlerInstance; + let ADMIN_ROLE; + + beforeEach(async () => { + BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + + ADMIN_ROLE = await BasicFeeHandlerInstance.DEFAULT_ADMIN_ROLE(); + }); + + it("should set fee property", async () => { + const fee = 3; + assert.equal(await BasicFeeHandlerInstance._fee.call(), "0"); + await BasicFeeHandlerInstance.changeFee(fee); + assert.equal(await BasicFeeHandlerInstance._fee.call(), fee); + }); + + it("should require admin role to change fee property", async () => { + const fee = 3; + await assertOnlyAdmin(BasicFeeHandlerInstance.changeFee, fee); + }); + + it('FeeHandlerWithOracle admin should be changed to expectedFeeHandlerWithOracleAdmin', async () => { + const expectedFeeHandlerWithOracleAdmin = accounts[1]; + + // check current admin + assert.isTrue(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin)); + + await TruffleAssert.passes(BasicFeeHandlerInstance.renounceAdmin(expectedFeeHandlerWithOracleAdmin)) + assert.isTrue(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, expectedFeeHandlerWithOracleAdmin)); + + // check that former admin is no longer admin + assert.isFalse(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin)); + }); +}); diff --git a/test/handlers/fee/withOracle/admin.js b/test/handlers/fee/withOracle/admin.js index 67d26c05..144494ac 100644 --- a/test/handlers/fee/withOracle/admin.js +++ b/test/handlers/fee/withOracle/admin.js @@ -12,6 +12,7 @@ contract("FeeHandlerWithOracle - [admin]", async accounts => { const domainID = 1; const initialRelayers = accounts.slice(0, 3); + const currentFeeHandlerAdmin = accounts[0]; const assertOnlyAdmin = (method, ...params) => { return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role"); @@ -19,10 +20,13 @@ let BridgeInstance; let FeeHandlerWithOracleInstance; + let ADMIN_ROLE; beforeEach(async () => { BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + + ADMIN_ROLE = await FeeHandlerWithOracleInstance.DEFAULT_ADMIN_ROLE(); }); it("should set fee oracle", async () => { @@ -53,4 +57,17 @@ const feePercent = 5; await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeProperties, gasUsed, feePercent); }); + + it('FeeHandlerWithOracle admin should be changed to expectedFeeHandlerWithOracleAdmin', async () => { + const expectedFeeHandlerWithOracleAdmin = accounts[1]; + + // check current admin + assert.isTrue(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin)); + + await TruffleAssert.passes(FeeHandlerWithOracleInstance.renounceAdmin(expectedFeeHandlerWithOracleAdmin)) + assert.isTrue(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, expectedFeeHandlerWithOracleAdmin)); + + // check that former admin is no longer admin + assert.isFalse(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin)); + }); }); From aa9614cc12e5e13c670d3ca94b8d19d77ab2ad5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Thu, 14 Jul 2022 12:44:28 +0200 Subject: [PATCH 17/20] Add `FeeHandlerRouter` (#588) * Make domainID immutable * Add FeeHandlerRouter contract * Update FeeHandlers with FeeRouter logic * Update old test with FeeHandlerRouter logic * Update old tests + add new tests for FeeHandlerRouter * Change resourceID-handler mapping type * Fix indentaton * Change onlyRouter modifier to onlyBridgeOrRouter * Remove redundant modifier * Update old tests + add new tests for onlyBridgeOrRouter modifier --- contracts/Bridge.sol | 1 - contracts/handlers/FeeHandlerRouter.sol | 86 ++++++ contracts/handlers/fee/BasicFeeHandler.sol | 31 +- .../handlers/fee/FeeHandlerWithOracle.sol | 40 +-- test/feeRouter/feeRouter.js | 0 test/handlers/fee/basic/admin.js | 4 +- test/handlers/fee/basic/calculateFee.js | 28 +- test/handlers/fee/basic/changeFee.js | 12 +- test/handlers/fee/basic/collectFee.js | 267 +++++++++++++++--- test/handlers/fee/basic/distributeFee.js | 12 +- test/handlers/fee/handlerRouter.js | 54 ++++ test/handlers/fee/withOracle/admin.js | 17 +- test/handlers/fee/withOracle/calculateFee.js | 80 +++--- test/handlers/fee/withOracle/collectFee.js | 138 +++++++-- test/handlers/fee/withOracle/distributeFee.js | 38 +-- 15 files changed, 638 insertions(+), 170 deletions(-) create mode 100644 contracts/handlers/FeeHandlerRouter.sol create mode 100644 test/feeRouter/feeRouter.js create mode 100644 test/handlers/fee/handlerRouter.js diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index 9ec19d96..e09655a8 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -18,7 +18,6 @@ import "./interfaces/IAccessControlSegregator.sol"; contract Bridge is Pausable, Context { using ECDSA for bytes32; - uint8 public immutable _domainID; address public _MPCAddress; diff --git a/contracts/handlers/FeeHandlerRouter.sol b/contracts/handlers/FeeHandlerRouter.sol new file mode 100644 index 00000000..e4977ebd --- /dev/null +++ b/contracts/handlers/FeeHandlerRouter.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity 0.8.11; +pragma experimental ABIEncoderV2; + +import "../interfaces/IFeeHandler.sol"; +import "../utils/AccessControl.sol"; + +/** + @title Handles FeeHandler routing for resources. + @author ChainSafe Systems. + @notice This contract is intended to be used with the Bridge contract. + */ +contract FeeHandlerRouter is IFeeHandler, AccessControl { + address public immutable _bridgeAddress; + + // destination domainID => resourceID => feeHandlerAddress + mapping (uint8 => mapping(bytes32 => IFeeHandler)) public _domainResourceIDToFeeHandlerAddress; + + event FeeChanged( + uint256 newFee + ); + + modifier onlyBridge() { + _onlyBridge(); + _; + } + + function _onlyBridge() private view { + require(msg.sender == _bridgeAddress, "sender must be bridge contract"); + } + + modifier onlyAdmin() { + _onlyAdmin(); + _; + } + + function _onlyAdmin() private view { + require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "sender doesn't have admin role"); + } + + /** + @param bridgeAddress Contract address of previously deployed Bridge. + */ + constructor(address bridgeAddress) public { + _bridgeAddress = bridgeAddress; + _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + /** + @notice Maps the {handlerAddress} to {resourceID} to {destinantionDomainID} in {_domainResourceIDToFeeHandlerAddress}. + @param destinationDomainID ID of chain FeeHandler contracts will be called. + @param resourceID ResourceID for which the corresponding FeeHandler will collect/calcualte fee. + @param handlerAddress Address of FeeHandler which will be called for specified resourceID. + */ + function adminSetResourceHandler(uint8 destinationDomainID, bytes32 resourceID, IFeeHandler handlerAddress) external onlyAdmin { + _domainResourceIDToFeeHandlerAddress[destinationDomainID][resourceID] = handlerAddress; + } + + + /** + @notice Initiates collecting fee with corresponding fee handler contract using IFeeHandler interface. + @param sender Sender of the deposit. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + */ + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridge { + IFeeHandler feeHandler = _domainResourceIDToFeeHandlerAddress[destinationDomainID][resourceID]; + feeHandler.collectFee{value: msg.value}(sender, fromDomainID, destinationDomainID, resourceID, depositData, feeData); + } + + /** + @notice Initiates calculating fee with corresponding fee handler contract using IFeeHandler interface. + @param sender Sender of the deposit. + @param destinationDomainID ID of chain deposit will be bridged to. + @param resourceID ResourceID to be used when making deposits. + @param depositData Additional data to be passed to specified handler. + @param feeData Additional data to be passed to the fee handler. + @return fee Returns the fee amount. + @return tokenAddress Returns the address of the token to be used for fee. + */ + function calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) external view returns(uint256 fee, address tokenAddress) { + IFeeHandler feeHandler = _domainResourceIDToFeeHandlerAddress[destinationDomainID][resourceID]; + return feeHandler.calculateFee(sender, fromDomainID, destinationDomainID, resourceID, depositData, feeData); + } +} diff --git a/contracts/handlers/fee/BasicFeeHandler.sol b/contracts/handlers/fee/BasicFeeHandler.sol index 6e0656ed..d7f2de50 100644 --- a/contracts/handlers/fee/BasicFeeHandler.sol +++ b/contracts/handlers/fee/BasicFeeHandler.sol @@ -12,6 +12,7 @@ import "../../utils/AccessControl.sol"; */ contract BasicFeeHandler is IFeeHandler, AccessControl { address public immutable _bridgeAddress; + address public immutable _feeHandlerRouterAddress; uint256 public _fee; @@ -19,20 +20,29 @@ contract BasicFeeHandler is IFeeHandler, AccessControl { uint256 newFee ); - modifier onlyBridge() { - _onlyBridge(); + modifier onlyAdmin() { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); + _; + } + + modifier onlyBridgeOrRouter() { + _onlyBridgeOrRouter(); _; } - function _onlyBridge() private view { - require(msg.sender == _bridgeAddress, "sender must be bridge contract"); + function _onlyBridgeOrRouter() private view { + require( + msg.sender == _bridgeAddress || msg.sender == _feeHandlerRouterAddress, + "sender must be bridge or fee router contract" + ); } /** - @param bridgeAddress Contract address of previously deployed Bridge. + @param feeHandlerRouterAddress Contract address of previously deployed FeeHandlerRouter. */ - constructor(address bridgeAddress) public { + constructor(address bridgeAddress, address feeHandlerRouterAddress) public { _bridgeAddress = bridgeAddress; + _feeHandlerRouterAddress = feeHandlerRouterAddress; _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } @@ -41,7 +51,7 @@ contract BasicFeeHandler is IFeeHandler, AccessControl { @notice Only callable by an address that currently has the admin role. @param newAdmin Address that admin role will be granted to. */ - function renounceAdmin(address newAdmin) external onlyAdmin { + function renounceAdmin(address newAdmin) external { address sender = _msgSender(); require(sender != newAdmin, 'Cannot renounce oneself'); grantRole(DEFAULT_ADMIN_ROLE, newAdmin); @@ -56,7 +66,7 @@ contract BasicFeeHandler is IFeeHandler, AccessControl { @param depositData Additional data to be passed to specified handler. @param feeData Additional data to be passed to the fee handler. */ - function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridge { + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridgeOrRouter { require(msg.value == _fee, "Incorrect fee supplied"); emit FeeCollected(sender, fromDomainID, destinationDomainID, resourceID, _fee, address(0)); } @@ -100,8 +110,5 @@ contract BasicFeeHandler is IFeeHandler, AccessControl { } } - modifier onlyAdmin() { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); - _; - } + } diff --git a/contracts/handlers/fee/FeeHandlerWithOracle.sol b/contracts/handlers/fee/FeeHandlerWithOracle.sol index 6bd966f9..dff3e6b8 100644 --- a/contracts/handlers/fee/FeeHandlerWithOracle.sol +++ b/contracts/handlers/fee/FeeHandlerWithOracle.sol @@ -17,6 +17,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; */ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { address public immutable _bridgeAddress; + address public immutable _feeHandlerRouterAddress; address public _oracleAddress; @@ -41,11 +42,30 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { uint256 amount; } + modifier onlyAdmin() { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); + _; + } + + modifier onlyBridgeOrRouter() { + _onlyBridgeOrRouter(); + _; + } + + function _onlyBridgeOrRouter() private view { + require( + msg.sender == _bridgeAddress || msg.sender == _feeHandlerRouterAddress, + "sender must be bridge or fee router contract" + ); + } + /** @param bridgeAddress Contract address of previously deployed Bridge. + @param feeHandlerRouterAddress Contract address of previously deployed FeeHandlerRouter. */ - constructor(address bridgeAddress) public { + constructor(address bridgeAddress, address feeHandlerRouterAddress) public { _bridgeAddress = bridgeAddress; + _feeHandlerRouterAddress = feeHandlerRouterAddress; _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } @@ -56,7 +76,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { @notice Only callable by an address that currently has the admin role. @param newAdmin Address that admin role will be granted to. */ - function renounceAdmin(address newAdmin) external onlyAdmin { + function renounceAdmin(address newAdmin) external { address sender = _msgSender(); require(sender != newAdmin, 'Cannot renounce oneself'); grantRole(DEFAULT_ADMIN_ROLE, newAdmin); @@ -90,7 +110,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { @param depositData Additional data to be passed to specified handler. @param feeData Additional data to be passed to the fee handler. */ - function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridge { + function collectFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) payable external onlyBridgeOrRouter { require(msg.value == 0, "collectFee: msg.value != 0"); (uint256 fee, address tokenAddress) = _calculateFee(sender, fromDomainID, destinationDomainID, resourceID, depositData, feeData); lockERC20(tokenAddress, sender, address(this), fee); @@ -189,18 +209,4 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe { address signerAddressRecovered = ECDSA.recover(message, signature); require(signerAddressRecovered == signerAddress, 'Invalid signature'); } - - modifier onlyAdmin() { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role"); - _; - } - - modifier onlyBridge() { - _onlyBridge(); - _; - } - - function _onlyBridge() private view { - require(msg.sender == _bridgeAddress, "sender must be bridge contract"); - } } diff --git a/test/feeRouter/feeRouter.js b/test/feeRouter/feeRouter.js new file mode 100644 index 00000000..e69de29b diff --git a/test/handlers/fee/basic/admin.js b/test/handlers/fee/basic/admin.js index 3d50a5be..3d6d2030 100644 --- a/test/handlers/fee/basic/admin.js +++ b/test/handlers/fee/basic/admin.js @@ -8,6 +8,7 @@ const Helpers = require("../../../helpers"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); + const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("BasicFeeHandler - [admin]", async accounts => { const domainID = 1; @@ -24,7 +25,8 @@ beforeEach(async () => { BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); - BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); ADMIN_ROLE = await BasicFeeHandlerInstance.DEFAULT_ADMIN_ROLE(); }); diff --git a/test/handlers/fee/basic/calculateFee.js b/test/handlers/fee/basic/calculateFee.js index b4515303..525a23a6 100644 --- a/test/handlers/fee/basic/calculateFee.js +++ b/test/handlers/fee/basic/calculateFee.js @@ -8,10 +8,10 @@ const Ethers = require("ethers"); const Helpers = require("../../../helpers"); -const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("BasicFeeHandler - [calculateFee]", async (accounts) => { const originDomainID = 1; @@ -27,31 +27,36 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { let initialResourceIDs; let initialContractAddresses; let ERC20MintableInstance; + let FeeHandlerRouterInstance; beforeEach(async () => { await Promise.all([ + BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]), ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), - BridgeInstance = BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]) ]); + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); initialResourceIDs = [resourceID]; initialContractAddresses = [ERC20MintableInstance.address]; - burnableContractAddresses = []; - - BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); - - ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + burnableContractAddresses = []; depositData = Helpers.createERCDepositData(100, 20, recipientAddress); + + await Promise.all([ + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address), + BridgeInstance.adminChangeFeeHandler(FeeHandlerRouterInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, resourceID, BasicFeeHandlerInstance.address), + ]); }); it("should return amount of fee", async () => { - await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); // current fee is set to 0 - let res = await BasicFeeHandlerInstance.calculateFee.call( + let res = await FeeHandlerRouterInstance.calculateFee.call( relayer, originDomainID, destinationDomainID, @@ -59,10 +64,11 @@ contract("BasicFeeHandler - [calculateFee]", async (accounts) => { depositData, feeData ); + assert.equal(web3.utils.fromWei(res[0], "ether"), "0"); // Change fee to 0.5 ether await BasicFeeHandlerInstance.changeFee(Ethers.utils.parseEther("0.5")); - res = await BasicFeeHandlerInstance.calculateFee.call( + res = await FeeHandlerRouterInstance.calculateFee.call( relayer, originDomainID, destinationDomainID, diff --git a/test/handlers/fee/basic/changeFee.js b/test/handlers/fee/basic/changeFee.js index 4b4abf3b..e25714f1 100644 --- a/test/handlers/fee/basic/changeFee.js +++ b/test/handlers/fee/basic/changeFee.js @@ -9,6 +9,7 @@ const Ethers = require("ethers"); const Helpers = require('../../../helpers'); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("BasicFeeHandler - [changeFee]", async accounts => { const domainID = 1; @@ -21,16 +22,17 @@ contract("BasicFeeHandler - [changeFee]", async accounts => { let BridgeInstance; beforeEach(async () => { - BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); }); it("[sanity] contract should be deployed successfully", async () => { TruffleAssert.passes( - await BasicFeeHandlerContract.new(BridgeInstance.address)); + await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address)); }); it("should set fee", async () => { - const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); const fee = Ethers.utils.parseEther("0.05"); const tx = await BasicFeeHandlerInstance.changeFee(fee); TruffleAssert.eventEmitted(tx, "FeeChanged", (event) => @@ -41,12 +43,12 @@ contract("BasicFeeHandler - [changeFee]", async accounts => { }); it("should not set the same fee", async () => { - const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); await TruffleAssert.reverts(BasicFeeHandlerInstance.changeFee(0), "Current fee is equal to new fee"); }); it("should require admin role to change fee", async () => { - const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + const BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); await assertOnlyAdmin(BasicFeeHandlerInstance.changeFee, 1); }); }); diff --git a/test/handlers/fee/basic/collectFee.js b/test/handlers/fee/basic/collectFee.js index ea27b085..c405453b 100644 --- a/test/handlers/fee/basic/collectFee.js +++ b/test/handlers/fee/basic/collectFee.js @@ -8,10 +8,12 @@ const Ethers = require("ethers"); const Helpers = require("../../../helpers"); -const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const ERC721MintableContract = artifacts.require("ERC721MinterBurnerPauser"); +const ERC721HandlerContract = artifacts.require("ERC721Handler"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("BasicFeeHandler - [collectFee]", async (accounts) => { @@ -20,38 +22,57 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { const depositerAddress = accounts[1]; const recipientAddress = accounts[2]; + const relayer1Address = accounts[3]; const depositAmount = 10; const feeData = "0x0"; + const tokenID = 1; + let BridgeInstance; let ERC20MintableInstance; let ERC20HandlerInstance; - let BasicFeeHandlerInstance; + let ERC721HandlerInstance; + let ERC721MintableInstance; + let ERC20BasicFeeHandlerInstance; + let ERC721BasicFeeHandlerInstance; + let FeeHandlerRouterInstance; - let resourceID; - let depositData; + let erc20ResourceID; + let erc721ResourceID; + let erc20depositData; beforeEach(async () => { await Promise.all([ BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), - ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ERC20MintableInstance = ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), + ERC721MintableInstance = ERC721MintableContract.new("ERC721Token", "ERC721TOK", "").then(instance => ERC721MintableInstance = instance), ]); - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + erc20ResourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + erc721ResourceID = Helpers.createResourceID(ERC721MintableInstance.address, originDomainID); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + ERC721HandlerInstance = await ERC721HandlerContract.new(BridgeInstance.address); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + ERC20BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); + ERC721BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); await Promise.all([ + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, erc20ResourceID, ERC20MintableInstance.address), + BridgeInstance.adminSetResource(ERC721HandlerInstance.address, erc721ResourceID, ERC721MintableInstance.address), ERC20MintableInstance.mint(depositerAddress, depositAmount), - BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address) + ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }), + ERC721MintableInstance.mint(depositerAddress, tokenID, ""), + ERC721MintableInstance.approve(ERC721HandlerInstance.address, tokenID, { from: depositerAddress }), + BridgeInstance.adminChangeFeeHandler(FeeHandlerRouterInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, erc20ResourceID, ERC20BasicFeeHandlerInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, erc721ResourceID, ERC721BasicFeeHandlerInstance.address), ]); - await ERC20MintableInstance.approve(ERC20HandlerInstance.address, depositAmount, { from: depositerAddress }); - - depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); + erc20depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); + erc721depositData = Helpers.createERCDepositData(tokenID, 20, recipientAddress); - BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); @@ -60,23 +81,22 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { it("[sanity] Generic deposit can be made", async () => { await TruffleAssert.passes(BridgeInstance.deposit( destinationDomainID, - resourceID, - depositData, + erc20ResourceID, + erc20depositData, feeData, { from: depositerAddress } )); }); it("deposit should revert if invalid fee amount supplied", async () => { - await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); // current fee is set to 0 - assert.equal(await BasicFeeHandlerInstance._fee.call(), 0); + assert.equal(await ERC20BasicFeeHandlerInstance._fee.call(), 0); await TruffleAssert.reverts( BridgeInstance.deposit( destinationDomainID, - resourceID, - depositData, + erc20ResourceID, + erc20depositData, feeData, { from: depositerAddress, @@ -87,21 +107,58 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { ) }); - it("deposit should pass if valid fee amount supplied", async () => { + it("deposit should pass if valid fee amount supplied for ERC20 deposit", async () => { const fee = Ethers.utils.parseEther("0.5"); - await BridgeInstance.adminChangeFeeHandler(BasicFeeHandlerInstance.address); // current fee is set to 0 - assert.equal(await BasicFeeHandlerInstance._fee.call(), 0); + assert.equal(await ERC20BasicFeeHandlerInstance._fee.call(), 0); // Change fee to 0.5 ether - await BasicFeeHandlerInstance.changeFee(fee); - assert.equal(web3.utils.fromWei((await BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + await ERC20BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC20BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + + const balanceBefore = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + + const depositTx = await BridgeInstance.deposit( + destinationDomainID, + erc20ResourceID, + erc20depositData, + feeData, + { + from: depositerAddress, + value: fee + } + ); + + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc20ResourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(ERC20BasicFeeHandlerInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc20ResourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === "0x0000000000000000000000000000000000000000"; + }); + const balanceAfter = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, fee.add(balanceBefore)); + }); - const balanceBefore = await web3.eth.getBalance(BasicFeeHandlerInstance.address); + it("deposit should pass if valid fee amount supplied for ERC721 deposit", async () => { + const fee = Ethers.utils.parseEther("0.4"); + // current fee is set to 0 + assert.equal(await ERC721BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.4 ether + await ERC721BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC721BasicFeeHandlerInstance._fee.call()), "ether"), "0.4"); + + const balanceBefore = await web3.eth.getBalance(ERC721BasicFeeHandlerInstance.address); const depositTx = await BridgeInstance.deposit( destinationDomainID, - resourceID, - depositData, + erc721ResourceID, + erc721depositData, feeData, { from: depositerAddress, @@ -111,27 +168,29 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { return event.destinationDomainID.toNumber() === destinationDomainID && - event.resourceID === resourceID.toLowerCase(); + event.resourceID === erc721ResourceID.toLowerCase(); }); - const internalTx = await TruffleAssert.createTransactionResult(BasicFeeHandlerInstance, depositTx.tx); + const internalTx = await TruffleAssert.createTransactionResult(ERC721BasicFeeHandlerInstance, depositTx.tx); TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { return event.sender === depositerAddress && event.fromDomainID.toNumber() === originDomainID && event.destinationDomainID.toNumber() === destinationDomainID && - event.resourceID === resourceID.toLowerCase() && + event.resourceID === erc721ResourceID.toLowerCase() && event.fee.toString() === fee.toString() && event.tokenAddress === "0x0000000000000000000000000000000000000000"; }); - const balanceAfter = await web3.eth.getBalance(BasicFeeHandlerInstance.address); + const balanceAfter = await web3.eth.getBalance(ERC721BasicFeeHandlerInstance.address); assert.equal(balanceAfter, fee.add(balanceBefore)); }); it("deposit should revert if fee handler not set and fee supplied", async () => { + await BridgeInstance.adminChangeFeeHandler("0x0000000000000000000000000000000000000000"); + await TruffleAssert.reverts( BridgeInstance.deposit( destinationDomainID, - resourceID, - depositData, + erc20ResourceID, + erc20depositData, feeData, { from: depositerAddress, @@ -146,11 +205,153 @@ contract("BasicFeeHandler - [collectFee]", async (accounts) => { await TruffleAssert.passes( BridgeInstance.deposit( destinationDomainID, - resourceID, - depositData, + erc20ResourceID, + erc20depositData, feeData, { from: depositerAddress } ) ) }); + + it("deposit should revert if not called by router on BasicFeeHandler contract", async () => { + const fee = Ethers.utils.parseEther("0.5"); + await BridgeInstance.adminChangeFeeHandler(ERC20BasicFeeHandlerInstance.address); + // current fee is set to 0 + assert.equal(await ERC20BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.5 ether + await ERC20BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC20BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + + const balanceBefore = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + + await TruffleAssert.reverts( + ERC20BasicFeeHandlerInstance.collectFee( + depositerAddress, + originDomainID, + destinationDomainID, + erc20ResourceID, + erc20depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ), + "sender must be bridge or fee router contract" + ); + + const balanceAfter = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, balanceBefore); + }); + + it("deposit should revert if not called by bridge on FeeHandlerRouter contract", async () => { + const fee = Ethers.utils.parseEther("0.5"); + await BridgeInstance.adminChangeFeeHandler(ERC20BasicFeeHandlerInstance.address); + // current fee is set to 0 + assert.equal(await ERC20BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.5 ether + await ERC20BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC20BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + + const balanceBefore = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + + await TruffleAssert.reverts( + FeeHandlerRouterInstance.collectFee( + depositerAddress, + originDomainID, + destinationDomainID, + erc20ResourceID, + erc20depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ), + "sender must be bridge contract" + ); + + const balanceAfter = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, balanceBefore); + }); + + it("should successfully change fee handler from FeeRouter to ERC20BasicFeeHandlerInstance and collect fee", async () => { + await BridgeInstance.adminChangeFeeHandler(ERC20BasicFeeHandlerInstance.address); + + const fee = Ethers.utils.parseEther("0.5"); + // current fee is set to 0 + assert.equal(await ERC20BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.5 ether + await ERC20BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC20BasicFeeHandlerInstance._fee.call()), "ether"), "0.5"); + + const balanceBefore = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + + const depositTx = await BridgeInstance.deposit( + destinationDomainID, + erc20ResourceID, + erc20depositData, + feeData, + { + from: depositerAddress, + value: fee + } + ); + + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc20ResourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(ERC20BasicFeeHandlerInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc20ResourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === "0x0000000000000000000000000000000000000000"; + }); + const balanceAfter = await web3.eth.getBalance(ERC20BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, fee.add(balanceBefore)); + }); + + it("should successfully change fee handler from FeeRouter to ERC721BasicFeeHandlerInstance and collect fee", async () => { + await BridgeInstance.adminChangeFeeHandler(ERC721BasicFeeHandlerInstance.address); + + const fee = Ethers.utils.parseEther("0.4"); + // current fee is set to 0 + assert.equal(await ERC721BasicFeeHandlerInstance._fee.call(), 0); + // Change fee to 0.4 ether + await ERC721BasicFeeHandlerInstance.changeFee(fee); + assert.equal(web3.utils.fromWei((await ERC721BasicFeeHandlerInstance._fee.call()), "ether"), "0.4"); + + const balanceBefore = await web3.eth.getBalance(ERC721BasicFeeHandlerInstance.address); + + const depositTx = await BridgeInstance.deposit( + destinationDomainID, + erc721ResourceID, + erc721depositData, + feeData, + { + from: depositerAddress, + value: fee + } + ); + + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc721ResourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(ERC721BasicFeeHandlerInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === erc721ResourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === "0x0000000000000000000000000000000000000000"; + }); + const balanceAfter = await web3.eth.getBalance(ERC721BasicFeeHandlerInstance.address); + assert.equal(balanceAfter, fee.add(balanceBefore)); + }); }); diff --git a/test/handlers/fee/basic/distributeFee.js b/test/handlers/fee/basic/distributeFee.js index 25593186..dda8ec7d 100644 --- a/test/handlers/fee/basic/distributeFee.js +++ b/test/handlers/fee/basic/distributeFee.js @@ -3,15 +3,15 @@ * SPDX-License-Identifier: LGPL-3.0-only */ - const TruffleAssert = require("truffle-assertions"); - const Ethers = require("ethers"); +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); - const Helpers = require("../../../helpers"); +const Helpers = require("../../../helpers"); - const BridgeContract = artifacts.require("Bridge"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("BasicFeeHandler - [distributeFee]", async (accounts) => { @@ -32,6 +32,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { let ERC20MintableInstance; let ERC20HandlerInstance; let BasicFeeHandlerInstance; + let FeeHandlerRouterInstance; let resourceID; let depositData; @@ -44,6 +45,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); await Promise.all([ @@ -55,7 +57,7 @@ contract("BasicFeeHandler - [distributeFee]", async (accounts) => { depositData = Helpers.createERCDepositData(depositAmount, 20, recipientAddress); - BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address); + BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); diff --git a/test/handlers/fee/handlerRouter.js b/test/handlers/fee/handlerRouter.js new file mode 100644 index 00000000..ea0a195e --- /dev/null +++ b/test/handlers/fee/handlerRouter.js @@ -0,0 +1,54 @@ +/** + * Copyright 2022 ChainSafe Systems + * SPDX-License-Identifier: LGPL-3.0-only + */ + +const TruffleAssert = require("truffle-assertions"); + +const Helpers = require("../../helpers"); + +const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); + + +contract("FeeHandlerRouter", async accounts => { + const originDomainID = 1; + const destinationDomainID = 2; + const nonAdmin = accounts[1]; + + const assertOnlyAdmin = (method, ...params) => { + return TruffleAssert.reverts(method(...params, {from: nonAdmin}), "sender doesn't have admin role"); + }; + + let BridgeInstance; + let FeeHandlerWithOracleInstance; + let FeeHandlerRouterInstance; + let ERC20MintableInstance; + let resourceID; + + beforeEach(async () => { + await Promise.all([ + BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]), + ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance) + ]); + + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + }); + + it("should successfully set handler to resourceID", async () => { + const feeHandlerAddress = accounts[1]; + assert.equal(await FeeHandlerRouterInstance._domainResourceIDToFeeHandlerAddress.call(destinationDomainID, resourceID), "0x0000000000000000000000000000000000000000"); + await FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, resourceID, feeHandlerAddress); + const newFeeHandler = await FeeHandlerRouterInstance._domainResourceIDToFeeHandlerAddress(destinationDomainID, resourceID); + assert.equal(newFeeHandler, feeHandlerAddress); + }); + + it("should require admin role to set handler for resourceID", async () => { + const feeHandlerAddress = accounts[1]; + await assertOnlyAdmin(FeeHandlerRouterInstance.adminSetResourceHandler, destinationDomainID, resourceID, feeHandlerAddress); + }); +}); diff --git a/test/handlers/fee/withOracle/admin.js b/test/handlers/fee/withOracle/admin.js index 144494ac..239e54fe 100644 --- a/test/handlers/fee/withOracle/admin.js +++ b/test/handlers/fee/withOracle/admin.js @@ -3,13 +3,15 @@ * SPDX-License-Identifier: LGPL-3.0-only */ - const TruffleAssert = require("truffle-assertions"); +const TruffleAssert = require("truffle-assertions"); - const Helpers = require("../../../helpers"); +const Helpers = require("../../../helpers"); - const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); - contract("FeeHandlerWithOracle - [admin]", async accounts => { + +contract("FeeHandlerWithOracle - [admin]", async accounts => { const domainID = 1; const initialRelayers = accounts.slice(0, 3); const currentFeeHandlerAdmin = accounts[0]; @@ -20,12 +22,13 @@ let BridgeInstance; let FeeHandlerWithOracleInstance; + let FeeHandlerRouterInstance; let ADMIN_ROLE; beforeEach(async () => { - BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); - FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); - + BridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); ADMIN_ROLE = await FeeHandlerWithOracleInstance.DEFAULT_ADMIN_ROLE(); }); diff --git a/test/handlers/fee/withOracle/calculateFee.js b/test/handlers/fee/withOracle/calculateFee.js index 308bd2bd..15c11f07 100644 --- a/test/handlers/fee/withOracle/calculateFee.js +++ b/test/handlers/fee/withOracle/calculateFee.js @@ -11,16 +11,22 @@ const Helpers = require("../../../helpers"); const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); const ERC20HandlerContract = artifacts.require("ERC20Handler"); const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { - const domainID = 1; + const originDomainID = 1; + const destinationDomainID = 1; const oracle = new Ethers.Wallet.createRandom(); const sender = accounts[0]; const recipientAddress = accounts[1]; + const gasUsed = 100000; + const feePercent = 500; let BridgeInstance; let FeeHandlerWithOracleInstance; let resourceID; + let FeeHandlerRouterInstance; + /* feeData structure: @@ -44,20 +50,24 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { */ beforeEach(async () => { - BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]); - FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); - await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); - - const gasUsed = 100000; - const feePercent = 500; - await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); - - ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); - resourceID = Helpers.createResourceID(ERC20MintableInstance.address, domainID); + await Promise.all([ + BridgeInstance = await Helpers.deployBridge(destinationDomainID, accounts[0]), + ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK").then(instance => ERC20MintableInstance = instance), + ]); ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - - await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); + + resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); + + await Promise.all([ + FeeHandlerWithOracleInstance.setFeeOracle(oracle.address), + FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent), + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address), + BridgeInstance.adminChangeFeeHandler(FeeHandlerRouterInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, resourceID, FeeHandlerWithOracleInstance.address ), + ]); }); it("should calculate amount of fee and return token address", async () => { @@ -69,13 +79,13 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); - const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + const res = await FeeHandlerRouterInstance.calculateFee.call(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData); assert.equal(Ethers.utils.formatEther(res.fee.toString()), "0.00491802"); assert.equal(res.tokenAddress, ERC20MintableInstance.address); }); @@ -88,13 +98,13 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); - const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + const res = await FeeHandlerRouterInstance.calculateFee.call(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData); assert.equal(web3.utils.fromWei(res.fee, "ether"), "0.05"); assert.equal(res.tokenAddress, ERC20MintableInstance.address); }); @@ -108,13 +118,13 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.5"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); - const res = await FeeHandlerWithOracleInstance.calculateFee.call(sender, domainID, domainID, resourceID, depositData, feeData); + const res = await FeeHandlerRouterInstance.calculateFee.call(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData); assert.equal(Ethers.utils.formatEther(res.fee.toString()), "0.0045"); assert.equal(res.tokenAddress, ERC20MintableInstance.address); }); @@ -128,17 +138,17 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.5"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount) + "11"; - await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Incorrect feeData length"); + await TruffleAssert.reverts(FeeHandlerRouterInstance.calculateFee(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData), "Incorrect feeData length"); }); it("should not calculate fee if deposit data differ from fee data", async () => { - const otherDomainId = 2; + const otherDestinationDomainID = 3; const tokenAmount = 100; const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); @@ -147,13 +157,13 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.5"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: otherDestinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); - await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, otherDomainId, resourceID, depositData, feeData), "Incorrect deposit params"); + await TruffleAssert.reverts(FeeHandlerRouterInstance.calculateFee(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData), "Incorrect deposit params"); }); it("should not calculate fee if oracle signature is incorrect", async () => { @@ -165,15 +175,15 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.5"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const oracle2 = new Ethers.Wallet.createRandom(); const feeData = Helpers.createOracleFeeData(oracleResponse, oracle2.privateKey, tokenAmount); - await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Invalid signature"); + await TruffleAssert.reverts(FeeHandlerRouterInstance.calculateFee(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData), "Invalid signature"); }); it("should not calculate fee if oracle data are outdated", async () => { @@ -188,11 +198,11 @@ contract("FeeHandlerWithOracle - [calculateFee]", async accounts => { ter: Ethers.utils.parseEther("1.63934"), dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), expiresAt: Math.floor(new Date().valueOf() / 1000) - 500, - fromDomainID: domainID, - toDomainID: domainID, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, resourceID }; const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); - await TruffleAssert.reverts(FeeHandlerWithOracleInstance.calculateFee(sender, domainID, domainID, resourceID, depositData, feeData), "Obsolete oracle data"); + await TruffleAssert.reverts(FeeHandlerRouterInstance.calculateFee(sender, originDomainID, destinationDomainID, resourceID, depositData, feeData), "Obsolete oracle data"); }); }); diff --git a/test/handlers/fee/withOracle/collectFee.js b/test/handlers/fee/withOracle/collectFee.js index c50f6d67..e6741368 100644 --- a/test/handlers/fee/withOracle/collectFee.js +++ b/test/handlers/fee/withOracle/collectFee.js @@ -3,28 +3,37 @@ * SPDX-License-Identifier: LGPL-3.0-only */ - const TruffleAssert = require("truffle-assertions"); - const Ethers = require("ethers"); +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); - const Helpers = require("../../../helpers"); +const Helpers = require("../../../helpers"); - const BridgeContract = artifacts.require("Bridge"); - const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); - const ERC20HandlerContract = artifacts.require("ERC20Handler"); - const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); - contract("FeeHandlerWithOracle - [collectFee]", async accounts => { +contract("FeeHandlerWithOracle - [collectFee]", async accounts => { const originDomainID = 1; const destinationDomainID = 2; const oracle = new Ethers.Wallet.createRandom(); const recipientAddress = accounts[2]; const tokenAmount = Ethers.utils.parseEther("1"); - const feeAmount =Ethers.utils.parseEther("0.05"); + const fee = Ethers.utils.parseEther("0.05"); const depositerAddress = accounts[1]; + const gasUsed = 100000; + const feePercent = 500; + let BridgeInstance; let FeeHandlerWithOracleInstance; let resourceID; + let depositData; + + let FeeHandlerRouterInstance; + let ERC20HandlerInstance; + let ERC20MintableInstance; + /* feeData structure: @@ -48,34 +57,38 @@ */ beforeEach(async () => { - BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]); - FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); - await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); + await Promise.all([ + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]), + ERC20MintableInstance = ERC20MintableContract.new("ERC20Token", "ERC20TOK").then(instance => ERC20MintableInstance = instance), + ]); + + ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); - const gasUsed = 100000; - const feePercent = 500; + await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); await FeeHandlerWithOracleInstance.setFeeProperties(gasUsed, feePercent); - ERC20MintableInstance = await ERC20MintableContract.new("token", "TOK"); resourceID = Helpers.createResourceID(ERC20MintableInstance.address, originDomainID); - ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); + await Promise.all([ + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address), + ERC20MintableInstance.mint(depositerAddress, tokenAmount + fee), + ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }), + ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, fee, { from: depositerAddress }), + BridgeInstance.adminChangeFeeHandler(FeeHandlerRouterInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, resourceID, FeeHandlerWithOracleInstance.address), + ]); - await ERC20MintableInstance.mint(depositerAddress, tokenAmount + feeAmount), + depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); - await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); - await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, feeAmount, { from: depositerAddress }); - await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); // set MPC address to unpause the Bridge await BridgeInstance.endKeygen(Helpers.mpcAddress); }); it("should collect fee in tokens", async () => { - const fee = Ethers.utils.parseEther("0.05"); - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), @@ -117,7 +130,6 @@ }); it("deposit should revert if msg.value != 0", async () => { - const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), ter: Ethers.utils.parseEther("1.63934"), @@ -172,7 +184,7 @@ ); }); - it("deposit should revert if called not by bridge", async () => { + it("deposit should revert if not called by router on FeeHandlerWithOracle contract", async () => { const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); const oracleResponse = { ber: Ethers.utils.parseEther("0.000533"), @@ -199,7 +211,81 @@ value: Ethers.utils.parseEther("0.5").toString(), } ), + "sender must be bridge or fee router contract" + ); + }); + + it("deposit should revert if not called by bridge on FeeHandlerRouter contract", async () => { + const depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, 0, { from: depositerAddress }); + await TruffleAssert.reverts( + FeeHandlerRouterInstance.collectFee( + depositerAddress, + originDomainID, + destinationDomainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress, + value: Ethers.utils.parseEther("0.5").toString(), + } + ), "sender must be bridge contract" ); }); - }); + + it("should successfully change fee handler from FeeRouter to FeeHandlerWithOracle and collect fee", async () => { + await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); + + const oracleResponse = { + ber: Ethers.utils.parseEther("0.000533"), + ter: Ethers.utils.parseEther("1.63934"), + dstGasPrice: Ethers.utils.parseUnits("30000000000", "wei"), + expiresAt: Math.floor(new Date().valueOf() / 1000) + 500, + fromDomainID: originDomainID, + toDomainID: destinationDomainID, + resourceID + }; + + const feeData = Helpers.createOracleFeeData(oracleResponse, oracle.privateKey, tokenAmount); + + const balanceBefore = (await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address)).toString(); + + const depositTx = await BridgeInstance.deposit( + destinationDomainID, + resourceID, + depositData, + feeData, + { + from: depositerAddress + } + ); + TruffleAssert.eventEmitted(depositTx, 'Deposit', (event) => { + return event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === resourceID.toLowerCase(); + }); + const internalTx = await TruffleAssert.createTransactionResult(FeeHandlerWithOracleInstance, depositTx.tx); + TruffleAssert.eventEmitted(internalTx, 'FeeCollected', event => { + return event.sender === depositerAddress && + event.fromDomainID.toNumber() === originDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && + event.resourceID === resourceID.toLowerCase() && + event.fee.toString() === fee.toString() && + event.tokenAddress === ERC20MintableInstance.address; + }); + const balanceAfter = (await ERC20MintableInstance.balanceOf(FeeHandlerWithOracleInstance.address)).toString(); + assert.equal(balanceAfter, fee.add(balanceBefore).toString()); + }); +}); diff --git a/test/handlers/fee/withOracle/distributeFee.js b/test/handlers/fee/withOracle/distributeFee.js index 5e8c1226..f06e2a8f 100644 --- a/test/handlers/fee/withOracle/distributeFee.js +++ b/test/handlers/fee/withOracle/distributeFee.js @@ -3,17 +3,18 @@ * SPDX-License-Identifier: LGPL-3.0-only */ - const TruffleAssert = require("truffle-assertions"); - const Ethers = require("ethers"); +const TruffleAssert = require("truffle-assertions"); +const Ethers = require("ethers"); - const Helpers = require("../../../helpers"); +const Helpers = require("../../../helpers"); - const BridgeContract = artifacts.require("Bridge"); - const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); - const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); - const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const BridgeContract = artifacts.require("Bridge"); +const FeeHandlerWithOracleContract = artifacts.require("FeeHandlerWithOracle"); +const ERC20MintableContract = artifacts.require("ERC20PresetMinterPauser"); +const ERC20HandlerContract = artifacts.require("ERC20Handler"); +const FeeHandlerRouterContract = artifacts.require("FeeHandlerRouter"); - contract("FeeHandlerWithOracle - [distributeFee]", async accounts => { +contract("FeeHandlerWithOracle - [distributeFee]", async accounts => { const originDomainID = 1; const destinationDomainID = 2; const oracle = new Ethers.Wallet.createRandom(); @@ -28,14 +29,16 @@ let depositData; let feeData; let oracleResponse; + let FeeHandlerRouterInstance; const assertOnlyAdmin = (method, ...params) => { return TruffleAssert.reverts(method(...params, {from: accounts[1]}), "sender doesn't have admin role"); }; beforeEach(async () => { - BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]); - FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address); + BridgeInstance = await Helpers.deployBridge(originDomainID, accounts[0]); + FeeHandlerRouterInstance = await FeeHandlerRouterContract.new(BridgeInstance.address); + FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address, FeeHandlerRouterInstance.address); await FeeHandlerWithOracleInstance.setFeeOracle(oracle.address); const gasUsed = 100000; @@ -47,13 +50,14 @@ ERC20HandlerInstance = await ERC20HandlerContract.new(BridgeInstance.address); - await BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address); - - await ERC20MintableInstance.mint(depositerAddress, tokenAmount.add(feeAmount)), - - await ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }); - await ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, tokenAmount, { from: depositerAddress }); - await BridgeInstance.adminChangeFeeHandler(FeeHandlerWithOracleInstance.address); + await Promise.all([ + BridgeInstance.adminSetResource(ERC20HandlerInstance.address, resourceID, ERC20MintableInstance.address), + ERC20MintableInstance.mint(depositerAddress, tokenAmount.add(feeAmount)), + ERC20MintableInstance.approve(ERC20HandlerInstance.address, tokenAmount, { from: depositerAddress }), + ERC20MintableInstance.approve(FeeHandlerWithOracleInstance.address, tokenAmount, { from: depositerAddress }), + BridgeInstance.adminChangeFeeHandler(FeeHandlerRouterInstance.address), + FeeHandlerRouterInstance.adminSetResourceHandler(destinationDomainID, resourceID, FeeHandlerWithOracleInstance.address), + ]); depositData = Helpers.createERCDepositData(tokenAmount, 20, recipientAddress); oracleResponse = { From 35a3e8ea8841d2e278d13ae718219e393354bbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Mlinari=C4=87?= <35880252+nmlinaric@users.noreply.github.com> Date: Thu, 14 Jul 2022 12:52:12 +0200 Subject: [PATCH 18/20] Update `refreshKey` event (#596) * Update refreshKey event to emit hash string * Update refreshKey signature * Update refreshKey tests --- contracts/Bridge.sol | 7 ++++--- test/contractBridge/admin.js | 11 +++++++---- test/helpers.js | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/contracts/Bridge.sol b/contracts/Bridge.sol index e09655a8..ae8dffdc 100644 --- a/contracts/Bridge.sol +++ b/contracts/Bridge.sol @@ -67,7 +67,7 @@ contract Bridge is Pausable, Context { event EndKeygen(); - event KeyRefresh(); + event KeyRefresh(string hash); event Retry(string txHash); @@ -364,9 +364,10 @@ contract Bridge is Pausable, Context { It's used to trigger the belonging process on the MPC side which also handles keygen function calls order. @notice Only callable by address that has the right to call the specific function, which is mapped in {functionAccess} in AccessControlSegregator contract. + @param hash Topology hash which prevents changes during refresh process. */ - function refreshKey() external onlyAllowed { - emit KeyRefresh(); + function refreshKey(string memory hash) external onlyAllowed { + emit KeyRefresh(hash); } /** diff --git a/test/contractBridge/admin.js b/test/contractBridge/admin.js index 76779ba8..0f9477bd 100644 --- a/test/contractBridge/admin.js +++ b/test/contractBridge/admin.js @@ -22,6 +22,7 @@ contract('Bridge - [admin]', async (accounts) => { const expectedBridgeAdmin = accounts[0]; const someAddress = "0xcafecafecafecafecafecafecafecafecafecafe"; const nullAddress = "0x0000000000000000000000000000000000000000"; + const topologyHash = "549f715f5b06809ada23145c2dc548db"; const bytes32 = "0x0"; let ADMIN_ROLE; @@ -103,14 +104,16 @@ contract('Bridge - [admin]', async (accounts) => { await TruffleAssert.reverts(BridgeInstance.endKeygen(someAddress), "MPC address can't be updated"); }); - it('Should successfully emit "KeyRefresh" event if called by admin', async () => { - const startKeygenTx = await BridgeInstance.refreshKey(); + it('Should successfully emit "KeyRefresh" event with expected hash value if called by admin', async () => { + const startKeygenTx = await BridgeInstance.refreshKey(topologyHash); - TruffleAssert.eventEmitted(startKeygenTx, 'KeyRefresh'); + TruffleAssert.eventEmitted(startKeygenTx, 'KeyRefresh', (event) => { + return event.hash = topologyHash; + }); }); it('Should fail if "refreshKey" is called by non admin', async () => { - await assertOnlyAdmin(BridgeInstance.refreshKey); + await assertOnlyAdmin(BridgeInstance.refreshKey, topologyHash); }); // Set Handler Address diff --git a/test/helpers.js b/test/helpers.js index dc1f3b84..c52a554b 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -235,7 +235,7 @@ const deployBridge = async (domainID, admin) => { "0xbd2a1820", // adminWithdraw "0x6ba6db6b", // startKeygen "0xd2e5fae9", // endKeygen - "0xf5f63b39", // refreshKey + "0xd8236744", // refreshKey ], Array(13).fill(admin) From aa22b0cd57b60044972e9e2596b6e115b440bbc3 Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 14 Jul 2022 20:33:49 +0200 Subject: [PATCH 19/20] release 3.1.0 (#597) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf2e8a9a..88af1ead 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/chainbridge-contracts", - "version": "3.0.1", + "version": "3.1.0", "description": "", "main": "dist/index.js", "repository": "https://github.com/ChainSafe/chainbridge-solidity.git", From f7d59e3943ae1675f613586143ffd029f2cadd62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Jul 2022 18:37:11 +0000 Subject: [PATCH 20/20] Bump @rollup/plugin-babel from 5.3.0 to 5.3.1 Bumps [@rollup/plugin-babel](https://github.com/rollup/plugins/tree/HEAD/packages/babel) from 5.3.0 to 5.3.1. - [Release notes](https://github.com/rollup/plugins/releases) - [Changelog](https://github.com/rollup/plugins/blob/master/packages/babel/CHANGELOG.md) - [Commits](https://github.com/rollup/plugins/commits/babel-v5.3.1/packages/babel) --- updated-dependencies: - dependency-name: "@rollup/plugin-babel" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b219a63..aa291c21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/chainbridge-contracts", - "version": "2.0.0", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1067,9 +1067,9 @@ "optional": true }, "@rollup/plugin-babel": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz", - "integrity": "sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.4", @@ -3585,7 +3585,7 @@ }, "@zondax/filecoin-signing-tools": { "version": "git+ssh://git@github.com/Digital-MOB-Filecoin/filecoin-signing-tools-js.git#8f8e92157cac2556d35cab866779e9a8ea8a4e25", - "from": "@zondax/filecoin-signing-tools@github:Digital-MOB-Filecoin/filecoin-signing-tools-js", + "from": "github:Digital-MOB-Filecoin/filecoin-signing-tools-js", "dev": true, "optional": true, "requires": { @@ -7608,7 +7608,7 @@ "@ledgerhq/hw-transport-webusb": "^5.22.0", "@nodefactory/filsnap-adapter": "^0.2.1", "@nodefactory/filsnap-types": "^0.2.1", - "@zondax/filecoin-signing-tools": "@zondax/filecoin-signing-tools@github:Digital-MOB-Filecoin/filecoin-signing-tools-js", + "@zondax/filecoin-signing-tools": "github:Digital-MOB-Filecoin/filecoin-signing-tools-js", "bignumber.js": "^9.0.0", "bitcore-lib": "^8.22.2", "bitcore-mnemonic": "^8.22.2",