diff --git a/.sample-env b/.sample-env index bb1ae2d..a2730c9 100644 --- a/.sample-env +++ b/.sample-env @@ -1,3 +1,6 @@ INFURA_PROJECT_ID= DEPLOYER_PRIVATE_KEY= ETHERSCAN_API_KEY= +ALCHEMY_KEY= +REPORT_GAS= +COINMARKETCAP_API_KEY= diff --git a/.solcover.js b/.solcover.js index 958b9d3..68931c9 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,4 +1,4 @@ // Exclude the legacy compiler MultiSigWallet.sol file from instrumentation. module.exports = { - skipFiles: [ 'MultiSigWallet.sol' ] + skipFiles: ["MultiSigWallet.sol"], }; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b4a8f4a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "solidity.compileUsingRemoteVersion": "v0.8.8+commit.dddeac2f", + "solidity-va.uml.actors.enable": false +} diff --git a/contracts/access/PermitControl.sol b/contracts/access/PermitControl.sol index e03afdc..104b07d 100644 --- a/contracts/access/PermitControl.sol +++ b/contracts/access/PermitControl.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.7; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; +import "hardhat/console.sol"; /** @title An advanced permission-management contract. @@ -18,21 +19,21 @@ import "@openzeppelin/contracts/utils/Address.sol"; August 23rd, 2021. */ abstract contract PermitControl is Ownable { - using Address for address; + using Address for address; - /// A special reserved constant for representing no rights. - bytes32 public constant ZERO_RIGHT = hex"00000000000000000000000000000000"; + /// A special reserved constant for representing no rights. + bytes32 public constant ZERO_RIGHT = hex"00000000000000000000000000000000"; - /// A special constant specifying the unique, universal-rights circumstance. - bytes32 public constant UNIVERSAL = hex"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; + /// A special constant specifying the unique, universal-rights circumstance. + bytes32 public constant UNIVERSAL = hex"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - /* + /* A special constant specifying the unique manager right. This right allows an address to freely-manipulate the `managedRight` mapping. **/ - bytes32 public constant MANAGER = hex"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; + bytes32 public constant MANAGER = hex"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; - /** + /** A mapping of per-address permissions to the circumstances, represented as an additional layer of generic bytes32 data, under which the addresses have various permits. A permit in this sense is represented by a per-circumstance @@ -45,19 +46,19 @@ abstract contract PermitControl is Ownable { max-integer circumstance. Perpetual rights may be given an expiry time of max-integer. */ - mapping( address => mapping( bytes32 => mapping( bytes32 => uint256 ))) - public permissions; + mapping(address => mapping(bytes32 => mapping(bytes32 => uint256))) + public permissions; - /** + /** An additional mapping of managed rights to manager rights. This mapping represents the administrator relationship that various rights have with one another. An address with a manager right may freely set permits for that manager right's managed rights. Each right may be managed by only one other right. */ - mapping( bytes32 => bytes32 ) public managerRight; + mapping(bytes32 => bytes32) public managerRight; - /** + /** An event emitted when an address has a permit updated. This event captures, through its various parameter combinations, the cases of granting a permit, updating the expiration time of a permit, or revoking a permit. @@ -68,32 +69,32 @@ abstract contract PermitControl is Ownable { @param role The role which was updated. @param expirationTime The time when the permit expires. */ - event PermitUpdated( - address indexed updator, - address indexed updatee, - bytes32 circumstance, - bytes32 indexed role, - uint256 expirationTime - ); - -// /** -// A version of PermitUpdated for work with setPermits() function. - -// @param updator The address which has updated the permit. -// @param updatees The addresses whose permit were updated. -// @param circumstances The circumstances wherein the permits were updated. -// @param roles The roles which were updated. -// @param expirationTimes The times when the permits expire. -// */ -// event PermitsUpdated( -// address indexed updator, -// address[] indexed updatees, -// bytes32[] circumstances, -// bytes32[] indexed roles, -// uint256[] expirationTimes -// ); - - /** + event PermitUpdated( + address indexed updator, + address indexed updatee, + bytes32 circumstance, + bytes32 indexed role, + uint256 expirationTime + ); + + // /** + // A version of PermitUpdated for work with setPermits() function. + + // @param updator The address which has updated the permit. + // @param updatees The addresses whose permit were updated. + // @param circumstances The circumstances wherein the permits were updated. + // @param roles The roles which were updated. + // @param expirationTimes The times when the permits expire. + // */ + // event PermitsUpdated( + // address indexed updator, + // address[] indexed updatees, + // bytes32[] circumstances, + // bytes32[] indexed roles, + // uint256[] expirationTimes + // ); + + /** An event emitted when a management relationship in `managerRight` is updated. This event captures adding and revoking management permissions via observing the update history of the `managerRight` value. @@ -102,13 +103,13 @@ abstract contract PermitControl is Ownable { @param managedRight The right which had its manager updated. @param managerRight The new manager right which was updated to. */ - event ManagementUpdated( - address indexed manager, - bytes32 indexed managedRight, - bytes32 indexed managerRight - ); + event ManagementUpdated( + address indexed manager, + bytes32 indexed managedRight, + bytes32 indexed managerRight + ); - /** + /** A modifier which allows only the super-administrative owner or addresses with a specified valid right to perform a call. @@ -117,24 +118,23 @@ abstract contract PermitControl is Ownable { @param _right The right to validate for the calling address. It must be non-expired and exist within the specified `_circumstance`. */ - modifier hasValidPermit( - bytes32 _circumstance, - bytes32 _right - ) { - require(_msgSender() == owner() - || hasRight(_msgSender(), _circumstance, _right), - "P1"); - _; - } - - /** + modifier hasValidPermit(bytes32 _circumstance, bytes32 _right) { + require( + _msgSender() == owner() || + hasRight(_msgSender(), _circumstance, _right), + "P1" + ); + _; + } + + /** Return a version number for this contract's interface. */ - function version() external virtual pure returns (uint256) { - return 1; - } + function version() external pure virtual returns (uint256) { + return 1; + } - /** + /** Determine whether or not an address has some rights under the given circumstance, and if they do have the right, until when. @@ -144,15 +144,15 @@ abstract contract PermitControl is Ownable { @return The timestamp in seconds when the `_right` expires. If the timestamp is zero, we can assume that the user never had the right. */ - function hasRightUntil( - address _address, - bytes32 _circumstance, - bytes32 _right - ) public view returns (uint256) { - return permissions[_address][_circumstance][_right]; - } - - /** + function hasRightUntil( + address _address, + bytes32 _circumstance, + bytes32 _right + ) public view returns (uint256) { + return permissions[_address][_circumstance][_right]; + } + + /** Determine whether or not an address has some rights under the given circumstance, @@ -161,15 +161,15 @@ abstract contract PermitControl is Ownable { @param _right The right to check for validity. @return true or false, whether user has rights and time is valid. */ - function hasRight( - address _address, - bytes32 _circumstance, - bytes32 _right - ) public view returns (bool) { - return permissions[_address][_circumstance][_right] > block.timestamp; - } - - /** + function hasRight( + address _address, + bytes32 _circumstance, + bytes32 _right + ) public view returns (bool) { + return permissions[_address][_circumstance][_right] > block.timestamp; + } + + /** Set the permit to a specific address under some circumstances. A permit may only be set by the super-administrative contract owner or an address holding some delegated management permit. @@ -180,59 +180,63 @@ abstract contract PermitControl is Ownable { @param _expirationTime The time when the `_right` expires for the provided `_circumstance`. */ - function setPermit( - address _address, - bytes32 _circumstance, - bytes32 _right, - uint256 _expirationTime - ) public virtual hasValidPermit(UNIVERSAL, managerRight[_right]) { - require(_right != ZERO_RIGHT, - "P2"); - permissions[_address][_circumstance][_right] = _expirationTime; - emit PermitUpdated(_msgSender(), _address, _circumstance, _right, - _expirationTime); - } - -// /** -// Version of setPermit() that works with multiple addresses in one transaction. - -// @param _addresses The array of addresses to assign the specified `_right` to. -// @param _circumstances The array of circumstances in which the `_right` is -// valid. -// @param _rights The array of specific rights to assign. -// @param _expirationTimes The array of times when the `_rights` expires for -// the provided _circumstance`. -// */ -// function setPermits( -// address[] memory _addresses, -// bytes32[] memory _circumstances, -// bytes32[] memory _rights, -// uint256[] memory _expirationTimes -// ) public virtual { -// require((_addresses.length == _circumstances.length) -// && (_circumstances.length == _rights.length) -// && (_rights.length == _expirationTimes.length), -// "leghts of input arrays are not equal" -// ); -// bytes32 lastRight; -// for(uint i = 0; i < _rights.length; i++) { -// if (lastRight != _rights[i] || (i == 0)) { -// require(_msgSender() == owner() || hasRight(_msgSender(), _circumstances[i], _rights[i]), "P1"); -// require(_rights[i] != ZERO_RIGHT, "P2"); -// lastRight = _rights[i]; -// } -// permissions[_addresses[i]][_circumstances[i]][_rights[i]] = _expirationTimes[i]; -// } -// emit PermitsUpdated( -// _msgSender(), -// _addresses, -// _circumstances, -// _rights, -// _expirationTimes -// ); -// } - - /** + function setPermit( + address _address, + bytes32 _circumstance, + bytes32 _right, + uint256 _expirationTime + ) public virtual hasValidPermit(UNIVERSAL, managerRight[_right]) { + require(_right != ZERO_RIGHT, "P2"); + permissions[_address][_circumstance][_right] = _expirationTime; + emit PermitUpdated( + _msgSender(), + _address, + _circumstance, + _right, + _expirationTime + ); + } + + // /** + // Version of setPermit() that works with multiple addresses in one transaction. + + // @param _addresses The array of addresses to assign the specified `_right` to. + // @param _circumstances The array of circumstances in which the `_right` is + // valid. + // @param _rights The array of specific rights to assign. + // @param _expirationTimes The array of times when the `_rights` expires for + // the provided _circumstance`. + // */ + // function setPermits( + // address[] memory _addresses, + // bytes32[] memory _circumstances, + // bytes32[] memory _rights, + // uint256[] memory _expirationTimes + // ) public virtual { + // require((_addresses.length == _circumstances.length) + // && (_circumstances.length == _rights.length) + // && (_rights.length == _expirationTimes.length), + // "leghts of input arrays are not equal" + // ); + // bytes32 lastRight; + // for(uint i = 0; i < _rights.length; i++) { + // if (lastRight != _rights[i] || (i == 0)) { + // require(_msgSender() == owner() || hasRight(_msgSender(), _circumstances[i], _rights[i]), "P1"); + // require(_rights[i] != ZERO_RIGHT, "P2"); + // lastRight = _rights[i]; + // } + // permissions[_addresses[i]][_circumstances[i]][_rights[i]] = _expirationTimes[i]; + // } + // emit PermitsUpdated( + // _msgSender(), + // _addresses, + // _circumstances, + // _rights, + // _expirationTimes + // ); + // } + + /** Set the `_managerRight` whose `UNIVERSAL` holders may freely manage the specified `_managedRight`. @@ -241,13 +245,13 @@ abstract contract PermitControl is Ownable { @param _managerRight The right whose `UNIVERSAL` holders may manage `_managedRight`. */ - function setManagerRight( - bytes32 _managedRight, - bytes32 _managerRight - ) external virtual hasValidPermit(UNIVERSAL, MANAGER) { - require(_managedRight != ZERO_RIGHT, - "P3"); - managerRight[_managedRight] = _managerRight; - emit ManagementUpdated(_msgSender(), _managedRight, _managerRight); - } -} \ No newline at end of file + function setManagerRight(bytes32 _managedRight, bytes32 _managerRight) + external + virtual + hasValidPermit(UNIVERSAL, MANAGER) + { + require(_managedRight != ZERO_RIGHT, "P3"); + managerRight[_managedRight] = _managerRight; + emit ManagementUpdated(_msgSender(), _managedRight, _managerRight); + } +} diff --git a/contracts/assets/erc721/IOUToken.sol b/contracts/assets/erc721/IOUToken.sol new file mode 100644 index 0000000..a6364a6 --- /dev/null +++ b/contracts/assets/erc721/IOUToken.sol @@ -0,0 +1,660 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.8; + +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import "./interfaces/IStaker.sol"; + +/* + It saves bytecode to revert on custom errors instead of using require + statements. We are just declaring these errors for reverting with upon various + conditions later in this contract. Thanks, Chiru Labs! +*/ +error ApprovalCallerNotOwnerNorApproved(); +error ApprovalQueryForNonexistentToken(); +error ApproveToCaller(); +error CapExceeded(); +error MintedQueryForZeroAddress(); +error MintToZeroAddress(); +error MintZeroQuantity(); +error NotAnAdmin(); +error OwnerIndexOutOfBounds(); +error OwnerQueryForNonexistentToken(); +error TokenIndexOutOfBounds(); +error TransferCallerNotOwnerNorApproved(); +error TransferFromIncorrectOwner(); +error TransferIsLockedGlobally(); +error TransferIsLocked(); +error TransferToNonERC721ReceiverImplementer(); +error TransferToZeroAddress(); +error URIQueryForNonexistentToken(); + +/** + @title A minimalistic, gas-efficient ERC-721 implementation forked from the + `Super721` ERC-721 implementation used by SuperFarm. + @author Tim Clancy + @author 0xthrpw + @author Qazawat Zirak + @author Rostislav Khlebnikov + + Compared to the original `Super721` implementation that this contract forked + from, this is a very pared-down contract that includes simple delegated + minting and transfer locks. + + This contract includes the gas efficiency techniques graciously shared with + the world in the specific ERC-721 implementation by Chiru Labs that is being + called "ERC-721A" (https://github.com/chiru-labs/ERC721A). We have validated + this contract against their test cases. + + February 8th, 2022. +*/ +contract IOUToken721 is ERC165, IERC721, IERC721Metadata, Ownable { + using Address for address; + using Strings for uint256; + + /// The name of this ERC-721 contract. + string public name; + + /// The symbol associated with this ERC-721 contract. + string public symbol; + + /// Staker address + address public stakerAddress; + + /** + The metadata URI to which token IDs are appended for generating `tokenUri` + results. The URI will always naively slap a decimal token ID to the end of + this provided URI. + */ + string public metadataUri; + + /// The maximum number of this NFT that may be minted. + uint256 public immutable cap; + + /** + The ID of the next token that will be minted. Our range of token IDs begins + at one in order to avoid downstream errors with uninitialized mappings. + */ + uint256 private nextId = 1; + + /** + A mapping from token IDs to their holding addresses. If the holding address + is the zero address, that does not necessarily mean that the token is + unowned; the ID space of owned tokens is gappy. The `_ownershipOf` function + handles these gaps for determining the appropriate owners. + */ + mapping(uint256 => address) private owners; + + /// A mapping from an address to the balance of tokens held by that address. + mapping(address => uint256) private balances; + + /** + A mapping from each token ID to an approved address for that specific ID. An + approved address is allowed to transfer the token with the specified ID on + behalf of that token's owner. + */ + mapping(uint256 => address) private tokenApprovals; + + /** + A mapping from each address to per-address operator approvals. Operators are + those addresses that have been approved to transfer tokens of any ID on + behalf of the approver. + */ + mapping(address => mapping(address => bool)) private operatorApprovals; + + /// A mapping to track administrative callers who have been set by the owner. + mapping(address => bool) private administrators; + + /// Whether or not transfer is locked for all items. + bool public allTransfersLocked; + + /// Whether or not the transfer of a particular token ID is locked. + mapping(uint256 => bool) public transferLocks; + + /// token id => pool id + mapping(uint256 => uint256) public associatedPool; + + /// mapping for watch burned items + mapping(uint256 => bool) private burned; + + /** + A modifier to see if a caller is an approved administrator. + */ + modifier onlyAdmin() { + if (_msgSender() != owner() && !administrators[_msgSender()]) { + revert NotAnAdmin(); + } + _; + } + + /** + Construct a new instance of this ERC-721 contract. + + @param _name The name to assign to this item collection contract. + @param _symbol The ticker symbol of this item collection. + @param _metadataURI The metadata URI to perform later token ID substitution + with. + @param _cap The maximum number of tokens that may be minted. + */ + constructor( + string memory _name, + string memory _symbol, + string memory _metadataURI, + uint256 _cap, + address _stakerAddress + ) { + name = _name; + symbol = _symbol; + metadataUri = _metadataURI; + cap = _cap; + stakerAddress = _stakerAddress; + } + + /** + Flag this contract as supporting the ERC-721 standard, the ERC-721 metadata + extension, and the enumerable ERC-721 extension. + + @param _interfaceId The identifier, as defined by ERC-165, of the contract + interface to support. + + @return Whether or not the interface being tested is supported. + */ + function supportsInterface(bytes4 _interfaceId) + public + view + virtual + override(ERC165, IERC165) + returns (bool) + { + return + (_interfaceId == type(IERC721).interfaceId) || + (_interfaceId == type(IERC721Metadata).interfaceId) || + (super.supportsInterface(_interfaceId)); + } + + /** + Return the total number of this token that have ever been minted. + + @return The total supply of minted tokens. + */ + function totalSupply() public view returns (uint256) { + return nextId - 1; + } + + /** + Retrieve the number of distinct token IDs held by `_owner`. + + @param _owner The address to retrieve a count of held tokens for. + + @return The number of tokens held by `_owner`. + */ + function balanceOf(address _owner) + external + view + override + returns (uint256) + { + return balances[_owner]; + } + + /** + Just as Chiru Labs does, we maintain a sparse list of token owners; for + example if Alice owns tokens with ID #1 through #3 and Bob owns tokens #4 + through #5, the ownership list would look like: + + [ 1: Alice, 2: 0x0, 3: 0x0, 4: Bob, 5: 0x0, ... ]. + + This function is able to consume that sparse list for determining an actual + owner. Chiru Labs says that the gas spent here starts off proportional to + the maximum mint batch size and gradually moves to O(1) as tokens get + transferred. + + @param _id The ID of the token which we are finding the owner for. + + @return owner The owner of the token with ID of `_id`. + */ + function _ownershipOf(uint256 _id) private view returns (address owner) { + if (!_exists(_id)) { + revert OwnerQueryForNonexistentToken(); + } + unchecked { + for (uint256 curr = _id; ; curr--) { + owner = owners[curr]; + if (owner != address(0)) { + return owner; + } + } + } + } + + /** + Return the address that holds a particular token ID. + + @param _id The token ID to check for the holding address of. + + @return The address that holds the token with ID of `_id`. + */ + function ownerOf(uint256 _id) external view override returns (address) { + return _ownershipOf(_id); + } + + /** + Return whether a particular token ID has been minted or not. + + @param _id The ID of a specific token to check for existence. + + @return Whether or not the token of ID `_id` exists. + */ + function _exists(uint256 _id) public view returns (bool) { + return _id > 0 && _id < nextId && !burned[_id]; + } + + /** + Return the address approved to perform transfers on behalf of the owner of + token `_id`. If no address is approved, this returns the zero address. + + @param _id The specific token ID to check for an approved address. + + @return The address that may operate on token `_id` on its owner's behalf. + */ + function getApproved(uint256 _id) public view override returns (address) { + if (!_exists(_id)) { + revert ApprovalQueryForNonexistentToken(); + } + return tokenApprovals[_id]; + } + + /** + This function returns true if `_operator` is approved to transfer items + owned by `_owner`. + + @param _owner The owner of items to check for transfer ability. + @param _operator The potential transferrer of `_owner`'s items. + + @return Whether `_operator` may transfer items owned by `_owner`. + */ + function isApprovedForAll(address _owner, address _operator) + public + view + virtual + override + returns (bool) + { + return operatorApprovals[_owner][_operator]; + } + + /** + Return the token URI of the token with the specified `_id`. The token URI is + dynamically constructed from this contract's `metadataUri`. + + @param _id The ID of the token to retrive a metadata URI for. + + @return The metadata URI of the token with the ID of `_id`. + */ + function tokenURI(uint256 _id) + external + view + virtual + override + returns (string memory) + { + if (!_exists(_id)) { + revert URIQueryForNonexistentToken(); + } + return + bytes(metadataUri).length != 0 + ? string(abi.encodePacked(metadataUri, _id.toString())) + : ""; + } + + /** + This private helper function updates the token approval address of the token + with ID of `_id` to the address `_to` and emits an event that the address + `_owner` triggered this approval. This function emits an {Approval} event. + + @param _owner The owner of the token with the ID of `_id`. + @param _to The address that is being granted approval to the token `_id`. + @param _id The ID of the token that is having its approval granted. + */ + function _approve( + address _owner, + address _to, + uint256 _id + ) private { + tokenApprovals[_id] = _to; + emit Approval(_owner, _to, _id); + } + + /** + Allow the owner of a particular token ID, or an approved operator of the + owner, to set the approved address of a particular token ID. + + @param _approved The address being approved to transfer the token of ID `_id`. + @param _id The token ID with its approved address being set to `_approved`. + */ + function approve(address _approved, uint256 _id) external override { + address owner = _ownershipOf(_id); + if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) { + revert ApprovalCallerNotOwnerNorApproved(); + } + _approve(owner, _approved, _id); + } + + /** + Enable or disable approval for a third party `_operator` address to manage + all of the caller's tokens. + + @param _operator The address to grant management rights over all of the + caller's tokens. + @param _approved The status of the `_operator`'s approval for the caller. + */ + function setApprovalForAll(address _operator, bool _approved) + external + override + { + operatorApprovals[_msgSender()][_operator] = _approved; + emit ApprovalForAll(_msgSender(), _operator, _approved); + } + + /** + This private helper function handles the portion of transferring an ERC-721 + token that is common to both the unsafe `transferFrom` and the + `safeTransferFrom` variants. + + This function does not support burning tokens and emits a {Transfer} event. + + @param _from The address to transfer the token with ID of `_id` from. + @param _to The address to transfer the token to. + @param _id The ID of the token to transfer. + */ + function _transfer( + address _from, + address _to, + uint256 _id + ) private { + address previousOwner = _ownershipOf(_id); + bool isApprovedOrOwner = (_msgSender() == previousOwner) || + (isApprovedForAll(previousOwner, _msgSender())) || + (getApproved(_id) == _msgSender()); + + if (!isApprovedOrOwner) { + revert TransferCallerNotOwnerNorApproved(); + } + if (previousOwner != _from) { + revert TransferFromIncorrectOwner(); + } + if (_to == address(0)) { + revert TransferToZeroAddress(); + } + if (allTransfersLocked) { + revert TransferIsLockedGlobally(); + } + if (transferLocks[_id]) { + revert TransferIsLocked(); + } + + // Clear any token approval set by the previous owner. + _approve(previousOwner, address(0), _id); + + /* + Another Chiru Labs tip: we may safely use unchecked math here given the + sender balance check and the limited range of our expected token ID space. + */ + unchecked { + balances[_from] -= 1; + balances[_to] += 1; + owners[_id] = _to; + + /* + The way the gappy token ownership list is setup, we can tell that + `_from` owns the next token ID if it has a zero address owner. This also + happens to be what limits an efficient burn implementation given the + current setup of this contract. We need to update this spot in the list + to mark `_from`'s ownership of this portion of the token range. + */ + uint256 nextTokenId = _id + 1; + if (owners[nextTokenId] == address(0) && _exists(nextTokenId)) { + owners[nextTokenId] = previousOwner; + } + } + IStaker(stakerAddress).updateOnIouTransfer( + associatedPool[_id], + _id, + _from, + _to + ); + + // Emit the transfer event. + emit Transfer(_from, _to, _id); + } + + /** + This function performs an unsafe transfer of token ID `_id` from address + `_from` to address `_to`. The transfer is considered unsafe because it does + not validate that the receiver can actually take proper receipt of an + ERC-721 token. + + @param _from The address to transfer the token from. + @param _to The address to transfer the token to. + @param _id The ID of the token being transferred. + */ + function transferFrom( + address _from, + address _to, + uint256 _id + ) external virtual override { + _transfer(_from, _to, _id); + } + + /** + This is an private helper function used to, if the transfer destination is + found to be a smart contract, check to see if that contract reports itself + as safely handling ERC-721 tokens by returning the magical value from its + `onERC721Received` function. + + @param _from The address of the previous owner of token `_id`. + @param _to The destination address that will receive the token. + @param _id The ID of the token being transferred. + @param _data Optional data to send along with the transfer check. + + @return Whether or not the destination contract reports itself as being able + to handle ERC-721 tokens. + */ + function _checkOnERC721Received( + address _from, + address _to, + uint256 _id, + bytes memory _data + ) private returns (bool) { + if (_to.isContract()) { + try + IERC721Receiver(_to).onERC721Received( + _msgSender(), + _from, + _id, + _data + ) + returns (bytes4 retval) { + return retval == IERC721Receiver(_to).onERC721Received.selector; + } catch (bytes memory reason) { + if (reason.length == 0) + revert TransferToNonERC721ReceiverImplementer(); + else { + assembly { + revert(add(32, reason), mload(reason)) + } + } + } + } else { + return true; + } + } + + /** + This function performs transfer of token ID `_id` from address `_from` to + address `_to`. This function validates that the receiving address reports + itself as being able to properly handle an ERC-721 token. + + @param _from The address to transfer the token from. + @param _to The address to transfer the token to. + @param _id The ID of the token being transferred. + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _id + ) public virtual override { + safeTransferFrom(_from, _to, _id, ""); + } + + /** + This function performs transfer of token ID `_id` from address `_from` to + address `_to`. This function validates that the receiving address reports + itself as being able to properly handle an ERC-721 token. This variant also + sends `_data` along with the transfer check. + + @param _from The address to transfer the token from. + @param _to The address to transfer the token to. + @param _id The ID of the token being transferred. + @param _data Optional data to send along with the transfer check. + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _id, + bytes memory _data + ) public override { + _transfer(_from, _to, _id); + if (!_checkOnERC721Received(_from, _to, _id, _data)) { + revert TransferToNonERC721ReceiverImplementer(); + } + } + + /** + This function allows permissioned minters of this contract to mint one or + more tokens dictated by the `_amount` parameter. Any minted tokens are sent + to the `_recipient` address. + + Note that tokens are always minted sequentially starting at one. That is, + the list of token IDs is always increasing and looks like [ 1, 2, 3... ]. + Also note that per our use cases the intended recipient of these minted + items will always be externally-owned accounts and not other contracts. As a + result there is no safety check on whether or not the mint destination can + actually correctly handle an ERC-721 token. + + @param _recipient The recipient of the tokens being minted. + @param _amount The amount of tokens to mint. + */ + function mintBatch( + address _recipient, + uint256 _amount, + uint256 _poolId + ) external onlyAdmin { + if (_recipient == address(0)) { + revert MintToZeroAddress(); + } + if (_amount == 0) { + revert MintZeroQuantity(); + } + if (nextId - 1 + _amount > cap) { + revert CapExceeded(); + } + + /** + Inspired by the Chiru Labs implementation, we use unchecked math here. + Only enormous minting counts that are unrealistic for our purposes would + cause an overflow. + */ + uint256 startTokenId = nextId; + unchecked { + balances[_recipient] += _amount; + owners[startTokenId] = _recipient; + + uint256 updatedIndex = startTokenId; + for (uint256 i; i < _amount; i++) { + associatedPool[updatedIndex] = _poolId; + emit Transfer(address(0), _recipient, updatedIndex); + updatedIndex++; + } + nextId = updatedIndex; + } + } + + function burnBatch(address _recipient, uint256[] memory _ids) + external + onlyAdmin + { + if (_recipient == address(0)) { + revert MintToZeroAddress(); + } + unchecked { + balances[_recipient] -= _ids.length; + } + for (uint256 i; i < _ids.length; i++) { + if (_exists(_ids[i])) { + revert MintZeroQuantity(); + } + + unchecked { + burned[_ids[i]] = true; + } + + if (owners[_ids[i] + 1] == address(0)) { + if (nextId != _ids[i] + 1) { + owners[_ids[i] + 1] = _recipient; + } + } + } + } + + /** + This function allows the original owner of the contract to add or remove + other addresses as administrators. Administrators may perform mints and may + lock token transfers. + + @param _newAdmin The new admin to update permissions for. + @param _isAdmin Whether or not the new admin should be an admin. + */ + function setAdmin(address _newAdmin, bool _isAdmin) external onlyOwner { + administrators[_newAdmin] = _isAdmin; + } + + /** + Allow the item collection owner to update the metadata URI of this + collection. + + @param _uri The new URI to update to. + */ + function setURI(string calldata _uri) external virtual onlyOwner { + metadataUri = _uri; + } + + /** + This function allows the owner to lock the transfer of all token IDs. This + is designed to prevent whitelisted presale users from using the secondary + market to undercut the auction before the sale has ended. + + @param _locked The status of the lock; true to lock, false to unlock. + */ + function lockAllTransfers(bool _locked) external onlyOwner { + allTransfersLocked = _locked; + } + + /** + This function allows an administrative caller to lock the transfer of + particular token IDs. This is designed for a non-escrow staking contract + that comes later to lock a user's NFT while still letting them keep it in + their wallet. + + @param _id The ID of the token to lock. + @param _locked The status of the lock; true to lock, false to unlock. + */ + function lockTransfer(uint256 _id, bool _locked) external onlyAdmin { + transferLocks[_id] = _locked; + } +} diff --git a/contracts/assets/erc721/Super721.sol b/contracts/assets/erc721/Super721.sol index d0d0a46..4ece608 100644 --- a/contracts/assets/erc721/Super721.sol +++ b/contracts/assets/erc721/Super721.sol @@ -26,119 +26,120 @@ import "../../utils/Utils.sol"; August 4th, 2021. */ contract Super721 is PermitControl, ERC165Storage, IERC721 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableMap for EnumerableMap.UintToAddressMap; - - /// The public identifier for the right to set this contract's metadata URI. - bytes32 public constant SET_URI = keccak256("SET_URI"); - - /// The public identifier for the right to set this contract's proxy registry. - bytes32 public constant SET_PROXY_REGISTRY = keccak256("SET_PROXY_REGISTRY"); - - /// The public identifier for the right to configure item groups. - bytes32 public constant CONFIGURE_GROUP = keccak256("CONFIGURE_GROUP"); - - /// The public identifier for the right to mint items. - bytes32 public constant MINT = keccak256("MINT"); - - /// The public identifier for the right to burn items. - bytes32 public constant BURN = keccak256("BURN"); - - /// The public identifier for the right to set item metadata. - bytes32 public constant SET_METADATA = keccak256("SET_METADATA"); - - /// The public identifier for the right to lock the metadata URI. - bytes32 public constant LOCK_URI = keccak256("LOCK_URI"); - - /// The public identifier for the right to lock an item's metadata. - bytes32 public constant LOCK_ITEM_URI = keccak256("LOCK_ITEM_URI"); - - /// The public identifier for the right to disable item creation. - bytes32 public constant LOCK_CREATION = keccak256("LOCK_CREATION"); - - /* - * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 - * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e - * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 - * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc - * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 - * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 - * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd - * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e - * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde - * - * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ - * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd - */ - bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; - - /* - * bytes4(keccak256('name()')) == 0x06fdde03 - * bytes4(keccak256('symbol()')) == 0x95d89b41 - * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd - * - * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f - */ - bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; - - /* - * bytes4(keccak256('totalSupply()')) == 0x18160ddd - * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 - * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 - * - * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 - */ - bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; - /// @dev Supply the magic number for the required ERC-721 interface. - - /// @dev A mask for isolating an item's group ID. - uint256 private constant GROUP_MASK = uint256(type(uint128).max) << 128; - - /// The public name of this contract. - string public name; - - string public symbol; - - /** + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableMap for EnumerableMap.UintToAddressMap; + + /// The public identifier for the right to set this contract's metadata URI. + bytes32 public constant SET_URI = keccak256("SET_URI"); + + /// The public identifier for the right to set this contract's proxy registry. + bytes32 public constant SET_PROXY_REGISTRY = + keccak256("SET_PROXY_REGISTRY"); + + /// The public identifier for the right to configure item groups. + bytes32 public constant CONFIGURE_GROUP = keccak256("CONFIGURE_GROUP"); + + /// The public identifier for the right to mint items. + bytes32 public constant MINT = keccak256("MINT"); + + /// The public identifier for the right to burn items. + bytes32 public constant BURN = keccak256("BURN"); + + /// The public identifier for the right to set item metadata. + bytes32 public constant SET_METADATA = keccak256("SET_METADATA"); + + /// The public identifier for the right to lock the metadata URI. + bytes32 public constant LOCK_URI = keccak256("LOCK_URI"); + + /// The public identifier for the right to lock an item's metadata. + bytes32 public constant LOCK_ITEM_URI = keccak256("LOCK_ITEM_URI"); + + /// The public identifier for the right to disable item creation. + bytes32 public constant LOCK_CREATION = keccak256("LOCK_CREATION"); + + /* + * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 + * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e + * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 + * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc + * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 + * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 + * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd + * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e + * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde + * + * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ + * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd + */ + bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; + + /* + * bytes4(keccak256('name()')) == 0x06fdde03 + * bytes4(keccak256('symbol()')) == 0x95d89b41 + * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd + * + * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f + */ + bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; + + /* + * bytes4(keccak256('totalSupply()')) == 0x18160ddd + * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 + * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 + * + * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 + */ + bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; + /// @dev Supply the magic number for the required ERC-721 interface. + + /// @dev A mask for isolating an item's group ID. + uint256 private constant GROUP_MASK = uint256(type(uint128).max) << 128; + + /// The public name of this contract. + string public name; + + string public symbol; + + /** The ERC-721 URI for tracking item metadata, supporting {id} substitution. For example: https://token-cdn-domain/{id}.json. See the ERC-721 spec for more details: https://eips.ethereum.org/EIPS/eip-721#metadata. */ - string public metadataUri; + string public metadataUri; - /// The URI for the storefront-level metadata of contract - string public contractURI; + /// The URI for the storefront-level metadata of contract + string public contractURI; - /// A proxy registry address for supporting automatic delegated approval. - address public proxyRegistryAddress; + /// A proxy registry address for supporting automatic delegated approval. + address public proxyRegistryAddress; - /// @dev A mapping from each token ID to per-address balances. - mapping (uint256 => mapping(address => uint256)) public balances; + /// @dev A mapping from each token ID to per-address balances. + mapping(uint256 => mapping(address => uint256)) public balances; - /// A mapping from each group ID to per-address balances. - mapping (uint256 => mapping(address => uint256)) public groupBalances; + /// A mapping from each group ID to per-address balances. + mapping(uint256 => mapping(address => uint256)) public groupBalances; - /// A mapping from each address to a collection-wide balance. - mapping(address => uint256) public totalBalances; + /// A mapping from each address to a collection-wide balance. + mapping(address => uint256) public totalBalances; - // Mapping from holder address to their (enumerable) set of owned tokens - mapping (address => EnumerableSet.UintSet) private _holderTokens; + // Mapping from holder address to their (enumerable) set of owned tokens + mapping(address => EnumerableSet.UintSet) private _holderTokens; - // Enumerable mapping from token ids to their owners - EnumerableMap.UintToAddressMap private _tokenOwners; - /** + // Enumerable mapping from token ids to their owners + EnumerableMap.UintToAddressMap private _tokenOwners; + /** @dev This is a mapping from each address to per-address operator approvals. Operators are those addresses that have been approved to transfer tokens on behalf of the approver. Transferring tokens includes the right to burn tokens. */ - mapping (address => mapping(address => bool)) private operatorApprovals; + mapping(address => mapping(address => bool)) private operatorApprovals; - // Mapping from token ID to approved address - mapping (uint256 => address) private _tokenApprovals; + // Mapping from token ID to approved address + mapping(uint256 => address) private _tokenApprovals; - /** + /** This enumeration lists the various supply types that each item group may use. In general, the administrator of this collection or those permissioned to do so may move from a more-permissive supply type to a less-permissive. @@ -153,13 +154,13 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { circulating supply) freely. The value of `supplyData` cannot be set below the current circulating supply and determines the cap. */ - enum SupplyType { - Capped, - Uncapped, - Flexible - } + enum SupplyType { + Capped, + Uncapped, + Flexible + } - /** + /** This enumeration lists the various burn types that each item group may use. These are static once chosen. @param None The items in this group may not be burnt. The value of @@ -169,13 +170,13 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param Replenishable The items in this group, once burnt, may be reminted by the owner. The value of `burnData` is ignored. */ - enum BurnType { - None, - Burnable, - Replenishable - } + enum BurnType { + None, + Burnable, + Replenishable + } - /** + /** This struct is a source of mapping-free input to the `configureGroup` function. It defines the settings for a particular item group. @param name A name for the item group. @@ -184,15 +185,15 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param burnType The type of burning permitted by this item group. @param burnData An optional integer used by some `burnType` values. */ - struct ItemGroupInput { - string name; - SupplyType supplyType; - uint256 supplyData; - BurnType burnType; - uint256 burnData; - } - - /** + struct ItemGroupInput { + string name; + SupplyType supplyType; + uint256 supplyData; + BurnType burnType; + uint256 burnData; + } + + /** This struct defines the settings for a particular item group and is tracked in storage. @param initialized Whether or not this `ItemGroup` has been initialized. @@ -206,96 +207,101 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param mintCount The number of times items in this group have been minted. @param burnCount The number of times items in this group have been burnt. */ - struct ItemGroup { - bool initialized; - string name; - SupplyType supplyType; - uint256 supplyData; - BurnType burnType; - uint256 burnData; - uint256 circulatingSupply; - uint256 mintCount; - uint256 burnCount; - } - - /// A mapping of data for each item group. - mapping (uint256 => ItemGroup) public itemGroups; - - /// A mapping of circulating supplies for each individual token. - mapping (uint256 => uint256) public circulatingSupply; - - /// A mapping of the number of times each individual token has been minted. - mapping (uint256 => uint256) public mintCount; - - /// A mapping of the number of times each individual token has been burnt. - mapping (uint256 => uint256) public burnCount; - - /** + struct ItemGroup { + bool initialized; + string name; + SupplyType supplyType; + uint256 supplyData; + BurnType burnType; + uint256 burnData; + uint256 circulatingSupply; + uint256 mintCount; + uint256 burnCount; + } + + /// A mapping of data for each item group. + mapping(uint256 => ItemGroup) public itemGroups; + + /// A mapping of circulating supplies for each individual token. + mapping(uint256 => uint256) public circulatingSupply; + + /// A mapping of the number of times each individual token has been minted. + mapping(uint256 => uint256) public mintCount; + + /// A mapping of the number of times each individual token has been burnt. + mapping(uint256 => uint256) public burnCount; + + /** A mapping of token ID to a boolean representing whether the item's metadata has been explicitly frozen via a call to `lockURI(string calldata _uri, uint256 _id)`. Do note that it is possible for an item's mapping here to be false while still having frozen metadata if the item collection as a whole has had its `uriLocked` value set to true. */ - mapping (uint256 => bool) public metadataFrozen; + mapping(uint256 => bool) public metadataFrozen; - /** + /** A public mapping of optional on-chain metadata for each token ID. A token's on-chain metadata is unable to be changed if the item's metadata URI has been permanently fixed or if the collection's metadata URI as a whole has been frozen. */ - mapping (uint256 => string) public metadata; + mapping(uint256 => string) public metadata; + + /// Whether or not the metadata URI has been locked to future changes. + bool public uriLocked; - /// Whether or not the metadata URI has been locked to future changes. - bool public uriLocked; - - /// Whether or not the metadata URI has been locked to future changes. - bool public contractUriLocked; + /// Whether or not the metadata URI has been locked to future changes. + bool public contractUriLocked; - /// Whether or not the item collection has been locked to all further minting. - bool public locked; + /// Whether or not the item collection has been locked to all further minting. + bool public locked; - /** + /** An event that gets emitted when the metadata collection URI is changed. @param oldURI The old metadata URI. @param newURI The new metadata URI. */ - event ChangeURI(string indexed oldURI, string indexed newURI); + event ChangeURI(string indexed oldURI, string indexed newURI); - /** + /** An event that gets emitted when the contract URI is changed. @param oldURI The old metadata URI. @param newURI The new metadata URI. */ - event ChangeContractURI(string indexed oldURI, string indexed newURI); + event ChangeContractURI(string indexed oldURI, string indexed newURI); - /** + /** An event that gets emitted when the proxy registry address is changed. @param oldRegistry The old proxy registry address. @param newRegistry The new proxy registry address. */ - event ChangeProxyRegistry(address indexed oldRegistry, - address indexed newRegistry); + event ChangeProxyRegistry( + address indexed oldRegistry, + address indexed newRegistry + ); - /** + /** An event that gets emitted when an item group is configured. @param manager The caller who configured the item group `_groupId`. @param groupId The groupId being configured. @param newGroup The new group configuration. */ - event ItemGroupConfigured(address indexed manager, uint256 groupId, - ItemGroupInput indexed newGroup); + event ItemGroupConfigured( + address indexed manager, + uint256 groupId, + ItemGroupInput indexed newGroup + ); - /** + /** An event that gets emitted when the item collection is locked to further creation. @param locker The caller who locked the collection. */ - event CollectionLocked(address indexed locker); + event CollectionLocked(address indexed locker); - /** + /** An event that gets emitted when a token ID has its on-chain metadata changed. @param changer The caller who triggered the metadata change. @@ -303,24 +309,28 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param oldMetadata The old metadata of the token. @param newMetadata The new metadata of the token. */ - event MetadataChanged(address indexed changer, uint256 indexed id, - string oldMetadata, string indexed newMetadata); - - /** + event MetadataChanged( + address indexed changer, + uint256 indexed id, + string oldMetadata, + string indexed newMetadata + ); + + /** An event that indicates we have set a permanent metadata URI for a token. @param _value The value of the permanent metadata URI. @param _id The token ID associated with the permanent metadata value. */ - event PermanentURI(string _value, uint256 indexed _id); + event PermanentURI(string _value, uint256 indexed _id); - /** + /** An event that indicates we have set a permanent contract URI. @param _value The value of the permanent contract URI. @param _id The token ID associated with the permanent contract value. */ - event PermanentContractURI(string _value, uint256 indexed _id); + event PermanentContractURI(string _value, uint256 indexed _id); - /** + /** A modifier which allows only the super-administrative owner or addresses with a specified valid right to perform a call on some specific item. Rights can be applied to the universal circumstance, the item-group-level @@ -330,22 +340,24 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _right The right to validate for the calling address. It must be non-expired and exist within the specified `_itemId`. */ - modifier hasItemRight(uint256 _id, bytes32 _right) { - uint256 groupId = (_id & GROUP_MASK) >> 128; - if (_msgSender() == owner()) { - _; - } else if (hasRight(_msgSender(), UNIVERSAL, _right)) { - _; - } else if (hasRight(_msgSender(), bytes32(groupId), _right)) { - _; - } else if (hasRight(_msgSender(), bytes32(_id), _right)) { - _; - } else { - revert("Super721::hasItemRight: _msgSender does not have the right to perform that action"); + modifier hasItemRight(uint256 _id, bytes32 _right) { + uint256 groupId = (_id & GROUP_MASK) >> 128; + if (_msgSender() == owner()) { + _; + } else if (hasRight(_msgSender(), UNIVERSAL, _right)) { + _; + } else if (hasRight(_msgSender(), bytes32(groupId), _right)) { + _; + } else if (hasRight(_msgSender(), bytes32(_id), _right)) { + _; + } else { + revert( + "Super721::hasItemRight: _msgSender does not have the right to perform that action" + ); + } } - } - /** + /** Construct a new ERC-721 item collection. @param _owner The address of the administrator governing this collection. @param _name The name to assign to this item collection contract. @@ -353,55 +365,67 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _contractURI The contract URI. @param _proxyRegistryAddress The address of a proxy registry contract. */ - constructor(address _owner, string memory _name, string memory _symbol, - string memory _metadataURI, string memory _contractURI, address _proxyRegistryAddress) { + constructor( + address _owner, + string memory _name, + string memory _symbol, + string memory _metadataURI, + string memory _contractURI, + address _proxyRegistryAddress + ) { + // Do not perform a redundant ownership transfer if the deployer should + // remain as the owner of the collection. + if (_owner != owner()) { + transferOwnership(_owner); + } - // Do not perform a redundant ownership transfer if the deployer should - // remain as the owner of the collection. - if (_owner != owner()) { - transferOwnership(_owner); + // Register 721 interfaces + _registerInterface(_INTERFACE_ID_ERC721); + _registerInterface(_INTERFACE_ID_ERC721_METADATA); + _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); + + // Continue initialization. + name = _name; + symbol = _symbol; + metadataUri = _metadataURI; + contractURI = _contractURI; + proxyRegistryAddress = _proxyRegistryAddress; } - // Register 721 interfaces - _registerInterface(_INTERFACE_ID_ERC721); - _registerInterface(_INTERFACE_ID_ERC721_METADATA); - _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); - - // Continue initialization. - name = _name; - symbol = _symbol; - metadataUri = _metadataURI; - contractURI = _contractURI; - proxyRegistryAddress = _proxyRegistryAddress; - } - /** - */ - function ownerOf(uint256 tokenId) public view override returns (address) { - return _tokenOwners.get(tokenId, "Super721::ownerOf: owner query for nonexistent token"); - } + /** + */ + function ownerOf(uint256 tokenId) public view override returns (address) { + return + _tokenOwners.get( + tokenId, + "Super721::ownerOf: owner query for nonexistent token" + ); + } - /** - * @dev See {IERC721-approve}. - */ - function approve(address to, uint256 tokenId) public virtual override { - address owner = ownerOf(tokenId); - require(to != owner, "Super721::approve: approval to current owner"); - - require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), - "Super721::approve: approve caller is not owner nor approved for all" - ); - - _tokenApprovals[tokenId] = to; - emit Approval(ownerOf(tokenId), to, tokenId); - } - /** + /** + * @dev See {IERC721-approve}. + */ + function approve(address to, uint256 tokenId) public virtual override { + address owner = ownerOf(tokenId); + require(to != owner, "Super721::approve: approval to current owner"); + + require( + _msgSender() == owner || isApprovedForAll(owner, _msgSender()), + "Super721::approve: approve caller is not owner nor approved for all" + ); + + _tokenApprovals[tokenId] = to; + emit Approval(ownerOf(tokenId), to, tokenId); + } + + /** Return a version number for this contract's interface. */ - function version() external virtual pure override returns (uint256) { - return 1; - } + function version() external pure virtual override returns (uint256) { + return 1; + } - /** + /** Return the item collection's metadata URI. This implementation returns the same URI for all tokens within the collection and relies on client-side ID substitution per https://eips.ethereum.org/EIPS/eip-721#metadata. Per @@ -410,60 +434,73 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { to 64 characters in length. @return The metadata URI string of the item with ID `_itemId`. */ - function tokenURI(uint256 id) external view returns (string memory) { - if(bytes(metadataUri).length == 0){ - return metadata[id]; + function tokenURI(uint256 id) external view returns (string memory) { + if (bytes(metadataUri).length == 0) { + return metadata[id]; + } + return Utils.interpolate(metadataUri, id); } - return Utils.interpolate(metadataUri, id); - } - /** + /** Allow the item collection owner or an approved manager to update the metadata URI of this collection. This implementation relies on a single URI for all items within the collection, and as such does not emit the standard URI event. Instead, we emit our own event to reflect changes in the URI. @param _uri The new URI to update to. */ - function setURI(string calldata _uri) external virtual - hasValidPermit(UNIVERSAL, SET_URI) { - require(!uriLocked, - "Super721::setURI: the collection URI has been permanently locked"); - string memory oldURI = metadataUri; - metadataUri = _uri; - emit ChangeURI(oldURI, _uri); - } - + function setURI(string calldata _uri) + external + virtual + hasValidPermit(UNIVERSAL, SET_URI) + { + require( + !uriLocked, + "Super721::setURI: the collection URI has been permanently locked" + ); + string memory oldURI = metadataUri; + metadataUri = _uri; + emit ChangeURI(oldURI, _uri); + } - /** + /** Allow approved manager to update the contract URI. At the end of update, we emit our own event to reflect changes in the URI. @param _uri The new contract URI to update to. */ - function setContractURI(string calldata _uri) external virtual - hasValidPermit(UNIVERSAL, SET_URI) { - require(!contractUriLocked, - "Super721::setContractURI: the contract URI has been permanently locked"); - string memory oldContractUri = contractURI; - contractURI = _uri; - emit ChangeContractURI(oldContractUri, _uri); - } - // TODO: change all require messages - - /** + function setContractURI(string calldata _uri) + external + virtual + hasValidPermit(UNIVERSAL, SET_URI) + { + require( + !contractUriLocked, + "Super721::setContractURI: the contract URI has been permanently locked" + ); + string memory oldContractUri = contractURI; + contractURI = _uri; + emit ChangeContractURI(oldContractUri, _uri); + } + + // TODO: change all require messages + + /** Allow the item collection owner or an approved manager to update the proxy registry address handling delegated approval. @param _proxyRegistryAddress The address of the new proxy registry to update to. */ - function setProxyRegistry(address _proxyRegistryAddress) external virtual - hasValidPermit(UNIVERSAL, SET_PROXY_REGISTRY) { - address oldRegistry = proxyRegistryAddress; - proxyRegistryAddress = _proxyRegistryAddress; - emit ChangeProxyRegistry(oldRegistry, _proxyRegistryAddress); - } - - /** + function setProxyRegistry(address _proxyRegistryAddress) + external + virtual + hasValidPermit(UNIVERSAL, SET_PROXY_REGISTRY) + { + address oldRegistry = proxyRegistryAddress; + proxyRegistryAddress = _proxyRegistryAddress; + emit ChangeProxyRegistry(oldRegistry, _proxyRegistryAddress); + } + + /** Retrieve the balance of a particular token `_id` for a particular address `_owner`. @param _owner The owner to check for this token balance. @@ -471,41 +508,60 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @return The amount of token `_id` owned by `_owner`. */ - function balanceOfGroup(address _owner, uint256 _id) public view virtual - returns (uint256) { - require(_owner != address(0), - "Super721::balanceOf: balance query for the zero address"); - return balances[_id][_owner]; - } - - function balanceOf(address _owner) public override view virtual - returns (uint256) { - require(_owner != address(0), - "Super721::balanceOf: balance query for the zero address"); - return totalBalances[_owner]; - } - - /** + function balanceOfGroup(address _owner, uint256 _id) + public + view + virtual + returns (uint256) + { + require( + _owner != address(0), + "Super721::balanceOf: balance query for the zero address" + ); + return balances[_id][_owner]; + } + + function balanceOf(address _owner) + public + view + virtual + override + returns (uint256) + { + require( + _owner != address(0), + "Super721::balanceOf: balance query for the zero address" + ); + return totalBalances[_owner]; + } + + /** Retrieve in a single call the balances of some mulitple particular token `_ids` held by corresponding `_owners`. @param _owners The owners to check for token balances. @param _ids The IDs of tokens to check for balances. @return the amount of each token owned by each owner. */ - function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) - external view virtual returns (uint256[] memory) { - require(_owners.length == _ids.length, - "Super721::balanceOfBatch: accounts and ids length mismatch"); - - // Populate and return an array of balances. - uint256[] memory batchBalances = new uint256[](_owners.length); - for (uint256 i = 0; i < _owners.length; ++i) { - batchBalances[i] = balanceOfGroup(_owners[i], _ids[i]); + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + virtual + returns (uint256[] memory) + { + require( + _owners.length == _ids.length, + "Super721::balanceOfBatch: accounts and ids length mismatch" + ); + + // Populate and return an array of balances. + uint256[] memory batchBalances = new uint256[](_owners.length); + for (uint256 i = 0; i < _owners.length; ++i) { + batchBalances[i] = balanceOfGroup(_owners[i], _ids[i]); + } + return batchBalances; } - return batchBalances; - } - /** + /** This function returns true if `_operator` is approved to transfer items owned by `_owner`. This approval check features an override to explicitly whitelist any addresses delegated in the proxy registry. @@ -513,45 +569,60 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _operator The potential transferrer of `_owner`'s items. @return Whether `_operator` may transfer items owned by `_owner`. */ - function isApprovedForAll(address _owner, address _operator) public override - view virtual returns (bool) { - StubProxyRegistry proxyRegistry = StubProxyRegistry(proxyRegistryAddress); - if (address(proxyRegistry.proxies(_owner)) == _operator) { - return true; - } + function isApprovedForAll(address _owner, address _operator) + public + view + virtual + override + returns (bool) + { + StubProxyRegistry proxyRegistry = StubProxyRegistry( + proxyRegistryAddress + ); + if (address(proxyRegistry.proxies(_owner)) == _operator) { + return true; + } - // We did not find an explicit whitelist in the proxy registry. - return operatorApprovals[_owner][_operator]; - } + // We did not find an explicit whitelist in the proxy registry. + return operatorApprovals[_owner][_operator]; + } - /** + /** Enable or disable approval for a third party `_operator` address to manage (transfer or burn) all of the caller's tokens. @param _operator The address to grant management rights over all of the caller's tokens. @param _approved The status of the `_operator`'s approval for the caller. */ - function setApprovalForAll(address _operator, bool _approved) external - override virtual { - require(_msgSender() != _operator, - "Super721::balanceOf: setting approval status for self"); - operatorApprovals[_msgSender()][_operator] = _approved; - emit ApprovalForAll(_msgSender(), _operator, _approved); - } - - /** + function setApprovalForAll(address _operator, bool _approved) + external + virtual + override + { + require( + _msgSender() != _operator, + "Super721::balanceOf: setting approval status for self" + ); + operatorApprovals[_msgSender()][_operator] = _approved; + emit ApprovalForAll(_msgSender(), _operator, _approved); + } + + /** This private helper function converts a number into a single-element array. @param _element The element to convert to an array. @return The array containing the single `_element`. */ - function _asSingletonArray(uint256 _element) private pure - returns (uint256[] memory) { - uint256[] memory array = new uint256[](1); - array[0] = _element; - return array; - } - - /** + function _asSingletonArray(uint256 _element) + private + pure + returns (uint256[] memory) + { + uint256[] memory array = new uint256[](1); + array[0] = _element; + return array; + } + + /** An inheritable and configurable pre-transfer hook that can be overridden. It fires before any token transfer, including mints and burns. @param _operator The caller who triggers the token transfer. @@ -561,12 +632,16 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _amounts The amounts of the specific `_ids` to transfer. @param _data Additional call data to send with this transfer. */ - function _beforeTokenTransfer(address _operator, address _from, address _to, - uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) - internal virtual { - } - - /** + function _beforeTokenTransfer( + address _operator, + address _from, + address _to, + uint256[] memory _ids, + uint256[] memory _amounts, + bytes memory _data + ) internal virtual {} + + /** ERC-721 dictates that any contract which wishes to receive ERC-721 tokens must explicitly designate itself as such. This function checks for such designation to prevent undesirable token transfers. @@ -576,23 +651,40 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _id The specific token ID to transfer. @param _data Additional call data to send with this transfer. */ - function _doSafeTransferAcceptanceCheck(address _operator, address _from, - address _to, uint256 _id, bytes memory _data) private { - if (_to.isContract()) { - try IERC721Receiver(_to).onERC721Received(_operator, _from, _id, - _data) returns (bytes4 response) { - if (response != IERC721Receiver(_to).onERC721Received.selector) { - revert("Super721::_doSafeTransferAcceptanceCheck: ERC721Receiver rejected tokens"); + function _doSafeTransferAcceptanceCheck( + address _operator, + address _from, + address _to, + uint256 _id, + bytes memory _data + ) private { + if (_to.isContract()) { + try + IERC721Receiver(_to).onERC721Received( + _operator, + _from, + _id, + _data + ) + returns (bytes4 response) { + if ( + response != IERC721Receiver(_to).onERC721Received.selector + ) { + revert( + "Super721::_doSafeTransferAcceptanceCheck: ERC721Receiver rejected tokens" + ); + } + } catch Error(string memory reason) { + revert(reason); + } catch { + revert( + "Super721::_doSafeTransferAcceptanceCheck: transfer to non ERC721Receiver implementer" + ); + } } - } catch Error(string memory reason) { - revert(reason); - } catch { - revert("Super721::_doSafeTransferAcceptanceCheck: transfer to non ERC721Receiver implementer"); - } } - } - /** + /** Transfer on behalf of a caller or one of their authorized token managers items from one address to another. @param _from The address to transfer tokens from. @@ -601,54 +693,79 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _data Additional call data to send with this transfer. */ - /** - * @dev See {IERC721-safeTransferFrom}. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { - _safeTransferFrom(from, to, tokenId, bytes("")); - } - - function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) - public virtual override { - _safeTransferFrom(from, to, tokenId, data); - } - - function _safeTransferFrom(address _from, address _to, uint256 _id, - bytes memory _data) internal virtual { - require(_to != address(0), - "Super721::_safeTransferFrom : transfer to the zero address"); - require(_from == _msgSender() || isApprovedForAll(_from, _msgSender()), - "Super721::_safeTransferFrom : caller is not owner nor approved"); - - // Validate transfer safety and send tokens away. - address operator = _msgSender(); - _beforeTokenTransfer(operator, _from, _to, _asSingletonArray(_id), - _asSingletonArray(1), _data); - - // Retrieve the item's group ID. - uint256 shiftedGroupId = (_id & GROUP_MASK); - uint256 groupId = shiftedGroupId >> 128; - - // Update all specially-tracked group-specific balances. - require(balances[_id][_from] >= 1, "Super721::_safeTransferFrom: insufficient balance for transfer"); - balances[_id][_from] = balances[_id][_from] - 1; - balances[_id][_to] = balances[_id][_to] + 1; - groupBalances[groupId][_from] = groupBalances[groupId][_from] - 1; - groupBalances[groupId][_to] = groupBalances[groupId][_to] + 1; - totalBalances[_from] = totalBalances[_from] - 1; - totalBalances[_to] = totalBalances[_to] + 1; - - _holderTokens[_from].remove(_id); - _holderTokens[_to].add(_id); + /** + * @dev See {IERC721-safeTransferFrom}. + */ + function safeTransferFrom( + address from, + address to, + uint256 tokenId + ) public virtual override { + _safeTransferFrom(from, to, tokenId, bytes("")); + } - _tokenOwners.set(_id, _to); + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) public virtual override { + _safeTransferFrom(from, to, tokenId, data); + } - // Emit the transfer event and perform the safety check. - emit Transfer(_from, _to, _id); - _doSafeTransferAcceptanceCheck(operator, _from, _to, _id, _data); - } + function _safeTransferFrom( + address _from, + address _to, + uint256 _id, + bytes memory _data + ) internal virtual { + require( + _to != address(0), + "Super721::_safeTransferFrom : transfer to the zero address" + ); + require( + _from == _msgSender() || isApprovedForAll(_from, _msgSender()), + "Super721::_safeTransferFrom : caller is not owner nor approved" + ); + + // Validate transfer safety and send tokens away. + address operator = _msgSender(); + _beforeTokenTransfer( + operator, + _from, + _to, + _asSingletonArray(_id), + _asSingletonArray(1), + _data + ); + + // Retrieve the item's group ID. + uint256 shiftedGroupId = (_id & GROUP_MASK); + uint256 groupId = shiftedGroupId >> 128; + + // Update all specially-tracked group-specific balances. + require( + balances[_id][_from] >= 1, + "Super721::_safeTransferFrom: insufficient balance for transfer" + ); + balances[_id][_from] = balances[_id][_from] - 1; + balances[_id][_to] = balances[_id][_to] + 1; + groupBalances[groupId][_from] = groupBalances[groupId][_from] - 1; + groupBalances[groupId][_to] = groupBalances[groupId][_to] + 1; + totalBalances[_from] = totalBalances[_from] - 1; + totalBalances[_to] = totalBalances[_to] + 1; + + _holderTokens[_from].remove(_id); + _holderTokens[_to].add(_id); + + _tokenOwners.set(_id, _to); + + // Emit the transfer event and perform the safety check. + emit Transfer(_from, _to, _id); + _doSafeTransferAcceptanceCheck(operator, _from, _to, _id, _data); + } - /** + /** Transfer on behalf of a caller or one of their authorized token managers items from one address to another. @param _from The address to transfer tokens from. @@ -690,9 +807,8 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { emit Transfer(_from, _to, _ids[i]); _doSafeTransferAcceptanceCheck(_msgSender(), _from, _to, _ids[i], _data); } - } - /** + /** Create a new NFT item group or configure an existing one. NFTs within a group share a group ID in the upper 128-bits of their full item ID. Within a group NFTs can be distinguished for the purposes of serializing @@ -700,56 +816,69 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _groupId The ID of the item group to create or configure. @param _data The `ItemGroup` data input. */ - function configureGroup(uint256 _groupId, ItemGroupInput memory _data) - external virtual hasItemRight(_groupId, CONFIGURE_GROUP) { - require(_groupId != 0, - "Super721::configureGroup: group ID 0 is invalid"); - - // If the collection is not locked, we may add a new item group. - if (!itemGroups[_groupId].initialized) { - require(!locked, - "Super721::configureGroup: the collection is locked so groups cannot be created"); - itemGroups[_groupId] = ItemGroup({ - initialized: true, - name: _data.name, - supplyType: _data.supplyType, - supplyData: _data.supplyData, - burnType: _data.burnType, - burnData: _data.burnData, - circulatingSupply: 0, - mintCount: 0, - burnCount: 0 - }); - - // Edit an existing item group. The name may always be updated. - } else { - itemGroups[_groupId].name = _data.name; - - // A capped supply type may not change. - // It may also not have its cap increased. - if (itemGroups[_groupId].supplyType == SupplyType.Capped) { - require(_data.supplyType == SupplyType.Capped, - "Super721::configureGroup: you may not uncap a capped supply type"); - require(_data.supplyData <= itemGroups[_groupId].supplyData, - "Super721::configureGroup: you may not increase the supply of a capped type"); - - // The flexible and uncapped types may freely change. - } else { - itemGroups[_groupId].supplyType = _data.supplyType; - } - - // Item supply data may not be reduced below the circulating supply. - require(_data.supplyData >= itemGroups[_groupId].circulatingSupply, - "Super721::configureGroup: you may not decrease supply below the circulating amount"); - itemGroups[_groupId].supplyData = _data.supplyData; - // do we want burnType to be updateable? - } + function configureGroup(uint256 _groupId, ItemGroupInput memory _data) + external + virtual + hasItemRight(_groupId, CONFIGURE_GROUP) + { + require( + _groupId != 0, + "Super721::configureGroup: group ID 0 is invalid" + ); + + // If the collection is not locked, we may add a new item group. + if (!itemGroups[_groupId].initialized) { + require( + !locked, + "Super721::configureGroup: the collection is locked so groups cannot be created" + ); + itemGroups[_groupId] = ItemGroup({ + initialized: true, + name: _data.name, + supplyType: _data.supplyType, + supplyData: _data.supplyData, + burnType: _data.burnType, + burnData: _data.burnData, + circulatingSupply: 0, + mintCount: 0, + burnCount: 0 + }); + + // Edit an existing item group. The name may always be updated. + } else { + itemGroups[_groupId].name = _data.name; + + // A capped supply type may not change. + // It may also not have its cap increased. + if (itemGroups[_groupId].supplyType == SupplyType.Capped) { + require( + _data.supplyType == SupplyType.Capped, + "Super721::configureGroup: you may not uncap a capped supply type" + ); + require( + _data.supplyData <= itemGroups[_groupId].supplyData, + "Super721::configureGroup: you may not increase the supply of a capped type" + ); + + // The flexible and uncapped types may freely change. + } else { + itemGroups[_groupId].supplyType = _data.supplyType; + } + + // Item supply data may not be reduced below the circulating supply. + require( + _data.supplyData >= itemGroups[_groupId].circulatingSupply, + "Super721::configureGroup: you may not decrease supply below the circulating amount" + ); + itemGroups[_groupId].supplyData = _data.supplyData; + // do we want burnType to be updateable? + } - // Emit the configuration event. - emit ItemGroupConfigured(_msgSender(), _groupId, _data); - } + // Emit the configuration event. + emit ItemGroupConfigured(_msgSender(), _groupId, _data); + } - /** + /** This is a private helper function to replace the `hasItemRight` modifier that we use on some functions in order to inline this check during batch minting and burning. @@ -757,63 +886,71 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _right The right that the caller is trying to exercise on `_id`. @return Whether or not the caller has a valid right on this item. */ - function _hasItemRight(uint256 _id, bytes32 _right) private view - returns (bool) { - uint256 groupId = (_id & GROUP_MASK) >> 128; - if (_msgSender() == owner()) { - return true; - } - if (hasRight(_msgSender(), UNIVERSAL, _right)) { - return true; - } - if (hasRight(_msgSender(), bytes32(groupId), _right)) { - return true; - } - if (hasRight(_msgSender(), bytes32(_id), _right)) { - return true; + function _hasItemRight(uint256 _id, bytes32 _right) + private + view + returns (bool) + { + uint256 groupId = (_id & GROUP_MASK) >> 128; + if (_msgSender() == owner()) { + return true; + } + if (hasRight(_msgSender(), UNIVERSAL, _right)) { + return true; + } + if (hasRight(_msgSender(), bytes32(groupId), _right)) { + return true; + } + if (hasRight(_msgSender(), bytes32(_id), _right)) { + return true; + } + return false; } - return false; - } - /** + /** This is a private helper function to verify, according to all of our various minting and burning rules, whether it would be valid to mint a particular item `_id`. @param _id The ID of the item to check for minting validity. @return The ID of the item that should be minted. */ - function _mintChecker(uint256 _id) private view returns (uint256) { - - // Retrieve the item's group ID. - uint256 shiftedGroupId = (_id & GROUP_MASK); - uint256 groupId = shiftedGroupId >> 128; - require(itemGroups[groupId].initialized, - "Super721::_mintChecker: you cannot mint a non-existent item group"); - - // If false, owned by address (or NULL_ADDRESS i.e, was burnable) - // If true, never minted, (or was removed i.e, was replenishable) - require(!_tokenOwners.contains(_id), - "Super721::_mintChecker: token already exists"); - - // If we can replenish burnt items, then only our currently-circulating - // supply matters. Otherwise, historic mints are what determine the cap. - uint256 currentGroupSupply = itemGroups[groupId].mintCount; - uint256 currentItemSupply = mintCount[_id]; - if (itemGroups[groupId].burnType == BurnType.Replenishable) { - currentGroupSupply = itemGroups[groupId].circulatingSupply; - currentItemSupply = circulatingSupply[_id]; - } + function _mintChecker(uint256 _id) private view returns (uint256) { + // Retrieve the item's group ID. + uint256 shiftedGroupId = (_id & GROUP_MASK); + uint256 groupId = shiftedGroupId >> 128; + require( + itemGroups[groupId].initialized, + "Super721::_mintChecker: you cannot mint a non-existent item group" + ); + + // If false, owned by address (or NULL_ADDRESS i.e, was burnable) + // If true, never minted, (or was removed i.e, was replenishable) + require( + !_tokenOwners.contains(_id), + "Super721::_mintChecker: token already exists" + ); + + // If we can replenish burnt items, then only our currently-circulating + // supply matters. Otherwise, historic mints are what determine the cap. + uint256 currentGroupSupply = itemGroups[groupId].mintCount; + uint256 currentItemSupply = mintCount[_id]; + if (itemGroups[groupId].burnType == BurnType.Replenishable) { + currentGroupSupply = itemGroups[groupId].circulatingSupply; + currentItemSupply = circulatingSupply[_id]; + } - // If we are subject to a cap on group size, ensure we don't exceed it. - if (itemGroups[groupId].supplyType != SupplyType.Uncapped) { - require(currentGroupSupply + 1 <= itemGroups[groupId].supplyData, - "Super721::_mintChecker: you cannot mint a group beyond its cap"); - } + // If we are subject to a cap on group size, ensure we don't exceed it. + if (itemGroups[groupId].supplyType != SupplyType.Uncapped) { + require( + currentGroupSupply + 1 <= itemGroups[groupId].supplyData, + "Super721::_mintChecker: you cannot mint a group beyond its cap" + ); + } - return _id; - } + return _id; + } - /** + /** Mint a batch of tokens into existence and send them to the `_recipient` address. In order to mint an item, its item group must first have been created. Minting an item must obey both the fungibility and size cap of its @@ -824,301 +961,381 @@ contract Super721 is PermitControl, ERC165Storage, IERC721 { @param _data Any associated data to use on items minted in this transaction. */ - function mintBatch(address _recipient, uint256[] calldata _ids, - bytes memory _data) - external virtual { - require(_recipient != address(0), - "Super721::mintBatch: mint to the zero address"); - - // Validate and perform the mint. - address operator = _msgSender(); - _beforeTokenTransfer(operator, address(0), _recipient, _ids, _asSingletonArray(1), - _data); - - // Loop through each of the batched IDs to update storage of special - // balances and circulation balances. - for (uint256 i = 0; i < _ids.length; i++) { - require(_hasItemRight(_ids[i], MINT), - "Super721::mintBatch: you do not have the right to mint that item"); - - // Retrieve the group ID from the given item `_id` and check mint. - uint256 shiftedGroupId = (_ids[i] & GROUP_MASK); - uint256 groupId = shiftedGroupId >> 128; - uint256 mintedItemId = _mintChecker(_ids[i]); - - // Update storage of special balances and circulating values. - balances[mintedItemId][_recipient] = balances[mintedItemId][_recipient] + 1; - groupBalances[groupId][_recipient] = groupBalances[groupId][_recipient] + 1; - totalBalances[_recipient] = totalBalances[_recipient] + 1; - mintCount[mintedItemId] = mintCount[mintedItemId] + 1; - circulatingSupply[mintedItemId] = circulatingSupply[mintedItemId] + 1; - itemGroups[groupId].mintCount = itemGroups[groupId].mintCount + 1; - itemGroups[groupId].circulatingSupply = - itemGroups[groupId].circulatingSupply + 1; - - //_holderTokens[address(0)].remove(_ids[i]); - _holderTokens[_recipient].add(_ids[i]); - - _tokenOwners.set(_ids[i], _recipient); - // Emit event and handle the safety check. - emit Transfer(address(0), _recipient, _ids[i]); - _doSafeTransferAcceptanceCheck(operator, address(0), _recipient, _ids[i], _data); + function mintBatch( + address _recipient, + uint256[] calldata _ids, + bytes memory _data + ) external virtual { + require( + _recipient != address(0), + "Super721::mintBatch: mint to the zero address" + ); + + // Validate and perform the mint. + address operator = _msgSender(); + _beforeTokenTransfer( + operator, + address(0), + _recipient, + _ids, + _asSingletonArray(1), + _data + ); + + // Loop through each of the batched IDs to update storage of special + // balances and circulation balances. + for (uint256 i = 0; i < _ids.length; i++) { + require( + _hasItemRight(_ids[i], MINT), + "Super721::mintBatch: you do not have the right to mint that item" + ); + + // Retrieve the group ID from the given item `_id` and check mint. + uint256 shiftedGroupId = (_ids[i] & GROUP_MASK); + uint256 groupId = shiftedGroupId >> 128; + uint256 mintedItemId = _mintChecker(_ids[i]); + + // Update storage of special balances and circulating values. + balances[mintedItemId][_recipient] = + balances[mintedItemId][_recipient] + + 1; + groupBalances[groupId][_recipient] = + groupBalances[groupId][_recipient] + + 1; + totalBalances[_recipient] = totalBalances[_recipient] + 1; + mintCount[mintedItemId] = mintCount[mintedItemId] + 1; + circulatingSupply[mintedItemId] = + circulatingSupply[mintedItemId] + + 1; + itemGroups[groupId].mintCount = itemGroups[groupId].mintCount + 1; + itemGroups[groupId].circulatingSupply = + itemGroups[groupId].circulatingSupply + + 1; + + //_holderTokens[address(0)].remove(_ids[i]); + _holderTokens[_recipient].add(_ids[i]); + + _tokenOwners.set(_ids[i], _recipient); + // Emit event and handle the safety check. + emit Transfer(address(0), _recipient, _ids[i]); + _doSafeTransferAcceptanceCheck( + operator, + address(0), + _recipient, + _ids[i], + _data + ); + } } - } - - /** + /** This is a private helper function to verify, according to all of our various minting and burning rules, whether it would be valid to burn some `_amount` of a particular item `_id`. @param _id The ID of the item to check for burning validity. @return The ID of the item that should have `_amount` burnt for it. */ - function _burnChecker(uint256 _id) private view - returns (uint256) { - - // Retrieve the item's group ID. - uint256 shiftedGroupId = (_id & GROUP_MASK); - uint256 groupId = shiftedGroupId >> 128; - require(itemGroups[groupId].initialized, - "Super721::_burnChecker: you cannot burn a non-existent item group"); - - // If the item group is non-burnable, then revert. - if (itemGroups[groupId].burnType == BurnType.None) { - revert("Super721::_burnChecker: you cannot burn a non-burnable item group"); - } - - // If we can burn items, then we must verify that we do not exceed the cap. - else if (itemGroups[groupId].burnType == BurnType.Burnable) { - require(itemGroups[groupId].burnCount + 1 - <= itemGroups[groupId].burnData, - "Super721::_burnChecker you may not exceed the burn limit on this item group"); - } + function _burnChecker(uint256 _id) private view returns (uint256) { + // Retrieve the item's group ID. + uint256 shiftedGroupId = (_id & GROUP_MASK); + uint256 groupId = shiftedGroupId >> 128; + require( + itemGroups[groupId].initialized, + "Super721::_burnChecker: you cannot burn a non-existent item group" + ); + + // If the item group is non-burnable, then revert. + if (itemGroups[groupId].burnType == BurnType.None) { + revert( + "Super721::_burnChecker: you cannot burn a non-burnable item group" + ); + } + // If we can burn items, then we must verify that we do not exceed the cap. + else if (itemGroups[groupId].burnType == BurnType.Burnable) { + require( + itemGroups[groupId].burnCount + 1 <= + itemGroups[groupId].burnData, + "Super721::_burnChecker you may not exceed the burn limit on this item group" + ); + } - // If the item is replenishable, then ignore checks + // If the item is replenishable, then ignore checks - uint256 burntItemId = _id; + uint256 burntItemId = _id; - return burntItemId; - } + return burntItemId; + } - /** + /** This function allows an address to destroy some of its items. @param _burner The address whose item is burning. @param _id The item ID to burn. @param _amount The amount of the corresponding item ID to burn. */ - // function burn(address _burner, uint256 _id, uint256 _amount) - // external virtual hasItemRight(_id, BURN) { - // require(_burner != address(0), - // "Super721::burn: burn from the zero address"); - // - // // Retrieve the group ID from the given item `_id` and check burn validity. - // uint256 shiftedGroupId = (_id & GROUP_MASK); - // uint256 groupId = shiftedGroupId >> 128; - // uint256 burntItemId = _burnChecker(_id, _amount); - // - // // Validate and perform the burn. - // address operator = _msgSender(); - // _beforeTokenTransfer(operator, _burner, address(0), - // _asSingletonArray(burntItemId), _asSingletonArray(_amount), ""); - // - // // Update storage of special balances and circulating values. - // balances[burntItemId][_burner] = balances[burntItemId][_burner] - // .sub(_amount, - // "Super721::burn: burn amount exceeds balance"); - // groupBalances[groupId][_burner] = groupBalances[groupId][_burner] - // .sub(_amount); - // totalBalances[_burner] = totalBalances[_burner].sub(_amount); - // burnCount[burntItemId] = burnCount[burntItemId].add(_amount); - // circulatingSupply[burntItemId] = circulatingSupply[burntItemId] - // .sub(_amount); - // itemGroups[groupId].burnCount = itemGroups[groupId].burnCount.add(_amount); - // itemGroups[groupId].circulatingSupply = - // itemGroups[groupId].circulatingSupply.sub(_amount); - // - // // Emit the burn event. - // emit Transfer(operator, address(0), _id); - // } - - /** + // function burn(address _burner, uint256 _id, uint256 _amount) + // external virtual hasItemRight(_id, BURN) { + // require(_burner != address(0), + // "Super721::burn: burn from the zero address"); + // + // // Retrieve the group ID from the given item `_id` and check burn validity. + // uint256 shiftedGroupId = (_id & GROUP_MASK); + // uint256 groupId = shiftedGroupId >> 128; + // uint256 burntItemId = _burnChecker(_id, _amount); + // + // // Validate and perform the burn. + // address operator = _msgSender(); + // _beforeTokenTransfer(operator, _burner, address(0), + // _asSingletonArray(burntItemId), _asSingletonArray(_amount), ""); + // + // // Update storage of special balances and circulating values. + // balances[burntItemId][_burner] = balances[burntItemId][_burner] + // .sub(_amount, + // "Super721::burn: burn amount exceeds balance"); + // groupBalances[groupId][_burner] = groupBalances[groupId][_burner] + // .sub(_amount); + // totalBalances[_burner] = totalBalances[_burner].sub(_amount); + // burnCount[burntItemId] = burnCount[burntItemId].add(_amount); + // circulatingSupply[burntItemId] = circulatingSupply[burntItemId] + // .sub(_amount); + // itemGroups[groupId].burnCount = itemGroups[groupId].burnCount.add(_amount); + // itemGroups[groupId].circulatingSupply = + // itemGroups[groupId].circulatingSupply.sub(_amount); + // + // // Emit the burn event. + // emit Transfer(operator, address(0), _id); + // } + + /** This function allows an address to destroy multiple different items in a single call. @param _burner The address whose items are burning. @param _ids The item IDs to burn. */ - function burnBatch(address _burner, uint256[] memory _ids) external virtual { - require(_burner != address(0), - "Super721::burnBatch: burn from the zero address"); - - // Validate and perform the burn. - address operator = _msgSender(); - _beforeTokenTransfer(operator, _burner, address(0), _ids, _asSingletonArray(1), ""); - - // Loop through each of the batched IDs to update storage of special - // balances and circulation balances. - for (uint i = 0; i < _ids.length; i++) { - require(_hasItemRight(_ids[i], BURN), - "Super721::burnBatch: you do not have the right to burn that item"); - - // Retrieve the group ID from the given item `_id` and check burn. - uint256 shiftedGroupId = (_ids[i] & GROUP_MASK); - uint256 groupId = shiftedGroupId >> 128; - uint256 burntItemId = _burnChecker(_ids[i]); - - // Update storage of special balances and circulating values. - require(balances[burntItemId][_burner] >= 1, "Super721::burn: burn amount exceeds balance"); - balances[burntItemId][_burner] = balances[burntItemId][_burner] - 1; - groupBalances[groupId][_burner] = groupBalances[groupId][_burner] - 1; - totalBalances[_burner] = totalBalances[_burner] - 1; - burnCount[burntItemId] = burnCount[burntItemId] + 1; - circulatingSupply[burntItemId] = circulatingSupply[burntItemId] - 1; - itemGroups[groupId].burnCount = itemGroups[groupId].burnCount + 1; - itemGroups[groupId].circulatingSupply = - itemGroups[groupId].circulatingSupply - 1; - - _holderTokens[_burner].remove(_ids[i]); - _holderTokens[address(0)].add(_ids[i]); - - // If burnType is None, burnChecker will revert that - if(itemGroups[groupId].burnType == BurnType.Burnable) - _tokenOwners.set(_ids[i], address(0)); - else - _tokenOwners.remove(_ids[i]); - - // Emit the burn event. - emit Transfer(operator, address(0), _ids[i]); + function burnBatch(address _burner, uint256[] memory _ids) + external + virtual + { + require( + _burner != address(0), + "Super721::burnBatch: burn from the zero address" + ); + + // Validate and perform the burn. + address operator = _msgSender(); + _beforeTokenTransfer( + operator, + _burner, + address(0), + _ids, + _asSingletonArray(1), + "" + ); + + // Loop through each of the batched IDs to update storage of special + // balances and circulation balances. + for (uint256 i = 0; i < _ids.length; i++) { + require( + _hasItemRight(_ids[i], BURN), + "Super721::burnBatch: you do not have the right to burn that item" + ); + + // Retrieve the group ID from the given item `_id` and check burn. + uint256 shiftedGroupId = (_ids[i] & GROUP_MASK); + uint256 groupId = shiftedGroupId >> 128; + uint256 burntItemId = _burnChecker(_ids[i]); + + // Update storage of special balances and circulating values. + require( + balances[burntItemId][_burner] >= 1, + "Super721::burn: burn amount exceeds balance" + ); + balances[burntItemId][_burner] = balances[burntItemId][_burner] - 1; + groupBalances[groupId][_burner] = + groupBalances[groupId][_burner] - + 1; + totalBalances[_burner] = totalBalances[_burner] - 1; + burnCount[burntItemId] = burnCount[burntItemId] + 1; + circulatingSupply[burntItemId] = circulatingSupply[burntItemId] - 1; + itemGroups[groupId].burnCount = itemGroups[groupId].burnCount + 1; + itemGroups[groupId].circulatingSupply = + itemGroups[groupId].circulatingSupply - + 1; + + _holderTokens[_burner].remove(_ids[i]); + _holderTokens[address(0)].add(_ids[i]); + + // If burnType is None, burnChecker will revert that + if (itemGroups[groupId].burnType == BurnType.Burnable) + _tokenOwners.set(_ids[i], address(0)); + else _tokenOwners.remove(_ids[i]); + + // Emit the burn event. + emit Transfer(operator, address(0), _ids[i]); + } } - } - /** + /** Set the on-chain metadata attached to a specific token ID so long as the collection as a whole or the token specifically has not had metadata editing frozen. @param _id The ID of the token to set the `_metadata` for. @param _metadata The metadata string to store on-chain. */ - function setMetadata(uint256 _id, string memory _metadata) - external hasItemRight(_id, SET_METADATA) { - uint groupId = _id >> 128; - require(!uriLocked && !metadataFrozen[_id] && !metadataFrozen[groupId], - "Super721::setMetadata: you cannot edit this metadata because it is frozen"); - string memory oldMetadata = metadata[_id]; - metadata[_id] = _metadata; - emit MetadataChanged(_msgSender(), _id, oldMetadata, _metadata); - } - - /** + function setMetadata(uint256 _id, string memory _metadata) + external + hasItemRight(_id, SET_METADATA) + { + uint256 groupId = _id >> 128; + require( + !uriLocked && !metadataFrozen[_id] && !metadataFrozen[groupId], + "Super721::setMetadata: you cannot edit this metadata because it is frozen" + ); + string memory oldMetadata = metadata[_id]; + metadata[_id] = _metadata; + emit MetadataChanged(_msgSender(), _id, oldMetadata, _metadata); + } + + /** Allow the item collection owner or an associated manager to forever lock the metadata URI on the entire collection to future changes. */ - function lockURI() external - hasValidPermit(UNIVERSAL, LOCK_URI) { - uriLocked = true; - emit PermanentURI(metadataUri, 2 ** 256 - 1); - } + function lockURI() external hasValidPermit(UNIVERSAL, LOCK_URI) { + uriLocked = true; + emit PermanentURI(metadataUri, 2**256 - 1); + } - /** + /** Allow the associated manager to forever lock the contract URI to future changes */ - function lockContractUri() external - hasValidPermit(UNIVERSAL, LOCK_URI) { - contractUriLocked = true; - emit PermanentContractURI(contractURI, 2 ** 256 - 1); - } + function lockContractUri() external hasValidPermit(UNIVERSAL, LOCK_URI) { + contractUriLocked = true; + emit PermanentContractURI(contractURI, 2**256 - 1); + } - /** + /** Allow the item collection owner or an associated manager to forever lock the metadata URI on an item to future changes. @param _uri The value of the URI to lock for `_id`. @param _id The token ID to lock a metadata URI value into. */ - function lockItemURI(string calldata _uri, uint256 _id) external - hasItemRight(_id, LOCK_ITEM_URI) { - metadataFrozen[_id] = true; - emit PermanentURI(_uri, _id); - } + function lockItemURI(string calldata _uri, uint256 _id) + external + hasItemRight(_id, LOCK_ITEM_URI) + { + metadataFrozen[_id] = true; + emit PermanentURI(_uri, _id); + } - /** + /** Allow the item collection owner or an associated manager to forever lock the metadata URI on a group of items to future changes. @param _uri The value of the URI to lock for `groupId`. @param groupId The group ID to lock a metadata URI value into. */ - function lockGroupURI(string calldata _uri, uint256 groupId) external - hasItemRight(groupId, LOCK_ITEM_URI) { - metadataFrozen[groupId] = true; - emit PermanentURI(_uri, groupId); - } + function lockGroupURI(string calldata _uri, uint256 groupId) + external + hasItemRight(groupId, LOCK_ITEM_URI) + { + metadataFrozen[groupId] = true; + emit PermanentURI(_uri, groupId); + } - /** + /** Allow the item collection owner or an associated manager to forever lock this contract to further item minting. */ - function lock() external virtual hasValidPermit(UNIVERSAL, LOCK_CREATION) { - locked = true; - emit CollectionLocked(_msgSender()); - } - - function getApproved(uint256 tokenId) public view override returns (address) { - require(_tokenOwners.contains(tokenId), "Super721::getApproved: approved query for nonexistent token"); - - return _tokenApprovals[tokenId]; - } - - function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { - require(_tokenOwners.contains(tokenId), "Super721::getApproved: operator query for nonexistent token"); - address owner = ownerOf(tokenId); - return (spender == owner || _tokenApprovals[tokenId] == spender || isApprovedForAll(owner, spender)); - } - /** - * @dev See {IERC721-transferFrom}. - */ - function transferFrom(address from, address to, uint256 tokenId) public virtual override { - // //solhint-disable-next-line max-line-length - require(_isApprovedOrOwner(_msgSender(), tokenId), "Super721::transferForm: transfer caller is not owner nor approved"); - safeTransferFrom(from, to, tokenId); - // - // require(ownerOf(tokenId) == from, "Super721::transferForm: transfer of token that is not own"); - // require(to != address(0), "Super721::transferForm: transfer to the zero address"); - // - // _beforeTokenTransfer(_msgSender(), from, to, _asSingletonArray(tokenId), _asSingletonArray(1), ""); - // - // // Clear approvals from the previous owner - // //_approve(address(0), tokenId); - // _tokenApprovals[tokenId] = address(0); - // emit Approval(ownerOf(tokenId), address(0), tokenId); - // - // _holderTokens[from].remove(tokenId); - // _holderTokens[to].add(tokenId); - // - // _tokenOwners.set(tokenId, to); - // - // emit Transfer(from, to, tokenId); - } - - /** - * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. - */ - function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { - return _holderTokens[owner].at(index); - } + function lock() external virtual hasValidPermit(UNIVERSAL, LOCK_CREATION) { + locked = true; + emit CollectionLocked(_msgSender()); + } - /** - * @dev See {IERC721Enumerable-totalSupply}. - */ - function totalSupply() public view returns (uint256) { - // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds - return _tokenOwners.length(); - } + function getApproved(uint256 tokenId) + public + view + override + returns (address) + { + require( + _tokenOwners.contains(tokenId), + "Super721::getApproved: approved query for nonexistent token" + ); + + return _tokenApprovals[tokenId]; + } - /** - * @dev See {IERC721Enumerable-tokenByIndex}. - */ - function tokenByIndex(uint256 index) public view returns (uint256) { - (uint256 tokenId, ) = _tokenOwners.at(index); - return tokenId; - } + function _isApprovedOrOwner(address spender, uint256 tokenId) + internal + view + returns (bool) + { + require( + _tokenOwners.contains(tokenId), + "Super721::getApproved: operator query for nonexistent token" + ); + address owner = ownerOf(tokenId); + return (spender == owner || + _tokenApprovals[tokenId] == spender || + isApprovedForAll(owner, spender)); + } -} \ No newline at end of file + /** + * @dev See {IERC721-transferFrom}. + */ + function transferFrom( + address from, + address to, + uint256 tokenId + ) public virtual override { + // //solhint-disable-next-line max-line-length + require( + _isApprovedOrOwner(_msgSender(), tokenId), + "Super721::transferForm: transfer caller is not owner nor approved" + ); + safeTransferFrom(from, to, tokenId); + // + // require(ownerOf(tokenId) == from, "Super721::transferForm: transfer of token that is not own"); + // require(to != address(0), "Super721::transferForm: transfer to the zero address"); + // + // _beforeTokenTransfer(_msgSender(), from, to, _asSingletonArray(tokenId), _asSingletonArray(1), ""); + // + // // Clear approvals from the previous owner + // //_approve(address(0), tokenId); + // _tokenApprovals[tokenId] = address(0); + // emit Approval(ownerOf(tokenId), address(0), tokenId); + // + // _holderTokens[from].remove(tokenId); + // _holderTokens[to].add(tokenId); + // + // _tokenOwners.set(tokenId, to); + // + // emit Transfer(from, to, tokenId); + } + + /** + * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. + */ + function tokenOfOwnerByIndex(address owner, uint256 index) + public + view + returns (uint256) + { + return _holderTokens[owner].at(index); + } + + /** + * @dev See {IERC721Enumerable-totalSupply}. + */ + function totalSupply() public view returns (uint256) { + // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds + return _tokenOwners.length(); + } + + /** + * @dev See {IERC721Enumerable-tokenByIndex}. + */ + function tokenByIndex(uint256 index) public view returns (uint256) { + (uint256 tokenId, ) = _tokenOwners.at(index); + return tokenId; + } +} diff --git a/contracts/assets/erc721/interfaces/IStaker.sol b/contracts/assets/erc721/interfaces/IStaker.sol new file mode 100644 index 0000000..324a1b5 --- /dev/null +++ b/contracts/assets/erc721/interfaces/IStaker.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.8; + +/** + @title Super721 interface + Interface for interacting with Super721 contract + */ +interface IStaker { + function updateOnIouTransfer( + uint256 _poolId, + uint256 _tokenId, + address _from, + address _to + ) external; +} diff --git a/contracts/assets/erc721/interfaces/ISuper721.sol b/contracts/assets/erc721/interfaces/ISuper721.sol index 5d9a7a8..c40b5e7 100644 --- a/contracts/assets/erc721/interfaces/ISuper721.sol +++ b/contracts/assets/erc721/interfaces/ISuper721.sol @@ -30,5 +30,4 @@ interface ISuper721 { function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, bytes memory _data) external; function transferOwnership(address newOwner) external; - } diff --git a/contracts/base/Sweepableds.sol b/contracts/base/Sweepableds.sol index ae27110..35e53af 100644 --- a/contracts/base/Sweepableds.sol +++ b/contracts/base/Sweepableds.sol @@ -33,6 +33,7 @@ contract Sweepableds is PermitControlds { @param amount The amount of the ERC-20 token being swept. @param recipient The recipient of the swept tokens. */ + event TokenSweep( address indexed sweeper, IERC20 indexed token, @@ -63,6 +64,7 @@ contract Sweepableds is PermitControlds { @param _amount The amount of token to sweep. @param _address The address to send the swept tokens to. */ + function sweep( IERC20 _token, uint256 _amount, diff --git a/contracts/interfaces/ISuperGeneric.sol b/contracts/interfaces/ISuperGeneric.sol index de7d905..d8aa7b9 100644 --- a/contracts/interfaces/ISuperGeneric.sol +++ b/contracts/interfaces/ISuperGeneric.sol @@ -9,32 +9,84 @@ import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @author Qazawat Zirak */ interface ISuperGeneric is IERC165 { - /** - * @dev safeBatchTransferFrom is not included in Original Openzeppelin IERC721. + /// ERC1155 functions + + /** + Mint a batch of tokens into existence and send them to the `_recipient` + address. In order to mint an item, its item group must first have been + created. Minting an item must obey both the fungibility and size cap of its + group. + + @param _recipient The address to receive all NFTs within the newly-minted + group. + @param _ids The item IDs for the new items to create. + @param _amounts The amount of each corresponding item ID to create. + @param _data Any associated data to use on items minted in this transaction. */ - function safeBatchTransferFrom( - address _from, - address _to, - uint256[] memory _ids, + function mintBatch( + address _recipient, + uint256[] memory _ids, + uint256[] memory _amounts, bytes memory _data ) external; function safeBatchTransferFrom( - address _from, + address _from, address _to, - uint256[] memory _ids, - uint256[] memory _amounts, + uint256[] memory _ids, + uint256[] memory _amounts, bytes memory _data ) external; function burnBatch( address _burner, - uint256[] memory _ids + uint256[] memory _ids, + uint256[] memory _amounts ) external; - function burnBatch( - address _burner, + /// Balace of ERC1155 + function balanceOf(address _owner, uint256 _id) + external + view + returns (uint256); + + /// ERC721 functions + /** + Returns overall amount of NFTs, which are owned by `_owner`. + @param _owner address of NFTs owner. + */ + function balanceOf(address _owner) external view returns (uint256); + + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + returns (uint256[] memory); + + function mintBatch( + address _recipient, + uint256[] calldata _ids, + bytes memory _data + ) external; + + function mintBatch( + address _recipient, + uint256 _amount, + uint256 _poolId + ) external; + + function burnBatch(address _burner, uint256[] memory _ids) external; + + function ownerOf(uint256 tokenId) external view returns (address); + + function totalSupply() external view returns (uint256); + + /** + * @dev safeBatchTransferFrom is not included in Original Openzeppelin IERC721. + */ + function safeBatchTransferFrom( + address _from, + address _to, uint256[] memory _ids, - uint256[] memory _amounts + bytes memory _data ) external; -} \ No newline at end of file +} diff --git a/contracts/staker/v1/Staker.sol b/contracts/staker/v1/Staker.sol index 5f11a1f..ec48d72 100644 --- a/contracts/staker/v1/Staker.sol +++ b/contracts/staker/v1/Staker.sol @@ -17,55 +17,55 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol */ contract Staker is Ownable, ReentrancyGuard { - using SafeERC20 for IERC20; + using SafeERC20 for IERC20; - /// A user-specified, descriptive name for this Staker. - string public name; + /// A user-specified, descriptive name for this Staker. + string public name; - /// The token to disburse. - IERC20 public token; + /// The token to disburse. + IERC20 public token; - /// A flag signalling whether the contract owner can add or set developers. - bool public canAlterDevelopers; + /// A flag signalling whether the contract owner can add or set developers. + bool public canAlterDevelopers; - /// An array of developer addresses for finding shares in the share mapping. - address[] public developerAddresses; + /// An array of developer addresses for finding shares in the share mapping. + address[] public developerAddresses; - /** + /** @dev A mapping of developer addresses to their percent share of emissions. Share percentages are represented as 1/1000th of a percent. That is, a 1% share of emissions should map an address to 1000. */ - mapping (address => uint256) public developerShares; + mapping(address => uint256) public developerShares; - /// A flag signalling whether or not the contract owner can alter emissions. - bool public canAlterTokenEmissionSchedule; - bool public canAlterPointEmissionSchedule; + /// A flag signalling whether or not the contract owner can alter emissions. + bool public canAlterTokenEmissionSchedule; + bool public canAlterPointEmissionSchedule; - /** + /** This emission schedule maps a timestamp to the amount of tokens or points that should be disbursed starting at that timestamp. @param timeStamp If current time reaches timestamp, the rate is applied. @param rate Measure of points/tokens emitted. */ - struct EmissionPoint { - uint256 timeStamp; - uint256 rate; - } - - /// Array of emission schedule timestamps for finding emission rate changes. - uint256 public tokenEmissionEventsCount; - mapping (uint256 => EmissionPoint) public tokenEmissionEvents; - uint256 public pointEmissionEventsCount; - mapping (uint256 => EmissionPoint) public pointEmissionEvents; - - /// Store the very earliest possible timestamp for quick reference. - uint256 MAX_INT = 2**256 - 1; - uint256 internal earliestTokenEmissionTime; - uint256 internal earliestPointEmissionTime; - -/** + struct EmissionPoint { + uint256 timeStamp; + uint256 rate; + } + + /// Array of emission schedule timestamps for finding emission rate changes. + uint256 public tokenEmissionEventsCount; + mapping(uint256 => EmissionPoint) public tokenEmissionEvents; + uint256 public pointEmissionEventsCount; + mapping(uint256 => EmissionPoint) public pointEmissionEvents; + + /// Store the very earliest possible timestamp for quick reference. + uint256 MAX_INT = 2**256 - 1; + uint256 internal earliestTokenEmissionTime; + uint256 internal earliestPointEmissionTime; + + /** A struct containing the pool info tracked in storage. @param token address of the ERC20 asset that is being staked in the pool. @@ -75,103 +75,117 @@ contract Staker is Ownable, ReentrancyGuard { @param pointsPerShare accumulated points per share times 1e12. @param lastRewardTime record of the time of the last disbursement. */ - struct PoolInfo { - IERC20 token; - uint256 tokenStrength; - uint256 tokensPerShare; - uint256 pointStrength; - uint256 pointsPerShare; - uint256 lastRewardTime; - } - - IERC20[] public poolTokens; - - /// Stored information for each available pool per its token address. - mapping (IERC20 => PoolInfo) public poolInfo; - - /** - A struct containing the user info tracked in storage. - - @param amount amount of the pool asset being provided by the user. - @param tokenPaid value of user's total token earnings paid out. - pending reward = (user.amount * pool.tokensPerShare) - user.rewardDebt. - @param tokenRewards amount of token rewards accumulated to be claimed. - @param pointPaid value of user's total point earnings paid out. - @param pointRewards amount of point rewards accumulated to be claimed. - */ - struct UserInfo { - uint256 amount; - uint256 tokenPaid; - uint256 tokenRewards; - uint256 pointPaid; - uint256 pointRewards; - } - - /// Stored information for each user staking in each pool. - mapping (IERC20 => mapping (address => UserInfo)) public userInfo; - - /// The total sum of the strength of all pools. - uint256 public totalTokenStrength; - uint256 public totalPointStrength; - - /// The total amount of the disbursed token ever emitted by this Staker. - uint256 public totalTokenDisbursed; - - /// Users additionally accrue non-token points for participating via staking. - mapping (address => uint256) public userPoints; - mapping (address => uint256) public userSpentPoints; - - /// A map of all external addresses that are permitted to spend user points. - mapping (address => bool) public approvedPointSpenders; - - /// Events for depositing assets into the Staker and later withdrawing them. - event Deposit(address indexed user, IERC20 indexed token, uint256 amount); - event Withdraw(address indexed user, IERC20 indexed token, uint256 amount); - event Claim(address indexed user, IERC20 indexed token, uint256 tokensAmount, uint256 pointsAmount); - - /// An event for tracking when a user has spent points. - event SpentPoints(address indexed source, address indexed user, uint256 amount); - - /** - Construct a new Staker by providing it a name and the token to disburse. - @param _name The name of the Staker contract. - @param _token The token to reward stakers in this contract with. - */ - constructor(string memory _name, IERC20 _token) { - name = _name; - token = _token; - token.approve(address(this), MAX_INT); - canAlterDevelopers = true; - canAlterTokenEmissionSchedule = true; - earliestTokenEmissionTime = MAX_INT; - canAlterPointEmissionSchedule = true; - earliestPointEmissionTime = MAX_INT; - } - - /** + struct PoolInfo { + IERC20 token; + uint256 tokenStrength; + uint256 tokensPerShare; + uint256 pointStrength; + uint256 pointsPerShare; + uint256 lastRewardTime; + } + + IERC20[] public poolTokens; + + /// Stored information for each available pool per its token address. + mapping(IERC20 => PoolInfo) public poolInfo; + + /** + * A struct containing the user info tracked in storage. + * + * @param amount amount of the pool asset being provided by the user. + * @param tokenPaid value of user's total token earnings paid out. + * pending reward = (user.amount * pool.tokensPerShare) - user.rewardDebt. + * @param tokenRewards amount of token rewards accumulated to be claimed. + * @param pointPaid value of user's total point earnings paid out. + * @param pointRewards amount of point rewards accumulated to be claimed. + */ + struct UserInfo { + uint256 amount; + uint256 tokenPaid; + uint256 tokenRewards; + uint256 pointPaid; + uint256 pointRewards; + } + + /// Stored information for each user staking in each pool. + mapping(IERC20 => mapping(address => UserInfo)) public userInfo; + + /// The total sum of the strength of all pools. + uint256 public totalTokenStrength; + uint256 public totalPointStrength; + + /// The total amount of the disbursed token ever emitted by this Staker. + uint256 public totalTokenDisbursed; + + /// Users additionally accrue non-token points for participating via staking. + mapping(address => uint256) public userPoints; + mapping(address => uint256) public userSpentPoints; + + /// A map of all external addresses that are permitted to spend user points. + mapping(address => bool) public approvedPointSpenders; + + /// Events for depositing assets into the Staker and later withdrawing them. + event Deposit(address indexed user, IERC20 indexed token, uint256 amount); + event Withdraw(address indexed user, IERC20 indexed token, uint256 amount); + event Claim( + address indexed user, + IERC20 indexed token, + uint256 tokensAmount, + uint256 pointsAmount + ); + + /// An event for tracking when a user has spent points. + event SpentPoints( + address indexed source, + address indexed user, + uint256 amount + ); + + /** + * Construct a new Staker by providing it a name and the token to disburse. + * @param _name The name of the Staker contract. + * @param _token The token to reward stakers in this contract with. + */ + constructor(string memory _name, IERC20 _token) { + name = _name; + token = _token; + token.approve(address(this), MAX_INT); + canAlterDevelopers = true; + canAlterTokenEmissionSchedule = true; + earliestTokenEmissionTime = MAX_INT; + canAlterPointEmissionSchedule = true; + earliestPointEmissionTime = MAX_INT; + } + + /** Add a new developer to the Staker or overwrite an existing one. This operation requires that developer address addition is not locked. @param _developerAddress The additional developer's address. @param _share The share in 1/1000th of a percent of each token emission sent to this new developer. */ - function addDeveloper(address _developerAddress, uint256 _share) external onlyOwner { - require(canAlterDevelopers, - "This Staker has locked the addition of developers; no more may be added."); - developerAddresses.push(_developerAddress); - developerShares[_developerAddress] = _share; - } - - /** + function addDeveloper(address _developerAddress, uint256 _share) + external + onlyOwner + { + require( + canAlterDevelopers, + "This Staker has locked the addition of developers; no more may be added." + ); + developerAddresses.push(_developerAddress); + developerShares[_developerAddress] = _share; + } + + /** Permanently forfeits owner ability to alter the state of Staker developers. Once called, this function is intended to give peace of mind to the Staker's developers and community that the fee structure is now immutable. */ - function lockDevelopers() external onlyOwner { - canAlterDevelopers = false; - } + function lockDevelopers() external onlyOwner { + canAlterDevelopers = false; + } - /** + /** A developer may at any time update their address or voluntarily reduce their share of emissions by calling this function from their current address. Note that updating a developer's share to zero effectively removes them. @@ -179,429 +193,540 @@ contract Staker is Ownable, ReentrancyGuard { @param _newShare The new share in 1/1000th of a percent of each token emission sent to this developer. */ - function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) external { - uint256 developerShare = developerShares[msg.sender]; - require(developerShare > 0, - "You are not a developer of this Staker."); - require(_newShare <= developerShare, - "You cannot increase your developer share."); - developerShares[msg.sender] = 0; - developerAddresses.push(_newDeveloperAddress); - developerShares[_newDeveloperAddress] = _newShare; - } - - /** + function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) + external + { + uint256 developerShare = developerShares[msg.sender]; + require(developerShare > 0, "You are not a developer of this Staker."); + require( + _newShare <= developerShare, + "You cannot increase your developer share." + ); + developerShares[msg.sender] = 0; + developerAddresses.push(_newDeveloperAddress); + developerShares[_newDeveloperAddress] = _newShare; + } + + /** Set new emission details to the Staker or overwrite existing ones. This operation requires that emission schedule alteration is not locked. @param _tokenSchedule An array of EmissionPoints defining the token schedule. @param _pointSchedule An array of EmissionPoints defining the point schedule. */ - function setEmissions(EmissionPoint[] memory _tokenSchedule, EmissionPoint[] memory _pointSchedule) external onlyOwner { - if (_tokenSchedule.length > 0) { - require(canAlterTokenEmissionSchedule, - "This Staker has locked the alteration of token emissions."); - tokenEmissionEventsCount = _tokenSchedule.length; - for (uint256 i = 0; i < tokenEmissionEventsCount; i++) { - tokenEmissionEvents[i] = _tokenSchedule[i]; - if (earliestTokenEmissionTime > _tokenSchedule[i].timeStamp) { - earliestTokenEmissionTime = _tokenSchedule[i].timeStamp; + function setEmissions( + EmissionPoint[] memory _tokenSchedule, + EmissionPoint[] memory _pointSchedule + ) external onlyOwner { + if (_tokenSchedule.length > 0) { + require( + canAlterTokenEmissionSchedule, + "This Staker has locked the alteration of token emissions." + ); + tokenEmissionEventsCount = _tokenSchedule.length; + for (uint256 i = 0; i < tokenEmissionEventsCount; i++) { + tokenEmissionEvents[i] = _tokenSchedule[i]; + if (earliestTokenEmissionTime > _tokenSchedule[i].timeStamp) { + earliestTokenEmissionTime = _tokenSchedule[i].timeStamp; + } + } } - } - } - require(tokenEmissionEventsCount > 0, - "You must set the token emission schedule."); - - if (_pointSchedule.length > 0) { - require(canAlterPointEmissionSchedule, - "This Staker has locked the alteration of point emissions."); - pointEmissionEventsCount = _pointSchedule.length; - for (uint256 i = 0; i < pointEmissionEventsCount; i++) { - pointEmissionEvents[i] = _pointSchedule[i]; - if (earliestPointEmissionTime > _pointSchedule[i].timeStamp) { - earliestPointEmissionTime = _pointSchedule[i].timeStamp; + require( + tokenEmissionEventsCount > 0, + "You must set the token emission schedule." + ); + + if (_pointSchedule.length > 0) { + require( + canAlterPointEmissionSchedule, + "This Staker has locked the alteration of point emissions." + ); + pointEmissionEventsCount = _pointSchedule.length; + for (uint256 i = 0; i < pointEmissionEventsCount; i++) { + pointEmissionEvents[i] = _pointSchedule[i]; + if (earliestPointEmissionTime > _pointSchedule[i].timeStamp) { + earliestPointEmissionTime = _pointSchedule[i].timeStamp; + } + } } - } + require( + pointEmissionEventsCount > 0, + "You must set the point emission schedule." + ); } - require(pointEmissionEventsCount > 0, - "You must set the point emission schedule."); - } - /** + /** Permanently forfeits owner ability to alter the emission schedule. Once called, this function is intended to give peace of mind to the Staker's developers and community that the inflation rate is now immutable. */ - function lockTokenEmissions() external onlyOwner { - canAlterTokenEmissionSchedule = false; - } + function lockTokenEmissions() external onlyOwner { + canAlterTokenEmissionSchedule = false; + } - /** + /** Permanently forfeits owner ability to alter the emission schedule. Once called, this function is intended to give peace of mind to the Staker's developers and community that the inflation rate is now immutable. */ - function lockPointEmissions() external onlyOwner { - canAlterPointEmissionSchedule = false; - } + function lockPointEmissions() external onlyOwner { + canAlterPointEmissionSchedule = false; + } - /** + /** Returns the length of the developer address array. @return the length of the developer address array. */ - function getDeveloperCount() external view returns (uint256) { - return developerAddresses.length; - } + function getDeveloperCount() external view returns (uint256) { + return developerAddresses.length; + } - /** + /** Returns the length of the staking pool array. @return the length of the staking pool array. */ - function getPoolCount() external view returns (uint256) { - return poolTokens.length; - } + function getPoolCount() external view returns (uint256) { + return poolTokens.length; + } - /** + /** Returns the amount of token that has not been disbursed by the Staker yet. @return the amount of token that has not been disbursed by the Staker yet. */ - function getRemainingToken() external view returns (uint256) { - return token.balanceOf(address(this)); - } + function getRemainingToken() external view returns (uint256) { + return token.balanceOf(address(this)); + } - /** + /** Allows the contract owner to add a new asset pool to the Staker or overwrite an existing one. @param _token The address of the asset to base this staking pool off of. @param _tokenStrength The relative strength of the new asset for earning token. @param _pointStrength The relative strength of the new asset for earning points. */ - function addPool(IERC20 _token, uint256 _tokenStrength, uint256 _pointStrength) external onlyOwner { - require(tokenEmissionEventsCount > 0 && pointEmissionEventsCount > 0, - "Staking pools cannot be addded until an emission schedule has been defined."); - require(address(_token) != address(token), - "Staking pool token can not be the same as reward token."); - require(_tokenStrength > 0 && _pointStrength > 0, - "Staking pool token/point strength must be greater than 0."); - - uint256 lastTokenRewardTime = block.timestamp > earliestTokenEmissionTime ? block.timestamp : earliestTokenEmissionTime; - uint256 lastPointRewardTime = block.timestamp > earliestPointEmissionTime ? block.timestamp : earliestPointEmissionTime; - uint256 lastRewardTime = lastTokenRewardTime > lastPointRewardTime ? lastTokenRewardTime : lastPointRewardTime; - if (address(poolInfo[_token].token) == address(0)) { - poolTokens.push(_token); - totalTokenStrength = totalTokenStrength + _tokenStrength; - totalPointStrength = totalPointStrength + _pointStrength; - poolInfo[_token] = PoolInfo({ - token: _token, - tokenStrength: _tokenStrength, - tokensPerShare: 0, - pointStrength: _pointStrength, - pointsPerShare: 0, - lastRewardTime: lastRewardTime - }); - } else { - totalTokenStrength = (totalTokenStrength - poolInfo[_token].tokenStrength) + _tokenStrength; - poolInfo[_token].tokenStrength = _tokenStrength; - totalPointStrength = (totalPointStrength - poolInfo[_token].pointStrength) + _pointStrength; - poolInfo[_token].pointStrength = _pointStrength; + function addPool( + IERC20 _token, + uint256 _tokenStrength, + uint256 _pointStrength + ) external onlyOwner { + require( + tokenEmissionEventsCount > 0 && pointEmissionEventsCount > 0, + "Staking pools cannot be addded until an emission schedule has been defined." + ); + require( + address(_token) != address(token), + "Staking pool token can not be the same as reward token." + ); + require( + _tokenStrength > 0 && _pointStrength > 0, + "Staking pool token/point strength must be greater than 0." + ); + + uint256 lastTokenRewardTime = block.timestamp > + earliestTokenEmissionTime + ? block.timestamp + : earliestTokenEmissionTime; + uint256 lastPointRewardTime = block.timestamp > + earliestPointEmissionTime + ? block.timestamp + : earliestPointEmissionTime; + uint256 lastRewardTime = lastTokenRewardTime > lastPointRewardTime + ? lastTokenRewardTime + : lastPointRewardTime; + if (address(poolInfo[_token].token) == address(0)) { + poolTokens.push(_token); + totalTokenStrength = totalTokenStrength + _tokenStrength; + totalPointStrength = totalPointStrength + _pointStrength; + poolInfo[_token] = PoolInfo({ + token: _token, + tokenStrength: _tokenStrength, + tokensPerShare: 0, + pointStrength: _pointStrength, + pointsPerShare: 0, + lastRewardTime: lastRewardTime + }); + } else { + totalTokenStrength = + (totalTokenStrength - poolInfo[_token].tokenStrength) + + _tokenStrength; + poolInfo[_token].tokenStrength = _tokenStrength; + totalPointStrength = + (totalPointStrength - poolInfo[_token].pointStrength) + + _pointStrength; + poolInfo[_token].pointStrength = _pointStrength; + } } - } - /** + /** Uses the emission schedule to calculate the total amount of staking reward token that was emitted between two specified timestamps. @param _fromTime The time to begin calculating emissions from. @param _toTime The time to calculate total emissions up to. */ - function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) public view returns (uint256) { - require(_toTime >= _fromTime, - "Tokens cannot be emitted from a higher timestsamp to a lower timestamp."); - uint256 totalEmittedTokens = 0; - uint256 workingRate = 0; - uint256 workingTime = _fromTime; - for (uint256 i = 0; i < tokenEmissionEventsCount; ++i) { - uint256 emissionTime = tokenEmissionEvents[i].timeStamp; - uint256 emissionRate = tokenEmissionEvents[i].rate; - if (_toTime < emissionTime) { - totalEmittedTokens = totalEmittedTokens + ((_toTime - workingTime) * workingRate); + function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) + public + view + returns (uint256) + { + require( + _toTime >= _fromTime, + "Tokens cannot be emitted from a higher timestsamp to a lower timestamp." + ); + uint256 totalEmittedTokens = 0; + uint256 workingRate = 0; + uint256 workingTime = _fromTime; + for (uint256 i = 0; i < tokenEmissionEventsCount; ++i) { + uint256 emissionTime = tokenEmissionEvents[i].timeStamp; + uint256 emissionRate = tokenEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedTokens = + totalEmittedTokens + + ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } else if (workingTime < emissionTime) { + totalEmittedTokens = + totalEmittedTokens + + ((emissionTime - workingTime) * workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + } + if (workingTime < _toTime) { + totalEmittedTokens = + totalEmittedTokens + + ((_toTime - workingTime) * workingRate); + } return totalEmittedTokens; - } else if (workingTime < emissionTime) { - totalEmittedTokens = totalEmittedTokens + ((emissionTime - workingTime) * workingRate); - workingTime = emissionTime; - } - workingRate = emissionRate; - } - if (workingTime < _toTime) { - totalEmittedTokens = totalEmittedTokens + ((_toTime - workingTime) * workingRate); } - return totalEmittedTokens; - } - /** + /** Uses the emission schedule to calculate the total amount of points emitted between two specified timestamps. @param _fromTime The time to begin calculating emissions from. @param _toTime The time to calculate total emissions up to. */ - function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) public view returns (uint256) { - require(_toTime >= _fromTime, - "Points cannot be emitted from a higher timestsamp to a lower timestamp."); - uint256 totalEmittedPoints = 0; - uint256 workingRate = 0; - uint256 workingTime = _fromTime; - for (uint256 i = 0; i < pointEmissionEventsCount; ++i) { - uint256 emissionTime = pointEmissionEvents[i].timeStamp; - uint256 emissionRate = pointEmissionEvents[i].rate; - if (_toTime < emissionTime) { - totalEmittedPoints = totalEmittedPoints + ((_toTime - workingTime) * workingRate); + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + public + view + returns (uint256) + { + require( + _toTime >= _fromTime, + "Points cannot be emitted from a higher timestsamp to a lower timestamp." + ); + uint256 totalEmittedPoints = 0; + uint256 workingRate = 0; + uint256 workingTime = _fromTime; + for (uint256 i = 0; i < pointEmissionEventsCount; ++i) { + uint256 emissionTime = pointEmissionEvents[i].timeStamp; + uint256 emissionRate = pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints = + totalEmittedPoints + + ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints = + totalEmittedPoints + + ((emissionTime - workingTime) * workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + } + if (workingTime < _toTime) { + totalEmittedPoints = + totalEmittedPoints + + ((_toTime - workingTime) * workingRate); + } return totalEmittedPoints; - } else if (workingTime < emissionTime) { - totalEmittedPoints = totalEmittedPoints + ((emissionTime - workingTime) * workingRate); - workingTime = emissionTime; - } - workingRate = emissionRate; - } - if (workingTime < _toTime) { - totalEmittedPoints = totalEmittedPoints + ((_toTime - workingTime) * workingRate); } - return totalEmittedPoints; - } - /** + /** Update the pool corresponding to the specified token address. @param _token The address of the asset to update the corresponding pool for. */ - function updatePool(IERC20 _token) internal { - PoolInfo storage pool = poolInfo[_token]; - if (block.timestamp <= pool.lastRewardTime) { - return; - } - uint256 poolTokenSupply = pool.token.balanceOf(address(this)); - if (poolTokenSupply <= 0) { - pool.lastRewardTime = block.timestamp; - return; - } + function updatePool(IERC20 _token) internal { + PoolInfo storage pool = poolInfo[_token]; + if (block.timestamp <= pool.lastRewardTime) { + return; + } + uint256 poolTokenSupply = pool.token.balanceOf(address(this)); + if (poolTokenSupply <= 0) { + pool.lastRewardTime = block.timestamp; + return; + } - // Calculate token and point rewards for this pool. - uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardTime, block.timestamp); - uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / totalTokenStrength) * 1e12; - uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardTime, block.timestamp); - uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / totalPointStrength) * 1e30; - - // Directly pay developers their corresponding share of tokens and points. - for (uint256 i = 0; i < developerAddresses.length; ++i) { - address developer = developerAddresses[i]; - uint256 share = developerShares[developer]; - uint256 devTokens = (tokensReward * share) / 100000; - tokensReward = tokensReward - devTokens; - uint256 devPoints = (pointsReward * share) / 100000; - pointsReward = pointsReward - devPoints; - token.safeTransferFrom(address(this), developer, devTokens / 1e12); - userPoints[developer] = userPoints[developer] + (devPoints / 1e30); - } + // Calculate token and point rewards for this pool. + uint256 totalEmittedTokens = getTotalEmittedTokens( + pool.lastRewardTime, + block.timestamp + ); + uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / + totalTokenStrength) * 1e12; + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardTime, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + totalPointStrength) * 1e30; + + // Directly pay developers their corresponding share of tokens and points. + for (uint256 i = 0; i < developerAddresses.length; ++i) { + address developer = developerAddresses[i]; + uint256 share = developerShares[developer]; + uint256 devTokens = (tokensReward * share) / 100000; + tokensReward = tokensReward - devTokens; + uint256 devPoints = (pointsReward * share) / 100000; + pointsReward = pointsReward - devPoints; + token.safeTransferFrom(address(this), developer, devTokens / 1e12); + userPoints[developer] = userPoints[developer] + (devPoints / 1e30); + } - // Update the pool rewards per share to pay users the amount remaining. - pool.tokensPerShare = pool.tokensPerShare + (tokensReward / poolTokenSupply); - pool.pointsPerShare = pool.pointsPerShare + (pointsReward / poolTokenSupply); - pool.lastRewardTime = block.timestamp; - } - - /** - A function to easily see the amount of token rewards pending for a user on a - given pool. Returns the pending reward token amount. - @param _token The address of a particular staking pool asset to check for a - pending reward. - @param _user The user address to check for a pending reward. - @return the pending reward token amount. - */ - function getPendingTokens(IERC20 _token, address _user) public view returns (uint256) { - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][_user]; - uint256 tokensPerShare = pool.tokensPerShare; - uint256 poolTokenSupply = pool.token.balanceOf(address(this)); - - if (block.timestamp > pool.lastRewardTime && poolTokenSupply > 0) { - uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardTime, block.timestamp); - uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / totalTokenStrength) * 1e12; - tokensPerShare = tokensPerShare + (tokensReward / poolTokenSupply); + // Update the pool rewards per share to pay users the amount remaining. + pool.tokensPerShare = + pool.tokensPerShare + + (tokensReward / poolTokenSupply); + pool.pointsPerShare = + pool.pointsPerShare + + (pointsReward / poolTokenSupply); + pool.lastRewardTime = block.timestamp; } - return ((user.amount * tokensPerShare) / 1e12) - user.tokenPaid; - } - - /** - A function to easily see the amount of point rewards pending for a user on a - given pool. Returns the pending reward point amount. + /** + * A function to easily see the amount of token rewards pending for a user on a + * given pool. Returns the pending reward token amount. + * @param _token The address of a particular staking pool asset to check for a + * pending reward. + * @param _user The user address to check for a pending reward. + * @return the pending reward token amount. + */ + function getPendingTokens(IERC20 _token, address _user) + public + view + returns (uint256) + { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][_user]; + uint256 tokensPerShare = pool.tokensPerShare; + uint256 poolTokenSupply = pool.token.balanceOf(address(this)); + + if (block.timestamp > pool.lastRewardTime && poolTokenSupply > 0) { + uint256 totalEmittedTokens = getTotalEmittedTokens( + pool.lastRewardTime, + block.timestamp + ); + uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / + totalTokenStrength) * 1e12; + tokensPerShare = tokensPerShare + (tokensReward / poolTokenSupply); + } - @param _token The address of a particular staking pool asset to check for a - pending reward. - @param _user The user address to check for a pending reward. - @return the pending reward token amount. - */ - function getPendingPoints(IERC20 _token, address _user) public view returns (uint256) { - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][_user]; - uint256 pointsPerShare = pool.pointsPerShare; - uint256 poolTokenSupply = pool.token.balanceOf(address(this)); - - if (block.timestamp > pool.lastRewardTime && poolTokenSupply > 0) { - uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardTime, block.timestamp); - uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / totalPointStrength) * 1e30; - pointsPerShare = pointsPerShare + (pointsReward / poolTokenSupply); + return ((user.amount * tokensPerShare) / 1e12) - user.tokenPaid; } - return ((user.amount * pointsPerShare) / 1e30) - user.pointPaid; - } + /** + * A function to easily see the amount of point rewards pending for a user on a + * given pool. Returns the pending reward point amount. + * + * @param _token The address of a particular staking pool asset to check for a + * pending reward. + * @param _user The user address to check for a pending reward. + * @return the pending reward token amount. + */ + function getPendingPoints(IERC20 _token, address _user) + public + view + returns (uint256) + { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][_user]; + uint256 pointsPerShare = pool.pointsPerShare; + uint256 poolTokenSupply = pool.token.balanceOf(address(this)); + + if (block.timestamp > pool.lastRewardTime && poolTokenSupply > 0) { + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardTime, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + totalPointStrength) * 1e30; + pointsPerShare = pointsPerShare + (pointsReward / poolTokenSupply); + } + + return ((user.amount * pointsPerShare) / 1e30) - user.pointPaid; + } - /** + /** Return the number of points that the user has available to spend. @return the number of points that the user has available to spend. */ - function getAvailablePoints(address _user) public view returns (uint256) { - uint256 concreteTotal = userPoints[_user]; - uint256 pendingTotal = 0; - for (uint256 i = 0; i < poolTokens.length; ++i) { - IERC20 poolToken = poolTokens[i]; - uint256 _pendingPoints = getPendingPoints(poolToken, _user); - pendingTotal = pendingTotal + _pendingPoints; + function getAvailablePoints(address _user) public view returns (uint256) { + uint256 concreteTotal = userPoints[_user]; + uint256 pendingTotal = 0; + for (uint256 i = 0; i < poolTokens.length; ++i) { + IERC20 poolToken = poolTokens[i]; + uint256 _pendingPoints = getPendingPoints(poolToken, _user); + pendingTotal = pendingTotal + _pendingPoints; + } + uint256 spentTotal = userSpentPoints[_user]; + return (concreteTotal + pendingTotal) - spentTotal; } - uint256 spentTotal = userSpentPoints[_user]; - return (concreteTotal + pendingTotal) - spentTotal; - } - /** + /** Return the total number of points that the user has ever accrued. @return the total number of points that the user has ever accrued. */ - function getTotalPoints(address _user) external view returns (uint256) { - uint256 concreteTotal = userPoints[_user]; - uint256 pendingTotal = 0; - for (uint256 i = 0; i < poolTokens.length; ++i) { - IERC20 poolToken = poolTokens[i]; - uint256 _pendingPoints = getPendingPoints(poolToken, _user); - pendingTotal = pendingTotal + _pendingPoints; + function getTotalPoints(address _user) external view returns (uint256) { + uint256 concreteTotal = userPoints[_user]; + uint256 pendingTotal = 0; + for (uint256 i = 0; i < poolTokens.length; ++i) { + IERC20 poolToken = poolTokens[i]; + uint256 _pendingPoints = getPendingPoints(poolToken, _user); + pendingTotal = pendingTotal + _pendingPoints; + } + return concreteTotal + pendingTotal; } - return concreteTotal + pendingTotal; - } - /** + /** Return the total number of points that the user has ever spent. @return the total number of points that the user has ever spent. */ - function getSpentPoints(address _user) external view returns (uint256) { - return userSpentPoints[_user]; - } + function getSpentPoints(address _user) external view returns (uint256) { + return userSpentPoints[_user]; + } - /** + /** Deposit some particular assets to a particular pool on the Staker. @param _token The asset to stake into its corresponding pool. @param _amount The amount of the provided asset to stake. */ - function deposit(IERC20 _token, uint256 _amount) external nonReentrant { - PoolInfo storage pool = poolInfo[_token]; - require(pool.tokenStrength > 0 || pool.pointStrength > 0, - "You cannot deposit assets into an inactive pool."); - UserInfo storage user = userInfo[_token][msg.sender]; - updatePool(_token); - if (user.amount > 0) { - uint256 pendingTokens = ((user.amount * pool.tokensPerShare) / 1e12) - user.tokenPaid; - user.tokenRewards += pendingTokens; - totalTokenDisbursed = totalTokenDisbursed + pendingTokens; - uint256 pendingPoints = ((user.amount * pool.pointsPerShare) / 1e30) - user.pointPaid; - user.pointRewards += pendingPoints; + function deposit(IERC20 _token, uint256 _amount) external { + PoolInfo storage pool = poolInfo[_token]; + require( + pool.tokenStrength > 0 || pool.pointStrength > 0, + "You cannot deposit assets into an inactive pool." + ); + UserInfo storage user = userInfo[_token][msg.sender]; + updatePool(_token); + if (user.amount > 0) { + uint256 pendingTokens = ((user.amount * pool.tokensPerShare) / + 1e12) - user.tokenPaid; + user.tokenRewards += pendingTokens; + totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + uint256 pendingPoints = ((user.amount * pool.pointsPerShare) / + 1e30) - user.pointPaid; + user.pointRewards += pendingPoints; + } + pool.token.safeTransferFrom( + address(msg.sender), + address(this), + _amount + ); + user.amount = user.amount + _amount; + user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; + user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; + emit Deposit(msg.sender, _token, _amount); } - pool.token.safeTransferFrom(address(msg.sender), address(this), _amount); - user.amount = user.amount +_amount; - user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; - user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; - emit Deposit(msg.sender, _token, _amount); - } - - /** + + /** Withdraw some particular assets from a particular pool on the Staker. @param _token The asset to withdraw from its corresponding staking pool. @param _amount The amount of the provided asset to withdraw. */ - function withdraw(IERC20 _token, uint256 _amount) external nonReentrant { - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][msg.sender]; - require(user.amount >= _amount, - "You cannot withdraw that much of the specified token; you are not owed it."); - updatePool(_token); - uint256 pendingTokens = ((user.amount * pool.tokensPerShare) / 1e12) - user.tokenPaid; - user.tokenRewards += pendingTokens; - totalTokenDisbursed = totalTokenDisbursed + pendingTokens; - uint256 pendingPoints = ((user.amount * pool.pointsPerShare) / 1e30) - user.pointPaid; - user.pointRewards += pendingPoints; - user.amount = user.amount - _amount; - user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; - user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; - pool.token.safeTransfer(address(msg.sender), _amount); - emit Withdraw(msg.sender, _token, _amount); - } - - /** + function withdraw(IERC20 _token, uint256 _amount) external nonReentrant { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][msg.sender]; + require( + user.amount >= _amount, + "You cannot withdraw that much of the specified token; you are not owed it." + ); + updatePool(_token); + uint256 pendingTokens = ((user.amount * pool.tokensPerShare) / 1e12) - + user.tokenPaid; + user.tokenRewards += pendingTokens; + totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + uint256 pendingPoints = ((user.amount * pool.pointsPerShare) / 1e30) - + user.pointPaid; + user.pointRewards += pendingPoints; + user.amount = user.amount - _amount; + user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; + user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; + pool.token.safeTransfer(address(msg.sender), _amount); + emit Withdraw(msg.sender, _token, _amount); + } + + /** Claim accumulated token and point rewards from the Staker. @param _token The asset to claim rewards from. */ - function claim(IERC20 _token) external nonReentrant { - UserInfo storage user = userInfo[_token][msg.sender]; - PoolInfo storage pool = poolInfo[_token]; - uint256 pendingTokens; - uint256 pendingPoints; - - updatePool(_token); - if (user.amount > 0) { - pendingTokens = ((user.amount * pool.tokensPerShare) / 1e12) - user.tokenPaid; - pendingPoints = ((user.amount * pool.pointsPerShare) / 1e30) - user.pointPaid; - totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + function claim(IERC20 _token) external nonReentrant { + UserInfo storage user = userInfo[_token][msg.sender]; + PoolInfo storage pool = poolInfo[_token]; + uint256 pendingTokens; + uint256 pendingPoints; + + updatePool(_token); + if (user.amount > 0) { + pendingTokens = + ((user.amount * pool.tokensPerShare) / 1e12) - + user.tokenPaid; + pendingPoints = + ((user.amount * pool.pointsPerShare) / 1e30) - + user.pointPaid; + totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + } + uint256 _tokenRewards = user.tokenRewards + pendingTokens; + uint256 _pointRewards = user.pointRewards + pendingPoints; + userPoints[msg.sender] = userPoints[msg.sender] + _pointRewards; + user.tokenRewards = 0; + user.pointRewards = 0; + + user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; + user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; + token.safeTransferFrom(address(this), msg.sender, _tokenRewards); + emit Claim(msg.sender, token, _tokenRewards, _pointRewards); } - uint256 _tokenRewards = user.tokenRewards + pendingTokens; - uint256 _pointRewards = user.pointRewards + pendingPoints; - userPoints[msg.sender] = userPoints[msg.sender] + _pointRewards; - user.tokenRewards = 0; - user.pointRewards = 0; - - user.tokenPaid = (user.amount * pool.tokensPerShare) / 1e12; - user.pointPaid = (user.amount * pool.pointsPerShare) / 1e30; - token.safeTransferFrom(address(this), msg.sender, _tokenRewards); - emit Claim(msg.sender, token, _tokenRewards, _pointRewards); - } - - /** + + /** Allows the owner of this Staker to grant or remove approval to an external spender of the points that users accrue from staking resources. @param _spender The external address allowed to spend user points. @param _approval The updated user approval status. */ - function approvePointSpender(address _spender, bool _approval) external onlyOwner { - approvedPointSpenders[_spender] = _approval; - } + function approvePointSpender(address _spender, bool _approval) + external + onlyOwner + { + approvedPointSpenders[_spender] = _approval; + } - /** + /** Allows an approved spender of points to spend points on behalf of a user. @param _user The user whose points are being spent. @param _amount The amount of the user's points being spent. */ - function spendPoints(address _user, uint256 _amount) external { - require(approvedPointSpenders[msg.sender], - "You are not permitted to spend user points."); - uint256 _userPoints = getAvailablePoints(_user); - require(_userPoints >= _amount, - "The user does not have enough points to spend the requested amount."); - userSpentPoints[_user] = userSpentPoints[_user] + _amount; - emit SpentPoints(msg.sender, _user, _amount); - } - - /** + function spendPoints(address _user, uint256 _amount) external { + require( + approvedPointSpenders[msg.sender], + "You are not permitted to spend user points." + ); + uint256 _userPoints = getAvailablePoints(_user); + require( + _userPoints >= _amount, + "The user does not have enough points to spend the requested amount." + ); + userSpentPoints[_user] = userSpentPoints[_user] + _amount; + emit SpentPoints(msg.sender, _user, _amount); + } + + /** Sweep all of a particular ERC-20 token from the contract. @param _token The token to sweep the balance from. */ - function sweep(IERC20 _token) external onlyOwner { - uint256 balance = _token.balanceOf(address(this)); - _token.safeTransferFrom(address(this), msg.sender, balance); - } + function sweep(IERC20 _token) external onlyOwner { + uint256 balance = _token.balanceOf(address(this)); + _token.safeTransferFrom(address(this), msg.sender, balance); + } } diff --git a/contracts/staker/v2/StakerV2.sol b/contracts/staker/v2/StakerV2.sol index d70a593..772f179 100644 --- a/contracts/staker/v2/StakerV2.sol +++ b/contracts/staker/v2/StakerV2.sol @@ -22,98 +22,107 @@ import "../../interfaces/ISuperGeneric.sol"; This code is inspired by and modified from Sushi's Master Chef contract. https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol */ -contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder { - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.UintSet; +contract StakerV2 is + Sweepable, + ReentrancyGuard, + IERC721Receiver, + ERC1155Holder +{ + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; - /// The public identifier for the right to add developer. - bytes32 public constant ADD_DEVELOPER = keccak256("ADD_DEVELOPER"); + /// The public identifier for the right to add developer. + bytes32 public constant ADD_DEVELOPER = keccak256("ADD_DEVELOPER"); - /// The public identifier for the right to lock developers. - bytes32 public constant LOCK_DEVELOPERS = keccak256("LOCK_DEVELOPERS"); + /// The public identifier for the right to lock developers. + bytes32 public constant LOCK_DEVELOPERS = keccak256("LOCK_DEVELOPERS"); - /// The public identifier for the right to set emissions. - bytes32 public constant SET_EMISSIONS = keccak256("SET_EMISSIONS"); + /// The public identifier for the right to set emissions. + bytes32 public constant SET_EMISSIONS = keccak256("SET_EMISSIONS"); - /// The public identifier for the right to lock token emissions. - bytes32 public constant LOCK_TOKEN_EMISSIONS = keccak256("LOCK_TOKEN_EMISSIONS"); + /// The public identifier for the right to lock token emissions. + bytes32 public constant LOCK_TOKEN_EMISSIONS = + keccak256("LOCK_TOKEN_EMISSIONS"); - /// The public identifier for the right to lock point emissions. - bytes32 public constant LOCK_POINT_EMISSIONS = keccak256("LOCK_POINT_EMISSIONS"); + /// The public identifier for the right to lock point emissions. + bytes32 public constant LOCK_POINT_EMISSIONS = + keccak256("LOCK_POINT_EMISSIONS"); - /// The public identifier for the right to configure boosters. - bytes32 public constant CONFIGURE_BOOSTERS = keccak256("CONFIGURE_BOOSTERS"); + /// The public identifier for the right to configure boosters. + bytes32 public constant CONFIGURE_BOOSTERS = + keccak256("CONFIGURE_BOOSTERS"); - /// The public identifier for the right to add pools. - bytes32 public constant ADD_POOL = keccak256("ADD_POOL"); + /// The public identifier for the right to add pools. + bytes32 public constant ADD_POOL = keccak256("ADD_POOL"); - /// The public identifier for the right to approve point spender. - bytes32 public constant APPROVE_POINT_SPENDER = keccak256("APPROVE_POINT_SPENDER"); + /// The public identifier for the right to approve point spender. + bytes32 public constant APPROVE_POINT_SPENDER = + keccak256("APPROVE_POINT_SPENDER"); - /// ERC721 interface ID to detect external contracts for Items staking. - bytes4 private constant INTERFACE_ERC721 = 0x80ac58cd; + /// ERC721 interface ID to detect external contracts for Items staking. + bytes4 private constant INTERFACE_ERC721 = 0x80ac58cd; - /// ERC1155 interface ID to detect external contracts for Items staking. - bytes4 private constant INTERFACE_ERC1155 = 0xd9b67a26; + /// ERC1155 interface ID to detect external contracts for Items staking. + bytes4 private constant INTERFACE_ERC1155 = 0xd9b67a26; - /// Descriptive name for this contract. - string public name; + /// Descriptive name for this contract. + string public name; - /// Token to disburse to stakers. - address public token; + /// Token to disburse to stakers. + address public token; - /// Flag for allowing contract owner to add or set developers. - bool public canAlterDevelopers; + /// Flag for allowing contract owner to add or set developers. + bool public canAlterDevelopers; - /// Developer addresses for finding shares in the 'developerShares'. - address[] public developerAddresses; + /// Developer addresses for finding shares in the 'developerShares'. + address[] public developerAddresses; - /** + /** @dev A mapping of developer addresses to their percent share of emissions. Share percentages are represented as 1/1000th of a percent. That is, a 1% share of emissions should map an address to 1000. */ - mapping (address => uint256) public developerShares; + mapping(address => uint256) public developerShares; - /// Flag for allowing contract owner to alter token emissions. - bool public canAlterTokenEmissionSchedule; + /// Flag for allowing contract owner to alter token emissions. + bool public canAlterTokenEmissionSchedule; - /// Flag for allowing contract owner to alter point emissions. - bool public canAlterPointEmissionSchedule; + /// Flag for allowing contract owner to alter point emissions. + bool public canAlterPointEmissionSchedule; - /** + /** This emission schedule maps a timestamp to the amount of tokens or points that should be disbursed starting at that timestamp per-second onwards. @param timeStamp if current time reaches timestamp, the rate is applied. @param rate measure of points or tokens emitted per-second. */ - struct EmissionPoint { - uint256 timeStamp; - uint256 rate; - } + struct EmissionPoint { + uint256 timeStamp; + uint256 rate; + } - /// The total number of 'EmissionPoint' as token emission events in the schedule. - uint256 public tokenEmissionEventsCount; + /// The total number of 'EmissionPoint' as token emission events in the schedule. + uint256 public tokenEmissionEventsCount; - /// The total number of 'EmissionPoint' as point emission events in the schedule. - uint256 public pointEmissionEventsCount; + /// The total number of 'EmissionPoint' as point emission events in the schedule. + uint256 public pointEmissionEventsCount; - /// Schedule of token 'EmissionPoint' for finding emission rate changes. - mapping (uint256 => EmissionPoint) public tokenEmissionEvents; + /// Schedule of token 'EmissionPoint' for finding emission rate changes. + mapping(uint256 => EmissionPoint) public tokenEmissionEvents; - /// Schedule of point 'EmissionPoint' for finding emission rate changes. - mapping (uint256 => EmissionPoint) public pointEmissionEvents; + /// Schedule of point 'EmissionPoint' for finding emission rate changes. + mapping(uint256 => EmissionPoint) public pointEmissionEvents; - /// @dev A max uint256 value that represents earliest timestamp for quick reference. - uint256 private MAX_INT = 2**256 - 1; + /// @dev A max uint256 value that represents earliest timestamp for quick reference. + uint256 private MAX_INT = 2**256 - 1; - /// Earliest possible token emission timestamp. - uint256 internal earliestTokenEmissionEvent; + /// Earliest possible token emission timestamp. + uint256 internal earliestTokenEmissionEvent; - /// Earliest possible point emission timestamp. - uint256 internal earliestPointEmissionEvent; + /// Earliest possible point emission timestamp. + uint256 internal earliestPointEmissionEvent; -/** + /** A struct containing the pool info. @param token address of the ERC20 asset that is being staked in the pool. @param tokenStrength the relative token emission strength of this pool. @@ -128,25 +137,25 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder 'tokenBoostedDeposit' and 'pointBoostedDeposit' do not change emission rate, but used to calculate perShare amount when there are boosters. */ - struct PoolInfo { - IERC20 token; - uint256 tokenStrength; - uint256 tokenBoostedDeposit; - uint256 tokensPerShare; - uint256 pointStrength; - uint256 pointBoostedDeposit; - uint256 pointsPerShare; - uint256 lastRewardEvent; - uint256[] boostInfo; - } - - /// Array for enumeration of the pools. - IERC20[] public poolTokens; - - /// Mapping of pools to 'PoolInfo' based on their deposit tokens. - mapping (IERC20 => PoolInfo) public poolInfo; - - /** + struct PoolInfo { + IERC20 token; + uint256 tokenStrength; + uint256 tokenBoostedDeposit; + uint256 tokensPerShare; + uint256 pointStrength; + uint256 pointBoostedDeposit; + uint256 pointsPerShare; + uint256 lastRewardEvent; + uint256[] boostInfo; + } + + /// Array for enumeration of the pools. + IERC20[] public poolTokens; + + /// Mapping of pools to 'PoolInfo' based on their deposit tokens. + mapping(IERC20 => PoolInfo) public poolInfo; + + /** A struct containing the Fungible Token Staker information. @param amount amount of the pool asset being provided by the user. @param tokenBoostedAmount tokens amount after boosts are applied. @@ -157,50 +166,50 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder pending reward = (user.amount * pool.tokensPerShare) - user.rewardDebt. @param pointPaid value of user's total point earnings paid out. */ - struct UserInfo { - uint256 amount; - uint256 tokenBoostedAmount; - uint256 pointBoostedAmount; - uint256 tokenRewards; - uint256 pointRewards; - uint256 tokenPaid; - uint256 pointPaid; - } + struct UserInfo { + uint256 amount; + uint256 tokenBoostedAmount; + uint256 pointBoostedAmount; + uint256 tokenRewards; + uint256 pointRewards; + uint256 tokenPaid; + uint256 pointPaid; + } - /// Stored information for each user staking in each pool. - mapping (IERC20 => mapping (address => UserInfo)) public userInfo; + /// Stored information for each user staking in each pool. + mapping(IERC20 => mapping(address => UserInfo)) public userInfo; - /// The total sum of the token strength of all pools. - uint256 public totalTokenStrength; + /// The total sum of the token strength of all pools. + uint256 public totalTokenStrength; - /// The total sum of the point strength of all pools. - uint256 public totalPointStrength; + /// The total sum of the point strength of all pools. + uint256 public totalPointStrength; - /// The total amount of the disbursed token ever emitted by this StakerV2. - uint256 public totalTokenDisbursed; + /// The total amount of the disbursed token ever emitted by this StakerV2. + uint256 public totalTokenDisbursed; - /// Users additionally accrue non-token points for participating via staking. - mapping (address => uint256) public userPoints; + /// Users additionally accrue non-token points for participating via staking. + mapping(address => uint256) public userPoints; - /// The amount of points belonging to a user already spent. - mapping (address => uint256) public userSpentPoints; + /// The amount of points belonging to a user already spent. + mapping(address => uint256) public userSpentPoints; - /// A map of all external addresses that are permitted to spend user points. - mapping (address => bool) public approvedPointSpenders; + /// A map of all external addresses that are permitted to spend user points. + mapping(address => bool) public approvedPointSpenders; - /** + /** The type of asset on which the boost is applied. @param Tokens boost is applied on the disburse token. @param Points boost is applied on the points. @param Both boost is applied on both. */ - enum AssetType { - Tokens, - Points, - Both - } + enum BoosterAssetType { + Tokens, + Points, + Both + } - /** + /** A booster struct, which stores information on the boost requirements. @param multiplier the rate which will act as a boost on basis points. A multiplier of Zero means, the booster is not set. @@ -208,23 +217,23 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param groupRequired (optional) specifies a group from Items contract as requirement for the boost. If 0, then any group or item. @param contractRequired contract that the required assets belong to. - @param assetType enum that specifies Tokens/Points to boost or both. + @param BoosterAssetType enum that specifies Tokens/Points to boost or both. */ - struct BoostInfo { - uint256 multiplier; - uint256 amountRequired; - uint256 groupRequired; - address contractRequired; - AssetType assetType; - } + struct BoostInfo { + uint256 multiplier; + uint256 amountRequired; + uint256 groupRequired; + address contractRequired; + BoosterAssetType assetType; + } - /// Mapping of Booster ID to its 'BoostInfo'. - mapping (uint256 => BoostInfo) public boostInfo; + /// Mapping of Booster ID to its 'BoostInfo'. + mapping(uint256 => BoostInfo) public boostInfo; - /// Number of boosters that are active. - uint256 public activeBoosters; + /// Number of boosters that are active. + uint256 public activeBoosters; - /** + /** A struct containing the Items staker information. @param totalItems total Items staked in this contract by Items staker. @param tokenIds actual ids of tokens mapped to booster Id. @@ -233,14 +242,14 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder Contract address at the time of unstaking is retreived from boostInfo. */ - struct ItemUserInfo { - uint256 totalItems; - mapping(uint256 => EnumerableSet.UintSet) tokenIds; - mapping(uint256 => uint256) amounts; - EnumerableSet.UintSet boosterIds; - } - - /** + struct ItemUserInfo { + uint256 totalItems; + mapping(uint256 => EnumerableSet.UintSet) tokenIds; + mapping(uint256 => uint256) amounts; + EnumerableSet.UintSet boosterIds; + } + + /** A struct as return parameter to get token Ids against a booster Id of a staker. Needed since EnumerableSets cannot have getters by default. @param boostersIds the booster Id to check the Items for. @@ -248,83 +257,106 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param amounts amount per token Id staked in a booster. @param totalItems total Items staked in this contract by Items staker. */ - struct GetItemUserInfo { - uint256 boosterId; - uint256[] tokenIds; - uint256[] amounts; - uint256 totalItems; - } - - /// Collection of Item stakers - mapping(address => ItemUserInfo) private itemUserInfo; - - /// Items staked in this contract. - uint256 public totalItemStakes; - - /// Event for depositing Fungible assets. - event Deposit(address indexed user, IERC20 indexed token, uint256 amount); - - /// Event for withdrawing Fungible assets. - event Withdraw(address indexed user, IERC20 indexed token, uint256 amount); - - /// Event for claiming rewards from Fungible assets. - event Claim(address indexed user, IERC20 indexed token, uint256 tokenRewards, uint256 pointRewards); - - /// Event for staking non fungible items for boosters. - event StakeItemBatch(address indexed user, IERC20 indexed token, uint256 boosterId); - - /// Event for unstaking non fungible items from boosters. - event UnstakeItemBatch(address indexed user, IERC20 indexed token, uint256 boosterId); - - /// An event for tracking when a user has spent points. - event SpentPoints(address indexed source, address indexed user, uint256 amount); + struct GetItemUserInfo { + uint256 boosterId; + uint256[] tokenIds; + uint256[] amounts; + uint256 totalItems; + } - /** + /// Collection of Item stakers + mapping(address => ItemUserInfo) private itemUserInfo; + + /// Items staked in this contract. + uint256 public totalItemStakes; + + /// Event for depositing Fungible assets. + event Deposit(address indexed user, IERC20 indexed token, uint256 amount); + + /// Event for withdrawing Fungible assets. + event Withdraw(address indexed user, IERC20 indexed token, uint256 amount); + + /// Event for claiming rewards from Fungible assets. + event Claim( + address indexed user, + IERC20 indexed token, + uint256 tokenRewards, + uint256 pointRewards + ); + + /// Event for staking non fungible items for boosters. + event StakeItemBatch( + address indexed user, + IERC20 indexed token, + uint256 boosterId + ); + + /// Event for unstaking non fungible items from boosters. + event UnstakeItemBatch( + address indexed user, + IERC20 indexed token, + uint256 boosterId + ); + + /// An event for tracking when a user has spent points. + event SpentPoints( + address indexed source, + address indexed user, + uint256 amount + ); + + /** Deploy a new StakerV2 contract with a name and the token to disburse. @param _name the name of the StakerV2 contract. @param _token the token to reward stakers in this contract with. */ - constructor(address _owner, string memory _name, address _token) { + constructor( + address _owner, + string memory _name, + address _token + ) { + if (_owner != owner()) { + transferOwnership(_owner); + } - if (_owner != owner()) { - transferOwnership(_owner); + name = _name; + token = _token; + canAlterDevelopers = true; + canAlterTokenEmissionSchedule = true; + canAlterPointEmissionSchedule = true; + earliestTokenEmissionEvent = MAX_INT; + earliestPointEmissionEvent = MAX_INT; } - name = _name; - token = _token; - canAlterDevelopers = true; - canAlterTokenEmissionSchedule = true; - canAlterPointEmissionSchedule = true; - earliestTokenEmissionEvent = MAX_INT; - earliestPointEmissionEvent = MAX_INT; - } - - /** + /** Add a new developer to the StakerV2 or overwrite an existing one. This operation requires that developer address addition is not locked. @param _developerAddress the additional developer's address. @param _share the share in 1/1000th of a percent of each token emission sent to this new developer. */ - function addDeveloper(address _developerAddress, uint256 _share) external hasValidPermit(UNIVERSAL, ADD_DEVELOPER) { - - require(canAlterDevelopers, - "Devs locked."); - developerAddresses.push(_developerAddress); - developerShares[_developerAddress] = _share; - } + function addDeveloper(address _developerAddress, uint256 _share) + external + hasValidPermit(UNIVERSAL, ADD_DEVELOPER) + { + require(canAlterDevelopers, "Devs locked."); + developerAddresses.push(_developerAddress); + developerShares[_developerAddress] = _share; + } - /** + /** Permanently forfeits owner ability to alter the state of StakerV2 developers. Once called, this function is intended to give peace of mind to the StakerV2's developers and community that the fee structure is now immutable. */ - function lockDevelopers() external hasValidPermit(UNIVERSAL, LOCK_DEVELOPERS) { - - canAlterDevelopers = false; - } + function lockDevelopers() + external + hasValidPermit(UNIVERSAL, LOCK_DEVELOPERS) + { + canAlterDevelopers = false; + } - /** + /** A developer may at any time update their address or voluntarily reduce their share of emissions by calling this function from their current address. Note that updating a developer's share to zero effectively removes them. @@ -332,140 +364,138 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _newShare the new share in 1/1000th of a percent of each token emission sent to this developer. */ - function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) external { - - uint256 developerShare = developerShares[msg.sender]; - require(developerShare > 0, - "0 shares."); - require(_newShare <= developerShare, - "Increase unsupported."); - developerShares[msg.sender] = 0; - developerAddresses.push(_newDeveloperAddress); - developerShares[_newDeveloperAddress] = _newShare; - } - - /** + function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) + external + { + uint256 developerShare = developerShares[msg.sender]; + require(developerShare > 0, "0 shares."); + require(_newShare <= developerShare, "Increase unsupported."); + developerShares[msg.sender] = 0; + developerAddresses.push(_newDeveloperAddress); + developerShares[_newDeveloperAddress] = _newShare; + } + + /** Set new emission details to the StakerV2 or overwrite existing ones. This operation requires that emission schedule alteration is not locked. @param _tokenSchedule an array of EmissionPoints defining the token schedule. @param _pointSchedule an array of EmissionPoints defining the point schedule. */ - function setEmissions(EmissionPoint[] memory _tokenSchedule, EmissionPoint[] memory _pointSchedule) external hasValidPermit(UNIVERSAL, SET_EMISSIONS) { - - if (_tokenSchedule.length > 0) { - require(canAlterTokenEmissionSchedule, - "Token emissions locked."); - tokenEmissionEventsCount = _tokenSchedule.length; - for (uint256 i = 0; i < tokenEmissionEventsCount; i++) { - tokenEmissionEvents[i] = _tokenSchedule[i]; - if (earliestTokenEmissionEvent > _tokenSchedule[i].timeStamp) { - earliestTokenEmissionEvent = _tokenSchedule[i].timeStamp; + function setEmissions( + EmissionPoint[] memory _tokenSchedule, + EmissionPoint[] memory _pointSchedule + ) external hasValidPermit(UNIVERSAL, SET_EMISSIONS) { + if (_tokenSchedule.length > 0) { + require(canAlterTokenEmissionSchedule, "Token emissions locked."); + tokenEmissionEventsCount = _tokenSchedule.length; + for (uint256 i = 0; i < tokenEmissionEventsCount; i++) { + tokenEmissionEvents[i] = _tokenSchedule[i]; + if (earliestTokenEmissionEvent > _tokenSchedule[i].timeStamp) { + earliestTokenEmissionEvent = _tokenSchedule[i].timeStamp; + } + } } - } - } - require(tokenEmissionEventsCount > 0, - "Set token emissions."); - - if (_pointSchedule.length > 0) { - require(canAlterPointEmissionSchedule, - "Point emissiosn locked."); - pointEmissionEventsCount = _pointSchedule.length; - for (uint256 i = 0; i < pointEmissionEventsCount; i++) { - pointEmissionEvents[i] = _pointSchedule[i]; - if (earliestPointEmissionEvent > _pointSchedule[i].timeStamp) { - earliestPointEmissionEvent = _pointSchedule[i].timeStamp; + require(tokenEmissionEventsCount > 0, "Set token emissions."); + + if (_pointSchedule.length > 0) { + require(canAlterPointEmissionSchedule, "Point emissiosn locked."); + pointEmissionEventsCount = _pointSchedule.length; + for (uint256 i = 0; i < pointEmissionEventsCount; i++) { + pointEmissionEvents[i] = _pointSchedule[i]; + if (earliestPointEmissionEvent > _pointSchedule[i].timeStamp) { + earliestPointEmissionEvent = _pointSchedule[i].timeStamp; + } + } } - } + require(pointEmissionEventsCount > 0, "Set point emissions."); } - require(pointEmissionEventsCount > 0, - "Set point emissions."); - } - /** + /** Permanently forfeits owner ability to alter the emission schedule. Once called, this function is intended to give peace of mind to the StakerV2's developers and community that the inflation rate is now immutable. */ - function lockTokenEmissions() external hasValidPermit(UNIVERSAL, LOCK_TOKEN_EMISSIONS) { - - canAlterTokenEmissionSchedule = false; - } + function lockTokenEmissions() + external + hasValidPermit(UNIVERSAL, LOCK_TOKEN_EMISSIONS) + { + canAlterTokenEmissionSchedule = false; + } - /** + /** Permanently forfeits owner ability to alter the emission schedule. Once called, this function is intended to give peace of mind to the StakerV2's developers and community that the inflation rate is now immutable. */ - function lockPointEmissions() external hasValidPermit(UNIVERSAL, LOCK_POINT_EMISSIONS) { - - canAlterPointEmissionSchedule = false; - } + function lockPointEmissions() + external + hasValidPermit(UNIVERSAL, LOCK_POINT_EMISSIONS) + { + canAlterPointEmissionSchedule = false; + } - /** + /** Returns the length of the developer address array. @return the length of the developer address array. */ - function getDeveloperCount() external view returns (uint256) { - - return developerAddresses.length; - } + function getDeveloperCount() external view returns (uint256) { + return developerAddresses.length; + } - /** + /** Returns the length of the staking pool array. @return the length of the staking pool array. */ - function getPoolCount() external view returns (uint256) { - - return poolTokens.length; - } + function getPoolCount() external view returns (uint256) { + return poolTokens.length; + } - /** + /** Returns the amount of token that has not been disbursed by the StakerV2 yet. @return the amount of token that has not been disbursed by the StakerV2 yet. */ - function getRemainingToken() external view returns (uint256) { - - return IERC20(token).balanceOf(address(this)); - } + function getRemainingToken() external view returns (uint256) { + return IERC20(token).balanceOf(address(this)); + } - /** + /** Create or edit boosters in batch with boost parameters @param _ids array of booster IDs. @param _boostInfo array of boostInfo. Should not be reconfigured if it was made public for staking Items. */ - function configureBoostersBatch(uint256[] memory _ids, BoostInfo[] memory _boostInfo) external hasValidPermit(UNIVERSAL, CONFIGURE_BOOSTERS) { - - require(_boostInfo.length > 0, - "0 BoostInfo."); - require(_ids.length == _boostInfo.length, - "Length mismatch."); - - for (uint256 i = 0; i < _boostInfo.length; i++) { - if (_boostInfo[i].multiplier == 0) { - revert("0 Multiplier."); - } else if (_boostInfo[i].amountRequired == 0) { - revert("0 Amount."); - } else if (_boostInfo[i].contractRequired == address(0)) { - revert("0 address."); - } - - if (boostInfo[i].multiplier == 0 && _boostInfo[i].multiplier != 0) { - activeBoosters++; - } - - boostInfo[_ids[i]] = BoostInfo({ - multiplier: _boostInfo[i].multiplier, - amountRequired: _boostInfo[i].amountRequired, - groupRequired: _boostInfo[i].groupRequired, - contractRequired: _boostInfo[i].contractRequired, - assetType: _boostInfo[i].assetType - }); + function configureBoostersBatch( + uint256[] memory _ids, + BoostInfo[] memory _boostInfo + ) external hasValidPermit(UNIVERSAL, CONFIGURE_BOOSTERS) { + require(_boostInfo.length > 0, "0 BoostInfo."); + require(_ids.length == _boostInfo.length, "Length mismatch."); + + for (uint256 i = 0; i < _boostInfo.length; i++) { + if (_boostInfo[i].multiplier == 0) { + revert("0 Multiplier."); + } else if (_boostInfo[i].amountRequired == 0) { + revert("0 Amount."); + } else if (_boostInfo[i].contractRequired == address(0)) { + revert("0 address."); + } + + if (boostInfo[i].multiplier == 0 && _boostInfo[i].multiplier != 0) { + activeBoosters++; + } + + boostInfo[_ids[i]] = BoostInfo({ + multiplier: _boostInfo[i].multiplier, + amountRequired: _boostInfo[i].amountRequired, + groupRequired: _boostInfo[i].groupRequired, + contractRequired: _boostInfo[i].contractRequired, + assetType: _boostInfo[i].assetType + }); + } } - } - /** + /** Allows the contract owner to add a new asset pool to the Staker or overwrite an existing one. @param _token the address of the asset to base this staking pool off of. @@ -473,115 +503,152 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _pointStrength the relative strength of the new asset for earning points. @param _boostInfo collection of boosters the pool supports. */ - function addPool(IERC20 _token, uint256 _tokenStrength, uint256 _pointStrength, uint256[] calldata _boostInfo) external hasValidPermit(UNIVERSAL, ADD_POOL) { - - require(tokenEmissionEventsCount > 0 && pointEmissionEventsCount > 0, - "Emissions required."); - require(address(_token) != address(token), - "Disburse token."); - require(_tokenStrength > 0 && _pointStrength > 0, - "Strength/s are Zero."); - - uint256 lastTokenRewardTime = block.timestamp > earliestTokenEmissionEvent ? block.timestamp : earliestTokenEmissionEvent; - uint256 lastPointRewardTime = block.timestamp > earliestPointEmissionEvent ? block.timestamp : earliestPointEmissionEvent; - uint256 lastRewardEvent = lastTokenRewardTime > lastPointRewardTime ? lastTokenRewardTime : lastPointRewardTime; - if (address(poolInfo[_token].token) == address(0)) { - poolTokens.push(_token); - totalTokenStrength = totalTokenStrength + _tokenStrength; - totalPointStrength = totalPointStrength + _pointStrength; - poolInfo[_token] = PoolInfo({ - token: _token, - tokenStrength: _tokenStrength, - tokenBoostedDeposit: 0, - tokensPerShare: 0, - pointStrength: _pointStrength, - pointBoostedDeposit: 0, - pointsPerShare: 0, - lastRewardEvent: lastRewardEvent, - boostInfo: _boostInfo - }); - } else { - totalTokenStrength = (totalTokenStrength - poolInfo[_token].tokenStrength) + _tokenStrength; - poolInfo[_token].tokenStrength = _tokenStrength; - totalPointStrength = (totalPointStrength - poolInfo[_token].pointStrength) + _pointStrength; - poolInfo[_token].pointStrength = _pointStrength; - - // Append boosters by avoid writing to storage directly in a loop to avoid costs - uint256[] memory boosters = new uint256[](poolInfo[_token].boostInfo.length + _boostInfo.length); - for (uint256 i = 0; i < poolInfo[_token].boostInfo.length; i++) { - boosters[i] = poolInfo[_token].boostInfo[i]; - } - for (uint256 i = 0; i < _boostInfo.length; i++) { - boosters[i + poolInfo[_token].boostInfo.length] = _boostInfo[i]; - } - PoolInfo storage pool = poolInfo[_token]; - pool.boostInfo = boosters; // Appended boosters + function addPool( + IERC20 _token, + uint256 _tokenStrength, + uint256 _pointStrength, + uint256[] calldata _boostInfo + ) external hasValidPermit(UNIVERSAL, ADD_POOL) { + require( + tokenEmissionEventsCount > 0 && pointEmissionEventsCount > 0, + "Emissions required." + ); + require(address(_token) != address(token), "Disburse token."); + require( + _tokenStrength > 0 && _pointStrength > 0, + "Strength/s are Zero." + ); + + uint256 lastTokenRewardTime = block.timestamp > + earliestTokenEmissionEvent + ? block.timestamp + : earliestTokenEmissionEvent; + uint256 lastPointRewardTime = block.timestamp > + earliestPointEmissionEvent + ? block.timestamp + : earliestPointEmissionEvent; + uint256 lastRewardEvent = lastTokenRewardTime > lastPointRewardTime + ? lastTokenRewardTime + : lastPointRewardTime; + if (address(poolInfo[_token].token) == address(0)) { + poolTokens.push(_token); + totalTokenStrength = totalTokenStrength + _tokenStrength; + totalPointStrength = totalPointStrength + _pointStrength; + poolInfo[_token] = PoolInfo({ + token: _token, + tokenStrength: _tokenStrength, + tokenBoostedDeposit: 0, + tokensPerShare: 0, + pointStrength: _pointStrength, + pointBoostedDeposit: 0, + pointsPerShare: 0, + lastRewardEvent: lastRewardEvent, + boostInfo: _boostInfo + }); + } else { + totalTokenStrength = + (totalTokenStrength - poolInfo[_token].tokenStrength) + + _tokenStrength; + poolInfo[_token].tokenStrength = _tokenStrength; + totalPointStrength = + (totalPointStrength - poolInfo[_token].pointStrength) + + _pointStrength; + poolInfo[_token].pointStrength = _pointStrength; + + // Append boosters by avoid writing to storage directly in a loop to avoid costs + uint256[] memory boosters = new uint256[]( + poolInfo[_token].boostInfo.length + _boostInfo.length + ); + for (uint256 i = 0; i < poolInfo[_token].boostInfo.length; i++) { + boosters[i] = poolInfo[_token].boostInfo[i]; + } + for (uint256 i = 0; i < _boostInfo.length; i++) { + boosters[i + poolInfo[_token].boostInfo.length] = _boostInfo[i]; + } + PoolInfo storage pool = poolInfo[_token]; + pool.boostInfo = boosters; // Appended boosters + } } - } - /** + /** Uses the emission schedule to calculate the total amount of staking reward token that was emitted between two specified timestamps. @param _fromTime the time to begin calculating emissions from. @param _toTime the time to calculate total emissions up to. */ - function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) internal view returns (uint256) { - - require(_toTime > _fromTime, - "Invalid order."); - uint256 totalEmittedTokens = 0; - uint256 workingRate = 0; - uint256 workingTime = _fromTime; - for (uint256 i = 0; i < tokenEmissionEventsCount; ++i) { - uint256 emissionTime = tokenEmissionEvents[i].timeStamp; - uint256 emissionRate = tokenEmissionEvents[i].rate; - if (_toTime < emissionTime) { - totalEmittedTokens = totalEmittedTokens + ((_toTime - workingTime) * workingRate); + function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + require(_toTime > _fromTime, "Invalid order."); + uint256 totalEmittedTokens = 0; + uint256 workingRate = 0; + uint256 workingTime = _fromTime; + for (uint256 i = 0; i < tokenEmissionEventsCount; ++i) { + uint256 emissionTime = tokenEmissionEvents[i].timeStamp; + uint256 emissionRate = tokenEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedTokens = + totalEmittedTokens + + ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } else if (workingTime < emissionTime) { + totalEmittedTokens = + totalEmittedTokens + + ((emissionTime - workingTime) * workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + } + if (workingTime < _toTime) { + totalEmittedTokens = + totalEmittedTokens + + ((_toTime - workingTime) * workingRate); + } return totalEmittedTokens; - } else if (workingTime < emissionTime) { - totalEmittedTokens = totalEmittedTokens + ((emissionTime - workingTime) * workingRate); - workingTime = emissionTime; - } - workingRate = emissionRate; } - if (workingTime < _toTime) { - totalEmittedTokens = totalEmittedTokens + ((_toTime - workingTime) * workingRate); - } - return totalEmittedTokens; - } - /** + /** Uses the emission schedule to calculate the total amount of points emitted between two specified timestamps. @param _fromTime the time to begin calculating emissions from. @param _toTime the time to calculate total emissions up to. */ - function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) public view returns (uint256) { - - require(_toTime > _fromTime, - "Invalid order."); - uint256 totalEmittedPoints = 0; - uint256 workingRate = 0; - uint256 workingTime = _fromTime; - for (uint256 i = 0; i < pointEmissionEventsCount; ++i) { - uint256 emissionTime = pointEmissionEvents[i].timeStamp; - uint256 emissionRate = pointEmissionEvents[i].rate; - if (_toTime < emissionTime) { - totalEmittedPoints = totalEmittedPoints + ((_toTime - workingTime) * workingRate); + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + public + view + returns (uint256) + { + require(_toTime > _fromTime, "Invalid order."); + uint256 totalEmittedPoints = 0; + uint256 workingRate = 0; + uint256 workingTime = _fromTime; + for (uint256 i = 0; i < pointEmissionEventsCount; ++i) { + uint256 emissionTime = pointEmissionEvents[i].timeStamp; + uint256 emissionRate = pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints = + totalEmittedPoints + + ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints = + totalEmittedPoints + + ((emissionTime - workingTime) * workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + } + if (workingTime < _toTime) { + totalEmittedPoints = + totalEmittedPoints + + ((_toTime - workingTime) * workingRate); + } return totalEmittedPoints; - } else if (workingTime < emissionTime) { - totalEmittedPoints = totalEmittedPoints + ((emissionTime - workingTime) * workingRate); - workingTime = emissionTime; - } - workingRate = emissionRate; - } - if (workingTime < _toTime) { - totalEmittedPoints = totalEmittedPoints + ((_toTime - workingTime) * workingRate); } - return totalEmittedPoints; - } - /** + /** A function to easily see the amount of token rewards pending for a user on a given pool. Returns the pending reward token amount. @param _token The address of a particular staking pool asset to check for a @@ -589,23 +656,32 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _user the user address to check for a pending reward. @return the pending reward token amount. */ - function getPendingTokens(IERC20 _token, address _user) public view returns (uint256) { - - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][_user]; - uint256 tokensPerShare = pool.tokensPerShare; - uint256 tokenBoostedDeposit = pool.tokenBoostedDeposit; + function getPendingTokens(IERC20 _token, address _user) + public + view + returns (uint256) + { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][_user]; + uint256 tokensPerShare = pool.tokensPerShare; + uint256 tokenBoostedDeposit = pool.tokenBoostedDeposit; + + if (block.timestamp > pool.lastRewardEvent && tokenBoostedDeposit > 0) { + uint256 totalEmittedTokens = getTotalEmittedTokens( + pool.lastRewardEvent, + block.timestamp + ); + uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / + totalTokenStrength) * 1e12; + tokensPerShare = + tokensPerShare + + (tokensReward / tokenBoostedDeposit); + } - if (block.timestamp > pool.lastRewardEvent && tokenBoostedDeposit > 0) { - uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardEvent, block.timestamp); - uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / totalTokenStrength) * 1e12; - tokensPerShare = tokensPerShare + (tokensReward / tokenBoostedDeposit); + return ((user.amount * tokensPerShare) / 1e12) - user.tokenPaid; } - return ((user.amount * tokensPerShare) / 1e12) - user.tokenPaid; - } - - /** + /** A function to easily see the amount of point rewards pending for a user on a given pool. Returns the pending reward point amount. @param _token The address of a particular staking pool asset to check for a @@ -613,105 +689,122 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _user The user address to check for a pending reward. @return the pending reward token amount. */ - function getPendingPoints(IERC20 _token, address _user) public view returns (uint256) { - - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][_user]; - uint256 pointsPerShare = pool.pointsPerShare; - uint256 pointBoostedDeposit = pool.pointBoostedDeposit; + function getPendingPoints(IERC20 _token, address _user) + public + view + returns (uint256) + { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][_user]; + uint256 pointsPerShare = pool.pointsPerShare; + uint256 pointBoostedDeposit = pool.pointBoostedDeposit; + + if (block.timestamp > pool.lastRewardEvent && pointBoostedDeposit > 0) { + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardEvent, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + totalPointStrength) * 1e30; + pointsPerShare = + pointsPerShare + + (pointsReward / pointBoostedDeposit); + } - if (block.timestamp > pool.lastRewardEvent && pointBoostedDeposit > 0) { - uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardEvent, block.timestamp); - uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / totalPointStrength) * 1e30; - pointsPerShare = pointsPerShare + (pointsReward / pointBoostedDeposit); + return ((user.amount * pointsPerShare) / 1e30) - user.pointPaid; } - return ((user.amount * pointsPerShare) / 1e30) - user.pointPaid; - } - - /** + /** Return the number of points that the user has available to spend. @return the number of points that the user has available to spend. */ - function getAvailablePoints(address _user) public view returns (uint256) { - - uint256 concreteTotal = userPoints[_user]; - uint256 pendingTotal = 0; - for (uint256 i = 0; i < poolTokens.length; ++i) { - IERC20 poolToken = poolTokens[i]; - uint256 _pendingPoints = getPendingPoints(poolToken, _user); - pendingTotal = pendingTotal + _pendingPoints; + function getAvailablePoints(address _user) public view returns (uint256) { + uint256 concreteTotal = userPoints[_user]; + uint256 pendingTotal = 0; + for (uint256 i = 0; i < poolTokens.length; ++i) { + IERC20 poolToken = poolTokens[i]; + uint256 _pendingPoints = getPendingPoints(poolToken, _user); + pendingTotal = pendingTotal + _pendingPoints; + } + uint256 spentTotal = userSpentPoints[_user]; + return (concreteTotal + pendingTotal) - spentTotal; } - uint256 spentTotal = userSpentPoints[_user]; - return (concreteTotal + pendingTotal) - spentTotal; - } - /** + /** Return the total number of points that the user has ever accrued. @return the total number of points that the user has ever accrued. */ - function getTotalPoints(address _user) external view returns (uint256) { - - uint256 concreteTotal = userPoints[_user]; - uint256 pendingTotal = 0; - for (uint256 i = 0; i < poolTokens.length; ++i) { - IERC20 poolToken = poolTokens[i]; - uint256 _pendingPoints = getPendingPoints(poolToken, _user); - pendingTotal = pendingTotal + _pendingPoints; + function getTotalPoints(address _user) external view returns (uint256) { + uint256 concreteTotal = userPoints[_user]; + uint256 pendingTotal = 0; + for (uint256 i = 0; i < poolTokens.length; ++i) { + IERC20 poolToken = poolTokens[i]; + uint256 _pendingPoints = getPendingPoints(poolToken, _user); + pendingTotal = pendingTotal + _pendingPoints; + } + return concreteTotal + pendingTotal; } - return concreteTotal + pendingTotal; - } - /** + /** Return the total number of points that the user has ever spent. @return the total number of points that the user has ever spent. */ - function getSpentPoints(address _user) external view returns (uint256) { - - return userSpentPoints[_user]; - } + function getSpentPoints(address _user) external view returns (uint256) { + return userSpentPoints[_user]; + } - /** + /** Update the pool corresponding to the specified token address. @param _token the address of the asset to update the corresponding pool for. */ - function updatePool(IERC20 _token) internal { + function updatePool(IERC20 _token) internal { + PoolInfo storage pool = poolInfo[_token]; + if (block.timestamp <= pool.lastRewardEvent) { + return; + } + uint256 poolTokenSupply = pool.token.balanceOf(address(this)); + if (poolTokenSupply <= 0) { + pool.lastRewardEvent = block.timestamp; + return; + } - PoolInfo storage pool = poolInfo[_token]; - if (block.timestamp <= pool.lastRewardEvent) { - return; - } - uint256 poolTokenSupply = pool.token.balanceOf(address(this)); - if (poolTokenSupply <= 0) { - pool.lastRewardEvent = block.timestamp; - return; - } + // Calculate token and point rewards for this pool. + uint256 totalEmittedTokens = getTotalEmittedTokens( + pool.lastRewardEvent, + block.timestamp + ); + uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / + totalTokenStrength) * 1e12; + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardEvent, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + totalPointStrength) * 1e30; + + // Directly pay developers their corresponding share of tokens and points. + for (uint256 i = 0; i < developerAddresses.length; ++i) { + address developer = developerAddresses[i]; + uint256 share = developerShares[developer]; + uint256 devTokens = (tokensReward * share) / 100000; + tokensReward = tokensReward - devTokens; + uint256 devPoints = (pointsReward * share) / 100000; + pointsReward = pointsReward - devPoints; + IERC20(token).safeTransfer(developer, devTokens / 1e12); + userPoints[developer] = userPoints[developer] + (devPoints / 1e30); + } - // Calculate token and point rewards for this pool. - uint256 totalEmittedTokens = getTotalEmittedTokens(pool.lastRewardEvent, block.timestamp); - uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / totalTokenStrength) * 1e12; - uint256 totalEmittedPoints = getTotalEmittedPoints(pool.lastRewardEvent, block.timestamp); - uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / totalPointStrength) * 1e30; - - // Directly pay developers their corresponding share of tokens and points. - for (uint256 i = 0; i < developerAddresses.length; ++i) { - address developer = developerAddresses[i]; - uint256 share = developerShares[developer]; - uint256 devTokens = (tokensReward * share) / 100000; - tokensReward = tokensReward - devTokens; - uint256 devPoints = (pointsReward * share) / 100000; - pointsReward = pointsReward - devPoints; - IERC20(token).safeTransfer(developer, devTokens / 1e12); - userPoints[developer] = userPoints[developer] + (devPoints / 1e30); + // Update the pool rewards per share to pay users the amount remaining. + pool.tokensPerShare = + pool.tokensPerShare + + (tokensReward / poolInfo[_token].tokenBoostedDeposit); + pool.pointsPerShare = + pool.pointsPerShare + + (pointsReward / poolInfo[_token].pointBoostedDeposit); + pool.lastRewardEvent = block.timestamp; } - // Update the pool rewards per share to pay users the amount remaining. - pool.tokensPerShare = pool.tokensPerShare + (tokensReward / poolInfo[_token].tokenBoostedDeposit); - pool.pointsPerShare = pool.pointsPerShare + (pointsReward / poolInfo[_token].pointBoostedDeposit); - pool.lastRewardEvent = block.timestamp; - } - - /** + /** Private helper function to update the deposits based on new shares. @param _amount base amount of the new boosted amounts. @param _token the deposit token of the pool. @@ -720,34 +813,47 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _isDeposit flag that represents the caller function. 0 is for deposit, 1 is for withdraw, other value represents no amount update. */ - function updateDeposits(uint256 _amount, IERC20 _token, PoolInfo storage _pool, UserInfo storage _user, uint8 _isDeposit) private { - - if (_user.amount > 0) { - uint256 pendingTokens = ((_user.tokenBoostedAmount * _pool.tokensPerShare) / 1e12) - _user.tokenPaid; - uint256 pendingPoints = ((_user.pointBoostedAmount * _pool.pointsPerShare) / 1e30) - _user.pointPaid; - _user.tokenRewards += pendingTokens; - _user.pointRewards += pendingPoints; - totalTokenDisbursed = totalTokenDisbursed + pendingTokens; - _pool.tokenBoostedDeposit -= _user.tokenBoostedAmount; - _pool.pointBoostedDeposit -= _user.pointBoostedAmount; - } + function updateDeposits( + uint256 _amount, + IERC20 _token, + PoolInfo storage _pool, + UserInfo storage _user, + uint8 _isDeposit + ) private { + if (_user.amount > 0) { + uint256 pendingTokens = ((_user.tokenBoostedAmount * + _pool.tokensPerShare) / 1e12) - _user.tokenPaid; + uint256 pendingPoints = ((_user.pointBoostedAmount * + _pool.pointsPerShare) / 1e30) - _user.pointPaid; + _user.tokenRewards += pendingTokens; + _user.pointRewards += pendingPoints; + totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + _pool.tokenBoostedDeposit -= _user.tokenBoostedAmount; + _pool.pointBoostedDeposit -= _user.pointBoostedAmount; + } - if (_isDeposit == 0) { // Flag for Deposit - _user.amount += _amount; - } else if(_isDeposit == 1) { // Flag for Withdraw - _user.amount -= _amount; - } - - _user.tokenBoostedAmount = applyBoosts(_user.amount, _token, true); - _user.pointBoostedAmount = applyBoosts(_user.amount, _token, false); - _pool.tokenBoostedDeposit += _user.tokenBoostedAmount; - _pool.pointBoostedDeposit += _user.pointBoostedAmount; + if (_isDeposit == 0) { + // Flag for Deposit + _user.amount += _amount; + } else if (_isDeposit == 1) { + // Flag for Withdraw + _user.amount -= _amount; + } - _user.tokenPaid = (_user.tokenBoostedAmount * _pool.tokensPerShare) / 1e12; - _user.pointPaid = (_user.pointBoostedAmount * _pool.pointsPerShare) / 1e30; - } + _user.tokenBoostedAmount = applyBoosts(_user.amount, _token, true); + _user.pointBoostedAmount = applyBoosts(_user.amount, _token, false); + _pool.tokenBoostedDeposit += _user.tokenBoostedAmount; + _pool.pointBoostedDeposit += _user.pointBoostedAmount; + + _user.tokenPaid = + (_user.tokenBoostedAmount * _pool.tokensPerShare) / + 1e12; + _user.pointPaid = + (_user.pointBoostedAmount * _pool.pointsPerShare) / + 1e30; + } - /** + /** Private helper function that applies boosts on deposits for Item staking. (amount * multiplier ) / 10000, where multiplier is in basis points. (20 * 20000) / 10000 = 40 => 2x boost @@ -756,103 +862,111 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _isToken is true if '_unboosted' argument is of token type. @return _boosted return value with applied boosts. */ - function applyBoosts(uint256 _unboosted, IERC20 _token, bool _isToken) internal view returns(uint256 _boosted) { - - if (_unboosted <= 0) { - return 0; - } else if (poolInfo[_token].boostInfo.length == 0) { - return _unboosted; - } else if (itemUserInfo[_msgSender()].boosterIds.length() == 0) { - return _unboosted; - } + function applyBoosts( + uint256 _unboosted, + IERC20 _token, + bool _isToken + ) internal view returns (uint256 _boosted) { + if (_unboosted <= 0) { + return 0; + } else if (poolInfo[_token].boostInfo.length == 0) { + return _unboosted; + } else if (itemUserInfo[_msgSender()].boosterIds.length() == 0) { + return _unboosted; + } - _boosted = _unboosted; - BoostInfo memory booster; - PoolInfo memory pool = poolInfo[_token]; - ItemUserInfo storage staker = itemUserInfo[_msgSender()]; - - // Iterate through all the boosters that the pool supports - for(uint256 i = 0; i < pool.boostInfo.length; i++) { - booster = boostInfo[pool.boostInfo[i]]; - if (staker.boosterIds.contains(pool.boostInfo[i])) { - if (booster.assetType == AssetType.Tokens && _isToken) { - _boosted += (_unboosted * booster.multiplier)/10000; - } else if (booster.assetType == AssetType.Points && !_isToken) { - _boosted += (_unboosted * booster.multiplier)/10000; - } else if (booster.assetType == AssetType.Both) { - _boosted += (_unboosted * booster.multiplier)/10000; + _boosted = _unboosted; + BoostInfo memory booster; + PoolInfo memory pool = poolInfo[_token]; + ItemUserInfo storage staker = itemUserInfo[_msgSender()]; + + // Iterate through all the boosters that the pool supports + for (uint256 i = 0; i < pool.boostInfo.length; i++) { + booster = boostInfo[pool.boostInfo[i]]; + if (staker.boosterIds.contains(pool.boostInfo[i])) { + if (booster.assetType == BoosterAssetType.Tokens && _isToken) { + _boosted += (_unboosted * booster.multiplier) / 10000; + } else if ( + booster.assetType == BoosterAssetType.Points && !_isToken + ) { + _boosted += (_unboosted * booster.multiplier) / 10000; + } else if (booster.assetType == BoosterAssetType.Both) { + _boosted += (_unboosted * booster.multiplier) / 10000; + } + } } - } } - } - /** + /** Deposit some particular assets to a particular pool on the Staker. @param _token the asset to stake into its corresponding pool. @param _amount the amount of the provided asset to stake. */ - function deposit(IERC20 _token, uint256 _amount) external nonReentrant { - - PoolInfo storage pool = poolInfo[_token]; - require(pool.tokenStrength > 0 || pool.pointStrength > 0, - "Inactive pool."); - UserInfo storage user = userInfo[_token][msg.sender]; - - updatePool(_token); - updateDeposits(_amount, _token, pool, user, 0); - - pool.token.safeTransferFrom(msg.sender, address(this), _amount); - emit Deposit(msg.sender, _token, _amount); - } + function deposit(IERC20 _token, uint256 _amount) external nonReentrant { + PoolInfo storage pool = poolInfo[_token]; + require( + pool.tokenStrength > 0 || pool.pointStrength > 0, + "Inactive pool." + ); + UserInfo storage user = userInfo[_token][msg.sender]; + + updatePool(_token); + updateDeposits(_amount, _token, pool, user, 0); + + pool.token.safeTransferFrom(msg.sender, address(this), _amount); + emit Deposit(msg.sender, _token, _amount); + } - /** + /** Withdraw some particular assets from a particular pool on the Staker. @param _token the asset to withdraw from its corresponding staking pool. @param _amount the amount of the provided asset to withdraw. */ - function withdraw(IERC20 _token, uint256 _amount) external nonReentrant { - - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][msg.sender]; - require(user.amount >= _amount, - "Invalid amount."); + function withdraw(IERC20 _token, uint256 _amount) external nonReentrant { + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][msg.sender]; + require(user.amount >= _amount, "Invalid amount."); - updatePool(_token); - updateDeposits(_amount, _token, pool, user, 1); + updatePool(_token); + updateDeposits(_amount, _token, pool, user, 1); - pool.token.safeTransfer(msg.sender, _amount); - emit Withdraw(msg.sender, _token, _amount); - } + pool.token.safeTransfer(msg.sender, _amount); + emit Withdraw(msg.sender, _token, _amount); + } - /** + /** Claim accumulated token and point rewards from the Staker. @param _token The asset to claim rewards from. */ - function claim(IERC20 _token) external nonReentrant { - UserInfo storage user = userInfo[_token][msg.sender]; - PoolInfo storage pool = poolInfo[_token]; - uint256 pendingTokens; - uint256 pendingPoints; - - updatePool(_token); - if (user.amount > 0) { - pendingTokens = ((user.tokenBoostedAmount * pool.tokensPerShare) / 1e12) - user.tokenPaid; - pendingPoints = ((user.pointBoostedAmount * pool.pointsPerShare) / 1e30) - user.pointPaid; - totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + function claim(IERC20 _token) external nonReentrant { + UserInfo storage user = userInfo[_token][msg.sender]; + PoolInfo storage pool = poolInfo[_token]; + uint256 pendingTokens; + uint256 pendingPoints; + + updatePool(_token); + if (user.amount > 0) { + pendingTokens = + ((user.tokenBoostedAmount * pool.tokensPerShare) / 1e12) - + user.tokenPaid; + pendingPoints = + ((user.pointBoostedAmount * pool.pointsPerShare) / 1e30) - + user.pointPaid; + totalTokenDisbursed = totalTokenDisbursed + pendingTokens; + } + uint256 _tokenRewards = user.tokenRewards + pendingTokens; + uint256 _pointRewards = user.pointRewards + pendingPoints; + IERC20(token).safeTransfer(msg.sender, _tokenRewards); + userPoints[msg.sender] = userPoints[msg.sender] + _pointRewards; + user.tokenRewards = 0; + user.pointRewards = 0; + + user.tokenPaid = (user.tokenBoostedAmount * pool.tokensPerShare) / 1e12; + user.pointPaid = (user.pointBoostedAmount * pool.pointsPerShare) / 1e30; + emit Claim(msg.sender, IERC20(token), _tokenRewards, _pointRewards); } - uint256 _tokenRewards = user.tokenRewards + pendingTokens; - uint256 _pointRewards = user.pointRewards + pendingPoints; - IERC20(token).safeTransfer(msg.sender, _tokenRewards); - userPoints[msg.sender] = userPoints[msg.sender] + _pointRewards; - user.tokenRewards = 0; - user.pointRewards = 0; - - user.tokenPaid = (user.tokenBoostedAmount * pool.tokensPerShare) / 1e12; - user.pointPaid = (user.pointBoostedAmount * pool.pointsPerShare) / 1e30; - emit Claim(msg.sender, IERC20(token), _tokenRewards, _pointRewards); - } - - /** + + /** Private helper function to check if Item staker is eligible for a booster. @param _ids ids of Items required for a booster. @param _amounts amount per token Id. @@ -860,31 +974,39 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _boosterId the booster for which Items are being staked. @return return true if eligible. */ - function eligible(uint256[] memory _ids, uint256[] memory _amounts, address _contract, uint256 _boosterId) private view returns(bool) { - - BoostInfo memory booster = boostInfo[_boosterId]; - uint256 totalAmount = 0; - - for (uint256 i = 0; i < _amounts.length; i++) { - totalAmount += _amounts[i]; - } - if (booster.multiplier == 0) { // Inactive - return false; - } else if (_contract != booster.contractRequired) { // Different contract - return false; - } else if (totalAmount < booster.amountRequired) { // Insufficient amount - return false; - } else if (booster.groupRequired != 0) { - for (uint256 i = 0; i < _ids.length; i++) { - if (_ids[i] >> 128 != booster.groupRequired) { // Wrong group item - return false; + function eligible( + uint256[] memory _ids, + uint256[] memory _amounts, + address _contract, + uint256 _boosterId + ) private view returns (bool) { + BoostInfo memory booster = boostInfo[_boosterId]; + uint256 totalAmount = 0; + + for (uint256 i = 0; i < _amounts.length; ++i) { + totalAmount += _amounts[i]; } - } + if (booster.multiplier == 0) { + // Inactive + return false; + } else if (_contract != booster.contractRequired) { + // Different contract + return false; + } else if (totalAmount < booster.amountRequired) { + // Insufficient amount + return false; + } else if (booster.groupRequired != 0) { + for (uint256 i = 0; i < _ids.length; i++) { + if (_ids[i] >> 128 != booster.groupRequired) { + // Wrong group item + return false; + } + } + } + return true; } - return true; - } - /** + /** Stake a collection of items for booster from a ERC721 or ERC1155 contract. @param _ids the ids collection of Items from a contract. @param _amounts the amount per token Id. @@ -892,156 +1014,198 @@ contract StakerV2 is Sweepable, ReentrancyGuard, IERC721Receiver, ERC1155Holder @param _token the pool that will be staked in. @param _boosterId the booster that accepts these Items. */ - function stakeItemsBatch(uint256[] calldata _ids, uint256[] calldata _amounts, address _contract, IERC20 _token, uint256 _boosterId) external nonReentrant { - - require(_ids.length == _amounts.length, - "Length Mismatch"); - bool exists = false; - for (uint256 i = 0; i < poolInfo[_token].boostInfo.length; i++) { - if (poolInfo[_token].boostInfo[i] == _boosterId) { - exists = true; - break; + function stakeItemsBatch( + uint256[] calldata _ids, + uint256[] calldata _amounts, + address _contract, + IERC20 _token, + uint256 _boosterId + ) external nonReentrant { + require(_ids.length == _amounts.length, "Length Mismatch"); + bool exists = false; + for (uint256 i = 0; i < poolInfo[_token].boostInfo.length; i++) { + if (poolInfo[_token].boostInfo[i] == _boosterId) { + exists = true; + break; + } + } + if (!exists) { + revert("Invalid pool/booster."); + } else if (!eligible(_ids, _amounts, _contract, _boosterId)) { + revert("Ineligible."); } - } - if (!exists) { - revert("Invalid pool/booster."); - } else if (!eligible(_ids, _amounts, _contract, _boosterId)) { - revert("Ineligible."); - } - - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][msg.sender]; - - if (ISuperGeneric(_contract).supportsInterface(INTERFACE_ERC721)) { - ISuperGeneric(_contract).safeBatchTransferFrom(_msgSender(), address(this), _ids, ""); - } else if (ISuperGeneric(_contract).supportsInterface(INTERFACE_ERC1155)) { - ISuperGeneric(_contract).safeBatchTransferFrom(_msgSender(), address(this), _ids, _amounts, ""); - } else { - revert("Unsupported Contract."); - } - - ItemUserInfo storage staker = itemUserInfo[msg.sender]; - staker.totalItems += _ids.length; - for (uint256 i = 0; i < _ids.length; i++) { - staker.tokenIds[_boosterId].add(_ids[i]); - staker.amounts[_ids[i]] += _amounts[i]; - } - staker.boosterIds.add(_boosterId); - totalItemStakes += _ids.length; + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][msg.sender]; + + if (ISuperGeneric(_contract).supportsInterface(INTERFACE_ERC721)) { + ISuperGeneric(_contract).safeBatchTransferFrom( + _msgSender(), + address(this), + _ids, + "" + ); + } else if ( + ISuperGeneric(_contract).supportsInterface(INTERFACE_ERC1155) + ) { + ISuperGeneric(_contract).safeBatchTransferFrom( + _msgSender(), + address(this), + _ids, + _amounts, + "" + ); + } else { + revert("Unsupported Contract."); + } - updatePool(_token); - updateDeposits(0, _token, pool, user, 2); // 2 = PlaceHolder + ItemUserInfo storage staker = itemUserInfo[msg.sender]; + staker.totalItems += _ids.length; + for (uint256 i = 0; i < _ids.length; i++) { + staker.tokenIds[_boosterId].add(_ids[i]); + staker.amounts[_ids[i]] += _amounts[i]; + } + staker.boosterIds.add(_boosterId); + + totalItemStakes += _ids.length; + + updatePool(_token); + updateDeposits(0, _token, pool, user, 2); // 2 = PlaceHolder - emit StakeItemBatch(msg.sender, _token, _boosterId); - } + emit StakeItemBatch(msg.sender, _token, _boosterId); + } - /** + /** Unstake collection of items from booster to ERC721 or ERC1155 contract. @param _token the pool that was previously staked in. @param _boosterId the booster that accepted these Items. */ - function unstakeItemsBatch(IERC20 _token, uint256 _boosterId) external nonReentrant { - - require(address(_token) != address(0), - "0 address."); - require(itemUserInfo[msg.sender].boosterIds.contains(_boosterId), - "No stakes."); - - ItemUserInfo storage staker = itemUserInfo[msg.sender]; - PoolInfo storage pool = poolInfo[_token]; - UserInfo storage user = userInfo[_token][msg.sender]; - address externalContract = boostInfo[_boosterId].contractRequired; - - uint256[] memory _ids = new uint256[](staker.tokenIds[_boosterId].length()); - uint256[] memory _amounts = new uint256[](_ids.length); - for (uint256 i = 0; i < _ids.length; i++) { - _ids[i] = staker.tokenIds[_boosterId].at(i); - _amounts[i] = staker.amounts[_ids[i]]; - } + function unstakeItemsBatch(IERC20 _token, uint256 _boosterId) + external + nonReentrant + { + require(address(_token) != address(0), "0 address."); + require( + itemUserInfo[msg.sender].boosterIds.contains(_boosterId), + "No stakes." + ); + + ItemUserInfo storage staker = itemUserInfo[msg.sender]; + PoolInfo storage pool = poolInfo[_token]; + UserInfo storage user = userInfo[_token][msg.sender]; + address externalContract = boostInfo[_boosterId].contractRequired; + + uint256[] memory _ids = new uint256[]( + staker.tokenIds[_boosterId].length() + ); + uint256[] memory _amounts = new uint256[](_ids.length); + for (uint256 i = 0; i < _ids.length; i++) { + _ids[i] = staker.tokenIds[_boosterId].at(i); + _amounts[i] = staker.amounts[_ids[i]]; + } - if (ISuperGeneric(externalContract).supportsInterface(INTERFACE_ERC721)) { - ISuperGeneric(externalContract).safeBatchTransferFrom(address(this), _msgSender(), _ids, ""); - } else if (ISuperGeneric(externalContract).supportsInterface(INTERFACE_ERC1155)) { - ISuperGeneric(externalContract).safeBatchTransferFrom(address(this), _msgSender(), _ids, _amounts, ""); - } else { - revert("Unsupported Contract."); - } + if ( + ISuperGeneric(externalContract).supportsInterface(INTERFACE_ERC721) + ) { + ISuperGeneric(externalContract).safeBatchTransferFrom( + address(this), + _msgSender(), + _ids, + "" + ); + } else if ( + ISuperGeneric(externalContract).supportsInterface(INTERFACE_ERC1155) + ) { + ISuperGeneric(externalContract).safeBatchTransferFrom( + address(this), + _msgSender(), + _ids, + _amounts, + "" + ); + } else { + revert("Unsupported Contract."); + } - staker.totalItems -= _ids.length; - for (uint256 i = 0; i < _ids.length; i++) { - staker.tokenIds[_boosterId].remove(_ids[i]); - staker.amounts[_ids[i]] = 0; - } - staker.boosterIds.remove(_boosterId); + staker.totalItems -= _ids.length; + for (uint256 i = 0; i < _ids.length; i++) { + staker.tokenIds[_boosterId].remove(_ids[i]); + staker.amounts[_ids[i]] = 0; + } + staker.boosterIds.remove(_boosterId); - totalItemStakes -= _ids.length; + totalItemStakes -= _ids.length; - updatePool(_token); - updateDeposits(0, _token, pool, user, 2); // 2 = PlaceHolder + updatePool(_token); + updateDeposits(0, _token, pool, user, 2); // 2 = PlaceHolder - emit UnstakeItemBatch(msg.sender, _token, _boosterId); - } + emit UnstakeItemBatch(msg.sender, _token, _boosterId); + } - /** + /** Allows to get information about tokens staked in a booster for Items staker address. @param _itemUserAddress the user address to check. @param _boosterId the booster Id to check the tokens staked for. @return a struct containing the information. */ - function getItemsUserInfo(address _itemUserAddress, uint256 _boosterId) external view returns(GetItemUserInfo memory) { - - uint256 length = itemUserInfo[_itemUserAddress].tokenIds[_boosterId].length(); - uint256[] memory _tokenIds = new uint256[](length); - uint256[] memory _amounts = new uint256[](length); - for (uint256 i = 0; i < length; i++) { - _tokenIds[i] = itemUserInfo[_itemUserAddress].tokenIds[_boosterId].at(i); - _amounts[i] = itemUserInfo[_itemUserAddress].amounts[_tokenIds[i]]; - } + function getItemsUserInfo(address _itemUserAddress, uint256 _boosterId) + external + view + returns (GetItemUserInfo memory) + { + uint256 length = itemUserInfo[_itemUserAddress] + .tokenIds[_boosterId] + .length(); + uint256[] memory _tokenIds = new uint256[](length); + uint256[] memory _amounts = new uint256[](length); + for (uint256 i = 0; i < length; i++) { + _tokenIds[i] = itemUserInfo[_itemUserAddress] + .tokenIds[_boosterId] + .at(i); + _amounts[i] = itemUserInfo[_itemUserAddress].amounts[_tokenIds[i]]; + } - GetItemUserInfo memory _userInfo = GetItemUserInfo({ - boosterId: _boosterId, - tokenIds: _tokenIds, - amounts: _amounts, - totalItems: itemUserInfo[_itemUserAddress].totalItems - }); - return _userInfo; - } + GetItemUserInfo memory _userInfo = GetItemUserInfo({ + boosterId: _boosterId, + tokenIds: _tokenIds, + amounts: _amounts, + totalItems: itemUserInfo[_itemUserAddress].totalItems + }); + return _userInfo; + } - /** + /** Allows the owner of this Staker to grant or remove approval to an external spender of the points that users accrue from staking resources. @param _spender The external address allowed to spend user points. @param _approval The updated user approval status. */ - function approvePointSpender(address _spender, bool _approval) external hasValidPermit(UNIVERSAL, APPROVE_POINT_SPENDER) { - - approvedPointSpenders[_spender] = _approval; - } + function approvePointSpender(address _spender, bool _approval) + external + hasValidPermit(UNIVERSAL, APPROVE_POINT_SPENDER) + { + approvedPointSpenders[_spender] = _approval; + } - /** + /** Allows an approved spender of points to spend points on behalf of a user. @param _user The user whose points are being spent. @param _amount The amount of the user's points being spent. */ - function spendPoints(address _user, uint256 _amount) external { - - require(approvedPointSpenders[msg.sender], - "Not allowed."); - uint256 _userPoints = getAvailablePoints(_user); - require(_userPoints >= _amount, - "Invalid amount."); - userSpentPoints[_user] = userSpentPoints[_user] + _amount; - emit SpentPoints(msg.sender, _user, _amount); - } - - function onERC721Received( - address operator, - address from, - uint256 tokenId, - bytes calldata data - ) external override returns (bytes4) { - - return this.onERC721Received.selector; - } -} \ No newline at end of file + function spendPoints(address _user, uint256 _amount) external { + require(approvedPointSpenders[msg.sender], "Not allowed."); + uint256 _userPoints = getAvailablePoints(_user); + require(_userPoints >= _amount, "Invalid amount."); + userSpentPoints[_user] = userSpentPoints[_user] + _amount; + emit SpentPoints(msg.sender, _user, _amount); + } + + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external override returns (bytes4) { + return this.onERC721Received.selector; + } +} diff --git a/contracts/staker/v3ds/StakerBlueprint.sol b/contracts/staker/v3ds/StakerBlueprint.sol new file mode 100644 index 0000000..1d4224f --- /dev/null +++ b/contracts/staker/v3ds/StakerBlueprint.sol @@ -0,0 +1,485 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.8; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/** + * @title Blueprint library for Staker. + * @author Qazawat Zirak + * This library acts as a blueprint for storage mechanim in the proxy contract. + * The library defines state variables in form of structs. It also defines the + * storage location of the variables using KECCAK256 to avoid memory collision. + * The state is stored in Proxy contract, which does a delegate call. + * 9th Feb, 2022. + */ +library StakerBlueprint { + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + error AssetArrayLengthsMismatch(); + error InvalidInfoStakeForBoost(); + error InactivePool(); + error InvalidAssetToStake(); + error NotStaked(); + error InvalidAmount(); + error IOUTokenFromDifferentPool(); + error NotAnOwnerOfIOUToken(); + error NotAnAdmin(); + error MismatchArgumentsAndHash(); + error HashUsed(); + error NotApprovedPointSpender(); + error InvalidAmountToLock(); + error TokensAlreadyLocked(); + error TokenLocked(); + error InvalidERC721Amount(); + error CantAlterDevs(); + error ZeroDevShare(); + error CantIncreaseDevShare(); + error InvalidNewAddress(); + error CantAlterTokenEmissionSchedule(); + error CantAlterPointEmissionSchedule(); + error ZeroTokenEmissionEvents(); + error ZeroPointEmissionEvents(); + error EmptyBoostInfoArray(); + error InputLengthsMismatch(); + error BoosterIdZero(); + error InvalidConfBoostersInputs(); + error InvalidConfBoostersAssetType(); + error EmissionNotSet(); + error ZeroStrength(); + error InvalidAsset(); + error InvalidTypeOfAsset(); + error InvalidERC20DepositInputs(); + error InvalidGroupIdForERC20(); + error InvalidGroupIdForStake(); + error InvalidTypeOfPool(); + error WrongTypeOfPoolForTypeOfAsset(); + error CantGetSameBoosterTwice(); + + /// Event for staking non fungible items for boosters. + event StakeItemBatch( + address indexed user, + uint256 indexed _poolId, + uint256 boosterId + ); + + /// Event for unstaking non fungible items from boosters. + event UnstakeItemBatch( + address indexed user, + uint256 indexed _poolId, + uint256 boosterId + ); + + /// An event for tracking when a user has spent points. + event SpentPoints( + address indexed source, + address indexed user, + uint256 amount + ); + + /// The public identifier for the right to add developer. + bytes32 public constant ADD_DEVELOPER = keccak256("ADD_DEVELOPER"); + + /// The public identifier for the right to lock developers. + bytes32 public constant LOCK_DEVELOPERS = keccak256("LOCK_DEVELOPERS"); + + /// The public identifier for the right to set emissions. + bytes32 public constant SET_EMISSIONS = keccak256("SET_EMISSIONS"); + + /// The public identifier for the right to lock token emissions. + bytes32 public constant LOCK_TOKEN_EMISSIONS = + keccak256("LOCK_TOKEN_EMISSIONS"); + + /// The public identifier for the right to lock point emissions. + bytes32 public constant LOCK_POINT_EMISSIONS = + keccak256("LOCK_POINT_EMISSIONS"); + + /// The public identifier for the right to configure boosters. + bytes32 public constant CONFIGURE_BOOSTERS = + keccak256("CONFIGURE_BOOSTERS"); + + /// The public identifier for the right to add pools. + bytes32 public constant ADD_POOL = keccak256("ADD_POOL"); + + /// The public identifier for the right to approve point spender. + bytes32 public constant APPROVE_POINT_SPENDER = + keccak256("APPROVE_POINT_SPENDER"); + + /// ERC721 interface ID to detect external contracts for Items staking. + bytes4 public constant INTERFACE_ERC721 = 0x80ac58cd; + + /// ERC1155 interface ID to detect external contracts for Items staking. + bytes4 public constant INTERFACE_ERC1155 = 0xd9b67a26; + + /// @dev A max uint256 value that represents earliest timestamp for quick reference. + uint256 public constant MAX_INT = 2**256 - 1; + + /** + * This struct defines the state variables for StakerProxy. + * + * @param admin Address of admin user for verify purposes. + * @param implementation Address of the logic contract corresponding to selector. + * @param IOUTokenAddress IOU token address. + * @param nextIOUTokenId The next available ID to be assumed by the next IOUToken minted. + * @param token Token to disburse to stakers. + * @param canAlterDevelopers Flag for allowing contract owner to add or set developers. + * @param developerAddresses Developer addresses for finding shares in the 'developerShares'. + * @param developerShares A mapping of developer addresses to their percent share of emissions. + * Share percentages are represented as 1/1000th of a percent. That is, a 1% + * share of emissions should map an address to 1000. + * @param canAlterTokenEmissionSchedule Flag for allowing contract owner to alter token emissions. + * @param canAlterPointEmissionSchedule Flag for allowing contract owner to alter point emissions. + * @param lastPoolId actual pool id. + * @param tokenEmissionEventsCount The total number of 'EmissionPoint' as token emission events in the schedule. + * @param pointEmissionEventsCount The total number of 'EmissionPoint' as point emission events in the schedule. + * @param tokenEmissionEvents Schedule of token 'EmissionPoint' for finding emission rate changes. + * @param pointEmissionEvents Schedule of point 'EmissionPoint' for finding emission rate changes. + * @param earliestTokenEmissionEvent Earliest possible token emission timestamp. + * @param earliestPointEmissionEvent Earliest possible point emission timestamp. + * @param poolAssets Array for enumeration of the pools. + * @param poolInfo Mapping of pools to 'PoolInfo' based on their id. + * @param userInfo Stored information for each user staking in each pool. + * @param totalTokenStrength The total sum of the token strength of all pools. + * @param totalPointStrength The total sum of the point strength of all pools. + * @param totalTokenDisbursed The total amount of the disbursed token ever emitted by this Staker. + * @param userPoints Users additionally accrue non-token points for participating via staking. + * @param userSpentPoints The amount of points belonging to a user already spent. + * @param approvedPointSpenders A map of all external addresses that are permitted to spend user points. + * @param boostInfo Mapping of Booster ID to its 'BoostInfo'. + * @param activeBoosters Number of boosters that are active. + * @param hashes Signature hashes created for claim function. + * @param itemUserInfo Collection of Item stakers. + * @param totalItemStakes Items staked in this contract. + * @param IOUIdToStakedAsset Mapping that matches pool id => IOU token id => staked assets. + * @param poolTokens Array for enumeration of the pools. + * @param name Name of the staker. + * @param poolLocks Mapping that contains user's address that locked his deposit and time when + * he locked for each pool. + * @param lockIndex Mapping that contains indexex from which start to bypass array of time locked deposits + * for each pool. + */ + struct StakerStateVariables { + address admin; + mapping(bytes4 => address) implementations; + address IOUTokenAddress; + uint256 nextIOUTokenId; + address token; + bool canAlterDevelopers; + bool canAlterTokenEmissionSchedule; + bool canAlterPointEmissionSchedule; + EnumerableSet.AddressSet developerAddresses; + mapping(address => uint256) developerShares; + //mapping(address => uint256) developerRewards; + mapping(uint256 => EnumerableSet.UintSet) boosterPools; + uint256 lastPoolId; + uint256 tokenEmissionEventsCount; + uint256 pointEmissionEventsCount; + mapping(uint256 => EmissionPoint) tokenEmissionEvents; + mapping(uint256 => EmissionPoint) pointEmissionEvents; + uint256 earliestTokenEmissionEvent; + uint256 earliestPointEmissionEvent; + address[] poolAssets; + mapping(IERC20 => PoolInfo) poolInfo; + mapping(IERC20 => mapping(address => UserInfo)) userInfo; + mapping(uint256 => PoolInfo) poolInfoV3; + mapping(uint256 => mapping(address => UserInfo)) userInfoV3; + mapping(uint256 => mapping(uint256 => RewardsTiedToNFT)) NFTRewards; + uint256 totalTokenStrength; + uint256 totalPointStrength; + uint256 totalTokenDisbursed; + mapping(address => uint256) userPoints; + mapping(address => uint256) userSpentPoints; + mapping(address => bool) approvedPointSpenders; + mapping(uint256 => BoostInfo) boostInfo; + uint256 activeBoosters; + mapping(bytes32 => bool) hashes; + mapping(address => ItemUserInfo) itemUserInfo; + uint256 totalItemStakes; + mapping(uint256 => mapping(uint256 => StakedAsset)) IOUIdToStakedAsset; + IERC20[] poolTokens; + string name; + mapping(uint256 => PoolLocks[]) poolLocks; + mapping(uint256 => uint256) lockIndex; + mapping(uint256 => mapping(uint256 => uint256)) boosterAmount; + mapping(uint256 => mapping(uint256 => uint256[])) tpsOnBoostUpdate; + mapping(uint256 => mapping(uint256 => uint256[])) ppsOnBoostUpdate; + } + + struct RewardsTiedToNFT { + uint256 shareOfTokenBoostedDeposited; + uint256 shareOfPointBoostedDeposited; + uint256 accamulatedTokenRewards; + uint256 accamulatedPointRewards; + uint256 tokenPaid; + uint256 pointPaid; + } + + struct PoolLocks { + uint256 lockedAt; + address lockedUser; + } + /** + * This emission schedule maps a timestamp to the amount of tokens or points + * that should be disbursed starting at that timestamp per-second onwards. + * @param timeStamp if current time reaches timestamp, the rate is applied. + * @param rate measure of points or tokens emitted per-second. + */ + struct EmissionPoint { + uint256 timeStamp; + uint256 rate; + } + + /** + * A struct containing the pool info. + * @param typeOfAsset type of asset that is represented in pool. + * @param tokenStrength the relative token emission strength of this pool. + * @param tokenBoostedDeposit amount of tokens after boosts are applied. + * @param tokensPerShare accumulated tokens per share times 1e12. + * @param pointStrength the relative point emission strength of this pool. + * @param pointBoostedDeposit amount of points after boosts are applied. + * @param pointsPerShare accumulated points per share times 1e30. + * @param lastRewardEvent record of the time of the last disbursement. + * @param boostInfo boosters applied to the pool rewards when eligible. !Must start with 1! + * @param lockPeriod the time for which the token will be locked with time locked deposit. + * @param lockAmount required amount of tokens for time lock deposit. + * @param lockMultiplier multiplier that applies for user's share if time lock deposit is active. + * @param compoundInterestThreshold minimum amount of rewards for compound interest multiplier to be applied. + * @param compoundInterestMultiplier multiplier that applies for user's rewards if treshold is reached. + * @param assetAddress address of asset that should be staked into the pool. + * @param typeOfAsset enum that shows which standard the token used in the pool belongs to. + * @param timeLockTypeOfBoost enum that specifies Tokens/Points to boost or both by time lock deposit. + * @param compoundTypeOfBoost enum that specifies Tokens/Points to boost or both by compound interest. + * + * 'tokenBoostedDeposit' and 'pointBoostedDeposit' do not change emission + * rate, but used to calculate perShare amount when there are boosters. + */ + struct PoolInfo { + uint256 tokenStrength; + uint256 tokenBoostedDeposit; + uint256 tokensPerShare; + uint256 pointStrength; + uint256 pointBoostedDeposit; + uint256 pointsPerShare; + uint256 groupId; + uint256 lastRewardEvent; + uint256[] boostInfo; + uint256 lockPeriod; + uint256 lockAmount; + uint256 lockMultiplier; + uint256 compoundInterestThreshold; + uint256 compoundInterestMultiplier; + address assetAddress; + PoolType typeOfPool; + AssetType typeOfAsset; + BoosterAssetType timeLockTypeOfBoost; + BoosterAssetType compoundTypeOfBoost; + } + + /** + * An auxiliary structure that is used to create or configure an existing pool + * @param id id of the generated boost. + * @param tokenStrength the relative token emission strength of this pool. + * @param pointStrength the relative point emission strength of this pool. + * @param groupId id of the group of tokens that should be staked in this pool. + * @param tokensPerShare accumulated tokens per share times 1e12. + * @param pointsPerShare accumulated points per share times 1e30. + * @param boostInfo boosters applied to the pool rewards when eligible. !Must start with 1! + * @param lockPeriod the time for which the token will be locked with time locked deposit. + * @param lockAmount required amount of tokens for time lock deposit. + * @param lockMultiplier multiplier that applies for user's share if time lock deposit is active. + * @param compoundInterestThreshold minimum amount of rewards for compound interest multiplier to be applied. + * @param compoundInterestMultiplier multiplier that applies for user's rewards if treshold is reached. + * @param assetAddress address of asset that should be staked into the pool. + * @param typeOfAsset enum that shows which standard the token used in the pool belongs to. + * @param timeLockTypeOfBoost enum that specifies Tokens/Points to boost or both by time lock deposit. + * @param compoundTypeOfBoost enum that specifies Tokens/Points to boost or both by compound interest. + */ + struct AddPoolStruct { + uint256 id; + uint256 tokenStrength; + uint256 pointStrength; + uint256 groupId; + uint256 tokensPerShare; + uint256 pointsPerShare; + uint256[] boostInfo; + uint256 lockPeriod; + uint256 lockAmount; + uint256 lockMultiplier; + uint256 compoundInterestThreshold; + uint256 compoundInterestMultiplier; + address assetAddress; + PoolType typeOfPool; + AssetType typeOfAsset; + BoosterAssetType timeLockTypeOfBoost; + BoosterAssetType compoundTypeOfBoost; + } + + /** + * A struct which represents the V, R, S variables of a signature. + * @param v v part of signature. + * @param r r part of signature. + * @param s s part of signature. + */ + struct Sig { + uint8 v; + bytes32 r; + bytes32 s; + } + + /** + * The structure stores the checkpoints when the user held the NFT + * + * @param startTime Beginning of holding + * @param endTime Ending of holding + * @param balance Holding balance. 1000 = 1 + */ + struct Checkpoint { + uint256[] startTime; + uint256[] endTime; + uint256[] tokensBalance; + uint256[] pointsBalance; + uint256[] tokensPerShare; + uint256[] pointsPerShare; + } + + /** + * A struct containing the Fungible Token Staker information. + * @param amount amount of the pool asset being provided by the user. + * @param tokenBoostedAmount tokens amount after boosts are applied. + * @param pointBoostedAmount points amount after boosts are applied. + * @param tokenRewards amount of token rewards accumulated to be claimed. + * @param pointRewards amount of point rewards accumulated to be claimed. + * @param tokenPaid value of user's total token earnings paid out. + * pending reward = (user.amount * pool.tokensPerShare) - user.rewardDebt. + * @param pointPaid value of user's total point earnings paid out. + * @param asset The structure stores information about what assets the user has staked + */ + struct UserInfo { + uint256 amount; + uint256 tokenBoostedAmount; + uint256 pointBoostedAmount; + uint256 tokenRewards; + uint256 pointRewards; + uint256 tokenPaid; + uint256 pointPaid; + StakedAsset asset; + } + + enum PoolType { + StakingTiedToHolder, + StakingTiedToNFT, + NoStakingTiedToHolder, + NoStakingTiedToNFT + } + + /** + * The type of asset on which the boost is applied. + * @param Tokens boost is applied on the disburse token. + * @param Points boost is applied on the points. + * @param Both boost is applied on both. + */ + enum BoosterAssetType { + Tokens, + Points, + Both + } + + /** + * The type of asset that available to stake in. + * @param ERC20 represents ERC20 token. + * @param ERC721 represents ERC721 token. + * @param ERC1155 represents ERC1155 token. + */ + enum AssetType { + ERC20, + ERC721, + ERC1155 + } + + /** + * A booster struct, which stores information on the boost requirements. + * @param multiplier the rate which will act as a boost on basis points. + * A multiplier of Zero means, the booster is not set. + * @param amountRequired number of Items required from the contract. + * @param groupRequired (optional) specifies a group from Items contract + * as requirement for the boost. If 0, then any group or item. + * @param contractRequired contract that the required assets belong to. + * @param boostType enum that specifies Tokens/Points to boost or both. + * @param typeOfAsset type of asset that is represented in booster for lock. + */ + struct BoostInfo { + uint32 multiplier; + uint24 amountRequired; + uint32 groupRequired; + address contractRequired; + BoosterAssetType boostType; + AssetType typeOfAsset; + uint256[] historyOfTokenMultipliers; + uint256[] historyOfPointMultipliers; + } + + /** + * The structure stores information about what assets the user has staked + * @param assetAddress Address of asset + * @param id Array of id's + * @param amounts Array of amounts + * @param IOUTokenId Arrays of id's of IOUtoken + */ + struct StakedAsset { + address assetAddress; + uint256[] id; + uint256[] amounts; + uint256[] IOUTokenId; + } + + /** + * A struct containing the Items staker information. + * @param totalItems total Items staked in this contract by Items staker. + * @param tokenIds actual ids of tokens mapped to booster Id. + * @param amounts amount of Items per tokenId. + * @param boosterIds enumerable booster Ids the user has staked Items in. + * + * Contract address at the time of unstaking is retreived from boostInfo. + */ + struct ItemUserInfo { + uint256 totalItems; + mapping(uint256 => EnumerableSet.UintSet) tokenIds; + mapping(uint256 => uint256) amounts; + EnumerableSet.UintSet boosterIds; + mapping(uint256 => LockedItems) lockedItems; + mapping(uint256 => uint256) lastNumberOfBoosterUpdate; + } + + struct LockedItems { + uint256 lockedAt; + uint256[] lockedIOUIds; + } + + /** + * A struct as return parameter to get token Ids against a booster Id of + * a staker. Needed since EnumerableSets cannot have getters by default. + * @param boostersIds the booster Id to check the Items for. + * @param tokenIds the token Ids that are staked in that booster. + * @param amounts amount per token Id staked in a booster. + * @param totalItems total Items staked in this contract by Items staker. + */ + struct GetItemUserInfo { + uint256 boosterId; + uint256[] tokenIds; + uint256[] amounts; + uint256 totalItems; + } + + // Storage Locations + function stakerStateVariables() + internal + pure + returns (StakerStateVariables storage _stakerStateVariables) + { + bytes32 storagePosition = keccak256("diamond.storage.StateVariables"); + assembly { + _stakerStateVariables.slot := storagePosition + } + } +} diff --git a/contracts/staker/v3ds/StakerProxy.sol b/contracts/staker/v3ds/StakerProxy.sol new file mode 100644 index 0000000..b98769c --- /dev/null +++ b/contracts/staker/v3ds/StakerProxy.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "./StakerBlueprint.sol"; + +/** + * @title A diamond standard proxy storage for Staker + * @author Qazawat Zirak + * A proxy storage for a Staker. It is the main entry point for + * contract calls. Every call to proxy storage will be delegated to + * Staker contract address. Storage is reflected in this contract. + */ +contract StakerProxy { + error ArraysLengthsMismatch(); + error DelegateCallFails(); + error NoImplementation(); + + /** + * Construct a new staker proxy. + * @param _implementation The address of the logic contract. + * @param _owner The address of the administrator governing this contract. + * @param _token The address of the disburse token. + * @param _admin The admin for verification purposes. + * @param _IOUTokenAddress IOUTokenAddress + */ + constructor( + address _implementation, + address _owner, + address _token, + address _admin, + address _IOUTokenAddress, + string memory _name, + bytes4[] memory _selectors, + address[] memory _addresses + ) { + if (_selectors.length != _addresses.length) { + revert ArraysLengthsMismatch(); + } + + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + // Execute a delegate call for initialization + (bool success, ) = _implementation.delegatecall( + abi.encodeWithSignature("initialize(address)", _owner) + ); + + // Represents collective succuess + if (!success) { + revert DelegateCallFails(); + } + + // If deployment is success, store constructor parameters + b.IOUTokenAddress = _IOUTokenAddress; + b.admin = _admin; + b.token = _token; + b.name = _name; + b.canAlterDevelopers = true; + b.canAlterTokenEmissionSchedule = true; + b.canAlterPointEmissionSchedule = true; + b.earliestTokenEmissionEvent = 2**256 - 1; + b.earliestPointEmissionEvent = 2**256 - 1; + + for (uint256 i = 0; i < _selectors.length; i++) { + b.implementations[_selectors[i]] = _addresses[i]; + } + } + + fallback() external payable { + // Load variables related to DiamondProxy from this contract's memory + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + address _implementation = b.implementations[msg.sig]; + + if (_implementation == address(0)) { + revert NoImplementation(); + } + + // Execute external function from facet using delegatecall and return any value. + assembly { + // Copy function selector and any arguments + calldatacopy(0, 0, calldatasize()) + // Execute function call using the facet + let result := delegatecall( + gas(), + _implementation, + 0, + calldatasize(), + 0, + 0 + ) + // Get any return value + returndatacopy(0, 0, returndatasize()) + // Return any return value or error back to the caller + switch result + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/contracts/staker/v3ds/facets/StakerV3FacetBoosters.sol b/contracts/staker/v3ds/facets/StakerV3FacetBoosters.sol new file mode 100644 index 0000000..ce1d4bc --- /dev/null +++ b/contracts/staker/v3ds/facets/StakerV3FacetBoosters.sol @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import "../../../base/Sweepableds.sol"; +import "../../../interfaces/ISuperGeneric.sol"; + +import "../StakerBlueprint.sol"; + +/** + * @title An asset staking contract. + * @author Tim Clancy + * @author Qazawat Zirak + * @author Nikita Elunin + * This staking contract disburses tokens from its internal reservoir according + * to a fixed emission schedule. Assets can be assigned varied staking weights. + * It also supports Items staking for boosts on native ERC20 staking rewards. + * The item staking supports Fungible, Non-Fungible and Semi-Fungible staking. + * This code is inspired by and modified from Sushi's Master Chef contract. + * https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol + */ +contract StakerV3FacetBoosters is Sweepableds { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * Deposit some particular assets to a particular pool on the Staker. + * @param _poolId The pool id. + * @param _boosterId Id of booster that you want to achieve. + * @param _asset Asset that user wants to lock for booster. + */ + function stakeItemsBatch( + uint256 _poolId, + uint256 _boosterId, + StakerBlueprint.StakedAsset memory _asset + ) external { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][ + msg.sender + ]; + + StakerBlueprint.AssetType typeOfAsset; + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + if (_asset.id.length != _asset.amounts.length) { + revert StakerBlueprint.AssetArrayLengthsMismatch(); + } + + bool exists; + for (uint256 i; i < pool.boostInfo.length; ) { + if (pool.boostInfo[i] == _boosterId) { + exists = true; + break; + } + unchecked { + ++i; + } + } + if ( + !exists || + !eligible( + _asset.id, + _asset.amounts, + _asset.assetAddress, + _boosterId + ) + ) { + revert StakerBlueprint.InvalidInfoStakeForBoost(); + } + + typeOfAsset = b.boostInfo[_boosterId].typeOfAsset; + + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[ + msg.sender + ]; + + if (staker.boosterIds.contains(_boosterId) == true) { + revert StakerBlueprint.CantGetSameBoosterTwice(); + } + + staker.totalItems += _asset.id.length; + for (uint256 i; i < _asset.id.length; ) { + staker.tokenIds[_boosterId].add(_asset.id[i]); + staker.amounts[_asset.id[i]] += _asset.amounts[i]; + unchecked { + ++i; + } + } + staker.boosterIds.add(_boosterId); + + staker.lastNumberOfBoosterUpdate[_boosterId] = b + .tpsOnBoostUpdate[_poolId][_boosterId].length; + + b.totalItemStakes += _asset.id.length; + updatePool(_poolId); + updateDeposits(_poolId); + b.boosterAmount[_poolId][_boosterId] += _user.amount; + + if (typeOfAsset == StakerBlueprint.AssetType.ERC721) { + for (uint256 i; i < _asset.amounts.length; ) { + if (_asset.amounts[i] != 1) { + revert StakerBlueprint.InvalidERC721Amount(); + } + unchecked { + ++i; + } + } + ISuperGeneric(_asset.assetAddress).safeBatchTransferFrom( + msg.sender, + address(this), + _asset.id, + "" + ); + } else { + ISuperGeneric(_asset.assetAddress).safeBatchTransferFrom( + msg.sender, + address(this), + _asset.id, + _asset.amounts, + "" + ); + } + emit StakerBlueprint.StakeItemBatch(msg.sender, _poolId, _boosterId); + } + + /** + * Withdraw some particular assets from a particular pool on the Staker. + * @param _poolId The id of pool, withdraw tokens from. + * @param _boosterId The booster that accepted these Items. + */ + function unstakeItemsBatch(uint256 _poolId, uint256 _boosterId) external { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + address assetAddress; + uint256[] memory ids; + uint256[] memory amounts; + StakerBlueprint.AssetType typeOfAsset; + + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][ + msg.sender + ]; + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[ + msg.sender + ]; + + if (!b.itemUserInfo[msg.sender].boosterIds.contains(_boosterId)) { + revert StakerBlueprint.NotStaked(); + } + + uint256[] memory _ids = new uint256[]( + staker.tokenIds[_boosterId].length() + ); + uint256[] memory _amounts = new uint256[](_ids.length); + for (uint256 i; i < _ids.length; ) { + _ids[i] = staker.tokenIds[_boosterId].at(i); + _amounts[i] = staker.amounts[_ids[i]]; + unchecked { + ++i; + } + } + assetAddress = b.boostInfo[_boosterId].contractRequired; + typeOfAsset = b.boostInfo[_boosterId].typeOfAsset; + ids = _ids; + amounts = _amounts; + + staker.totalItems -= _ids.length; + for (uint256 i; i < _ids.length; ) { + staker.tokenIds[_boosterId].remove(_ids[i]); + staker.amounts[_ids[i]] = 0; + unchecked { + ++i; + } + } + // TODO: think about case of pools with rewardsTiedToNFT + checkOnBoostersChanged(_user.amount, _poolId, msg.sender); + b.boosterAmount[_poolId][_boosterId] -= _user.amount; + staker.boosterIds.remove(_boosterId); + b.totalItemStakes -= _ids.length; + updatePool(_poolId); + updateDeposits(_poolId); + + if (typeOfAsset == StakerBlueprint.AssetType.ERC721) { + ISuperGeneric(assetAddress).safeBatchTransferFrom( + address(this), + msg.sender, + ids, + "" + ); + } else { + ISuperGeneric(assetAddress).safeBatchTransferFrom( + address(this), + msg.sender, + ids, + amounts, + "" + ); + } + emit StakerBlueprint.UnstakeItemBatch(msg.sender, _poolId, _boosterId); + } + + /** + * Private helper function to check if Item staker is eligible for a booster. + * @param _ids Ids of Items required for a booster. + * @param _amounts Amount per token Id. + * @param _contract External contract from which Items are required. + * @param _boosterId The booster for which Items are being staked. + * @return Return true if eligible. + */ + function eligible( + uint256[] memory _ids, + uint256[] memory _amounts, + address _contract, + uint256 _boosterId + ) private view returns (bool) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.BoostInfo storage booster = b.boostInfo[_boosterId]; + uint256 totalAmount = 0; + + for (uint256 i; i < _amounts.length; ) { + totalAmount += _amounts[i]; + unchecked { + ++i; + } + } + if (booster.multiplier == 0) { + // Inactive + return false; + } else if (_contract != booster.contractRequired) { + // Different conatract + return false; + } else if (totalAmount < booster.amountRequired) { + // Insufficient amount + return false; + } else if (booster.groupRequired > 0) { + for (uint256 i; i < _ids.length; ) { + if (_ids[i] >> 128 != booster.groupRequired) { + // Wrong group item + return false; + } + unchecked { + ++i; + } + } + } + return true; + } + + /** + * Uses the emission schedule to calculate the total amount of staking reward + * token that was emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedTokens; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.tokenEmissionEventsCount; ) { + uint256 emissionTime = b.tokenEmissionEvents[i].timeStamp; + uint256 emissionRate = b.tokenEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } else if (workingTime < emissionTime) { + totalEmittedTokens += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } + + /** + * Uses the emission schedule to calculate the total amount of points + * emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedPoints; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.pointEmissionEventsCount; ) { + uint256 emissionTime = b.pointEmissionEvents[i].timeStamp; + uint256 emissionRate = b.pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } + + /** + * Update the pool corresponding to the specified token address. + * @param _poolId The id of pool to update the corresponding pool for. + */ + function updatePool(uint256 _poolId) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + + if (pool.tokenBoostedDeposit == 0) { + pool.lastRewardEvent = block.timestamp; + return; + } + + // Calculate token and point rewards for this pool. + uint256 tokensReward; + uint256 pointsReward; + + tokensReward = + ((getTotalEmittedTokens(pool.lastRewardEvent, block.timestamp) * + pool.tokenStrength) / b.totalTokenStrength) * + 1e12; + pointsReward = + ((getTotalEmittedPoints(pool.lastRewardEvent, block.timestamp) * + pool.pointStrength) / b.totalPointStrength) * + 1e30; + + // Directly pay developers their corresponding share of tokens and points. + (tokensReward, pointsReward) = sendDeveloperShares( + tokensReward, + pointsReward + ); + + // Update the pool rewards per share to pay users the amount remaining. + pool.tokensPerShare += (tokensReward / pool.tokenBoostedDeposit); + pool.pointsPerShare += (pointsReward / pool.pointBoostedDeposit); + pool.lastRewardEvent = block.timestamp; + } + + /** + * Private helper function to send developers shares + * @param tokensReward Amount of tokens that available as rewards. + * @param pointsReward Amount of points that available as rewards. + */ + function sendDeveloperShares(uint256 tokensReward, uint256 pointsReward) + internal + returns (uint256, uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + for (uint256 i; i < b.developerAddresses.length(); ) { + address developer = b.developerAddresses.at(i); + uint256 share = b.developerShares[developer]; + uint256 devTokens = (tokensReward * share) / 100_000; + tokensReward -= devTokens; + uint256 devPoints = (pointsReward * share) / 100_000; + pointsReward -= devPoints; + IERC20(b.token).safeTransfer(developer, devTokens / 1e12); + b.userPoints[developer] += (devPoints / 1e30); + unchecked { + ++i; + } + } + return (tokensReward, pointsReward); + } + + /** + * Private helper function to update the deposits based on new shares. + * @param _poolId The pool id, the deposit of which is to be updated. + */ + function updateDeposits(uint256 _poolId) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage _pool = b.poolInfoV3[_poolId]; + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][ + msg.sender + ]; + bool isTiedToHolder = _pool.typeOfPool == + StakerBlueprint.PoolType.StakingTiedToHolder || + _pool.typeOfPool == StakerBlueprint.PoolType.NoStakingTiedToHolder; + + uint256 accamulatedPendingTokens; + uint256 pendingTokens; + uint256 pendingPoints; + + if (isTiedToHolder) { + if (_user.amount > 0) { + pendingTokens = + ((_user.tokenBoostedAmount * _pool.tokensPerShare) / 1e12) - + _user.tokenPaid; + pendingPoints = + ((_user.pointBoostedAmount * _pool.pointsPerShare) / 1e30) - + _user.pointPaid; + _user.tokenRewards += pendingTokens; + _user.pointRewards += pendingPoints; + accamulatedPendingTokens += pendingTokens; + _pool.tokenBoostedDeposit -= _user.tokenBoostedAmount; + _pool.pointBoostedDeposit -= _user.pointBoostedAmount; + } + + (_user.tokenBoostedAmount, _user.pointBoostedAmount) = applyBoosts( + _user.amount, + _poolId, + msg.sender + ); + _pool.tokenBoostedDeposit += _user.tokenBoostedAmount; + _pool.pointBoostedDeposit += _user.pointBoostedAmount; + + _user.tokenPaid = + (_user.tokenBoostedAmount * _pool.tokensPerShare) / + 1e12; + _user.pointPaid = + (_user.pointBoostedAmount * _pool.pointsPerShare) / + 1e30; + } else { + for (uint256 i; i < _user.asset.id.length; ) { + _user.asset.id.push(_user.asset.id[i]); + StakerBlueprint.RewardsTiedToNFT storage nftRewards = b + .NFTRewards[_poolId][_user.asset.id[i]]; + pendingTokens = + ((nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / 1e12) - + nftRewards.tokenPaid; + pendingPoints = + ((nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / 1e30) - + nftRewards.pointPaid; + nftRewards.accamulatedTokenRewards += pendingTokens; + nftRewards.accamulatedPointRewards += pendingPoints; + _pool.tokenBoostedDeposit -= nftRewards + .shareOfTokenBoostedDeposited; + _pool.pointBoostedDeposit -= nftRewards + .shareOfPointBoostedDeposited; + + ( + nftRewards.shareOfTokenBoostedDeposited, + nftRewards.shareOfPointBoostedDeposited + ) = applyBoosts(1_000, _poolId, msg.sender); + _pool.tokenBoostedDeposit += nftRewards + .shareOfTokenBoostedDeposited; + _pool.pointBoostedDeposit += nftRewards + .shareOfPointBoostedDeposited; + accamulatedPendingTokens += pendingTokens; + + nftRewards.tokenPaid = + (nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / + 1e12; + nftRewards.pointPaid = + (nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / + 1e30; + unchecked { + ++i; + } + } + b.totalTokenDisbursed += accamulatedPendingTokens; + } + } + + /** + * Function that handles recalc of shares and rewards if + * some of booster multipliers that applied to user's share + * have changed. + * @param _unboosted Unboosted amount of tokens that user have staked. + * @param _poolId Id of the pool, in which we are checking. + * @param _staker Address of user which staked tokens. + */ + function checkOnBoostersChanged( + uint256 _unboosted, + uint256 _poolId, + address _staker + ) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[_staker]; + + if (_unboosted == 0) { + return; + } + if (pool.boostInfo.length == 0) { + return; + } + if (staker.boosterIds.length() == 0) { + return; + } + + for (uint256 i; i < pool.boostInfo.length; ) { + if (staker.boosterIds.contains(pool.boostInfo[i])) { + StakerBlueprint.BoostInfo storage booster = b.boostInfo[ + pool.boostInfo[i] + ]; + + uint256 _tokenPaid; + uint256 _pointPaid; + for ( + uint256 j = staker.lastNumberOfBoosterUpdate[ + pool.boostInfo[i] + ]; + j < b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length; + + ) { + uint256 changedMul; + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length + ) { + changedMul = booster.multiplier; + } else { + changedMul = booster.historyOfTokenMultipliers[j + 1]; + } + + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length && + booster.boostType == + StakerBlueprint.BoosterAssetType.Points + ) { + changedMul = 0; + } + _tokenPaid += ( + (b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + (_unboosted * + changedMul - + booster.historyOfTokenMultipliers[j] * + _unboosted)) + ); + + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length && + booster.boostType != + StakerBlueprint.BoosterAssetType.Tokens + ) { + changedMul = booster.multiplier; + } + _pointPaid += ( + (b.ppsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + (_unboosted * + changedMul - + booster.historyOfPointMultipliers[j] * + _unboosted)) + ); + unchecked { + ++j; + } + } + if (_tokenPaid > 0 || _pointPaid > 0) { + StakerBlueprint.UserInfo storage _user = b.userInfoV3[ + _poolId + ][_staker]; + _user.tokenPaid = _tokenPaid / 1e12 / 10_000; + _user.pointPaid = _pointPaid / 1e30 / 10_000; + } + } + unchecked { + ++i; + } + } + } + + /** + * Private helper function that applies boosts on deposits for Item staking. + * (amount * multiplier ) / 10_000, where multiplier is in basis points. + * (20 * 20_000) / 10_000 = 40 => 2x boost + * @param _unboosted Value that needs to have boosts applied to. + * @param _poolId Id of the pool. + * @return _boostedTokens Return tokens with applied boosts. + * @return _boostedPoints Return points with applied boosts. + */ + function applyBoosts( + uint256 _unboosted, + uint256 _poolId, + address _staker + ) internal view returns (uint256 _boostedTokens, uint256 _boostedPoints) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[_staker]; + + if (_unboosted == 0) { + return (0, 0); + } + if (pool.boostInfo.length == 0) { + return (_unboosted, _unboosted); + } + if (staker.boosterIds.length() == 0) { + return (_unboosted, _unboosted); + } + + _boostedTokens = _unboosted; + _boostedPoints = _unboosted; + + // Iterate through all the boosters that the pool supports + for (uint256 i; i < pool.boostInfo.length; ) { + if (staker.boosterIds.contains(pool.boostInfo[i])) { + StakerBlueprint.BoostInfo storage booster = b.boostInfo[ + pool.boostInfo[i] + ]; + if ( + booster.boostType == StakerBlueprint.BoosterAssetType.Tokens + ) { + _boostedTokens += + (_unboosted * booster.multiplier) / + 10_000; + } else if ( + booster.boostType == StakerBlueprint.BoosterAssetType.Points + ) { + _boostedPoints += + (_unboosted * booster.multiplier) / + 10_000; + } else { + _boostedTokens += + (_unboosted * booster.multiplier) / + 10_000; + _boostedPoints += + (_unboosted * booster.multiplier) / + 10_000; + } + } + unchecked { + ++i; + } + } + } +} diff --git a/contracts/staker/v3ds/facets/StakerV3FacetCore.sol b/contracts/staker/v3ds/facets/StakerV3FacetCore.sol new file mode 100644 index 0000000..c0f91c2 --- /dev/null +++ b/contracts/staker/v3ds/facets/StakerV3FacetCore.sol @@ -0,0 +1,727 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import "../../../base/Sweepableds.sol"; +import "../../../interfaces/ISuperGeneric.sol"; +// import "../../assets/erc721/interfaces/ISuper721.sol"; + +import "../StakerBlueprint.sol"; + +/** + * @title An asset staking contract. + * @author Tim Clancy + * @author Qazawat Zirak + * @author Nikita Elunin + * This staking contract disburses tokens from its internal reservoir according + * to a fixed emission schedule. Assets can be assigned varied staking weights. + * It also supports Items staking for boosts on native ERC20 staking rewards. + * The item staking supports Fungible, Non-Fungible and Semi-Fungible staking. + * This code is inspired by and modified from Sushi's Master Chef contract. + * https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol + */ +contract StakerV3FacetCore is Sweepableds, ERC1155Holder, IERC721Receiver { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * A function that needs to be called immediately after deployment. + * Sets the owner of the newly deployed proxy. + */ + function initialize(address _owner) external initializer { + __Ownable_init_unchained(); + transferOwnership(_owner); + } + + /** + * Add a new developer to the StakerV2 or overwrite an existing one. + * This operation requires that developer address addition is not locked. + * @param _developerAddress The additional developer's address. + * @param _share The share in 1/1_000th of a percent of each token emission sent + * to this new developer. + */ + function addDeveloper(address _developerAddress, uint256 _share) + external + hasValidPermit(UNIVERSAL, StakerBlueprint.ADD_DEVELOPER) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if (!b.canAlterDevelopers) { + revert StakerBlueprint.CantAlterDevs(); + } + b.developerAddresses.add(_developerAddress); + b.developerShares[_developerAddress] = _share; + } + + /** + * Permanently forfeits owner ability to alter the state of StakerV2 developers. + * Once called, this function is intended to give peace of mind to the StakerV2's + * developers and community that the fee structure is now immutable. + */ + function lockDevelopers() + external + hasValidPermit(UNIVERSAL, StakerBlueprint.LOCK_DEVELOPERS) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + b.canAlterDevelopers = false; + } + + /** + * A developer may at any time update their address or voluntarily reduce their + * share of emissions by calling this function from their current address. + * Note That updating a developer's share to zero effectively removes them. + * @param _newDeveloperAddress An address to update this developer's address. + * @param _newShare The new share in 1/1_000th of a percent of each token + * emission sent to this developer. + */ + function updateDeveloper(address _newDeveloperAddress, uint256 _newShare) + external + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 developerShare = b.developerShares[msg.sender]; + if (developerShare == 0) { + revert StakerBlueprint.ZeroDevShare(); + } + if (_newShare > developerShare) { + revert StakerBlueprint.CantIncreaseDevShare(); + } + if (_newShare == 0) { + b.developerAddresses.remove(msg.sender); + delete b.developerShares[msg.sender]; + } else { + if (_newDeveloperAddress != msg.sender) { + if ( + b.developerShares[_newDeveloperAddress] != 0 || + _newDeveloperAddress == address(0) + ) { + revert StakerBlueprint.InvalidNewAddress(); + } + delete b.developerShares[msg.sender]; + b.developerAddresses.remove(msg.sender); + b.developerAddresses.add(_newDeveloperAddress); + b.developerShares[_newDeveloperAddress] = _newShare; + } else if (_newShare < developerShare) { + b.developerShares[_newDeveloperAddress] = _newShare; + } + } + } + + /** + * Set new emission details to the StakerV2 or overwrite existing ones. + * This operation requires that emission schedule alteration is not locked. + * @param _tokenSchedule An array of EmissionPoints defining the token schedule. + * @param _pointSchedule An array of EmissionPoints defining the point schedule. + */ + function setEmissions( + StakerBlueprint.EmissionPoint[] memory _tokenSchedule, + StakerBlueprint.EmissionPoint[] memory _pointSchedule + ) external hasValidPermit(UNIVERSAL, StakerBlueprint.SET_EMISSIONS) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if (_tokenSchedule.length > 0) { + if (!b.canAlterTokenEmissionSchedule) { + revert StakerBlueprint.CantAlterTokenEmissionSchedule(); + } + b.tokenEmissionEventsCount = _tokenSchedule.length; + for (uint256 i; i < b.tokenEmissionEventsCount; ) { + b.tokenEmissionEvents[i] = _tokenSchedule[i]; + if ( + b.earliestTokenEmissionEvent > _tokenSchedule[i].timeStamp + ) { + b.earliestTokenEmissionEvent = _tokenSchedule[i].timeStamp; + } + unchecked { + ++i; + } + } + } + if (b.tokenEmissionEventsCount == 0) { + revert StakerBlueprint.ZeroTokenEmissionEvents(); + } + + if (_pointSchedule.length > 0) { + if (!b.canAlterPointEmissionSchedule) { + revert StakerBlueprint.CantAlterPointEmissionSchedule(); + } + b.pointEmissionEventsCount = _pointSchedule.length; + for (uint256 i; i < b.pointEmissionEventsCount; ) { + b.pointEmissionEvents[i] = _pointSchedule[i]; + if ( + b.earliestPointEmissionEvent > _pointSchedule[i].timeStamp + ) { + b.earliestPointEmissionEvent = _pointSchedule[i].timeStamp; + } + unchecked { + ++i; + } + } + } + if (b.pointEmissionEventsCount == 0) { + revert StakerBlueprint.ZeroPointEmissionEvents(); + } + } + + /** + * Permanently forfeits owner ability to alter the emission schedule. + * Once called, this function is intended to give peace of mind to the StakerV2's + * developers and community that the inflation rate is now immutable. + */ + function lockTokenEmissions() + external + hasValidPermit(UNIVERSAL, StakerBlueprint.LOCK_TOKEN_EMISSIONS) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + b.canAlterTokenEmissionSchedule = false; + } + + /** + * Permanently forfeits owner ability to alter the emission schedule. + * Once called, this function is intended to give peace of mind to the StakerV2's + * developers and community that the inflation rate is now immutable. + */ + function lockPointEmissions() + external + hasValidPermit(UNIVERSAL, StakerBlueprint.LOCK_POINT_EMISSIONS) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + b.canAlterPointEmissionSchedule = false; + } + + /** + * Create or edit boosters in batch with boost parameters + * @param _ids Array of booster IDs. + * @param _boostInfo Array of boostInfo. + * Should not be reconfigured if it was made public for staking Items. + */ + function configureBoostersBatch( + uint256[] memory _ids, + StakerBlueprint.BoostInfo[] memory _boostInfo + ) external hasValidPermit(UNIVERSAL, StakerBlueprint.CONFIGURE_BOOSTERS) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if (_boostInfo.length == 0) { + revert StakerBlueprint.EmptyBoostInfoArray(); + } + if (_ids.length != _boostInfo.length) { + revert StakerBlueprint.InputLengthsMismatch(); + } + + for (uint256 i; i < _boostInfo.length; ) { + if (_ids[i] == 0) { + revert StakerBlueprint.BoosterIdZero(); + } + if ( + (_boostInfo[i].multiplier == 0 && + _boostInfo[i].amountRequired == 0) || + _boostInfo[i].contractRequired == address(0) + ) { + revert StakerBlueprint.InvalidConfBoostersInputs(); + } + if ( + _boostInfo[i].typeOfAsset != StakerBlueprint.AssetType.ERC721 && + _boostInfo[i].typeOfAsset != StakerBlueprint.AssetType.ERC1155 + ) { + revert StakerBlueprint.InvalidConfBoostersAssetType(); + } + + unchecked { + if ( + b.boostInfo[_ids[i]].multiplier == 0 && + _boostInfo[i].multiplier != 0 + ) { + b.activeBoosters++; + } else if ( + b.boostInfo[_ids[i]].multiplier != 0 && + _boostInfo[i].multiplier == 0 + ) { + b.activeBoosters--; + } + } + + // b.boostInfo[_ids[i]].historyOfMultipliers.push( + // _boostInfo[i].multiplier + // ); + if ( + b.boostInfo[_ids[i]].multiplier != _boostInfo[i].multiplier || + b.boostInfo[_ids[i]].boostType != _boostInfo[i].boostType + ) { + if ( + _boostInfo[i].boostType == + StakerBlueprint.BoosterAssetType.Tokens + ) { + b.boostInfo[_ids[i]].historyOfTokenMultipliers.push( + _boostInfo[i].multiplier + ); + b.boostInfo[_ids[i]].historyOfPointMultipliers.push(0); + } else if ( + _boostInfo[i].boostType == + StakerBlueprint.BoosterAssetType.Points + ) { + b.boostInfo[_ids[i]].historyOfTokenMultipliers.push(0); + b.boostInfo[_ids[i]].historyOfPointMultipliers.push( + _boostInfo[i].multiplier + ); + } else { + b.boostInfo[_ids[i]].historyOfTokenMultipliers.push( + _boostInfo[i].multiplier + ); + b.boostInfo[_ids[i]].historyOfPointMultipliers.push( + _boostInfo[i].multiplier + ); + } + recalculateShares(_ids[i], _boostInfo[i].multiplier); + } + b.boostInfo[_ids[i]].multiplier = _boostInfo[i].multiplier; + b.boostInfo[_ids[i]].amountRequired = _boostInfo[i].amountRequired; + b.boostInfo[_ids[i]].groupRequired = _boostInfo[i].groupRequired; + b.boostInfo[_ids[i]].contractRequired = _boostInfo[i] + .contractRequired; + b.boostInfo[_ids[i]].boostType = _boostInfo[i].boostType; + b.boostInfo[_ids[i]].typeOfAsset = _boostInfo[i].typeOfAsset; + unchecked { + ++i; + } + } + } + + /** + * Allows the contract owner to add a new asset pool to the Staker or overwrite + * an existing one. + * @param _addPoolStruct Struct, which we use to create new pool + */ + function addPool(StakerBlueprint.AddPoolStruct memory _addPoolStruct) + external + hasValidPermit(UNIVERSAL, StakerBlueprint.ADD_POOL) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + checkInputPoolOnValid(_addPoolStruct); + + if ( + address(b.poolInfoV3[_addPoolStruct.id].assetAddress) == address(0) + ) { + addNewPool(_addPoolStruct); + } else { + changeExistingPool(_addPoolStruct); + } + } + + /** + * Update the pool corresponding to the specified token address. + * @param _poolId the id of pool to update the corresponding pool for. + */ + function updatePool( + uint256 _poolId, + uint256 _boosterId, + uint256 newMul + ) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + + if (pool.tokenBoostedDeposit == 0) { + pool.lastRewardEvent = block.timestamp; + return; + } + + // Calculate token and point rewards for this pool. + uint256 tokensReward; + uint256 pointsReward; + + tokensReward = + ((getTotalEmittedTokens(pool.lastRewardEvent, block.timestamp) * + pool.tokenStrength) / b.totalTokenStrength) * + 1e12; + pointsReward = + ((getTotalEmittedPoints(pool.lastRewardEvent, block.timestamp) * + pool.pointStrength) / b.totalPointStrength) * + 1e30; + + // Directly pay developers their corresponding share of tokens and points. + (tokensReward, pointsReward) = sendDeveloperShares( + tokensReward, + pointsReward + ); + + // Update the pool rewards per share to pay users the amount remaining. + pool.tokensPerShare += (tokensReward / pool.tokenBoostedDeposit); + b.tpsOnBoostUpdate[_boosterId][_poolId].push(pool.tokensPerShare); + pool.pointsPerShare += (pointsReward / pool.pointBoostedDeposit); + b.ppsOnBoostUpdate[_boosterId][_poolId].push(pool.pointsPerShare); + pool.lastRewardEvent = block.timestamp; + + // recalculate + uint256 unboosted = b.boosterAmount[_poolId][_boosterId]; + uint256 oldMul = b.boostInfo[_boosterId].multiplier; + StakerBlueprint.BoostInfo storage booster = b.boostInfo[_boosterId]; + if (booster.boostType == StakerBlueprint.BoosterAssetType.Tokens) { + pool.tokenBoostedDeposit = + pool.tokenBoostedDeposit - + (unboosted * oldMul) / + 10_000 + + (unboosted * newMul) / + 10_000; + } else if ( + booster.boostType == StakerBlueprint.BoosterAssetType.Points + ) { + pool.pointBoostedDeposit = + pool.pointBoostedDeposit - + (unboosted * oldMul) / + 10_000 + + (unboosted * newMul) / + 10_000; + } else { + pool.tokenBoostedDeposit = + pool.tokenBoostedDeposit - + (unboosted * oldMul) / + 10_000 + + (unboosted * newMul) / + 10_000; + pool.pointBoostedDeposit = + pool.pointBoostedDeposit - + (unboosted * oldMul) / + 10_000 + + (unboosted * newMul) / + 10_000; + } + } + + /** + * Private helper function to send developers shares + * @param tokensReward Amount of tokens that available as rewards. + * @param pointsReward Amount of points that available as rewards. + */ + function sendDeveloperShares(uint256 tokensReward, uint256 pointsReward) + internal + returns (uint256, uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + for (uint256 i; i < b.developerAddresses.length(); ) { + address developer = b.developerAddresses.at(i); + uint256 share = b.developerShares[developer]; + uint256 devTokens = (tokensReward * share) / 100_000; + tokensReward -= devTokens; + uint256 devPoints = (pointsReward * share) / 100_000; + pointsReward -= devPoints; + IERC20(b.token).safeTransfer(developer, devTokens / 1e12); + b.userPoints[developer] += (devPoints / 1e30); + unchecked { + ++i; + } + } + return (tokensReward, pointsReward); + } + + /** + * Private helper that handles recalculate total boosted amount + * and tps of pools of certain booster in case of booster multiplier + * have changed. + * @param boosterId Id of booster multiplier of which was changed. + * @param newMul New multiplier of 'boosterId'. + */ + function recalculateShares(uint256 boosterId, uint256 newMul) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + //uint256[] storage _boosterPools = b.boosterPools[_boosterId]; + + for (uint256 j; j < b.boosterPools[boosterId].length(); ) { + uint256 _poolId = b.boosterPools[boosterId].at(j); + updatePool(_poolId, boosterId, newMul); + unchecked { + ++j; + } + } + } + + /** + * Uses the emission schedule to calculate the total amount of staking reward + * token that was emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedTokens; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.tokenEmissionEventsCount; ) { + uint256 emissionTime = b.tokenEmissionEvents[i].timeStamp; + uint256 emissionRate = b.tokenEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } else if (workingTime < emissionTime) { + totalEmittedTokens += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } + + /** + * Uses the emission schedule to calculate the total amount of points + * emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedPoints; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.pointEmissionEventsCount; ) { + uint256 emissionTime = b.pointEmissionEvents[i].timeStamp; + uint256 emissionRate = b.pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } + + /** + * Private helper function that checks 'addPool' input on valid. + * @param _addPoolStruct Struct with info about pool which should + * be added. + */ + function checkInputPoolOnValid( + StakerBlueprint.AddPoolStruct memory _addPoolStruct + ) private view { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if ( + b.tokenEmissionEventsCount == 0 || b.pointEmissionEventsCount == 0 + ) { + revert StakerBlueprint.EmissionNotSet(); + } + if ( + _addPoolStruct.typeOfAsset != StakerBlueprint.AssetType.ERC721 && + (_addPoolStruct.typeOfPool == + StakerBlueprint.PoolType.NoStakingTiedToNFT || + _addPoolStruct.typeOfPool == + StakerBlueprint.PoolType.StakingTiedToNFT) + ) { + revert StakerBlueprint.WrongTypeOfPoolForTypeOfAsset(); + } + + if (_addPoolStruct.typeOfAsset == StakerBlueprint.AssetType.ERC721) { + if ( + !IERC721(_addPoolStruct.assetAddress).supportsInterface( + StakerBlueprint.INTERFACE_ERC721 + ) + ) { + revert StakerBlueprint.InvalidAsset(); + } + } else if ( + _addPoolStruct.typeOfAsset == StakerBlueprint.AssetType.ERC1155 + ) { + if ( + !IERC1155(_addPoolStruct.assetAddress).supportsInterface( + StakerBlueprint.INTERFACE_ERC1155 + ) + ) { + revert StakerBlueprint.InvalidAsset(); + } + } + + if ( + _addPoolStruct.tokenStrength == 0 || + _addPoolStruct.pointStrength == 0 + ) { + revert StakerBlueprint.ZeroStrength(); + } + if ( + _addPoolStruct.groupId != 0 && + _addPoolStruct.typeOfAsset == StakerBlueprint.AssetType.ERC20 + ) { + revert StakerBlueprint.InvalidGroupIdForERC20(); + } + } + + /** + * Private helper function that determines and returns last time when + * rewards was calculated. + */ + function determineLastRewardEvent() private view returns (uint256) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 lastTokenRewardTime = block.timestamp > + b.earliestTokenEmissionEvent + ? block.timestamp + : b.earliestTokenEmissionEvent; + uint256 lastPointRewardTime = block.timestamp > + b.earliestPointEmissionEvent + ? block.timestamp + : b.earliestPointEmissionEvent; + uint256 lastRewardEvent = lastTokenRewardTime > lastPointRewardTime + ? lastTokenRewardTime + : lastPointRewardTime; + + return lastRewardEvent; + } + + /** + * Private helper function that handles adds of the new pool. + * @param _addPoolStruct Struct that contains info about new pool. + */ + function addNewPool(StakerBlueprint.AddPoolStruct memory _addPoolStruct) + private + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 lastRewardEvent = determineLastRewardEvent(); + + b.poolAssets.push(_addPoolStruct.assetAddress); + b.totalTokenStrength = + b.totalTokenStrength + + _addPoolStruct.tokenStrength; + b.totalPointStrength = + b.totalPointStrength + + _addPoolStruct.pointStrength; + + b.poolInfoV3[_addPoolStruct.id].assetAddress = _addPoolStruct + .assetAddress; + b.poolInfoV3[_addPoolStruct.id].tokenStrength = _addPoolStruct + .tokenStrength; + b.poolInfoV3[_addPoolStruct.id].tokensPerShare = _addPoolStruct + .tokensPerShare; + b.poolInfoV3[_addPoolStruct.id].pointStrength = _addPoolStruct + .pointStrength; + b.poolInfoV3[_addPoolStruct.id].pointsPerShare = _addPoolStruct + .pointsPerShare; + + if ( + _addPoolStruct.typeOfPool == + StakerBlueprint.PoolType.NoStakingTiedToHolder || + _addPoolStruct.typeOfPool == + StakerBlueprint.PoolType.NoStakingTiedToNFT + ) { + b.poolInfoV3[_addPoolStruct.id].tokenBoostedDeposit = ISuperGeneric( + _addPoolStruct.assetAddress + ).totalSupply(); + b.poolInfoV3[_addPoolStruct.id].pointBoostedDeposit = ISuperGeneric( + _addPoolStruct.assetAddress + ).totalSupply(); + } else { + b.poolInfoV3[_addPoolStruct.id].tokenBoostedDeposit = 0; + b.poolInfoV3[_addPoolStruct.id].pointBoostedDeposit = 0; + } + b.poolInfoV3[_addPoolStruct.id].groupId = _addPoolStruct.groupId; + b.poolInfoV3[_addPoolStruct.id].lastRewardEvent = lastRewardEvent; + b.poolInfoV3[_addPoolStruct.id].boostInfo = _addPoolStruct.boostInfo; + for (uint256 i; i < _addPoolStruct.boostInfo.length; ) { + b.boosterPools[_addPoolStruct.boostInfo[i]].add(_addPoolStruct.id); + unchecked { + ++i; + } + } + b.poolInfoV3[_addPoolStruct.id].typeOfPool = _addPoolStruct.typeOfPool; + b.poolInfoV3[_addPoolStruct.id].typeOfAsset = _addPoolStruct + .typeOfAsset; + } + + /** + * Private helper function that handles changes of the existing pool. + * @param _addPoolStruct Struct that contains info about changes of the pool. + */ + function changeExistingPool( + StakerBlueprint.AddPoolStruct memory _addPoolStruct + ) private { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + b.totalTokenStrength = + (b.totalTokenStrength - + b.poolInfoV3[_addPoolStruct.id].tokenStrength) + + _addPoolStruct.tokenStrength; + b.poolInfoV3[_addPoolStruct.id].tokenStrength = _addPoolStruct + .tokenStrength; + b.totalPointStrength = + (b.totalPointStrength - + b.poolInfoV3[_addPoolStruct.id].pointStrength) + + _addPoolStruct.pointStrength; + b.poolInfoV3[_addPoolStruct.id].pointStrength = _addPoolStruct + .pointStrength; + + for (uint256 i; i < _addPoolStruct.boostInfo.length; ) { + if ( + !b.boosterPools[_addPoolStruct.boostInfo[i]].contains( + _addPoolStruct.id + ) + ) { + b.boosterPools[_addPoolStruct.boostInfo[i]].add( + _addPoolStruct.id + ); + b.poolInfoV3[_addPoolStruct.id].boostInfo.push( + _addPoolStruct.boostInfo[i] + ); + } + unchecked { + ++i; + } + } + } + + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external override returns (bytes4) { + return this.onERC721Received.selector; + } +} diff --git a/contracts/staker/v3ds/facets/StakerV3FacetPoints.sol b/contracts/staker/v3ds/facets/StakerV3FacetPoints.sol new file mode 100644 index 0000000..3c1543e --- /dev/null +++ b/contracts/staker/v3ds/facets/StakerV3FacetPoints.sol @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "../../../base/Sweepableds.sol"; +import "../../../interfaces/ISuperGeneric.sol"; + +import "../StakerBlueprint.sol"; + +/** + * @title An asset staking contract. + * @author Tim Clancy + * @author Qazawat Zirak + * @author Nikita Elunin + * This staking contract disburses tokens from its internal reservoir according + * to a fixed emission schedule. Assets can be assigned varied staking weights. + * It also supports Items staking for boosts on native ERC20 staking rewards. + * The item staking supports Fungible, Non-Fungible and Semi-Fungible staking. + * This code is inspired by and modified from Sushi's Master Chef contract. + * https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol + */ +contract StakerV3FacetPoints is Sweepableds { + /** + * Uses the emission schedule to calculate the total amount of points + * emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedPoints; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.pointEmissionEventsCount; ) { + uint256 emissionTime = b.pointEmissionEvents[i].timeStamp; + uint256 emissionRate = b.pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } + + /** + * A function to easily see the amount of point rewards pending for a user on a + * given pool. Returns the pending reward point amount. + * @param _poolId The address of a particular staking pool asset to check for a + * pending reward. + * @param _user The user address to check for a pending reward. + * @return The pending reward token amount. + */ + function getPendingPoints(uint256 _poolId, address _user) + public + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.UserInfo storage user = b.userInfoV3[_poolId][_user]; + uint256 pointsPerShare = pool.pointsPerShare; + uint256 pointBoostedDeposit = pool.pointBoostedDeposit; + + if (block.timestamp > pool.lastRewardEvent && pointBoostedDeposit > 0) { + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardEvent, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + b.totalPointStrength) * 1e30; + pointsPerShare += (pointsReward / pointBoostedDeposit); + } + + return + ((user.pointBoostedAmount * pointsPerShare) / 1e30) - + user.pointPaid; + } + + /** + * Return the number of points that the user has available to spend. + * @param _user The user whose available points we want to get. + * @return The number of points that the user has available to spend. + */ + function getAvailablePoints(address _user) public view returns (uint256) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 pendingTotal; + for (uint256 i; i < b.poolAssets.length; ) { + uint256 _pendingPoints = getPendingPoints(i, _user); + pendingTotal += _pendingPoints; + unchecked { + ++i; + } + } + return (b.userPoints[_user] + pendingTotal) - b.userSpentPoints[_user]; + } + + /** + * Return the total number of points that the user has ever accrued. + * @param _user The user whose total points we want to get. + * @return The total number of points that the user has ever accrued. + */ + function getTotalPoints(address _user) external view returns (uint256) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 pendingTotal; + for (uint256 i; i < b.poolAssets.length; ) { + uint256 _pendingPoints = getPendingPoints(i, _user); + pendingTotal += _pendingPoints; + unchecked { + ++i; + } + } + return b.userPoints[_user] + pendingTotal; + } + + /** + * Allows the owner of this Staker to grant or remove approval to an external + * spender of the points that users accrue from staking resources. + * @param _spender The external address allowed to spend user points. + * @param _approval The updated user approval status. + */ + function approvePointSpender(address _spender, bool _approval) + external + hasValidPermit(UNIVERSAL, StakerBlueprint.APPROVE_POINT_SPENDER) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + b.approvedPointSpenders[_spender] = _approval; + } + + /** + * Allows an approved spender of points to spend points on behalf of a user. + * @param _user The user whose points are being spent. + * @param _amount The amount of the user's points being spent. + */ + function spendPoints(address _user, uint256 _amount) external { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if (!b.approvedPointSpenders[msg.sender]) { + revert StakerBlueprint.NotApprovedPointSpender(); + } + if (getAvailablePoints(_user) < _amount) { + revert StakerBlueprint.InvalidAmount(); + } + b.userSpentPoints[_user] += _amount; + emit StakerBlueprint.SpentPoints(msg.sender, _user, _amount); + } +} diff --git a/contracts/staker/v3ds/facets/StakerV3FacetStaking.sol b/contracts/staker/v3ds/facets/StakerV3FacetStaking.sol new file mode 100644 index 0000000..ec808be --- /dev/null +++ b/contracts/staker/v3ds/facets/StakerV3FacetStaking.sol @@ -0,0 +1,1211 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import "../../../base/Sweepableds.sol"; +import "../../../interfaces/ISuperGeneric.sol"; + +import "../StakerBlueprint.sol"; +import "hardhat/console.sol"; + +/** + * @title An asset staking contract. + * @author Tim Clancy + * @author Qazawat Zirak + * @author Nikita Elunin + * This staking contract disburses tokens from its internal reservoir according + * to a fixed emission schedule. Assets can be assigned varied staking weights. + * It also supports Items staking for boosts on native ERC20 staking rewards. + * The item staking supports Fungible, Non-Fungible and Semi-Fungible staking. + * This code is inspired by and modified from Sushi's Master Chef contract. + * https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol + */ +contract StakerV3FacetStaking is Sweepableds { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /// Event for depositing NonFungible assets. + event Deposit( + address indexed user, + uint256 indexed _poolId, + uint256[] amount, + uint256[] itemIds, + address collection + ); + + /// Event for withdrawing NonFungible assets. + event Withdraw( + address indexed user, + uint256 indexed _poolId, + uint256[] amount, + uint256[] itemIds, + address collection + ); + + /// Event for claiming rewards from Fungible assets. + event Claim( + address indexed user, + uint256 indexed _poolId, + uint256 tokenRewards, + uint256 pointRewards + ); + + /// An event for tracking when a user has spent points. + event SpentPoints( + address indexed source, + address indexed user, + uint256 amount + ); + + /// An event for tracking when user locking tokens on pool + event TokenLock( + address indexed user, + uint256 indexed poolId, + uint256 lockedAt + ); + + /// An event for tracking when user locking tokens on pool + event TokenUnlock(address indexed user, uint256 indexed poolId); + + /** + * Uses the emission schedule to calculate the total amount of staking reward + * token that was emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedTokens(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedTokens; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.tokenEmissionEventsCount; ) { + uint256 emissionTime = b.tokenEmissionEvents[i].timeStamp; + uint256 emissionRate = b.tokenEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } else if (workingTime < emissionTime) { + totalEmittedTokens += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedTokens += ((_toTime - workingTime) * workingRate); + return totalEmittedTokens; + } + + /** + * Uses the emission schedule to calculate the total amount of points + * emitted between two specified timestamps. + * @param _fromTime The time to begin calculating emissions from. + * @param _toTime The time to calculate total emissions up to. + */ + function getTotalEmittedPoints(uint256 _fromTime, uint256 _toTime) + internal + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 totalEmittedPoints; + uint256 workingRate; + uint256 workingTime = _fromTime; + for (uint256 i; i < b.pointEmissionEventsCount; ) { + uint256 emissionTime = b.pointEmissionEvents[i].timeStamp; + uint256 emissionRate = b.pointEmissionEvents[i].rate; + if (_toTime < emissionTime) { + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } else if (workingTime < emissionTime) { + totalEmittedPoints += ((emissionTime - workingTime) * + workingRate); + workingTime = emissionTime; + } + workingRate = emissionRate; + unchecked { + ++i; + } + } + totalEmittedPoints += ((_toTime - workingTime) * workingRate); + return totalEmittedPoints; + } + + /** + * A function to easily see the amount of token rewards pending for a user on a + * given pool. Returns the pending reward token amount. + * @param _poolId The id of a particular staking pool asset to check for a + * pending reward. + * @param _user The user address to check for a pending reward. + * @return The pending reward token amount. + */ + function getPendingTokens(uint256 _poolId, address _user) + public + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.UserInfo storage user = b.userInfoV3[_poolId][_user]; + uint256 tokensPerShare = pool.tokensPerShare; + uint256 tokenBoostedDeposit = pool.tokenBoostedDeposit; + + if (block.timestamp > pool.lastRewardEvent && tokenBoostedDeposit > 0) { + uint256 totalEmittedTokens = getTotalEmittedTokens( + pool.lastRewardEvent, + block.timestamp + ); + uint256 tokensReward = ((totalEmittedTokens * pool.tokenStrength) / + b.totalTokenStrength) * 1e12; + tokensPerShare += (tokensReward / tokenBoostedDeposit); + } + + return + ((user.tokenBoostedAmount * tokensPerShare) / 1e12) - + user.tokenPaid; + } + + /** + * A function to easily see the amount of point rewards pending for a user on a + * given pool. Returns the pending reward point amount. + * @param _poolId The address of a particular staking pool asset to check for a + * pending reward. + * @param _user The user address to check for a pending reward. + * @return The pending reward token amount. + */ + function getPendingPoints(uint256 _poolId, address _user) + public + view + returns (uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo memory pool = b.poolInfoV3[_poolId]; + StakerBlueprint.UserInfo memory user = b.userInfoV3[_poolId][_user]; + uint256 pointsPerShare = pool.pointsPerShare; + uint256 pointBoostedDeposit = pool.pointBoostedDeposit; + + if (block.timestamp > pool.lastRewardEvent && pointBoostedDeposit > 0) { + uint256 totalEmittedPoints = getTotalEmittedPoints( + pool.lastRewardEvent, + block.timestamp + ); + uint256 pointsReward = ((totalEmittedPoints * pool.pointStrength) / + b.totalPointStrength) * 1e30; + pointsPerShare += (pointsReward / pointBoostedDeposit); + } + + return + ((user.pointBoostedAmount * pointsPerShare) / 1e30) - + user.pointPaid; + } + + /** + * Update the pool corresponding to the specified token address. + * @param _poolId The id of pool to update the corresponding pool for. + */ + function updatePool(uint256 _poolId) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + + if (pool.tokenBoostedDeposit == 0) { + pool.lastRewardEvent = block.timestamp; + return; + } + + // Calculate token and point rewards for this pool. + uint256 tokensReward; + uint256 pointsReward; + + tokensReward = + ((getTotalEmittedTokens(pool.lastRewardEvent, block.timestamp) * + pool.tokenStrength) / b.totalTokenStrength) * + 1e12; + pointsReward = + ((getTotalEmittedPoints(pool.lastRewardEvent, block.timestamp) * + pool.pointStrength) / b.totalPointStrength) * + 1e30; + + // Directly pay developers their corresponding share of tokens and points. + (tokensReward, pointsReward) = sendDeveloperShares( + tokensReward, + pointsReward + ); + + // Update the pool rewards per share to pay users the amount remaining. + pool.tokensPerShare += (tokensReward / pool.tokenBoostedDeposit); + pool.pointsPerShare += (pointsReward / pool.pointBoostedDeposit); + pool.lastRewardEvent = block.timestamp; + } + + /** + * Private helper function to send developers shares + * @param tokensReward Amount of tokens that available as rewards. + * @param pointsReward Amount of points that available as rewards. + */ + function sendDeveloperShares(uint256 tokensReward, uint256 pointsReward) + internal + returns (uint256, uint256) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + for (uint256 i; i < b.developerAddresses.length(); ) { + address developer = b.developerAddresses.at(i); + uint256 share = b.developerShares[developer]; + uint256 devTokens = (tokensReward * share) / 100_000; + tokensReward -= devTokens; + uint256 devPoints = (pointsReward * share) / 100_000; + pointsReward -= devPoints; + // TODO: think about not perform the transfer in 'updatePool' function + // but store developers rewards in mapping. + IERC20(b.token).safeTransfer(developer, devTokens / 1e12); + b.userPoints[developer] += (devPoints / 1e30); + unchecked { + ++i; + } + } + return (tokensReward, pointsReward); + } + + /** + * Private helper function to update the deposits based on new shares. + * @param _ids Array of token ids that was deposited. + * @param _ids Array of amounts of tokens that was deposited. + * @param _poolId Id of the pool, in which we are operating. + * @param _isDeposit Flag that represents the caller function. True is for deposit, + * false is for withdraw. + */ + function updateDeposits( + uint256[] memory _ids, + uint256 _amount, + uint256 _poolId, + bool _isDeposit, + address _staker + ) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage _pool = b.poolInfoV3[_poolId]; + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][_staker]; + + uint256 accamulatedPendingTokens; + uint256 pendingTokens; + uint256 pendingPoints; + + // check if booster was changed + // TODO: think about case in pools with RewardsTiedToNFT + checkOnBoostersChanged(_user.amount, _poolId, _staker); + + // isTiedToHolder + if ( + _pool.typeOfPool == StakerBlueprint.PoolType.StakingTiedToHolder || + _pool.typeOfPool == StakerBlueprint.PoolType.NoStakingTiedToHolder + ) { + if (_user.amount > 0) { + pendingTokens = + ((_user.tokenBoostedAmount * _pool.tokensPerShare) / 1e12) - + _user.tokenPaid; + pendingPoints = + ((_user.pointBoostedAmount * _pool.pointsPerShare) / 1e30) - + _user.pointPaid; + _user.tokenRewards += pendingTokens; + _user.pointRewards += pendingPoints; + accamulatedPendingTokens += pendingTokens; + _pool.tokenBoostedDeposit -= _user.tokenBoostedAmount; + _pool.pointBoostedDeposit -= _user.pointBoostedAmount; + } + + // Preventing stack too deep. + { + // Extra multiplier for ERC721 and ERC1155 to make calculations + // more accurate. + uint256 nftMul = 1_000; + if (_pool.typeOfAsset == StakerBlueprint.AssetType.ERC20) { + nftMul = 1; + } + if (_isDeposit) { + _user.amount += _amount * nftMul; + } else { + _user.amount -= _amount * nftMul; + } + } + + (_user.tokenBoostedAmount, _user.pointBoostedAmount) = applyBoosts( + _user.amount, + _poolId, + _staker, + _isDeposit, + _ids.length + ); + _pool.tokenBoostedDeposit += _user.tokenBoostedAmount; + _pool.pointBoostedDeposit += _user.pointBoostedAmount; + + _user.tokenPaid = + (_user.tokenBoostedAmount * _pool.tokensPerShare) / + 1e12; + _user.pointPaid = + (_user.pointBoostedAmount * _pool.pointsPerShare) / + 1e30; + } else { + // TODO: think about to remove loops with whole users rewards divisioned + // by number of nfts and add logic in claim functions + uint256 length = _ids.length; + for (uint256 i; i < length; ) { + _user.asset.id.push(_ids[i]); + StakerBlueprint.RewardsTiedToNFT storage nftRewards = b + .NFTRewards[_poolId][_ids[i]]; + pendingTokens = + ((nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / 1e12) - + nftRewards.tokenPaid; + pendingPoints = + ((nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / 1e30) - + nftRewards.pointPaid; + nftRewards.accamulatedTokenRewards += pendingTokens; + nftRewards.accamulatedPointRewards += pendingPoints; + _pool.tokenBoostedDeposit -= nftRewards + .shareOfTokenBoostedDeposited; + _pool.pointBoostedDeposit -= nftRewards + .shareOfPointBoostedDeposited; + + ( + nftRewards.shareOfTokenBoostedDeposited, + nftRewards.shareOfPointBoostedDeposited + ) = applyBoosts(1_000, _poolId, _staker, _isDeposit, 1); + if (_isDeposit) { + _pool.tokenBoostedDeposit += nftRewards + .shareOfTokenBoostedDeposited; + _pool.pointBoostedDeposit += nftRewards + .shareOfPointBoostedDeposited; + accamulatedPendingTokens += pendingTokens; + } else { + delete nftRewards.shareOfTokenBoostedDeposited; + delete nftRewards.shareOfPointBoostedDeposited; + } + + nftRewards.tokenPaid = + (nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / + 1e12; + nftRewards.pointPaid = + (nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / + 1e30; + unchecked { + ++i; + } + } + } + b.totalTokenDisbursed += accamulatedPendingTokens; + } + + /** + * Function that executes when IOU token is transerring and recalculate + * shares on staker of previus and new owners of token. + * @param _poolId Id of the pool that IOU token links to. + * @param _tokenId The ID of the token being transferred. + * @param _from The address to transfer the token from. + * @param _to The address to transfer the token to. + */ + function updateOnIouTransfer( + uint256 _poolId, + uint256 _tokenId, + address _from, + address _to + ) external { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256[] memory id = new uint256[](1); + id[0] = b.IOUIdToStakedAsset[_poolId][_tokenId].id[0]; + uint256 totalAmount; + for ( + uint256 i; + i < b.IOUIdToStakedAsset[_poolId][_tokenId].amounts.length; + + ) { + totalAmount += b.IOUIdToStakedAsset[_poolId][_tokenId].amounts[i]; + unchecked { + ++i; + } + } + updatePool(_poolId); + updateDeposits(id, totalAmount, _poolId, false, _from); + updateDeposits(id, totalAmount, _poolId, true, _to); + } + + /** + * Private helper function that applies boosts on deposits for Item staking. + * (amount * multiplier ) / 10_000, where multiplier is in basis points. + * (20 * 20_000) / 10_000 = 40 => 2x boost + * @param _unboosted Value that needs to have boosts applied to. + * @param _poolId Id of the pool. + * @return _boostedTokens Return tokens with applied boosts. + * @return _boostedPoints Return points with applied boosts. + */ + function applyBoosts( + uint256 _unboosted, + uint256 _poolId, + address _staker, + bool isDeposit, + uint256 _changedValue + ) internal returns (uint256 _boostedTokens, uint256 _boostedPoints) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[_staker]; + + if (_unboosted == 0) { + return (0, 0); + } + if (pool.boostInfo.length == 0) { + return (_unboosted, _unboosted); + } + if (staker.boosterIds.length() == 0) { + return (_unboosted, _unboosted); + } + + _boostedTokens = _unboosted; + _boostedPoints = _unboosted; + + // Iterate through all the boosters that the pool supports + for (uint256 i; i < pool.boostInfo.length; ) { + if (staker.boosterIds.contains(pool.boostInfo[i])) { + StakerBlueprint.BoostInfo storage booster = b.boostInfo[ + pool.boostInfo[i] + ]; + + // Calculate boosted amount of certain boost for handle booster change cases. + // Also preventing stack too deep. + { + // Extra multiplier for ERC721 and ERC1155 tokens to make calculations + // more accurate. + uint256 nftMul = 1_000; + if (pool.typeOfAsset == StakerBlueprint.AssetType.ERC20) { + nftMul = 1; + } + if (isDeposit) { + b.boosterAmount[_poolId][pool.boostInfo[i]] += + _changedValue * + nftMul; + } else { + b.boosterAmount[_poolId][pool.boostInfo[i]] -= + _changedValue * + nftMul; + } + } + if ( + booster.boostType == StakerBlueprint.BoosterAssetType.Tokens + ) { + _boostedTokens += + (_unboosted * booster.multiplier) / + 10_000; + } else if ( + booster.boostType == StakerBlueprint.BoosterAssetType.Points + ) { + _boostedPoints += + (_unboosted * booster.multiplier) / + 10_000; + } else { + _boostedTokens += + (_unboosted * booster.multiplier) / + 10_000; + _boostedPoints += + (_unboosted * booster.multiplier) / + 10_000; + } + } + unchecked { + ++i; + } + } + } + + /** + * Function that handles recalc of shares and rewards if + * some of booster multipliers that applied to user's share + * have changed. + * @param _unboosted Unboosted amount of tokens that user have staked. + * @param _poolId Id of the pool. + * @param _staker Address of user which staked tokens. + */ + function checkOnBoostersChanged( + uint256 _unboosted, + uint256 _poolId, + address _staker + ) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + StakerBlueprint.ItemUserInfo storage staker = b.itemUserInfo[_staker]; + + if (_unboosted == 0) { + return; + } + if (pool.boostInfo.length == 0) { + return; + } + if (staker.boosterIds.length() == 0) { + return; + } + + for (uint256 i; i < pool.boostInfo.length; ) { + if (staker.boosterIds.contains(pool.boostInfo[i])) { + StakerBlueprint.BoostInfo storage booster = b.boostInfo[ + pool.boostInfo[i] + ]; + + uint256 _tokenMissed; + uint256 _tokenGained; + uint256 _pointMissed; + uint256 _pointGained; + for ( + uint256 j = staker.lastNumberOfBoosterUpdate[ + pool.boostInfo[i] + ]; + j < b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length; + j++ + ) { + uint256 changedMul; + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length + ) { + changedMul = booster.multiplier; + } else { + changedMul = booster.historyOfTokenMultipliers[j + 1]; + } + + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length && + booster.boostType == + StakerBlueprint.BoosterAssetType.Points + ) { + changedMul = 0; + } + if (changedMul > booster.historyOfTokenMultipliers[j]) { + _tokenMissed += ( + (b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + ((_unboosted * + (changedMul - + booster.historyOfTokenMultipliers[j])) / + 10_000)) + ); + } else { + _tokenGained += ( + (b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + ((_unboosted * + (booster.historyOfTokenMultipliers[j] - + changedMul)) / 10_000)) + ); + } + + if ( + j + 1 == + b.tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length && + booster.boostType != + StakerBlueprint.BoosterAssetType.Tokens + ) { + changedMul = booster.multiplier; + } + if (changedMul > booster.historyOfTokenMultipliers[j]) { + _pointMissed += ( + (b.ppsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + ((_unboosted * + (changedMul - + booster.historyOfPointMultipliers[j])) / + 10_000)) + ); + } else { + _pointGained += ( + (b.ppsOnBoostUpdate[pool.boostInfo[i]][_poolId][j] * + ((_unboosted * + (booster.historyOfPointMultipliers[j] - + changedMul)) / 10_000)) + ); + } + } + + staker.lastNumberOfBoosterUpdate[pool.boostInfo[i]] = b + .tpsOnBoostUpdate[pool.boostInfo[i]][_poolId].length; + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][ + _staker + ]; + + if (_tokenMissed > _tokenGained) { + _user.tokenPaid += (_tokenMissed - _tokenGained) / 1e12; + } else { + if (_tokenGained / 1e12 < _user.tokenPaid) { + _user.tokenPaid -= _tokenGained / 1e12; + } + } + if (_pointMissed > _pointGained) { + _user.pointPaid += (_pointMissed - _pointGained) / 1e30; + } else { + if (_pointGained / 1e30 < _user.pointPaid) { + _user.pointPaid -= _pointGained / 1e30; + } + } + } + unchecked { + ++i; + } + } + + ( + b.userInfoV3[_poolId][_staker].tokenBoostedAmount, + b.userInfoV3[_poolId][_staker].pointBoostedAmount + ) = applyBoosts(_unboosted, _poolId, _staker, false, 0); + } + + /** + * Deposit some particular assets to a particular pool on the Staker. + * When asset for stake in the pool is ERC20, you should set input _asset's amounts + * with length equal to 1(same for id length). + * @param _poolId The pool id. + * @param _asset Asset user wants to deposit + */ + function deposit( + uint256 _poolId, + StakerBlueprint.StakedAsset memory _asset, + bool isLocking + ) external { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.AssetType typeOfAsset; + + StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + + if ( + pool.typeOfPool != StakerBlueprint.PoolType.StakingTiedToHolder && + pool.typeOfPool != StakerBlueprint.PoolType.StakingTiedToNFT + ) { + revert StakerBlueprint.InvalidTypeOfPool(); + } + if (_asset.id.length != _asset.amounts.length) { + revert StakerBlueprint.AssetArrayLengthsMismatch(); + } + + if (pool.tokenStrength == 0) { + revert StakerBlueprint.InactivePool(); + } + if (_asset.assetAddress != pool.assetAddress) { + revert StakerBlueprint.InvalidAssetToStake(); + } + if (pool.groupId > 0) { + for (uint256 i; i < _asset.id.length; ) { + if (_asset.id[i] >> 128 != pool.groupId) { + revert StakerBlueprint.InvalidGroupIdForStake(); + } + unchecked { + ++i; + } + } + } + + typeOfAsset = pool.typeOfAsset; + uint256 amount; + + uint256[] memory IOUTokenIdsToMint = new uint256[]( + _asset.amounts.length + ); + uint256 IOUTokenCounter = b.nextIOUTokenId; + if ( + typeOfAsset == StakerBlueprint.AssetType.ERC20 && + _asset.amounts.length != 1 + ) { + revert StakerBlueprint.InvalidERC20DepositInputs(); + } + for (uint256 i; i < _asset.amounts.length; ) { + amount += _asset.amounts[i]; + b.IOUIdToStakedAsset[_poolId][IOUTokenCounter].assetAddress = _asset + .assetAddress; + b.IOUIdToStakedAsset[_poolId][IOUTokenCounter].amounts.push( + _asset.amounts[i] + ); + b.IOUIdToStakedAsset[_poolId][IOUTokenCounter].id.push( + _asset.id[i] + ); + IOUTokenIdsToMint[i] = IOUTokenCounter; + unchecked { + ++IOUTokenCounter; + ++i; + } + } + + b.nextIOUTokenId = IOUTokenCounter; + + ISuperGeneric(b.IOUTokenAddress).mintBatch( + msg.sender, + IOUTokenIdsToMint, + "" + ); + updatePool(_poolId); + updateDeposits(_asset.id, amount, _poolId, true, msg.sender); + + if (typeOfAsset == StakerBlueprint.AssetType.ERC721) { + for (uint256 i; i < _asset.amounts.length; ) { + if (_asset.amounts[i] != 1) { + revert StakerBlueprint.InvalidERC721Amount(); + } + unchecked { + ++i; + } + } + ISuperGeneric(_asset.assetAddress).safeBatchTransferFrom( + msg.sender, + address(this), + _asset.id, + "" + ); + } else if (typeOfAsset == StakerBlueprint.AssetType.ERC1155) { + ISuperGeneric(_asset.assetAddress).safeBatchTransferFrom( + msg.sender, + address(this), + _asset.id, + _asset.amounts, + "" + ); + } else { + IERC20(pool.assetAddress).safeTransferFrom( + msg.sender, + address(this), + amount + ); + } + + emit Deposit( + msg.sender, + _poolId, + _asset.amounts, + _asset.id, + pool.assetAddress + ); + } + + /** + * Withdraw some particular assets from a particular pool on the Staker. + * @param _poolId The id of pool, withdraw tokens from. + * @param IOUTokenIds Array of IOU token ids bonded to which you want to withdraw. + */ + function withdraw(uint256 _poolId, uint256[] calldata IOUTokenIds) + external + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + if ( + b.poolInfoV3[_poolId].typeOfPool != + StakerBlueprint.PoolType.StakingTiedToHolder && + b.poolInfoV3[_poolId].typeOfPool != + StakerBlueprint.PoolType.StakingTiedToNFT + ) { + revert StakerBlueprint.InvalidTypeOfPool(); + } + + address assetAddress; + StakerBlueprint.AssetType typeOfAsset; + + uint256 amount; + + assetAddress = b.poolInfoV3[_poolId].assetAddress; + + uint256[] memory amounts = new uint256[](IOUTokenIds.length); + uint256[] memory ids = new uint256[](IOUTokenIds.length); + + updatePool(_poolId); + + for (uint256 i; i < amounts.length; ) { + if ( + ISuperGeneric(b.IOUTokenAddress).ownerOf(IOUTokenIds[i]) != + msg.sender + ) { + revert StakerBlueprint.NotAnOwnerOfIOUToken(); + } + // TODO: try to redesign the 'IOUIdToStakedAsset' mapping by erase + // unneceassary key '_poolID', and maybe erase 'poolId' from input + // of 'withdraw' function if we gonna withdraw via IOU tokens. + if (b.IOUIdToStakedAsset[_poolId][IOUTokenIds[i]].id.length == 0) { + revert StakerBlueprint.IOUTokenFromDifferentPool(); + } + ids[i] = b.IOUIdToStakedAsset[_poolId][IOUTokenIds[i]].id[0]; + amounts[i] = b.IOUIdToStakedAsset[_poolId][IOUTokenIds[i]].amounts[ + 0 + ]; + unchecked { + amount += amounts[i]; + ++i; + } + } + typeOfAsset = b.poolInfoV3[_poolId].typeOfAsset; + + updateDeposits(ids, amount, _poolId, false, msg.sender); + ISuperGeneric(b.IOUTokenAddress).burnBatch(msg.sender, IOUTokenIds); + + if (typeOfAsset == StakerBlueprint.AssetType.ERC721) { + ISuperGeneric(assetAddress).safeBatchTransferFrom( + address(this), + msg.sender, + ids, + "" + ); + } else if (typeOfAsset == StakerBlueprint.AssetType.ERC1155) { + ISuperGeneric(assetAddress).safeBatchTransferFrom( + address(this), + msg.sender, + ids, + amounts, + "" + ); + } else { + IERC20(assetAddress).safeTransfer(msg.sender, amount); + } + emit Withdraw(msg.sender, _poolId, amounts, ids, assetAddress); + } + + /** + * Claim accumulated token and point rewards from the Staker. + * @param _poolId The id of pool to claim rewards from. + * @param _data Bytes with calldata for use by backend, casual users should send empty bytes array. + */ + function claim(uint256 _poolId, bytes memory _data) external { + if (_data.length == 0) { + _claim(_poolId); + } else { + bytes32 _hash; + StakerBlueprint.Sig memory _sig; + StakerBlueprint.Checkpoint memory _checkpoints; + + (_hash, _sig, _checkpoints) = serializeClaimData(_data); + _claim(_poolId, _hash, _sig, _checkpoints); + } + } + + /** Private helper function that serialize input data for claim with checkpoints. + * @param _data Bytes32 data that contains checkpoints and signature. + * @return _hash Data hash. + * @return _sig Struct that contains v,r and s parts of signature. + * @return _checkpoints Struct that contains info about balance of user at certain amounts of time. + */ + function serializeClaimData(bytes memory _data) + private + pure + returns ( + bytes32 _hash, + StakerBlueprint.Sig memory _sig, + StakerBlueprint.Checkpoint memory _checkpoints + ) + { + uint8 _v; + bytes32 _r; + bytes32 _s; + uint256 checkpointsLength; + + assembly { + _hash := mload(add(_data, 32)) + _v := mload(add(_data, 64)) + _r := mload(add(_data, 96)) + _s := mload(add(_data, 128)) + checkpointsLength := mload(add(_data, 160)) + } + + uint256[] memory _startTime = new uint256[](checkpointsLength); + uint256[] memory _endTime = new uint256[](checkpointsLength); + uint256[] memory _tokensBalance = new uint256[](checkpointsLength); + uint256[] memory _pointsBalance = new uint256[](checkpointsLength); + uint256[] memory _tps = new uint256[](checkpointsLength); + uint256[] memory _pps = new uint256[](checkpointsLength); + uint256 oldPointer = 192; + + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _startTime + ); + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _endTime + ); + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _tokensBalance + ); + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _pointsBalance + ); + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _tps + ); + oldPointer = parseCheckpointsArray( + _data, + oldPointer, + checkpointsLength, + _pps + ); + + _sig.v = _v; + _sig.r = _r; + _sig.s = _s; + _checkpoints.startTime = _startTime; + _checkpoints.endTime = _endTime; + _checkpoints.tokensBalance = _tokensBalance; + _checkpoints.pointsBalance = _pointsBalance; + _checkpoints.tokensPerShare = _tps; + _checkpoints.pointsPerShare = _pps; + } + + /** + * Helper function that parsing input data and store in memory array with known + * length + * @param data Input bytes array that should be parsed. + * @param pointer Pointer to start byte of 'data; for parse. + * @param arrayLength Known length of array. + * @param output Pointer to memory slot where we should store the array. + */ + function parseCheckpointsArray( + bytes memory data, + uint256 pointer, + uint256 arrayLength, + uint256[] memory output + ) internal pure returns (uint256) { + uint256 oldPointer = pointer; + for (pointer; pointer < 32 * arrayLength + oldPointer; pointer += 32) { + uint256 localPointer = pointer - oldPointer + 32; + assembly { + mstore(add(output, localPointer), mload(add(data, pointer))) + } + } + return pointer; + } + + /** + * Claim accumulated token and point rewards from the Staker. + * @param _poolId The id of pool to claim rewards from. + */ + function _claim(uint256 _poolId) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.UserInfo storage _user = b.userInfoV3[_poolId][ + msg.sender + ]; + StakerBlueprint.PoolInfo storage _pool = b.poolInfoV3[_poolId]; + uint256 pendingTokens; + uint256 pendingPoints; + uint256 _tokenRewards; + uint256 _pointRewards; + uint256 accamulatedPendingTokens; + uint256 accamulatedPendingPoints; + + checkOnBoostersChanged(_user.amount, _poolId, msg.sender); + updatePool(_poolId); + bool isTiedToHolder = _pool.typeOfPool == + StakerBlueprint.PoolType.StakingTiedToHolder || + _pool.typeOfPool == StakerBlueprint.PoolType.NoStakingTiedToHolder; + if (isTiedToHolder) { + if (_user.amount > 0) { + pendingTokens = + ((_user.tokenBoostedAmount * _pool.tokensPerShare) / 1e12) - + _user.tokenPaid; + pendingPoints = + ((_user.pointBoostedAmount * _pool.pointsPerShare) / 1e30) - + _user.pointPaid; + _tokenRewards = _user.tokenRewards + pendingTokens; + _pointRewards = _user.pointRewards + pendingPoints; + accamulatedPendingTokens += pendingTokens; + IERC20(b.token).safeTransfer(msg.sender, _tokenRewards); + b.userPoints[msg.sender] = + b.userPoints[msg.sender] + + _pointRewards; + + _user.tokenPaid = + (_user.tokenBoostedAmount * _pool.tokensPerShare) / + 1e12; + _user.pointPaid = + (_user.pointBoostedAmount * _pool.pointsPerShare) / + 1e30; + } else { + IERC20(b.token).safeTransfer(msg.sender, _user.tokenRewards); + } + _user.tokenRewards = 0; + _user.pointRewards = 0; + } else { + // TODO: think about to remove loops with whole users rewards divisioned + // by number of nfts and add logic in claim functions + for (uint256 i; i < _user.asset.id.length; ) { + _user.asset.id.push(_user.asset.id[i]); + StakerBlueprint.RewardsTiedToNFT storage nftRewards = b + .NFTRewards[_poolId][_user.asset.id[i]]; + pendingTokens = + ((nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / 1e12) - + nftRewards.tokenPaid; + pendingPoints = + ((nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / 1e30) - + nftRewards.pointPaid; + _tokenRewards = + nftRewards.accamulatedTokenRewards + + pendingTokens; + _pointRewards = + nftRewards.accamulatedPointRewards + + pendingPoints; + accamulatedPendingTokens += _tokenRewards; + accamulatedPendingPoints += _pointRewards; + + nftRewards.tokenPaid = + (nftRewards.shareOfTokenBoostedDeposited * + _pool.tokensPerShare) / + 1e12; + nftRewards.pointPaid = + (nftRewards.shareOfPointBoostedDeposited * + _pool.pointsPerShare) / + 1e30; + + nftRewards.accamulatedTokenRewards = 0; + nftRewards.accamulatedPointRewards = 0; + unchecked { + ++i; + } + } + IERC20(b.token).safeTransfer(msg.sender, accamulatedPendingTokens); + b.userPoints[msg.sender] = + b.userPoints[msg.sender] + + accamulatedPendingPoints; + } + b.totalTokenDisbursed += accamulatedPendingTokens; + emit Claim( + msg.sender, + _poolId, + accamulatedPendingTokens, + accamulatedPendingPoints + ); + } + + /** + * Claim accumulated token and point rewards from the Staker. + * @param _poolId The id of pool to claim rewards from. + * @param _sig Structure that contains v,r,s parameters of signature. + * @param _checkpoints Structure that contains info about balance of user at certain periods. + */ + function _claim( + uint256 _poolId, + bytes32 _hash, + StakerBlueprint.Sig memory _sig, + StakerBlueprint.Checkpoint memory _checkpoints + ) internal { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + StakerBlueprint.UserInfo storage user = b.userInfoV3[_poolId][ + msg.sender + ]; + // StakerBlueprint.PoolInfo storage pool = b.poolInfoV3[_poolId]; + + uint256 pendingTokens; + uint256 pendingPoints; + + bytes32 messageDigest = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash) + ); + + if (b.admin != ecrecover(messageDigest, _sig.v, _sig.r, _sig.s)) { + revert StakerBlueprint.NotAnAdmin(); + } + + if ( + keccak256( + abi.encodePacked( + keccak256(abi.encodePacked(_checkpoints.startTime)), + keccak256(abi.encodePacked(_checkpoints.endTime)), + keccak256(abi.encodePacked(_checkpoints.tokensBalance)), + keccak256(abi.encodePacked(_checkpoints.pointsBalance)), + keccak256(abi.encodePacked(_checkpoints.tokensPerShare)), + keccak256(abi.encodePacked(_checkpoints.pointsPerShare)) + ) + ) != _hash + ) { + revert StakerBlueprint.MismatchArgumentsAndHash(); + } + + if (b.hashes[_hash]) { + revert StakerBlueprint.HashUsed(); + } + + for (uint256 i; i < _checkpoints.startTime.length; ) { + pendingTokens += + ( + ((_checkpoints.tokensBalance[i] * + _checkpoints.tokensPerShare[i]) / 1e12) + ) - + user.tokenPaid; + pendingPoints += + ( + ((_checkpoints.pointsBalance[i] * + _checkpoints.pointsPerShare[i]) / 1e30) + ) - + user.pointPaid; + if (i + 1 != _checkpoints.startTime.length) { + user.tokenPaid = ((_checkpoints.tokensBalance[i + 1] * + _checkpoints.tokensPerShare[i]) / 1e12); + user.pointPaid = ((_checkpoints.pointsBalance[i + 1] * + _checkpoints.pointsPerShare[i]) / 1e30); + } else { + user.tokenPaid = ((_checkpoints.tokensBalance[i] * + _checkpoints.tokensPerShare[i]) / 1e12); + user.pointPaid = ((_checkpoints.pointsBalance[i] * + _checkpoints.pointsPerShare[i]) / 1e30); + } + unchecked { + ++i; + } + } + b.totalTokenDisbursed = b.totalTokenDisbursed + pendingTokens; + uint256 _tokenRewards = user.tokenRewards + pendingTokens; + uint256 _pointRewards = user.pointRewards + pendingPoints; + + IERC20(b.token).safeTransfer(msg.sender, _tokenRewards); + b.userPoints[msg.sender] += _pointRewards; + user.tokenRewards = 0; + user.pointRewards = 0; + b.hashes[_hash] = true; + emit Claim(msg.sender, _poolId, _tokenRewards, _pointRewards); + } +} diff --git a/contracts/staker/v3ds/facets/StakerV3FacetViews.sol b/contracts/staker/v3ds/facets/StakerV3FacetViews.sol new file mode 100644 index 0000000..96fa84c --- /dev/null +++ b/contracts/staker/v3ds/facets/StakerV3FacetViews.sol @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +import "../../../base/Sweepableds.sol"; +import "../../../interfaces/ISuperGeneric.sol"; +// import "../../assets/erc721/interfaces/ISuper721.sol"; + +import "../StakerBlueprint.sol"; + +/** + * @title An asset staking contract. + * @author Tim Clancy + * @author Qazawat Zirak + * @author Nikita Elunin + * This staking contract disburses tokens from its internal reservoir according + * to a fixed emission schedule. Assets can be assigned varied staking weights. + * It also supports Items staking for boosts on native ERC20 staking rewards. + * The item staking supports Fungible, Non-Fungible and Semi-Fungible staking. + * This code is inspired by and modified from Sushi's Master Chef contract. + * https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol + */ +contract StakerV3FacetViews is Sweepableds { + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * Allows to get information about tokens staked in a booster for Items staker address. + * @param _itemUserAddress The user address to check. + * @param _boosterId The booster Id to check the tokens staked for. + * @return A struct containing the information. + */ + function getItemsUserInfo(address _itemUserAddress, uint256 _boosterId) + external + view + returns (StakerBlueprint.GetItemUserInfo memory) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 length = b + .itemUserInfo[_itemUserAddress] + .tokenIds[_boosterId] + .length(); + uint256[] memory _tokenIds = new uint256[](length); + uint256[] memory _amounts = new uint256[](length); + for (uint256 i = 0; i < length; ) { + _tokenIds[i] = b + .itemUserInfo[_itemUserAddress] + .tokenIds[_boosterId] + .at(i); + _amounts[i] = b.itemUserInfo[_itemUserAddress].amounts[ + _tokenIds[i] + ]; + unchecked { + ++i; + } + } + + StakerBlueprint.GetItemUserInfo memory _userInfo = StakerBlueprint + .GetItemUserInfo({ + boosterId: _boosterId, + tokenIds: _tokenIds, + amounts: _amounts, + totalItems: b.itemUserInfo[_itemUserAddress].totalItems + }); + return _userInfo; + } + + /** + * Allows to get information about all developers that will get % by stakers rewatds. + * @return Developers array of developers addresses. + */ + function getDeveloperAddresses() external view returns (address[] memory) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + uint256 developerAddressLength = b.developerAddresses.length(); + address[] memory developers = new address[](developerAddressLength); + for (uint256 i; i < developerAddressLength; ) { + developers[i] = b.developerAddresses.at(i); + unchecked { + ++i; + } + } + return developers; + } + + /** + * Returns info about current developer share. + * @param developer Address of developer whose share should be returned. + */ + function getDeveloperShare(address developer) + external + view + returns (uint256 share) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + share = b.developerShares[developer]; + } + + /** + * Returns the length of the staking pool array. + * @return The length of the staking pool array. + */ + function getPoolCount() external view returns (uint256) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + return b.poolAssets.length; + } + + /** + * Returns info about pool by id at staking. + * @return _poolInfo Info about pool by id at staking. + */ + function getPoolInfo(uint256 id) + external + view + returns (StakerBlueprint.PoolInfo memory _poolInfo) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + _poolInfo = b.poolInfoV3[id]; + } + + /** + * Returns the count of active boosters at staking. + * @return The count of active boosters at staking. + */ + function getBoostersCount() external view returns (uint256) { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + return b.activeBoosters; + } + + /** + * Returns info about boost by id at staking. + * @return _boostInfo Info about boost by id at staking. + */ + function getBoosterInfo(uint256 id) + external + view + returns (StakerBlueprint.BoostInfo memory _boostInfo) + { + StakerBlueprint.StakerStateVariables storage b = StakerBlueprint + .stakerStateVariables(); + + _boostInfo = b.boostInfo[id]; + } +} diff --git a/contracts/test/SMPERC721.sol b/contracts/test/SMPERC721.sol index 31e2fb0..1697b5f 100644 --- a/contracts/test/SMPERC721.sol +++ b/contracts/test/SMPERC721.sol @@ -4,7 +4,8 @@ pragma solidity ^0.8.8; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; -contract TestERC721 is Ownable, ERC721("Test ERC721 Token","T721"){ +contract TestERC721 is Ownable, ERC721("Test ERC721 Token", "T721") { + constructor() {} constructor () { } diff --git a/hardhat.config.js b/hardhat.config.js index 2e1dfa6..8d8b590 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -1,25 +1,25 @@ -'use strict'; +"use strict"; // Configure environment variables. -require('dotenv').config(); +require("dotenv").config(); // Include Babel so that we may use some newer JavaScript syntax. -require('@babel/register'); +require("@babel/register"); // Include Waffle with Ethers as our preferred engine for testing. -require('@nomiclabs/hardhat-waffle'); +require("@nomiclabs/hardhat-waffle"); // Include the detailed gas usage reporter for tests. -require('hardhat-gas-reporter'); +require("hardhat-gas-reporter"); // Include the contract size output display. -require('hardhat-contract-sizer'); +require("hardhat-contract-sizer"); // Include coverage checking for unit tests. -require('solidity-coverage'); +require("solidity-coverage"); // Include the Etherscan contract verifier. -require('@nomiclabs/hardhat-etherscan'); +require("@nomiclabs/hardhat-etherscan"); // Retrieve sensitive node and private key details from environment variables. const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID; diff --git a/package.json b/package.json index 2805f06..5c96c7b 100644 --- a/package.json +++ b/package.json @@ -57,15 +57,15 @@ "eslint-plugin-standard": "^4.0.1", "ethereum-waffle": "^3.1.1", "ethers": "^5.4.0", - "hardhat": "^2.6.5", + "hardhat": "^2.9.3", "hardhat-contract-sizer": "^2.1.1", - "hardhat-gas-reporter": "^1.0.4", + "hardhat-gas-reporter": "^1.0.8", "husky": "^4.3.0", "npm-run-all": "^4.1.5", "prettier": "^2.7.1", "prettier-plugin-solidity": "^1.0.0-beta.19", "solc-0.6.12": "npm:solc@^0.6.12", - "solidity-coverage": "^0.7.16", + "solidity-coverage": "^0.7.20", "solidity-docgen": "^0.5.11" } } diff --git a/test/MintShop1155.test.js b/test/MintShop1155.test.js index 13e7b61..ab9cb10 100644 --- a/test/MintShop1155.test.js +++ b/test/MintShop1155.test.js @@ -1,9 +1,14 @@ -const { expect } = require('chai'); -const { BigNumber} = require('ethers'); +const { expect } = require("chai"); +const { BigNumber } = require("ethers"); -import {getIndex, computeMerkleProof, computeRootHash, hash} from "./utils.js"; +import { + getIndex, + computeMerkleProof, + computeRootHash, + hash, +} from "./utils.js"; -const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; const DATA = "0x02"; @@ -15,1786 +20,2323 @@ const DATA = "0x02"; /////////////////////////////////////////////////////////// // Start test block -describe('===MintShop1155, PermitControl, Sweepable===', function () { - let tree; - let deployer, owner, paymentReceiver, proxyRegistryOwner, signer1, signer2, signer3; - let UNIVERSAL, - MANAGER, - zeroRight, - - setSweepRight, - setLockSweepRight, - - setPaymentReceiverRight, - setLockPaymentReceiverRight, - setUpdateGlobalLimitRight, - setLockGlobalLimitRight, - setWhiteListRight, - setPoolRight, - - setMintRight; - - let mintShop1155; - let super1155; - let super1155Second; - let mockERC20; - let staker; - let proxyRegistry; - const originalUri = "://ipfs/uri/{id}"; - let itemGroupId = ethers.BigNumber.from(1); - let shiftedItemGroupId = itemGroupId.shl(128); - let itemGroupId2 = ethers.BigNumber.from(2); - let shiftedItemGroupId2 = itemGroupId2.shl(128); - let item721, Item721; - let MINT721; - - before(async function () { - this.MintShop1155 = await ethers.getContractFactory("MintShop1155"); - this.MockERC20 = await ethers.getContractFactory("MockERC20"); - this.Staker = await ethers.getContractFactory("Staker"); - this.ProxyRegistry = await ethers.getContractFactory("ProxyRegistry"); - this.Super1155 = await ethers.getContractFactory("Super1155"); - // this.Item721 = await ethers.getContractFactory("Super721"); +describe("===MintShop1155, PermitControl, Sweepable===", function () { + let tree; + let deployer, + owner, + paymentReceiver, + proxyRegistryOwner, + signer1, + signer2, + signer3; + let UNIVERSAL, + MANAGER, + zeroRight, + setSweepRight, + setLockSweepRight, + setPaymentReceiverRight, + setLockPaymentReceiverRight, + setUpdateGlobalLimitRight, + setLockGlobalLimitRight, + setWhiteListRight, + setPoolRight, + setMintRight; + + let mintShop1155; + let super1155; + let super1155Second; + let mockERC20; + let staker; + let proxyRegistry; + const originalUri = "://ipfs/uri/{id}"; + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let item721, Item721; + let MINT721; + + before(async function () { + this.MintShop1155 = await ethers.getContractFactory("MintShop1155"); + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.Staker = await ethers.getContractFactory("Staker"); + this.ProxyRegistry = await ethers.getContractFactory("ProxyRegistry"); + this.Super1155 = await ethers.getContractFactory("Super1155"); + //this.Item721 = await ethers.getContractFactory("Super721"); + }); + + beforeEach(async function () { + [ + deployer, + owner, + paymentReceiver, + proxyRegistryOwner, + signer1, + signer2, + signer3, + ] = await ethers.getSigners(); + // console.log(deployer.address, owner.address, paymentReceiver.address, proxyRegistryOwner.address, signer1.address, signer2.address, signer3.address) + // [deployer, owner, paymentReceiver, signer1, signer2, signer3] = await ethers.getSigners(); + + proxyRegistry = await this.ProxyRegistry.deploy(); + await proxyRegistry.deployed(); + await proxyRegistry.transferOwnership(proxyRegistryOwner.address); + + super1155 = await this.Super1155.deploy( + owner.address, + "Super1155", + originalUri, + originalUri, + proxyRegistry.address + ); + + //item721 = await this.Item721.deploy(); + + // await super1155._transferOwnership(owner.address); + super1155Second = await this.Super1155.deploy( + owner.address, + "Super1155142", + originalUri + "uri2", + originalUri + "uri2", + proxyRegistry.address + ); + await super1155.deployed(); + // await super1155Second._transferOwnership(owner.address); + + mintShop1155 = await this.MintShop1155.deploy( + owner.address, + paymentReceiver.address, + 4, + 200 + ); + await mintShop1155.deployed(); + + mockERC20 = await this.MockERC20.deploy(); + await mockERC20.deployed(); + + staker = await this.Staker.deploy("firstStaker", mockERC20.address); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + // let tree = getMerkleTree(whiteListAddresses); + + const root = computeRootHash(whiteList); + + const whiteListCreate = { + _accesslistId: 0, + _merkleRoot: root, + _startTime: 0, + _endTime: ethers.constants.MaxUint256, + _price: ethers.utils.parseEther("0.001"), + _token: NULL_ADDRESS, + }; + + // console.log("ROOT js ", root); + + await mintShop1155 + .connect(owner) + .setItems([super1155.address, super1155Second.address]); + // await mintShop1155.connect(owner).addWhiteList(0, [whiteListCreate]); + + await staker.transferOwnership(owner.address); + + UNIVERSAL = await mintShop1155.UNIVERSAL(); + MANAGER = await mintShop1155.MANAGER(); + zeroRight = await mintShop1155.ZERO_RIGHT(); + // MINT721 = await item721.MINT(); + + setSweepRight = await mintShop1155.SWEEP(); + setLockSweepRight = await mintShop1155.LOCK_SWEEP(); + + setPaymentReceiverRight = await mintShop1155.SET_PAYMENT_RECEIVER(); + setLockPaymentReceiverRight = await mintShop1155.LOCK_PAYMENT_RECEIVER(); + setUpdateGlobalLimitRight = await mintShop1155.UPDATE_GLOBAL_LIMIT(); + setLockGlobalLimitRight = await mintShop1155.LOCK_GLOBAL_LIMIT(); + setWhiteListRight = await mintShop1155.WHITELIST(); + setPoolRight = await mintShop1155.POOL(); + + setMintRight = await super1155.MINT(); + }); + + // Test cases + + ////////////////////////////// + // Constructor + ////////////////////////////// + describe("Constructor", function () { + it("should initialize values as expected", async function () { + // expect(await mintShop1155.owner()).to.equal(owner.address); + // expect(await mintShop1155.item()).to.equal(super1155.address); + expect(await mintShop1155.paymentReceiver()).to.equal( + paymentReceiver.address + ); + expect(await mintShop1155.globalPurchaseLimit()).to.equal("4"); }); - beforeEach(async function () { - [deployer, owner, paymentReceiver, proxyRegistryOwner, signer1, signer2, signer3] = await ethers.getSigners(); - // console.log(deployer.address, owner.address, paymentReceiver.address, proxyRegistryOwner.address, signer1.address, signer2.address, signer3.address) - // [deployer, owner, paymentReceiver, signer1, signer2, signer3] = await ethers.getSigners(); - - - proxyRegistry = await this.ProxyRegistry.deploy(); - await proxyRegistry.deployed(); - await proxyRegistry.transferOwnership(proxyRegistryOwner.address); - - super1155 = await this.Super1155.deploy( - owner.address, - "Super1155", - originalUri, - originalUri, - proxyRegistry.address - ); - - // await super1155._transferOwnership(owner.address); - super1155Second = await this.Super1155.deploy( - owner.address, - "Super1155142", - originalUri + "uri2", - originalUri + "uri2", - proxyRegistry.address - ); - await super1155.deployed(); - // await super1155Second._transferOwnership(owner.address); - - mintShop1155 = await this.MintShop1155.deploy( - owner.address, - paymentReceiver.address, - 4, - 200 - ); - await mintShop1155.deployed(); - - mockERC20 = await this.MockERC20.deploy(); - await mockERC20.deployed(); - - staker = await this.Staker.deploy( - "firstStaker", - mockERC20.address - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - // let tree = getMerkleTree(whiteListAddresses); - - const root = computeRootHash(whiteList); - - const whiteListCreate = { - _accesslistId: 0, - _merkleRoot: root, - _startTime: 0, - _endTime: ethers.constants.MaxUint256, - _price: ethers.utils.parseEther("0.001"), - _token: NULL_ADDRESS - } - - // console.log("ROOT js ", root); - - await mintShop1155.connect(owner).setItems([super1155.address, super1155Second.address]); - // await mintShop1155.connect(owner).addWhiteList(0, [whiteListCreate]); - - await staker.transferOwnership(owner.address); - - UNIVERSAL = await mintShop1155.UNIVERSAL(); - MANAGER = await mintShop1155.MANAGER(); - zeroRight = await mintShop1155.ZERO_RIGHT(); - // MINT721 = await item721.MINT(); - - setSweepRight = await mintShop1155.SWEEP(); - setLockSweepRight = await mintShop1155.LOCK_SWEEP(); - - setPaymentReceiverRight = await mintShop1155.SET_PAYMENT_RECEIVER(); - setLockPaymentReceiverRight = await mintShop1155.LOCK_PAYMENT_RECEIVER(); - setUpdateGlobalLimitRight = await mintShop1155.UPDATE_GLOBAL_LIMIT(); - setLockGlobalLimitRight = await mintShop1155.LOCK_GLOBAL_LIMIT(); - setWhiteListRight = await mintShop1155.WHITELIST(); - setPoolRight = await mintShop1155.POOL(); - - setMintRight = await super1155.MINT(); + it("should deploy a new instance where deployer is the owner", async function () { + let mintShop1155v2 = await this.MintShop1155.deploy( + deployer.address, + paymentReceiver.address, + "4", + 1 + ); + await super1155.deployed(); + + // await mintShop1155v2._transferOwnership(deployer.address); + + expect(await mintShop1155v2.owner()).to.equal(deployer.address); + // expect(await mintShop1155v2.item()).to.equal(super1155.address); + expect(await mintShop1155v2.paymentReceiver()).to.equal( + paymentReceiver.address + ); + expect(await mintShop1155v2.globalPurchaseLimit()).to.equal("4"); }); + }); + describe("version", function () { + it("should return the correct version", async function () { + expect(await mintShop1155.version()).to.equal(1); + }); + }); + + describe("updatePaymentReceiver", function () { + it("Reverts: payment receiver address is locked", async function () { + await mintShop1155.connect(owner).lockPaymentReceiver(); + await expect( + mintShop1155.connect(owner).updatePaymentReceiver(owner.address) + ).to.be.revertedWith("XXX"); + }); - // Test cases - - ////////////////////////////// - // Constructor - ////////////////////////////// - describe("Constructor", function () { - it('should initialize values as expected', async function () { - // expect(await mintShop1155.owner()).to.equal(owner.address); - // expect(await mintShop1155.item()).to.equal(super1155.address); - expect(await mintShop1155.paymentReceiver()).to.equal(paymentReceiver.address); - expect(await mintShop1155.globalPurchaseLimit()).to.equal("4"); - }); - - it('should deploy a new instance where deployer is the owner', async function () { - let mintShop1155v2 = await this.MintShop1155.deploy( - deployer.address, - paymentReceiver.address, - "4", - 1 - ); - await super1155.deployed(); - - // await mintShop1155v2._transferOwnership(deployer.address); - - expect(await mintShop1155v2.owner()).to.equal(deployer.address); - // expect(await mintShop1155v2.item()).to.equal(super1155.address); - expect(await mintShop1155v2.paymentReceiver()).to.equal(paymentReceiver.address); - expect(await mintShop1155v2.globalPurchaseLimit()).to.equal("4"); - }); + it("Reverts: no valid permit", async function () { + await expect( + mintShop1155.connect(deployer).updatePaymentReceiver(owner.address) + ).to.be.revertedWith("P1"); }); - describe("version", function () { - it('should return the correct version', async function(){ - expect(await mintShop1155.version()).to.equal(1) - }); + it("Reverts: setting manager for Zero address", async function () { + let input = { + types: ["address"], + values: [deployer.address], + }; + + await expect( + mintShop1155 + .connect(owner) + .setManagerRight( + zeroRight, + ethers.utils.defaultAbiCoder.encode(input.types, input.values) + ) + ).to.be.revertedWith("P3"); }); - describe("updatePaymentReceiver", function () { - it('Reverts: payment receiver address is locked', async function(){ - await mintShop1155.connect(owner).lockPaymentReceiver(); - await expect( - mintShop1155.connect(owner).updatePaymentReceiver(owner.address) - ).to.be.revertedWith("XXX"); - }); + it("should test PermitControl to set a manager who can further create permits to update payment receiver", async function () { + // Declare a rights relationship for manager => payment + await mintShop1155 + .connect(owner) + .setManagerRight(setPaymentReceiverRight, MANAGER); + + // Give a manager a permit + await mintShop1155 + .connect(owner) + .setPermit( + deployer.address, + UNIVERSAL, + MANAGER, + ethers.constants.MaxUint256 + ); - it('Reverts: no valid permit', async function(){ - await expect( - mintShop1155.connect(deployer).updatePaymentReceiver(owner.address) - ).to.be.revertedWith("P1"); - }); + // Give a manager a payment permit + await mintShop1155 + .connect(owner) + .setPermit( + deployer.address, + UNIVERSAL, + setPaymentReceiverRight, + ethers.constants.MaxUint256 + ); - it('Reverts: setting manager for Zero address', async function(){ - let input = { - types: ["address"], - values: [deployer.address] - } + // That manager creates a further permit for signer1 to update payment + await mintShop1155 + .connect(deployer) + .setPermit( + signer1.address, + UNIVERSAL, + setPaymentReceiverRight, + ethers.constants.MaxUint256 + ); - await expect( - mintShop1155.connect(owner).setManagerRight(zeroRight, ethers.utils.defaultAbiCoder.encode(input.types, input.values)) - ).to.be.revertedWith("P3"); - }); + await mintShop1155.connect(signer1).updatePaymentReceiver(owner.address); + expect(await mintShop1155.paymentReceiver()).to.equal(owner.address); - it('should test PermitControl to set a manager who can further create permits to update payment receiver', async function(){ - // Declare a rights relationship for manager => payment - await mintShop1155.connect(owner).setManagerRight(setPaymentReceiverRight, MANAGER); - - // Give a manager a permit - await mintShop1155.connect(owner).setPermit( - deployer.address, - UNIVERSAL, - MANAGER, - ethers.constants.MaxUint256 - ); - - // Give a manager a payment permit - await mintShop1155.connect(owner).setPermit( - deployer.address, - UNIVERSAL, - setPaymentReceiverRight, - ethers.constants.MaxUint256 - ); - - // That manager creates a further permit for signer1 to update payment - await mintShop1155.connect(deployer).setPermit( - signer1.address, - UNIVERSAL, - setPaymentReceiverRight, - ethers.constants.MaxUint256 - ); - - await mintShop1155.connect(signer1).updatePaymentReceiver(owner.address); - expect(await mintShop1155.paymentReceiver()).to.equal(owner.address); - - await mintShop1155.connect(signer1).updatePaymentReceiver(paymentReceiver.address); - expect(await mintShop1155.paymentReceiver()).to.equal(paymentReceiver.address); - }); + await mintShop1155 + .connect(signer1) + .updatePaymentReceiver(paymentReceiver.address); + expect(await mintShop1155.paymentReceiver()).to.equal( + paymentReceiver.address + ); }); + }); - describe("updateGlobalPurchaseLimit", function () { - it('Reverts: global purchase limit is locked', async function(){ - await mintShop1155.connect(owner).lockGlobalPurchaseLimit(); + describe("updateGlobalPurchaseLimit", function () { + it("Reverts: global purchase limit is locked", async function () { + await mintShop1155.connect(owner).lockGlobalPurchaseLimit(); - await expect( - mintShop1155.connect(owner).updateGlobalPurchaseLimit("6") - ).to.be.revertedWith("0x0A"); - }); + await expect( + mintShop1155.connect(owner).updateGlobalPurchaseLimit("6") + ).to.be.revertedWith("0x0A"); + }); - it('should update global purchase limit', async function(){ - await mintShop1155.connect(owner).updateGlobalPurchaseLimit("6"); - }); + it("should update global purchase limit", async function () { + await mintShop1155.connect(owner).updateGlobalPurchaseLimit("6"); + }); + }); + describe("updatePool, addPool, getPools", function () { + beforeEach(async function () { + // Configure token groups + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "FUNGIBLE", + supplyType: 1, + supplyData: 10, + itemType: 1, + itemData: 0, + burnType: 1, + burnData: 5, + }); + + await super1155.connect(owner).configureGroup(itemGroupId2, { + name: "NONFUNGIBLE", + supplyType: 0, + supplyData: 1, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await super1155Second.connect(owner).configureGroup(itemGroupId2, { + name: "NONFUNGIBLE", + supplyType: 0, + supplyData: 1, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await super1155Second.connect(owner).configureGroup(itemGroupId2, { + name: "NONFUNGIBLE", + supplyType: 0, + supplyData: 1, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); }); - describe("updatePool, addPool, getPools", function () { - beforeEach(async function(){ - // Configure token groups - await super1155.connect(owner).configureGroup(itemGroupId, { - name: 'FUNGIBLE', - supplyType: 1, - supplyData: 10, - itemType: 1, - itemData: 0, - burnType: 1, - burnData: 5 - }); - - await super1155.connect(owner).configureGroup(itemGroupId2, { - name: 'NONFUNGIBLE', - supplyType: 0, - supplyData: 1, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await super1155Second.connect(owner).configureGroup(itemGroupId2, { - name: 'NONFUNGIBLE', - supplyType: 0, - supplyData: 1, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await super1155Second.connect(owner).configureGroup(itemGroupId2, { - name: 'NONFUNGIBLE', - supplyType: 0, - supplyData: 1, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - }); - it('Reverts: updatePool a non-existent pool', async function(){ - // Updating a pool with non-existent pool id - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(1, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1], [1], [1], [[{ + it("Reverts: updatePool a non-existent pool", async function () { + // Updating a pool with non-existent pool id + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 1, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1], + [1], + [1], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x1A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x1A"); + }); - it('Reverts: updatePool end time preceeds start time', async function(){ - // Updating a pool with endTime preceeding startTime - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp - 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1], [1], [1], [[{ + it("Reverts: updatePool end time preceeds start time", async function () { + // Updating a pool with endTime preceeding startTime + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp - 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1], + [1], + [1], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x1A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x1A"); + }); - it('Reverts: updatePool no item groups included', async function(){ - // Updating a pool with 0 groups - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [], [1], [1], [[{ + it("Reverts: updatePool no item groups included", async function () { + // Updating a pool with 0 groups + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [], + [1], + [1], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x1A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x1A"); + }); - it('Reverts: updatePool groups and offsets length mismatch', async function(){ - // Updating a pool with groups and offsets length mismatch - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1], [1, 2], [1], [[{ + it("Reverts: updatePool groups and offsets length mismatch", async function () { + // Updating a pool with groups and offsets length mismatch + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1], + [1, 2], + [1], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x4A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x4A"); + }); - it('Reverts: updatePool groups and caps length mismatch', async function(){ - // Updating a pool with groups and caps length mismatch - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1], [1], [1, 2], [[{ + it("Reverts: updatePool groups and caps length mismatch", async function () { + // Updating a pool with groups and caps length mismatch + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1], + [1], + [1, 2], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x4A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x4A"); + }); - it('Reverts: updatePool groups and prices length mismatch', async function(){ - // Updating a pool with groups and prices length mismatch - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1, 2], [1, 2], [1, 2], [[{ + it("Reverts: updatePool groups and prices length mismatch", async function () { + // Updating a pool with groups and prices length mismatch + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], + [1, 2], + [1, 2], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x4A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x4A"); + }); - it('Reverts: updatePool no mintable amount', async function(){ - // Updating a pool with no mintable amount - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect(mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1], [1], [0], [[{ + it("Reverts: updatePool no mintable amount", async function () { + // Updating a pool with no mintable amount + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1], + [1], + [0], + [ + [ + { assetType: 1, asset: NULL_ADDRESS, - price: 1 - }]])).to.be.revertedWith("0x5A"); - }); + price: 1, + }, + ], + ] + ) + ).to.be.revertedWith("0x5A"); + }); - it('should add a pool, update it, get the pool', async function(){ - // Creating a pool - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).addPool({ - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 5, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1, 2], [1, 1], [10, 1], [[{ - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }], [{ - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }]]); - - // Updating the purchase limit to 1 - latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).updatePool(0, { - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 1, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - whitelistId: 1, - requiredId: [] - }, - collection: super1155.address - }, [1, 2], [1, 1], [10, 1], [[{ - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }], [{ - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }]]); + it("should add a pool, update it, get the pool", async function () { + // Creating a pool + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).addPool( + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 5, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], + [1, 1], + [10, 1], + [ + [ + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + [ + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + // Updating the purchase limit to 1 + latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).updatePool( + 0, + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 1, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + whitelistId: 1, + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], + [1, 1], + [10, 1], + [ + [ + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + [ + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + //Get the pool + let pools = await mintShop1155.connect(owner).getPools([0], 0); + + expect(pools[0].config.name).to.be.equal("firstPool"); + }); - //Get the pool - let pools = await mintShop1155.connect(owner).getPools([0], 0); + // it("CHECK REQ", async function() { + // let res = await mintShop1155.checkRequirments("0"); + // console.log(res); + // }); + }); - expect(pools[0].config.name).to.be.equal("firstPool"); - }); + describe("mintFromPool, getPoolsWithAddress, getPurchaseCounts", function () { + beforeEach(async function () { + // Configure token groups + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "FUNGIBLE", + supplyType: 1, + supplyData: 10, + itemType: 1, + itemData: 0, + burnType: 1, + burnData: 5, + }); + + await super1155.connect(owner).configureGroup(itemGroupId2, { + name: "NFT", + supplyType: 0, + supplyData: 5, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await super1155.connect(owner).configureGroup(itemGroupId2.add(1), { + name: "SUPERNFT", + supplyType: 0, + supplyData: 5, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + // Create Pools + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).addPool( + { + name: "firstPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 3, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], // Groups 1 = FT, 2 = NFT + [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 + [10, 5], // Caps 10 = FT, 5 = NFT + [ + [ + { + // Price pair for FTs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + + [ + { + // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).addPool( + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 3, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 0, + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [2], // Caps + [ + [ + { + // Price pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + // Get the pool + let pools = await mintShop1155.connect(owner).getPools([0], 0); + expect(pools[0].config.name).to.be.equal("firstPool"); + }); - // it("CHECK REQ", async function() { - // let res = await mintShop1155.checkRequirments("0"); - // console.log(res); - // }); + it("Reverts: mintFromPool amount less than 0", async function () { + // Mint from pool + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + + // let root = computeRootHash(whiteList); + // console.log("Noviy root: " + root) + + await expect( + mintShop1155.connect(owner).mintFromPool(0, 2, 1, 0, 0, whiteListInput) + ).to.be.revertedWith("0x0B"); }); - describe("mintFromPool, getPoolsWithAddress, getPurchaseCounts", function () { - beforeEach(async function(){ - // Configure token groups - await super1155.connect(owner).configureGroup(itemGroupId, { - name: 'FUNGIBLE', - supplyType: 1, - supplyData: 10, - itemType: 1, - itemData: 0, - burnType: 1, - burnData: 5 - }); - - await super1155.connect(owner).configureGroup(itemGroupId2, { - name: 'NFT', - supplyType: 0, - supplyData: 5, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await super1155.connect(owner).configureGroup(itemGroupId2.add(1), { - name: 'SUPERNFT', - supplyType: 0, - supplyData: 5, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - // Create Pools - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).addPool({ - name: "firstPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 3, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [1, 2], // Groups 1 = FT, 2 = NFT - [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 - [10, 5], // Caps 10 = FT, 5 = NFT - [ - [{ // Price pair for FTs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }], - - [{ // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).addPool({ - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 3, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 0, - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [2], // Caps - [ - [{ // Price pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - // Get the pool - let pools = await mintShop1155.connect(owner).getPools([0], 0); - expect(pools[0].config.name).to.be.equal("firstPool"); + it("Reverts: mintFromPool pool not active", async function () { + // Mint from pool + const whiteListAddresses = [ + owner.address, + signer2.address, + owner.address, + signer1.address, + signer2.address, + ]; + // let tree1 = this.tree; + + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + await expect( + mintShop1155.connect(owner).mintFromPool(2, 2, 1, 1, 0, whiteListInput) + ).to.be.revertedWith("0x1B"); + }); - }); + it("Reverts: mintFromPool amount greater than singlePurchaseLimit", async function () { + // Mint from pool + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + + await expect( + mintShop1155 + .connect(deployer) + .mintFromPool(0, 2, 1, 3, 0, whiteListInput) + ).to.be.revertedWith("0x1B"); + }); - it('Reverts: mintFromPool amount less than 0', async function(){ - // Mint from pool - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - - // let root = computeRootHash(whiteList); - // console.log("Noviy root: " + root) - - await expect( - mintShop1155.connect(owner).mintFromPool(0, 2, 1, 0, 0, whiteListInput) - ).to.be.revertedWith("0x0B"); - }); + it("Reverts: mintFromPool assetindex not valid", async function () { + // Mint from pool + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // console.log(tree.leaves[1].proof); + + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 5, 1, 0, whiteListInput) + ).to.be.revertedWith("0x3B"); + }); - it('Reverts: mintFromPool pool not active', async function(){ - // Mint from pool - const whiteListAddresses = [owner.address, signer2.address, owner.address, signer1.address, signer2.address]; - // let tree1 = this.tree; - - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - await expect( - mintShop1155.connect(owner).mintFromPool(2, 2, 1, 1, 0, whiteListInput) - ).to.be.revertedWith("0x1B"); - }); + it("Reverts: mintFromPool pool is not running", async function () { + // Jump forward in time more than the pool end time + await ethers.provider.send("evm_increaseTime", [70]); + await ethers.provider.send("evm_mine", []); + + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); - it('Reverts: mintFromPool amount greater than singlePurchaseLimit', async function(){ - // Mint from pool - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - - await expect( - mintShop1155.connect(deployer).mintFromPool(0, 2, 1, 3, 0, whiteListInput) - ).to.be.revertedWith("0x1B"); - }); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // console.log(whiteListInput); + + // Mint from pool + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }) + ).to.be.revertedWith("0x4B"); + }); - it('Reverts: mintFromPool assetindex not valid', async function(){ - // Mint from pool - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // console.log(tree.leaves[1].proof); - - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 5, 1, 0, whiteListInput) - ).to.be.revertedWith("0x3B"); + it("Reverts: mintFromPool pool purchase limit reach", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Mint three times + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts: mintFromPool pool is not running', async function(){ - // Jump forward in time more than the pool end time - await ethers.provider.send("evm_increaseTime", [70]); - await ethers.provider.send("evm_mine", []); - - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // console.log(whiteListInput); - - // Mint from pool - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x4B"); + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts: mintFromPool pool purchase limit reach', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Mint three times - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - - // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - // await mintShop1155.connect(signer1).mintFromPool(1, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - - - // Mint again surpassing the purchase limit of the pool - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x5B"); + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts: mintFromPool global purchase limit reach', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Mint four times - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - - - // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - - // Mint again surpassing the global purchase limit - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x5B"); + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - // it('Reverts: mintFromPool not whitelisted in the pool', async function(){ - // // Give the Shop permit to mint items in Super1155 contract - // await super1155.connect(owner).setPermit( - // mintShop1155.address, - // UNIVERSAL, - // setMintRight, - // ethers.constants.MaxUint256 - // ); - - // // await mintShop1155.connect(owner).addWhiteList(1, 2, root, 0, ethers.constants.MaxUint256); - - - // // Create whitelist with deployer's address in it - // // await mintShop1155.connect(owner).addWhitelist({ - // // expiryTime: ethers.constants.MaxUint256, - // // isActive: false, - // // addresses: [deployer.address] - // // }); - - // // Set the whitelist status to active - // // await mintShop1155.connect(owner).setWhitelistActive(1, true); - - // // Update the pool from beforeEach to include whitelist - // let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - // await mintShop1155.connect(owner).updatePool(1, { - // name: "secondPool", - // startTime: latestBlock.timestamp, - // endTime: latestBlock.timestamp + 60, - // purchaseLimit: 2, - // singlePurchaseLimit: 1, - // requirement: { - // requiredType: 0, - // requiredAsset: [NULL_ADDRESS], - // requiredAmount: 1, - // whitelistId: 2, - // requiredId: [] - // }, - // collection: super1155.address - // }, [3], // Group - // [0], // NumberOffset - // [2], // Caps - // [ - // [{ // Price pairs - // assetType: 1, - // asset: NULL_ADDRESS, - // price: 1 - // }, { - // assetType: 1, - // asset: NULL_ADDRESS, - // price: 1 - // }] - // ]); - // let whiteListAddresses = [deployer.address, owner.address, paymentReceiver.address, proxyRegistryOwner.address,signer1.address, signer2.address]; - - // let whiteListInput = { - // index: 1, - // node: "0x66bec8af3e1db24c080f949a93ecca4f99c46c7afb08389d93b59e5f73514c75", - // merkleProof: computeMerkleProof(1, whiteListAddresses) - // }; - // // Mint - // await expect( - // mintShop1155.connect(owner).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - // ).to.be.revertedWith("Invalid Proof."); - // }); - - it('Reverts: mintFromPool not enough items available for purchase', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Update the pool from beforeEach to lower its cap - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).updatePool(1, { - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 2, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [1], // Caps - [ - [{ // Price pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - await mintShop1155.connect(signer1).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - - // Mint until cap reached - await expect( - mintShop1155.connect(signer1).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x7B"); - }); + // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + // await mintShop1155.connect(signer1).mintFromPool(1, 2, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + + // Mint again surpassing the purchase limit of the pool + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }) + ).to.be.revertedWith("0x5B"); + }); - it('Reverts: not enough ether sent', async function(){ - - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).updatePool(1, { - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 2, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [2], // Caps - [ - [{ // Price pairs - assetType: 1, - asset: NULL_ADDRESS, - price: ethers.utils.parseEther("1") - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - await expect( - mintShop1155.connect(signer1).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("0.5")}) - ).to.be.revertedWith("0x9B"); + it("Reverts: mintFromPool global purchase limit reach", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Mint four times + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts => Success: mintFromPool not enough ERC20 tokens for the pool then getPrchaseCount', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - - // Update the pool from beforeEach to include ERC20 token as price pair - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).updatePool(1, { - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 4, - singlePurchaseLimit: 3, - requirement: { - requiredType: 1, - requiredAsset: [mockERC20.address], - requiredAmount: ethers.utils.parseEther("10"), - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [5], // Caps - [ - [{ // Price pairs - assetType: 2, - asset: mockERC20.address, - price: ethers.utils.parseEther("15") - }, { - assetType: 2, - asset: mockERC20.address, - price: ethers.utils.parseEther("15") - }] - ]); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Give signer1 some amount of ERC20 Tokens - await mockERC20.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("5")); - - // Mint until cap reached - await expect( - mintShop1155.connect(signer1).mintFromPool(1, 3, 0, 1, 0, whiteListInput) - ).to.be.revertedWith("0x8B"); - - // Give signer1 some more amount of ERC20 Tokens - await mockERC20.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("5")); - - // Signer1 approves mintshop1155 contract - await mockERC20.connect(signer1).approve(mintShop1155.address, ethers.utils.parseEther("15")); - - await expect( - mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 3, 0, whiteListInput) - ).to.be.revertedWith("0x1C"); - - // Successful purchase, Give signer1 some more amount of ERC20 Tokens - await mockERC20.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("5")); - - await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput); - - // getPurchaseCounts - let balances = await mintShop1155.connect(signer1).getPurchaseCounts([signer1.address, signer2.address, owner.address], [1]); - - await expect(balances[0][0]).to.be.equal("1"); //First index is the address, second is the ids - await expect(balances[1][0]).to.be.equal("0"); //First index is the address, second is the ids - await expect(balances[2][0]).to.be.equal("0"); //First index is the address, second is the ids + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts: mintFromPool unrecognized asset type (But it gets reverted at the time of assigning instead of actual revert)', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Update the pool from beforeEach to include ERC20 token as price pair - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await expect( - mintShop1155.connect(owner).updatePool(1, { - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 2, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [2], // Caps - [ - [{ // Price pairs - assetType: 3, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 3, - asset: NULL_ADDRESS, - price: 1 - }] - ])).to.be.reverted; - + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - - it('Reverts: not enough ERC1155 required items', async function(){ - // Give the Shop permit to mint items in Super1155 contract - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - - // Update the pool from beforeEach to include ERC1155 requirement - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).updatePool(1, { - name: "secondPool", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 2, - singlePurchaseLimit: 1, - requirement: { - requiredType: 2, - requiredAsset: [super1155.address], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [3], // Group - [0], // NumberOffset - [2], // Caps - [ - [{ // Price pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - // Mint based on ERC1155 item holdings - await expect( - mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput) - ).to.be.revertedWith("0x8B"); - - // Mint ERC1155 for signer1 - await super1155.connect(owner).mintBatch(signer1.address, [shiftedItemGroupId], ["1"], DATA); - - await mintShop1155.connect(signer1).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}); + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); + + // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + // await mintShop1155.connect(signer1).mintFromPool(1, 3, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + + // Mint again surpassing the global purchase limit + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }) + ).to.be.revertedWith("0x5B"); }); - // describe("mintFromPool for staker contract for a specific Super1155 group", function () { - // it('should purchase using staking points', async function(){ - // // Configure token group - // await super1155.connect(owner).configureGroup(itemGroupId, { - // name: 'FUNGIBLE', - // supplyType: 1, - // supplyData: 10, - // itemType: 0, - // itemData: 0, - // burnType: 1, - // burnData: 5 - // }); - - // // Create Pool of that token group - // let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - // await mintShop1155.connect(owner).addPool({ - // name: "firstPool", - // startTime: latestBlock.timestamp, - // endTime: latestBlock.timestamp + 60, - // purchaseLimit: 3, - // singlePurchaseLimit: 2, - // requirement: { - // requiredType: 3, - // requiredAsset: [staker.address], - // requiredAmount: 1000, // Required amount of points - // - // requiredId: [] - // }, - // collection: super1155.address - // }, [1], // Groups 1 = FT, 2 = NFT - // [0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 - // [10], // Caps 10 = FT, 5 = NFT - // [ - // [{ // Price pair for FTs - // assetType: 0, - // asset: staker.address, - // price: 1 - // }] - // ]); - - // // Set Emission rate to current block number - // await staker.connect(owner).setEmissions([ - // { blockNumber: (await (await ethers.provider.getBlock()).number) + 5, rate: ethers.utils.parseEther('10') }, - // ], [ - // { blockNumber: (await (await ethers.provider.getBlock()).number) + 5, rate: 100 }, - // ]); - // await staker.connect(owner).addPool(mockERC20.address, 100, 50); - - // for (let i = 0; i < 4; ++i) { - // ethers.provider.send('evm_mine'); - // } - - // // Give the signer1 some mockERC20 tokens - // await mockERC20.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("10")); - - // // Give staker contract some mockERC20 tokens - // await mockERC20.connect(deployer).transfer(staker.address, ethers.utils.parseEther("1000")); - - // // Signer1 approves staker contract - // await mockERC20.connect(signer1).approve(staker.address, ethers.utils.parseEther("10")); - - // // Signer1 deposits the tokens - // await staker.connect(signer1).deposit(mockERC20.address, ethers.utils.parseEther("10")); - - // // Jump forward and travel in time through the portal - // for (let i = 0; i < 5; ++i) { - // ethers.provider.send('evm_mine'); - // } - - // await expect(( - // await staker.connect(owner).getPendingPoints(mockERC20.address, signer1.address)).toString() - // ).to.be.equal("500"); - - // let whiteList = { - // "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - // "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - // "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - // "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - // "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - // "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - // "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - // } + // it('Reverts: mintFromPool not whitelisted in the pool', async function(){ + // // Give the Shop permit to mint items in Super1155 contract + // await super1155.connect(owner).setPermit( + // mintShop1155.address, + // UNIVERSAL, + // setMintRight, + // ethers.constants.MaxUint256 + // ); + + // // await mintShop1155.connect(owner).addWhiteList(1, 2, root, 0, ethers.constants.MaxUint256); + + // // Create whitelist with deployer's address in it + // // await mintShop1155.connect(owner).addWhitelist({ + // // expiryTime: ethers.constants.MaxUint256, + // // isActive: false, + // // addresses: [deployer.address] + // // }); + + // // Set the whitelist status to active + // // await mintShop1155.connect(owner).setWhitelistActive(1, true); + + // // Update the pool from beforeEach to include whitelist + // let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); + // await mintShop1155.connect(owner).updatePool(1, { + // name: "secondPool", + // startTime: latestBlock.timestamp, + // endTime: latestBlock.timestamp + 60, + // purchaseLimit: 2, + // singlePurchaseLimit: 1, + // requirement: { + // requiredType: 0, + // requiredAsset: [NULL_ADDRESS], + // requiredAmount: 1, + // whitelistId: 2, + // requiredId: [] + // }, + // collection: super1155.address + // }, [3], // Group + // [0], // NumberOffset + // [2], // Caps + // [ + // [{ // Price pairs + // assetType: 1, + // asset: NULL_ADDRESS, + // price: 1 + // }, { + // assetType: 1, + // asset: NULL_ADDRESS, + // price: 1 + // }] + // ]); + // let whiteListAddresses = [deployer.address, owner.address, paymentReceiver.address, proxyRegistryOwner.address,signer1.address, signer2.address]; // let whiteListInput = { - // whiteListId: 0, - // index: getIndex(whiteList, signer1.address), - // allowance: whiteList[signer1.address], - // node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - // merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - // } - // // Signer1 hasn't claimed points - // // mintFromPool of mintshop1155 must revert - // await expect( - // mintShop1155.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput) - // ).to.be.revertedWith("MintShop1155: you do not have enough required points for this pool"); - - // // Jump forward and travel in time through the portal, signer1 must be eligible for the pool now - // for (let i = 0; i < 5; ++i) { - // ethers.provider.send('evm_mine'); - // } - - // // Signer1 withdraws his deposits thus receiving points - // await staker.connect(signer1).withdraw(mockERC20.address, ethers.utils.parseEther("10")); - - // await expect( - // await staker.connect(signer1).getAvailablePoints(signer1.address) - // ).to.be.above("1000"); - - // // Owner of staker contract approves the mintshop1155 to use user points - // await staker.connect(owner).approvePointSpender(mintShop1155.address, true); - - // // Owner of mintshop1155 contract sets a permit for signer1 to mint - // await super1155.connect(owner).setPermit( - // mintShop1155.address, - // UNIVERSAL, - // setMintRight, - // ethers.constants.MaxUint256 - // ); - - // // Signer1 Successfully mint - // await mintShop1155.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput); - // }); + // index: 1, + // node: "0x66bec8af3e1db24c080f949a93ecca4f99c46c7afb08389d93b59e5f73514c75", + // merkleProof: computeMerkleProof(1, whiteListAddresses) + // }; + // // Mint + // await expect( + // mintShop1155.connect(owner).mintFromPool(1, 3, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) + // ).to.be.revertedWith("Invalid Proof."); // }); - describe("sweep, lockSweep", function () { - it('Reverts: sweep is locked', async function(){ - await mintShop1155.connect(owner).lockSweep(); - - await expect( - mintShop1155.connect(owner).sweep(mockERC20.address, ethers.utils.parseEther("10"), signer1.address) - ).to.be.revertedWith("Sweep: the sweep function is locked"); + it("Reverts: mintFromPool not enough items available for purchase", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Update the pool from beforeEach to lower its cap + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).updatePool( + 1, + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 2, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [1], // Caps + [ + [ + { + // Price pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + await mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); - it('should sweep tokens back from mintshop1155 to the user address', async function(){ - await mockERC20.connect(deployer).transfer(signer3.address, ethers.utils.parseEther("10")); + // Mint until cap reached + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }) + ).to.be.revertedWith("0x7B"); + }); - await mockERC20.connect(signer3).transfer(mintShop1155.address, ethers.utils.parseEther("5")); + it("Reverts: not enough ether sent", async function () { + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).updatePool( + 1, + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 2, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [2], // Caps + [ + [ + { + // Price pairs + assetType: 1, + asset: NULL_ADDRESS, + price: ethers.utils.parseEther("1"), + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("0.5"), + }) + ).to.be.revertedWith("0x9B"); + }); - await mintShop1155.connect(owner).sweep(mockERC20.address, ethers.utils.parseEther("5"), signer3.address); + it("Reverts => Success: mintFromPool not enough ERC20 tokens for the pool then getPrchaseCount", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); - await expect( - await mockERC20.balanceOf(signer3.address) - ).to.be.equal(ethers.utils.parseEther("10")); - }); + // Update the pool from beforeEach to include ERC20 token as price pair + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).updatePool( + 1, + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 4, + singlePurchaseLimit: 3, + requirement: { + requiredType: 1, + requiredAsset: [mockERC20.address], + requiredAmount: ethers.utils.parseEther("10"), + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [5], // Caps + [ + [ + { + // Price pairs + assetType: 2, + asset: mockERC20.address, + price: ethers.utils.parseEther("15"), + }, + { + assetType: 2, + asset: mockERC20.address, + price: ethers.utils.parseEther("15"), + }, + ], + ] + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Give signer1 some amount of ERC20 Tokens + await mockERC20 + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("5")); + + // Mint until cap reached + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 0, 1, 0, whiteListInput) + ).to.be.revertedWith("0x8B"); + + // Give signer1 some more amount of ERC20 Tokens + await mockERC20 + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("5")); + + // Signer1 approves mintshop1155 contract + await mockERC20 + .connect(signer1) + .approve(mintShop1155.address, ethers.utils.parseEther("15")); + + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 1, 3, 0, whiteListInput) + ).to.be.revertedWith("0x1C"); + + // Successful purchase, Give signer1 some more amount of ERC20 Tokens + await mockERC20 + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("5")); + + await mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 1, 1, 0, whiteListInput); + + // getPurchaseCounts + let balances = await mintShop1155 + .connect(signer1) + .getPurchaseCounts( + [signer1.address, signer2.address, owner.address], + [1] + ); + + await expect(balances[0][0]).to.be.equal("1"); //First index is the address, second is the ids + await expect(balances[1][0]).to.be.equal("0"); //First index is the address, second is the ids + await expect(balances[2][0]).to.be.equal("0"); //First index is the address, second is the ids }); - describe("max allocation test", function() { - it("Shoud revert", async function() { - let mShop = await this.MintShop1155.deploy( - deployer.address, - paymentReceiver.address, - "4", - 1 - ); - - - let sup = await this.Super1155.deploy( - owner.address, - "Super1155142", - originalUri + "uri2", - originalUri + "uri2", - proxyRegistry.address - ); - await sup.connect(owner).configureGroup(1, { - name: 'NFT', - supplyType: 0, - supplyData: 5, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await sup.connect(owner).setPermit( - mShop.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - - await mShop.setItems([sup.address]); - - // await super1155.setPermit(); - - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - console.log() - await mShop.connect(deployer).addPool({ - name: "maxAllocationTest", - startTime: latestBlock.timestamp, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 100, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: sup.address - }, [1], // Groups 1 = FT, 2 = NFT - [1], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 - [10], // Caps 10 = FT, 5 = NFT - [ - [{ // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - let pools = await mShop.getPools([0], 0); - console.log(pools[0].items[0].groupId.toString()); - - await mShop.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - await expect( - mShop.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x0D"); - }); + it("Reverts: mintFromPool unrecognized asset type (But it gets reverted at the time of assigning instead of actual revert)", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Update the pool from beforeEach to include ERC20 token as price pair + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await expect( + mintShop1155.connect(owner).updatePool( + 1, + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 2, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [2], // Caps + [ + [ + { + // Price pairs + assetType: 3, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 3, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ) + ).to.be.reverted; }); - describe("mintFromPool with whiteList ristrictions", function() { - beforeEach(async function(){ - - - - // Configure token groups - await super1155.connect(owner).configureGroup(itemGroupId, { - name: 'FUNGIBLE', - supplyType: 1, - supplyData: 10, - itemType: 1, - itemData: 0, - burnType: 1, - burnData: 5 - }); - - await super1155.connect(owner).configureGroup(itemGroupId2, { - name: 'NFT', - supplyType: 0, - supplyData: 5, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await super1155.connect(owner).configureGroup(itemGroupId2.add(1), { - name: 'SUPERNFT', - supplyType: 0, - supplyData: 5, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - - await super1155.connect(owner).setPermit( - mintShop1155.address, - UNIVERSAL, - setMintRight, - ethers.constants.MaxUint256 - ); - - // Create Pools - let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).addPool({ - name: "firstPool", - startTime: latestBlock.timestamp + 10, - endTime: latestBlock.timestamp + 60, - purchaseLimit: 3, - singlePurchaseLimit: 2, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 1, - - requiredId: [] - }, - collection: super1155.address - }, [1, 2], // Groups 1 = FT, 2 = NFT - [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 - [10, 5], // Caps 10 = FT, 5 = NFT - [ - [{ // Price pair for FTs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }], - - [{ // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); - await mintShop1155.connect(owner).addPool({ - name: "secondPool", - startTime: latestBlock.timestamp + 60, - endTime: latestBlock.timestamp + 120, - purchaseLimit: 3, - singlePurchaseLimit: 1, - requirement: { - requiredType: 0, - requiredAsset: [NULL_ADDRESS], - requiredAmount: 0, - - requiredId: [] - }, - collection: super1155.address - }, [1, 2], // Groups 1 = FT, 2 = NFT - [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 - [10, 5], // Caps 10 = FT, 5 = NFT - [ - [{ // Price pair for FTs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }], - - [{ // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }, { - assetType: 1, - asset: NULL_ADDRESS, - price: 1 - }] - ]); - - // Get the pool - let pools = await mintShop1155.connect(owner).getPools([0], 0); - expect(pools[0].config.name).to.be.equal("firstPool"); - - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - const root = computeRootHash(whiteList); - - const whiteListCreate = { - _accesslistId: 0, - _merkleRoot: root, - _startTime: 0, - _endTime: ethers.constants.MaxUint256, - _price: ethers.utils.parseEther("100"), - _token: NULL_ADDRESS - } - - - // await mintShop1155.connect(owner).setItems([super1155.address, super1155Second.address]); - await mintShop1155.connect(owner).addWhiteList(0, [whiteListCreate]); + it("Reverts: not enough ERC1155 required items", async function () { + // Give the Shop permit to mint items in Super1155 contract + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + // Update the pool from beforeEach to include ERC1155 requirement + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).updatePool( + 1, + { + name: "secondPool", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 2, + singlePurchaseLimit: 1, + requirement: { + requiredType: 2, + requiredAsset: [super1155.address], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [3], // Group + [0], // NumberOffset + [2], // Caps + [ + [ + { + // Price pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + // Mint based on ERC1155 item holdings + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 1, 1, 0, whiteListInput) + ).to.be.revertedWith("0x8B"); + + // Mint ERC1155 for signer1 + await super1155 + .connect(owner) + .mintBatch(signer1.address, [shiftedItemGroupId], ["1"], DATA); + + await mintShop1155 + .connect(signer1) + .mintFromPool(1, 3, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }); + }); + }); + + // describe("mintFromPool for staker contract for a specific Super1155 group", function () { + // it('should purchase using staking points', async function(){ + // // Configure token group + // await super1155.connect(owner).configureGroup(itemGroupId, { + // name: 'FUNGIBLE', + // supplyType: 1, + // supplyData: 10, + // itemType: 0, + // itemData: 0, + // burnType: 1, + // burnData: 5 + // }); + + // // Create Pool of that token group + // let latestBlock = await ethers.provider.getBlock(await ethers.provider.getBlockNumber()); + // await mintShop1155.connect(owner).addPool({ + // name: "firstPool", + // startTime: latestBlock.timestamp, + // endTime: latestBlock.timestamp + 60, + // purchaseLimit: 3, + // singlePurchaseLimit: 2, + // requirement: { + // requiredType: 3, + // requiredAsset: [staker.address], + // requiredAmount: 1000, // Required amount of points + // + // requiredId: [] + // }, + // collection: super1155.address + // }, [1], // Groups 1 = FT, 2 = NFT + // [0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 + // [10], // Caps 10 = FT, 5 = NFT + // [ + // [{ // Price pair for FTs + // assetType: 0, + // asset: staker.address, + // price: 1 + // }] + // ]); + + // // Set Emission rate to current block number + // await staker.connect(owner).setEmissions([ + // { blockNumber: (await (await ethers.provider.getBlock()).number) + 5, rate: ethers.utils.parseEther('10') }, + // ], [ + // { blockNumber: (await (await ethers.provider.getBlock()).number) + 5, rate: 100 }, + // ]); + // await staker.connect(owner).addPool(mockERC20.address, 100, 50); + + // for (let i = 0; i < 4; ++i) { + // ethers.provider.send('evm_mine'); + // } + + // // Give the signer1 some mockERC20 tokens + // await mockERC20.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("10")); + + // // Give staker contract some mockERC20 tokens + // await mockERC20.connect(deployer).transfer(staker.address, ethers.utils.parseEther("1000")); + + // // Signer1 approves staker contract + // await mockERC20.connect(signer1).approve(staker.address, ethers.utils.parseEther("10")); + + // // Signer1 deposits the tokens + // await staker.connect(signer1).deposit(mockERC20.address, ethers.utils.parseEther("10")); + + // // Jump forward and travel in time through the portal + // for (let i = 0; i < 5; ++i) { + // ethers.provider.send('evm_mine'); + // } + + // await expect(( + // await staker.connect(owner).getPendingPoints(mockERC20.address, signer1.address)).toString() + // ).to.be.equal("500"); + + // let whiteList = { + // "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, + // "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, + // "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + // "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + // "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + // "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + // "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 + // } + + // let whiteListInput = { + // whiteListId: 0, + // index: getIndex(whiteList, signer1.address), + // allowance: whiteList[signer1.address], + // node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), + // merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), + // } + // // Signer1 hasn't claimed points + // // mintFromPool of mintshop1155 must revert + // await expect( + // mintShop1155.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput) + // ).to.be.revertedWith("MintShop1155: you do not have enough required points for this pool"); + + // // Jump forward and travel in time through the portal, signer1 must be eligible for the pool now + // for (let i = 0; i < 5; ++i) { + // ethers.provider.send('evm_mine'); + // } + + // // Signer1 withdraws his deposits thus receiving points + // await staker.connect(signer1).withdraw(mockERC20.address, ethers.utils.parseEther("10")); + + // await expect( + // await staker.connect(signer1).getAvailablePoints(signer1.address) + // ).to.be.above("1000"); + + // // Owner of staker contract approves the mintshop1155 to use user points + // await staker.connect(owner).approvePointSpender(mintShop1155.address, true); + + // // Owner of mintshop1155 contract sets a permit for signer1 to mint + // await super1155.connect(owner).setPermit( + // mintShop1155.address, + // UNIVERSAL, + // setMintRight, + // ethers.constants.MaxUint256 + // ); + + // // Signer1 Successfully mint + // await mintShop1155.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput); + // }); + // }); + + describe("sweep, lockSweep", function () { + it("Reverts: sweep is locked", async function () { + await mintShop1155.connect(owner).lockSweep(); + + await expect( + mintShop1155 + .connect(owner) + .sweep( + mockERC20.address, + ethers.utils.parseEther("10"), + signer1.address + ) + ).to.be.revertedWith("Sweep: the sweep function is locked"); + }); - it("Shoud revert, user already bought", async function() { - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - await mintShop1155.connect(signer1).mintFromPool(0, 2, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("100")}) - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("100")}) - ).to.be.revertedWith("0x4B"); - }); + it("should sweep tokens back from mintshop1155 to the user address", async function () { + await mockERC20 + .connect(deployer) + .transfer(signer3.address, ethers.utils.parseEther("10")); + + await mockERC20 + .connect(signer3) + .transfer(mintShop1155.address, ethers.utils.parseEther("5")); + + await mintShop1155 + .connect(owner) + .sweep( + mockERC20.address, + ethers.utils.parseEther("5"), + signer3.address + ); - it("Shoud revert, user not in whiteList", async function() { - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - await expect( - mintShop1155.connect(owner).mintFromPool(1, 2, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("1")}) - ).to.be.revertedWith("0x4B"); - }) + await expect(await mockERC20.balanceOf(signer3.address)).to.be.equal( + ethers.utils.parseEther("10") + ); + }); + }); + + describe("max allocation test", function () { + it("Shoud revert", async function () { + let mShop = await this.MintShop1155.deploy( + deployer.address, + paymentReceiver.address, + "4", + 1 + ); + + let sup = await this.Super1155.deploy( + owner.address, + "Super1155142", + originalUri + "uri2", + originalUri + "uri2", + proxyRegistry.address + ); + await sup.connect(owner).configureGroup(1, { + name: "NFT", + supplyType: 0, + supplyData: 5, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await sup + .connect(owner) + .setPermit( + mShop.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); - it("Shoud revert: sent less than the value on the whitelist", async function() { - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - await expect( - mintShop1155.connect(signer1).mintFromPool(0, 2, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("99")}) - ).to.be.revertedWith("0x9B"); + await mShop.setItems([sup.address]); + + // await super1155.setPermit(); + + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + console.log(); + await mShop.connect(deployer).addPool( + { + name: "maxAllocationTest", + startTime: latestBlock.timestamp, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 100, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: sup.address, + }, + [1], // Groups 1 = FT, 2 = NFT + [1], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 + [10], // Caps 10 = FT, 5 = NFT + [ + [ + { + // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + let pools = await mShop.getPools([0], 0); + console.log(pools[0].items[0].groupId.toString()); + + await mShop.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }); + await expect( + mShop.connect(signer1).mintFromPool(0, 1, 0, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), }) + ).to.be.revertedWith("0x0D"); + }); + }); - it("Shoud buy for whitelist price", async function() { - await ethers.provider.send("evm_increaseTime", [70]); - await ethers.provider.send("evm_mine", []); - let whiteList = { - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" : 1, - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" : 1, - "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, - "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, - "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, - "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, - "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1 - } - - let whiteListInput = { - whiteListId: 0, - index: getIndex(whiteList, signer1.address), - allowance: whiteList[signer1.address], - node: hash(getIndex(whiteList, signer1.address), signer1.address, whiteList[signer1.address]), - merkleProof: computeMerkleProof(getIndex(whiteList, signer1.address), whiteList), - } - let provider = signer1.provider; - let balanceBefore = await provider.getBalance(signer1.address); - console.log(balanceBefore.toString()) - await mintShop1155.connect(signer1).mintFromPool(1, 2, 1, 1, 0, whiteListInput, {value: ethers.utils.parseEther("100")}) - let balanceAfter = await provider.getBalance(signer1.address); - console.log(balanceAfter.toString()) - - - console.log(balanceBefore.toString() - balanceAfter.toString()); - }) + describe("mintFromPool with whiteList ristrictions", function () { + beforeEach(async function () { + // Configure token groups + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "FUNGIBLE", + supplyType: 1, + supplyData: 10, + itemType: 1, + itemData: 0, + burnType: 1, + burnData: 5, + }); + + await super1155.connect(owner).configureGroup(itemGroupId2, { + name: "NFT", + supplyType: 0, + supplyData: 5, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await super1155.connect(owner).configureGroup(itemGroupId2.add(1), { + name: "SUPERNFT", + supplyType: 0, + supplyData: 5, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + + await super1155 + .connect(owner) + .setPermit( + mintShop1155.address, + UNIVERSAL, + setMintRight, + ethers.constants.MaxUint256 + ); + + // Create Pools + let latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).addPool( + { + name: "firstPool", + startTime: latestBlock.timestamp + 10, + endTime: latestBlock.timestamp + 60, + purchaseLimit: 3, + singlePurchaseLimit: 2, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 1, + + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], // Groups 1 = FT, 2 = NFT + [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 + [10, 5], // Caps 10 = FT, 5 = NFT + [ + [ + { + // Price pair for FTs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + + [ + { + // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + latestBlock = await ethers.provider.getBlock( + await ethers.provider.getBlockNumber() + ); + await mintShop1155.connect(owner).addPool( + { + name: "secondPool", + startTime: latestBlock.timestamp + 60, + endTime: latestBlock.timestamp + 120, + purchaseLimit: 3, + singlePurchaseLimit: 1, + requirement: { + requiredType: 0, + requiredAsset: [NULL_ADDRESS], + requiredAmount: 0, + + requiredId: [], + }, + collection: super1155.address, + }, + [1, 2], // Groups 1 = FT, 2 = NFT + [1, 0], // NumberOffset 1 = FT, 0 = NFT // FT's are coerced to index 1 + [10, 5], // Caps 10 = FT, 5 = NFT + [ + [ + { + // Price pair for FTs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + + [ + { + // Price pairs for NFTs, 5 NFTs = 5 Prices Pairs + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + { + assetType: 1, + asset: NULL_ADDRESS, + price: 1, + }, + ], + ] + ); + + // Get the pool + let pools = await mintShop1155.connect(owner).getPools([0], 0); + expect(pools[0].config.name).to.be.equal("firstPool"); + + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + const root = computeRootHash(whiteList); + + const whiteListCreate = { + _accesslistId: 0, + _merkleRoot: root, + _startTime: 0, + _endTime: ethers.constants.MaxUint256, + _price: ethers.utils.parseEther("100"), + _token: NULL_ADDRESS, + }; + + // await mintShop1155.connect(owner).setItems([super1155.address, super1155Second.address]); + await mintShop1155.connect(owner).addWhiteList(0, [whiteListCreate]); + }); + + it("Shoud revert, user already bought", async function () { + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + await mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 1, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("100"), + }); + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 1, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("100"), + }) + ).to.be.revertedWith("0x4B"); + }); + + it("Shoud revert, user not in whiteList", async function () { + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + await expect( + mintShop1155 + .connect(owner) + .mintFromPool(1, 2, 1, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("1"), + }) + ).to.be.revertedWith("0x4B"); + }); + + it("Shoud revert: sent less than the value on the whitelist", async function () { + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + await expect( + mintShop1155 + .connect(signer1) + .mintFromPool(0, 2, 1, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("99"), + }) + ).to.be.revertedWith("0x9B"); + }); + + it("Shoud buy for whitelist price", async function () { + await ethers.provider.send("evm_increaseTime", [70]); + await ethers.provider.send("evm_mine", []); + let whiteList = { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": 1, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": 1, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": 1, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": 1, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": 1, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": 1, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": 1, + }; + + let whiteListInput = { + whiteListId: 0, + index: getIndex(whiteList, signer1.address), + allowance: whiteList[signer1.address], + node: hash( + getIndex(whiteList, signer1.address), + signer1.address, + whiteList[signer1.address] + ), + merkleProof: computeMerkleProof( + getIndex(whiteList, signer1.address), + whiteList + ), + }; + let provider = signer1.provider; + let balanceBefore = await provider.getBalance(signer1.address); + console.log(balanceBefore.toString()); + await mintShop1155 + .connect(signer1) + .mintFromPool(1, 2, 1, 1, 0, whiteListInput, { + value: ethers.utils.parseEther("100"), + }); + let balanceAfter = await provider.getBalance(signer1.address); + console.log(balanceAfter.toString()); - + console.log(balanceBefore.toString() - balanceAfter.toString()); }); -}); \ No newline at end of file + }); +}); diff --git a/test/Staker.test.js b/test/Staker.test.js index 4a2a186..e0621ce 100644 --- a/test/Staker.test.js +++ b/test/Staker.test.js @@ -1,10 +1,10 @@ -const { expect } = require('chai'); -const { BigNumber } = require('ethers'); -const { mnemonicToSeed } = require('ethers/lib/utils'); -const { ethers } = require('hardhat'); -const Web3 = require('web3'); +const { expect } = require("chai"); +const { BigNumber } = require("ethers"); +const { mnemonicToSeed } = require("ethers/lib/utils"); +const { ethers } = require("hardhat"); +const Web3 = require("web3"); -const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; const DATA = "0x02"; @@ -16,459 +16,818 @@ const DATA = "0x02"; /////////////////////////////////////////////////////////// // Start test block -describe('===Staker===', function () { - let deployer, owner, paymentReceiver, proxyRegistryOwner, signer1, signer2, signer3; - - let rewardToken, - depositToken, - staker; - - before(async function () { - this.MockERC20 = await ethers.getContractFactory("MockERC20"); - this.Staker = await ethers.getContractFactory("Staker"); +describe("===Staker===", function () { + let deployer, + owner, + paymentReceiver, + proxyRegistryOwner, + signer1, + signer2, + signer3; + + let rewardToken, depositToken, staker; + + before(async function () { + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.Staker = await ethers.getContractFactory("Staker"); + }); + + beforeEach(async function () { + [ + deployer, + owner, + paymentReceiver, + proxyRegistryOwner, + signer1, + signer2, + signer3, + ] = await ethers.getSigners(); + + rewardToken = await this.MockERC20.deploy(); + await rewardToken.deployed(); + + depositToken = await this.MockERC20.deploy(); + await depositToken.deployed(); + + staker = await this.Staker.deploy("firstStaker", rewardToken.address); + await staker.deployed(); + + await staker.transferOwnership(owner.address); + }); + + // Test cases + + ////////////////////////////// + // Constructor + ////////////////////////////// + describe("Constructor", function () { + it("should initialize values as expected", async function () { + expect(await staker.name()).to.equal("firstStaker"); + expect(await staker.owner()).to.equal(owner.address); + expect(await staker.canAlterDevelopers()).to.equal(true); + expect(await staker.canAlterTokenEmissionSchedule()).to.equal(true); + expect(await staker.canAlterPointEmissionSchedule()).to.equal(true); }); + }); - beforeEach(async function () { - [deployer, owner, paymentReceiver, proxyRegistryOwner, signer1, signer2, signer3] = await ethers.getSigners(); + describe("addDeveloper, lockDevelopers, updateDeveloper, getDeveloperCount", function () { + it("Reverts: addition of developers is locked", async function () { + await staker.connect(owner).lockDevelopers(); - rewardToken = await this.MockERC20.deploy(); - await rewardToken.deployed(); + await expect( + staker.connect(owner).addDeveloper(deployer.address, "1000") + ).to.be.revertedWith( + "This Staker has locked the addition of developers; no more may be added." + ); + }); - depositToken = await this.MockERC20.deploy(); - await depositToken.deployed(); + it("should add new developer", async function () { + await staker.connect(owner).addDeveloper(deployer.address, "1000"); - staker = await this.Staker.deploy( - "firstStaker", - rewardToken.address - ); - await staker.deployed(); + await expect( + await staker.connect(owner).developerAddresses(0) + ).to.be.equal(deployer.address); + }); + + it("Reverts: Not a developer of the staker", async function () { + await staker.connect(owner).addDeveloper(deployer.address, "1000"); + + await expect( + staker.connect(signer1).updateDeveloper(signer1.address, "500") + ).to.be.revertedWith("You are not a developer of this Staker."); + }); - await staker.transferOwnership(owner.address); + it("Reverts: Can not increase share", async function () { + await staker.connect(owner).addDeveloper(deployer.address, "1000"); + + await expect( + staker.connect(deployer).updateDeveloper(deployer.address, "1500") + ).to.be.revertedWith("You cannot increase your developer share."); }); - // Test cases - - ////////////////////////////// - // Constructor - ////////////////////////////// - describe("Constructor", function () { - it('should initialize values as expected', async function () { - expect(await staker.name()).to.equal("firstStaker"); - expect(await staker.owner()).to.equal(owner.address); - expect(await staker.canAlterDevelopers()).to.equal(true); - expect(await staker.canAlterTokenEmissionSchedule()).to.equal(true); - expect(await staker.canAlterPointEmissionSchedule()).to.equal(true); - }); + it("should update developer", async function () { + await staker.connect(owner).addDeveloper(deployer.address, "1000"); + await staker.connect(deployer).updateDeveloper(deployer.address, "900"); + + await expect( + await staker.connect(deployer).developerShares(deployer.address) + ).to.be.equal("900"); }); - describe("addDeveloper, lockDevelopers, updateDeveloper, getDeveloperCount", function () { - it('Reverts: addition of developers is locked', async function () { - await staker.connect(owner).lockDevelopers(); - - await expect( - staker.connect(owner).addDeveloper(deployer.address, "1000") - ).to.be.revertedWith("This Staker has locked the addition of developers; no more may be added."); - }); - - it('should add new developer', async function () { - await staker.connect(owner).addDeveloper(deployer.address, "1000"); - - await expect( - await staker.connect(owner).developerAddresses(0) - ).to.be.equal(deployer.address); - }); - - it('Reverts: Not a developer of the staker', async function () { - await staker.connect(owner).addDeveloper(deployer.address, "1000"); - - await expect( - staker.connect(signer1).updateDeveloper(signer1.address, "500") - ).to.be.revertedWith("You are not a developer of this Staker."); - }); - - it('Reverts: Can not increase share', async function () { - await staker.connect(owner).addDeveloper(deployer.address, "1000"); - - await expect( - staker.connect(deployer).updateDeveloper(deployer.address, "1500") - ).to.be.revertedWith("You cannot increase your developer share."); - }); - - it('should update developer', async function () { - await staker.connect(owner).addDeveloper(deployer.address, "1000"); - await staker.connect(deployer).updateDeveloper(deployer.address, "900"); - - await expect( - await staker.connect(deployer).developerShares(deployer.address) - ).to.be.equal("900"); - }); - - it('should return developers count', async function () { - await staker.connect(owner).addDeveloper(deployer.address, "1000"); - await staker.connect(owner).addDeveloper(signer1.address, "900"); - - - await expect( - await staker.connect(deployer).getDeveloperCount() - ).to.be.equal("2"); - }); + it("should return developers count", async function () { + await staker.connect(owner).addDeveloper(deployer.address, "1000"); + await staker.connect(owner).addDeveloper(signer1.address, "900"); + + await expect( + await staker.connect(deployer).getDeveloperCount() + ).to.be.equal("2"); + }); + }); + + describe("setEmissions, lockTokenEmissions", function () { + it("Reverts: alteration of token emissions is locked", async function () { + await staker.connect(owner).lockTokenEmissions(); + + await expect( + staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ) + ).to.be.revertedWith( + "This Staker has locked the alteration of token emissions." + ); }); - describe("setEmissions, lockTokenEmissions", function () { - it('Reverts: alteration of token emissions is locked', async function () { - await staker.connect(owner).lockTokenEmissions(); - - await expect( - staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]) - ).to.be.revertedWith("This Staker has locked the alteration of token emissions."); - }); - - it('Reverts: alteration of point emissions is locked', async function () { - await staker.connect(owner).lockPointEmissions(); - - await expect( - staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]) - ).to.be.revertedWith("his Staker has locked the alteration of point emissions."); - }); - - it('Reverts: token emission schedule must be set', async function () { - await expect( - staker.connect(owner).setEmissions([],[]) - ).to.be.revertedWith("You must set the token emission schedule."); - }); - - it('Reverts: point emission schedule must be set', async function () { - await expect( - staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[]) - ).to.be.revertedWith("You must set the point emission schedule."); - }); - - it('should set emissions', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - }); - - it('should set emissions of staker where earliestTokenEmission/earliestPointEmission timestamps are less', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - - // Increase time so that the earliestTokenEmission/EarliestPointEmission timestamps are less - await ethers.provider.send("evm_increaseTime", [70]); - await ethers.provider.send("evm_mine", []); - - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - }); + it("Reverts: alteration of point emissions is locked", async function () { + await staker.connect(owner).lockPointEmissions(); + + await expect( + staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ) + ).to.be.revertedWith( + "This Staker has locked the alteration of point emissions." + ); }); - describe("addPool, overwrite pool, getPoolCount", function () { - it('Reverts: emission schedule not defined', async function () { - await expect( - staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ) - ).to.be.revertedWith("Staking pools cannot be addded until an emission schedule has been defined."); - }); - - it('Reverts: pool token is the disburse token', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: ethers.utils.parseEther('10') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 110, rate: ethers.utils.parseEther('5') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 120, rate: ethers.utils.parseEther('1') } - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 100 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 110, rate: 50 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 120, rate: 10 } - ]); - await expect( - staker.connect(owner).addPool(rewardToken.address, 100, 50) - ).to.be.revertedWith("Staking pool token can not be the same as reward token."); - }); - - it('Reverts: token or point strength of the pool is set to 0 or less', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: ethers.utils.parseEther('10') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 110, rate: ethers.utils.parseEther('5') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 120, rate: ethers.utils.parseEther('1') } - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 100 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 110, rate: 50 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 120, rate: 10 } - ]); - await expect( - staker.connect(owner).addPool(depositToken.address, 0, 1) - ).to.be.revertedWith("Staking pool token/point strength must be greater than 0."); - }); - - it('should add a new pool, overwrite it and get pool count', async function () { - // Set emission - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - - // Create new pool - await staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ); - - await expect( - await (await staker.connect(owner).poolInfo(depositToken.address)).tokenStrength - ).to.be.equal("1"); - - // Update the pool with 2x the strength - await staker.connect(owner).addPool( - depositToken.address, - 2, - 2 - ); - - await expect( - await (await staker.connect(owner).poolInfo(depositToken.address)).tokenStrength - ).to.be.equal("2"); - - // Get Pool count - await expect( - await staker.connect(owner).getPoolCount() - ).to.be.equal("1"); - }); + it("Reverts: token emission schedule must be set", async function () { + await expect( + staker.connect(owner).setEmissions([], []) + ).to.be.revertedWith("You must set the token emission schedule."); }); - describe("deposit, withdraw, getRemainingToken", function () { - it('Reverts: Inactive pool', async function () { - await expect( - staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("100")) - ).to.be.revertedWith("You cannot deposit assets into an inactive pool."); - }); - - it('should deposit and Return at updatePool: block.timestamp <= pool.lastRewardTime', async function () { - // Set emission such that time hasn't reached the emissionTime - // It can also be thought of stopping hackers to mine blocks in advance - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 5 } // Increasing the last reward by 100 seconds - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 5 } - ]); - - // Create new pool - await staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ); - - // Give the signer some mockERC20 tokens - await depositToken.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("1000")); - - // Signer approves staker contract - await depositToken.connect(signer1).approve(staker.address, ethers.utils.parseEther("100")); - - // Signer deposits the tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("100")); - }); - - it('should deposit and Return at updatePool: poolTokenSupply <= 0', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - - // Create new pool - await staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ); - - // Give the signer some mockERC20 tokens - await depositToken.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("1000")); - - // Signer approves staker contract - await depositToken.connect(signer1).approve(staker.address, ethers.utils.parseEther("100")); - - // Signer deposits the tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("100")); - }); - - it('should deposit and withdraw amount of tokens in the pool, different from the rewardToken', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - - // Create new pool - await staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ); - - // Let Signer2 be the developer - await staker.connect(owner).addDeveloper(deployer.address, "2"); - - // Give the signer some mockERC20 tokens - await depositToken.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("1000")); - - // Signer approves staker contract - await depositToken.connect(signer1).approve(staker.address, ethers.utils.parseEther("200")); - - // Signer deposits the tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("100")); - - // Signer deposits some more tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("50")); - - // Withdraw deposited tokens - await expect( - staker.connect(signer1).withdraw(depositToken.address, ethers.utils.parseEther("200")) - ).to.be.revertedWith("You cannot withdraw that much of the specified token; you are not owed it."); - - await staker.connect(signer1).withdraw(depositToken.address, ethers.utils.parseEther("140")); - - // Get remaining tokens - await expect(( - await staker.connect(owner).getRemainingToken()).toString() - ).to.be.equal("0"); - }); + it("Reverts: point emission schedule must be set", async function () { + await expect( + staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [] + ) + ).to.be.revertedWith("You must set the point emission schedule."); }); - describe("getTotalEmittedTokens, getTotalEmittedPoints", function () { - it('Reverts: tokens/points emission from higher timestamp to lower timestamp', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 5 } - ]); - - await expect( - staker.connect(signer1).getTotalEmittedTokens(await (await ethers.provider.getBlock()).timestamp, - (await (await ethers.provider.getBlock()).timestamp) - 10) - ).to.be.revertedWith("Tokens cannot be emitted from a higher timestsamp to a lower timestamp."); - - await expect( - staker.connect(signer1).getTotalEmittedPoints(await (await ethers.provider.getBlock()).timestamp, - (await (await ethers.provider.getBlock()).timestamp) - 10) - ).to.be.revertedWith("Points cannot be emitted from a higher timestsamp to a lower timestamp."); - }); - - it('should get emitted tokens/points where _toTime < emissionTime', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: ethers.utils.parseEther('10')}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 200, rate: ethers.utils.parseEther('5') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 300, rate: ethers.utils.parseEther('1') } - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 100}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 200, rate: 50 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 300, rate: 10 } - ]); - - let emissionTokens = await staker.connect(signer1).getTotalEmittedTokens(await (await ethers.provider.getBlock()).timestamp, - (await (await ethers.provider.getBlock()).timestamp) + 150); - let emissionPoints = await staker.connect(signer1).getTotalEmittedPoints(await (await ethers.provider.getBlock()).timestamp, - (await (await ethers.provider.getBlock()).timestamp) + 150); - - await expect(emissionTokens).to.be.equal(ethers.utils.parseEther("510")); - await expect(emissionPoints).to.be.equal("5100"); - }); - - it('should get emitted points where workingTime < emissionTime', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 50, rate: ethers.utils.parseEther('10')}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: ethers.utils.parseEther('5') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 150, rate: ethers.utils.parseEther('1') } - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 50, rate: 100}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 50 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 150, rate: 10 } - ]); - - let emissionTokens = await staker.connect(signer1).getTotalEmittedTokens(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp + 2); - let emissionPoints = await staker.connect(signer1).getTotalEmittedPoints(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp + 2); - - await expect(emissionTokens).to.be.equal(ethers.utils.parseEther("0")); - await expect(emissionPoints).to.be.equal("0"); - }); - - it('should get emitted tokens/points where workingTime < _toTime', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther('10')}, - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 100}, - ]); - - let emissionTokens = await staker.connect(signer1).getTotalEmittedTokens(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp + 30); - let emissionPoints = await staker.connect(signer1).getTotalEmittedPoints(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp + 30); - }); - - it('should get emitted tokens/points where workingTime > _toTime', async function () { - // Assuming the Emission rate was already set in the past - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp - 50, rate: ethers.utils.parseEther('10')}, - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp - 50, rate: 100}, - ]); - - let emissionTokens = await staker.connect(signer1).getTotalEmittedTokens(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp); - let emissionPoints = await staker.connect(signer1).getTotalEmittedPoints(await (await ethers.provider.getBlock()).timestamp, - await (await ethers.provider.getBlock()).timestamp); - }); + it("should set emissions", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); }); - describe("getPendingTokens, getPendingPoints, getAvailablePoints, getTotalPoints, approvePointSpender, spendPoints, getSpentPoints, sweep", function () { - it('should get pending tokens/points when pool token is not disburse token. Should getAvailablePoints, getTotalPoints, approvePointSpender, spendPoints, getSpentPoints, sweep', async function () { - // Give the signer some mockERC20 tokens - await depositToken.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("10")); - - // Give staker contract some mockERC20 tokens - await depositToken.connect(deployer).transfer(staker.address, ethers.utils.parseEther("100")); - - // Signer approves staker contract - await depositToken.connect(signer1).approve(staker.address, ethers.utils.parseEther("10")); - - // Set Emission rate - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther('10')}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 50, rate: ethers.utils.parseEther('5') }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: ethers.utils.parseEther('1') } - ], [ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: 100}, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 50, rate: 50 }, - { timeStamp: await (await ethers.provider.getBlock()).timestamp + 100, rate: 10 } - ]); - await staker.connect(owner).addPool(depositToken.address, 10, 20); - - /*Mine up to a preconfigured point for deposits. + it("should set emissions of staker where earliestTokenEmission/earliestPointEmission timestamps are less", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + + // Increase time so that the earliestTokenEmission/EarliestPointEmission timestamps are less + await ethers.provider.send("evm_increaseTime", [70]); + await ethers.provider.send("evm_mine", []); + + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + }); + }); + + describe("addPool, overwrite pool, getPoolCount", function () { + it("Reverts: emission schedule not defined", async function () { + await expect( + staker.connect(owner).addPool(depositToken.address, 1, 1) + ).to.be.revertedWith( + "Staking pools cannot be addded until an emission schedule has been defined." + ); + }); + + it("Reverts: pool token is the disburse token", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: ethers.utils.parseEther("10"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 110, + rate: ethers.utils.parseEther("5"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 120, + rate: ethers.utils.parseEther("1"), + }, + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 100, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 110, + rate: 50, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 120, + rate: 10, + }, + ] + ); + await expect( + staker.connect(owner).addPool(rewardToken.address, 100, 50) + ).to.be.revertedWith( + "Staking pool token can not be the same as reward token." + ); + }); + + it("Reverts: token or point strength of the pool is set to 0 or less", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: ethers.utils.parseEther("10"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 110, + rate: ethers.utils.parseEther("5"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 120, + rate: ethers.utils.parseEther("1"), + }, + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 100, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 110, + rate: 50, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 120, + rate: 10, + }, + ] + ); + await expect( + staker.connect(owner).addPool(depositToken.address, 0, 1) + ).to.be.revertedWith( + "Staking pool token/point strength must be greater than 0." + ); + }); + + it("should add a new pool, overwrite it and get pool count", async function () { + // Set emission + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + + // Create new pool + await staker.connect(owner).addPool(depositToken.address, 1, 1); + + await expect( + await ( + await staker.connect(owner).poolInfo(depositToken.address) + ).tokenStrength + ).to.be.equal("1"); + + // Update the pool with 2x the strength + await staker.connect(owner).addPool(depositToken.address, 2, 2); + + await expect( + await ( + await staker.connect(owner).poolInfo(depositToken.address) + ).tokenStrength + ).to.be.equal("2"); + + // Get Pool count + await expect(await staker.connect(owner).getPoolCount()).to.be.equal("1"); + }); + }); + + describe("deposit, withdraw, getRemainingToken", function () { + it("Reverts: Inactive pool", async function () { + await expect( + staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("100")) + ).to.be.revertedWith("You cannot deposit assets into an inactive pool."); + }); + + it("should deposit and Return at updatePool: block.timestamp <= pool.lastRewardTime", async function () { + // Set emission such that time hasn't reached the emissionTime + // It can also be thought of stopping hackers to mine blocks in advance + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 5, + }, // Increasing the last reward by 100 seconds + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 5, + }, + ] + ); + + // Create new pool + await staker.connect(owner).addPool(depositToken.address, 1, 1); + + // Give the signer some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("1000")); + + // Signer approves staker contract + await depositToken + .connect(signer1) + .approve(staker.address, ethers.utils.parseEther("100")); + + // Signer deposits the tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("100")); + }); + + it("should deposit and Return at updatePool: poolTokenSupply <= 0", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + + // Create new pool + await staker.connect(owner).addPool(depositToken.address, 1, 1); + + // Give the signer some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("1000")); + + // Signer approves staker contract + await depositToken + .connect(signer1) + .approve(staker.address, ethers.utils.parseEther("100")); + + // Signer deposits the tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("100")); + }); + + it("should deposit and withdraw amount of tokens in the pool, different from the rewardToken", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + + // Create new pool + await staker.connect(owner).addPool(depositToken.address, 1, 1); + + // Let Signer2 be the developer + await staker.connect(owner).addDeveloper(deployer.address, "2"); + + // Give the signer some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("1000")); + + // Signer approves staker contract + await depositToken + .connect(signer1) + .approve(staker.address, ethers.utils.parseEther("200")); + + // Signer deposits the tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("100")); + + console.log(await depositToken.balanceOf(staker.address)); + + // Signer deposits some more tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("50")); + + console.log(await depositToken.balanceOf(staker.address)); + console.log(await staker.connect(owner).getRemainingToken()); + + // Withdraw deposited tokens + await expect( + staker + .connect(signer1) + .withdraw(depositToken.address, ethers.utils.parseEther("200")) + ).to.be.revertedWith( + "You cannot withdraw that much of the specified token; you are not owed it." + ); + + await staker + .connect(signer1) + .withdraw(depositToken.address, ethers.utils.parseEther("140")); + + console.log(await depositToken.balanceOf(staker.address)); + // Get remaining tokens + await expect( + (await staker.connect(owner).getRemainingToken()).toString() + ).to.be.equal("0"); + + console.log(await staker.connect(owner).getRemainingToken()); + }); + }); + + describe("getTotalEmittedTokens, getTotalEmittedPoints", function () { + it("Reverts: tokens/points emission from higher timestamp to lower timestamp", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 5, + }, + ] + ); + + await expect( + staker + .connect(signer1) + .getTotalEmittedTokens( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) - 10 + ) + ).to.be.revertedWith( + "Tokens cannot be emitted from a higher timestsamp to a lower timestamp." + ); + + await expect( + staker + .connect(signer1) + .getTotalEmittedPoints( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) - 10 + ) + ).to.be.revertedWith( + "Points cannot be emitted from a higher timestsamp to a lower timestamp." + ); + }); + + it("should get emitted tokens/points where _toTime < emissionTime", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: ethers.utils.parseEther("10"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 200, + rate: ethers.utils.parseEther("5"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 300, + rate: ethers.utils.parseEther("1"), + }, + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 100, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 200, + rate: 50, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 300, + rate: 10, + }, + ] + ); + + let emissionTokens = await staker + .connect(signer1) + .getTotalEmittedTokens( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 150 + ); + let emissionPoints = await staker + .connect(signer1) + .getTotalEmittedPoints( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 150 + ); + + await expect(emissionTokens).to.be.equal(ethers.utils.parseEther("510")); + await expect(emissionPoints).to.be.equal("5100"); + }); + + it("should get emitted points where workingTime < emissionTime", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 50, + rate: ethers.utils.parseEther("10"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: ethers.utils.parseEther("5"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 150, + rate: ethers.utils.parseEther("1"), + }, + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 50, + rate: 100, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 50, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 150, + rate: 10, + }, + ] + ); + + let emissionTokens = await staker + .connect(signer1) + .getTotalEmittedTokens( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 2 + ); + let emissionPoints = await staker + .connect(signer1) + .getTotalEmittedPoints( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 2 + ); + + await expect(emissionTokens).to.be.equal(ethers.utils.parseEther("0")); + await expect(emissionPoints).to.be.equal("0"); + }); + + it("should get emitted tokens/points where workingTime < _toTime", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("10"), + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 100, + }, + ] + ); + + let emissionTokens = await staker + .connect(signer1) + .getTotalEmittedTokens( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 30 + ); + let emissionPoints = await staker + .connect(signer1) + .getTotalEmittedPoints( + await ( + await ethers.provider.getBlock() + ).timestamp, + (await (await ethers.provider.getBlock()).timestamp) + 30 + ); + }); + + it("should get emitted tokens/points where workingTime > _toTime", async function () { + // Assuming the Emission rate was already set in the past + await staker.connect(owner).setEmissions( + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) - 50, + rate: ethers.utils.parseEther("10"), + }, + ], + [ + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) - 50, + rate: 100, + }, + ] + ); + + let emissionTokens = await staker + .connect(signer1) + .getTotalEmittedTokens( + await ( + await ethers.provider.getBlock() + ).timestamp, + await ( + await ethers.provider.getBlock() + ).timestamp + ); + let emissionPoints = await staker + .connect(signer1) + .getTotalEmittedPoints( + await ( + await ethers.provider.getBlock() + ).timestamp, + await ( + await ethers.provider.getBlock() + ).timestamp + ); + }); + }); + + describe("getPendingTokens, getPendingPoints, getAvailablePoints, getTotalPoints, approvePointSpender, spendPoints, getSpentPoints, sweep", function () { + it("should get pending tokens/points when pool token is not disburse token. Should getAvailablePoints, getTotalPoints, approvePointSpender, spendPoints, getSpentPoints, sweep", async function () { + // Give the signer some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("10")); + + // Give staker contract some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(staker.address, ethers.utils.parseEther("100")); + + // Signer approves staker contract + await depositToken + .connect(signer1) + .approve(staker.address, ethers.utils.parseEther("10")); + + // Set Emission rate + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("10"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 50, + rate: ethers.utils.parseEther("5"), + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: ethers.utils.parseEther("1"), + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: 100, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 50, + rate: 50, + }, + { + timeStamp: + (await (await ethers.provider.getBlock()).timestamp) + 100, + rate: 10, + }, + ] + ); + await staker.connect(owner).addPool(depositToken.address, 10, 20); + + /*Mine up to a preconfigured point for deposits. let timeStamp = await ethers.provider.getBlock(); let blocksToMine = 998 - timeStamp; @@ -476,125 +835,175 @@ describe('===Staker===', function () { ethers.provider.send('evm_mine'); }*/ - // Signer deposits the tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("10")); - - // Get Pending Tokens - await expect(( - await staker.connect(owner).getPendingTokens(depositToken.address, signer1.address)).toString() - ).to.be.equal("0"); - await expect(( - await staker.connect(owner).getPendingPoints(depositToken.address, signer1.address)).toString() - ).to.be.equal("0"); - - // Jump forward and travel in time through the portal - await network.provider.send("evm_increaseTime", [100]) - await ethers.provider.send('evm_mine'); - - // Has pending tokens - await expect(( - await staker.connect(owner).getPendingTokens(depositToken.address, signer1.address)).toString() - ).not.to.be.equal("0"); - await expect(( - await staker.connect(owner).getPendingPoints(depositToken.address, signer1.address)).toString() - ).not.to.be.equal("0"); - - // Has available points - await expect( - await staker.connect(signer1).getAvailablePoints(signer1.address) - ).not.to.be.equal("0"); - await expect( - await staker.connect(signer1).getTotalPoints(signer1.address) - ).not.to.be.equal("0"); - - // Signer2 tries to spend points without approval - await expect( - staker.connect(signer2).spendPoints(signer1.address, 5) - ).to.be.revertedWith("You are not permitted to spend user points."); - - // Approve signer2 as point spender - await staker.connect(owner).approvePointSpender(signer2.address, true); - await expect( - await staker.approvedPointSpenders(signer2.address)).to.be.equal(true); - - // Signer2 spends points more than available - await expect( - staker.connect(signer2).spendPoints(signer1.address, 10000) - ).to.be.revertedWith("The user does not have enough points to spend the requested amount."); - - // Signer2 spends correct amount - await staker.connect(signer2).spendPoints(signer1.address, 2); - - // Get points spent - await expect( - await staker.getSpentPoints(signer1.address) - ).to.be.equal(2); - - // Sweep all specific tokens back - await rewardToken.connect(deployer).transfer(staker.address, ethers.utils.parseEther("10")); - - await expect( - await rewardToken.balanceOf(staker.address) - ).not.to.be.equal("0"); - - await staker.connect(owner).sweep(rewardToken.address); - - await expect( - await rewardToken.balanceOf(staker.address) - ).to.be.equal("0"); - }); + // Signer deposits the tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("10")); + + // Get Pending Tokens + await expect( + ( + await staker + .connect(owner) + .getPendingTokens(depositToken.address, signer1.address) + ).toString() + ).to.be.equal("0"); + await expect( + ( + await staker + .connect(owner) + .getPendingPoints(depositToken.address, signer1.address) + ).toString() + ).to.be.equal("0"); + + // Jump forward and travel in time through the portal + await network.provider.send("evm_increaseTime", [100]); + await ethers.provider.send("evm_mine"); + + // Has pending tokens + await expect( + ( + await staker + .connect(owner) + .getPendingTokens(depositToken.address, signer1.address) + ).toString() + ).not.to.be.equal("0"); + await expect( + ( + await staker + .connect(owner) + .getPendingPoints(depositToken.address, signer1.address) + ).toString() + ).not.to.be.equal("0"); + + // Has available points + await expect( + await staker.connect(signer1).getAvailablePoints(signer1.address) + ).not.to.be.equal("0"); + await expect( + await staker.connect(signer1).getTotalPoints(signer1.address) + ).not.to.be.equal("0"); + + // Signer2 tries to spend points without approval + await expect( + staker.connect(signer2).spendPoints(signer1.address, 5) + ).to.be.revertedWith("You are not permitted to spend user points."); + + // Approve signer2 as point spender + await staker.connect(owner).approvePointSpender(signer2.address, true); + await expect( + await staker.approvedPointSpenders(signer2.address) + ).to.be.equal(true); + + // Signer2 spends points more than available + await expect( + staker.connect(signer2).spendPoints(signer1.address, 10000) + ).to.be.revertedWith( + "The user does not have enough points to spend the requested amount." + ); + + // Signer2 spends correct amount + await staker.connect(signer2).spendPoints(signer1.address, 2); + + // Get points spent + await expect(await staker.getSpentPoints(signer1.address)).to.be.equal(2); + + // Sweep all specific tokens back + await rewardToken + .connect(deployer) + .transfer(staker.address, ethers.utils.parseEther("10")); + + await expect(await rewardToken.balanceOf(staker.address)).not.to.be.equal( + "0" + ); + + await staker.connect(owner).sweep(rewardToken.address); + + await expect(await rewardToken.balanceOf(staker.address)).to.be.equal( + "0" + ); }); - - describe("Check claim function", function () { - it('should be able to claim correctly', async function () { - await staker.connect(owner).setEmissions([ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther("6.6666") } - ],[ - { timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther("6.6666") } - ]); - - // Create new pool - await staker.connect(owner).addPool( - depositToken.address, - 1, - 1 - ); - - // Give the signer some mockERC20 tokens - await depositToken.connect(deployer).transfer(signer1.address, ethers.utils.parseEther("10")); - await rewardToken.connect(deployer).transfer(staker.address, ethers.utils.parseEther("1000000")); - - // Signer approves staker contract - await depositToken.connect(signer1).approve(staker.address, ethers.utils.parseEther("10")); - - // Signer deposits the tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("5")); //== - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be 0 //== - await network.provider.send("evm_increaseTime", [30])//== - - await staker.connect(signer1).claim(depositToken.address);//== - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be some balance - await network.provider.send("evm_increaseTime", [30]) - - // Signer deposits some more tokens - await staker.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("5")); - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be the same as last claim - - await staker.connect(signer1).claim(depositToken.address); - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should increase more - - await staker.connect(signer1).claim(depositToken.address); - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be almost the same - - await staker.connect(signer1).withdraw(depositToken.address, ethers.utils.parseEther("10")); - await network.provider.send("evm_increaseTime", [30]) - await staker.connect(signer1).claim(depositToken.address); - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be almost the same - - await network.provider.send("evm_increaseTime", [30]) - console.log(await(await rewardToken.balanceOf(signer1.address)).toString()); // Should be exactly the same - - - }); + }); + + describe("Check claim function", function () { + it("should be able to claim correctly", async function () { + await staker.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("6.6666"), + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("6.6666"), + }, + ] + ); + + // Create new pool + await staker.connect(owner).addPool(depositToken.address, 1, 1); + + // Give the signer some mockERC20 tokens + await depositToken + .connect(deployer) + .transfer(signer1.address, ethers.utils.parseEther("10")); + await rewardToken + .connect(deployer) + .transfer(staker.address, ethers.utils.parseEther("1000000")); + + // Signer approves staker contract + await depositToken + .connect(signer1) + .approve(staker.address, ethers.utils.parseEther("10")); + + // Signer deposits the tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("5")); //== + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be 0 //== + await network.provider.send("evm_increaseTime", [30]); //== + + await staker.connect(signer1).claim(depositToken.address); //== + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be some balance + await network.provider.send("evm_increaseTime", [30]); + + // Signer deposits some more tokens + await staker + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("5")); + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be the same as last claim + + await staker.connect(signer1).claim(depositToken.address); + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should increase more + + await staker.connect(signer1).claim(depositToken.address); + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be almost the same + + await staker + .connect(signer1) + .withdraw(depositToken.address, ethers.utils.parseEther("10")); + await network.provider.send("evm_increaseTime", [30]); + await staker.connect(signer1).claim(depositToken.address); + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be almost the same + + await network.provider.send("evm_increaseTime", [30]); + console.log( + await (await rewardToken.balanceOf(signer1.address)).toString() + ); // Should be exactly the same }); -}); \ No newline at end of file + }); +}); diff --git a/test/Staker1000users.test.js b/test/Staker1000users.test.js new file mode 100644 index 0000000..2c94106 --- /dev/null +++ b/test/Staker1000users.test.js @@ -0,0 +1,434 @@ +const { expect, util } = require("chai"); +const { BigNumber } = require("ethers"); +const { mnemonicToSeed, checkProperties } = require("ethers/lib/utils"); +const { ethers, network } = require("hardhat"); +//const Web3 = require('web3'); + +import * as utils from "./utils.js"; + +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + +const DATA = "0x02"; + +/////////////////////////////////////////////////////////// +// SEE https://hardhat.org/tutorial/testing-contracts.html +// FOR HELP WRITING TESTS +// USE https://github.com/gnosis/mock-contract FOR HELP +// WITH MOCK CONTRACT +/////////////////////////////////////////////////////////// + +// Start test block +describe("===Stakerv3ds===", function () { + let deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer; + + let coreSelectors, + stakingSelectors, + pointsSelectors, + boostersSelectors, + viewsSelectors, + addressesForSelectors, + allSelectors; + + let some721, + some1155, + rewardToken, + depositToken, + IOUToken, + super721, + super1155, + proxyRegistry, + stakerV3FacetCore, + stakerV3FacetStaking, + stakerV3FacetPoints, + stakerV3FacetBoosters, + stakerV3FacetViews, + stakerV3dsProxy, + diamondStakingFacet, + diamondCoreFacet, + diamondPointsFacet, + diamondBoostersFacet, + diamondViewsFacet; + let startOfStaking; + const originalUri = "://ipfs/uri/"; + const originalUri721 = "://ipfs/uri/"; + const originalUri1155 = "://ipfs/uri/"; + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + let stakerName = "StakerV3ds"; + + before(async function () { + this.MockERC721 = await ethers.getContractFactory("TestERC721"); + this.MockERC1155 = await ethers.getContractFactory("TestERC1155"); + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.StakerV3Proxy = await ethers.getContractFactory("StakerProxy"); + this.StakerV3FacetCore = await ethers.getContractFactory( + "StakerV3FacetCore" + ); + this.StakerV3FacetViews = await ethers.getContractFactory( + "StakerV3FacetViews" + ); + this.StakerV3FacetStaking = await ethers.getContractFactory( + "StakerV3FacetStaking" + ); + this.StakerV3FacetPoints = await ethers.getContractFactory( + "StakerV3FacetPoints" + ); + this.StakerV3FacetBoosters = await ethers.getContractFactory( + "StakerV3FacetBoosters" + ); + this.Super721 = await ethers.getContractFactory("Super721"); + this.Super1155 = await ethers.getContractFactory("Super1155"); + this.ProxyRegistry = await ethers.getContractFactory("MockProxyRegistry"); + }); + + beforeEach(async function () { + [ + deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer, + ] = await ethers.getSigners(); + + some721 = await this.MockERC721.deploy(); + await await some721.deployed(); + + // some1155 = await this.MockERC1155.deploy(); + // some1155.deployed(); + + rewardToken = await this.MockERC20.deploy(); + await rewardToken.deployed(); + + depositToken = await this.MockERC20.deploy(); + await depositToken.deployed(); + + stakerV3FacetCore = await this.StakerV3FacetCore.deploy(); + await stakerV3FacetCore.deployed(); + + stakerV3FacetStaking = await this.StakerV3FacetStaking.deploy(); + await stakerV3FacetStaking.deployed(); + + stakerV3FacetPoints = await this.StakerV3FacetPoints.deploy(); + await stakerV3FacetPoints.deployed(); + + stakerV3FacetBoosters = await this.StakerV3FacetBoosters.deploy(); + await stakerV3FacetBoosters.deployed(); + + stakerV3FacetViews = await this.StakerV3FacetViews.deploy(); + await stakerV3FacetViews.deployed(); + + proxyRegistry = await this.ProxyRegistry.deploy(); + await proxyRegistry.deployed(); + + IOUToken = await this.MockERC721.deploy(); + await IOUToken.deployed(); + + super721 = await this.Super721.deploy( + owner.address, + "Super721", + "SIMX721", + originalUri, + originalUri721, + proxyRegistry.address + ); + await super721.deployed(); + + super1155 = await this.Super1155.deploy( + owner.address, + "Super1155", + originalUri, + originalUri1155, + proxyRegistry.address + ); + await super1155.deployed(); + + var someSelector1 = await utils.getSelector( + "function setEmissions((uint256,uint256)[],(uint256,uint256)[])" + ); + //console.log(someSelector1); + + var someSelector = await utils.getSelector("function initialize(address)"); + //console.log(someSelector); + + coreSelectors = await utils.getSelectors(stakerV3FacetCore); + addressesForSelectors = []; + // console.log(coreSelectors); + let counter = 0; + for (counter; counter < coreSelectors.length; counter++) { + addressesForSelectors.push(stakerV3FacetCore.address); + } + + oldCounter = counter; + viewsSelectors = await utils.getSelectors(stakerV3FacetViews); + for (counter; counter < viewsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetViews.address); + } + + oldCounter = counter; + pointsSelectors = await utils.getSelectors(stakerV3FacetPoints); + for (counter; counter < pointsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetPoints.address); + } + // console.log(pointsSelectors); + + oldCounter = counter; + boostersSelectors = await utils.getSelectors(stakerV3FacetBoosters); + for (counter; counter < boostersSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetBoosters.address); + } + + var oldCounter = counter; + stakingSelectors = await utils.getSelectors(stakerV3FacetStaking); + for (counter; counter < stakingSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetStaking.address); + } + //console.log(stakingSelectors); + + allSelectors = [ + ...coreSelectors, + ...viewsSelectors, + ...pointsSelectors, + ...boostersSelectors, + ...stakingSelectors, + ]; + //console.log(allSelectors); + + stakerV3dsProxy = await this.StakerV3Proxy.deploy( + stakerV3FacetCore.address, + owner.address, + rewardToken.address, + admin.address, + IOUToken.address, + stakerName, + allSelectors, + addressesForSelectors + ); + await stakerV3dsProxy.deployed(); + + some721.mint(signer1.address, 1); + + rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("1000000") + ); + + IOUToken.transferOwnership(stakerV3dsProxy.address); + + diamondStakingFacet = await ethers.getContractAt( + "StakerV3FacetStaking", + stakerV3dsProxy.address + ); + + diamondCoreFacet = await ethers.getContractAt( + "StakerV3FacetCore", + stakerV3dsProxy.address + ); + + diamondBoostersFacet = await ethers.getContractAt( + "StakerV3FacetBoosters", + stakerV3dsProxy.address + ); + + diamondPointsFacet = await ethers.getContractAt( + "StakerV3FacetPoints", + stakerV3dsProxy.address + ); + + diamondViewsFacet = await ethers.getContractAt( + "StakerV3FacetViews", + stakerV3dsProxy.address + ); + }); + + describe("change booster with 1000 partcipants", function () { + it("stakerv3", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 2100, + burnType: 0, + burnData: 0, + }); + + const accounts = await hre.ethers.getSigners(); + let arrayOfSigners = []; + //let signersS = []; + + let tokenCounter = 0; + for (let i = 0; i < 100; i++) { + arrayOfSigners.push(await ethers.Wallet.createRandom()); + arrayOfSigners[i] = arrayOfSigners[i].connect(ethers.provider); + await signer3.sendTransaction({ + to: arrayOfSigners[i].address, + value: ethers.utils.parseEther("1"), + }); + + await depositToken.transfer( + arrayOfSigners[i].address, + ethers.utils.parseEther("1000") + ); + + await super721 + .connect(owner) + .mintBatch( + arrayOfSigners[i].address, + [ + shiftedItemGroupId2.add(tokenCounter), + shiftedItemGroupId2.add(tokenCounter + 1), + ], + DATA + ); + + await super721 + .connect(arrayOfSigners[i]) + .setApprovalForAll(stakerV3dsProxy.address, true); + + console.log(i + " " + arrayOfSigners[i].address); + + await diamondBoostersFacet + .connect(arrayOfSigners[i]) + .stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(tokenCounter)], + amounts: [1], + IOUTokenId: [], + }); + + await diamondStakingFacet.connect(arrayOfSigners[i]).deposit( + 0, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(tokenCounter + 1)], + amounts: [1], + IOUTokenId: [], + }, + false + ); + + tokenCounter += 2; + } + + console.log("withdraws starts"); + + await diamondStakingFacet.connect(arrayOfSigners[0]).withdraw(0, [0]); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 3000, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await utils.evm_increaseTime(30); + + await diamondStakingFacet.connect(arrayOfSigners[1]).withdraw(0, [1]); + + await utils.evm_increaseTime(30); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 2900, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + for (let i = 2; i < 10; i++) { + await diamondStakingFacet.connect(arrayOfSigners[i]).claim(0, []); + } + }); + }); +}); diff --git a/test/StakerChangeBoosters.test.js b/test/StakerChangeBoosters.test.js new file mode 100644 index 0000000..197f288 --- /dev/null +++ b/test/StakerChangeBoosters.test.js @@ -0,0 +1,504 @@ +const { expect, util } = require("chai"); +const { BigNumber } = require("ethers"); +const { mnemonicToSeed, checkProperties } = require("ethers/lib/utils"); +const { ethers, network } = require("hardhat"); +//const Web3 = require('web3'); + +import * as utils from "./utils.js"; + +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + +const DATA = "0x02"; + +/////////////////////////////////////////////////////////// +// SEE https://hardhat.org/tutorial/testing-contracts.html +// FOR HELP WRITING TESTS +// USE https://github.com/gnosis/mock-contract FOR HELP +// WITH MOCK CONTRACT +/////////////////////////////////////////////////////////// + +///////////////////////DISCLAIMER////////////////////////// +// This test is uses manual mining option, for more +// accurate calculation. Because of it gas-reporter +// won't work immidietly after automine disabled. +/////////////////////////////////////////////////////////// + +// Start test block +describe("===Stakerv3ds===", function () { + let deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer; + + let coreSelectors, + stakingSelectors, + pointsSelectors, + boostersSelectors, + viewsSelectors, + addressesForSelectors, + allSelectors; + + let some721, + some1155, + rewardToken, + depositToken, + IOUToken, + super721, + super1155, + proxyRegistry, + stakerV3FacetCore, + stakerV3FacetStaking, + stakerV3FacetPoints, + stakerV3FacetBoosters, + stakerV3FacetViews, + stakerV3dsProxy, + diamondStakingFacet, + diamondCoreFacet, + diamondPointsFacet, + diamondBoostersFacet, + diamondViewsFacet; + let startOfStaking; + const originalUri = "://ipfs/uri/"; + const originalUri721 = "://ipfs/uri/"; + const originalUri1155 = "://ipfs/uri/"; + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + let stakerName = "StakerV3ds"; + + before(async function () { + this.MockERC721 = await ethers.getContractFactory("TestERC721"); + this.MockERC1155 = await ethers.getContractFactory("TestERC1155"); + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.StakerV3Proxy = await ethers.getContractFactory("StakerProxy"); + this.StakerV3FacetCore = await ethers.getContractFactory( + "StakerV3FacetCore" + ); + this.StakerV3FacetViews = await ethers.getContractFactory( + "StakerV3FacetViews" + ); + this.StakerV3FacetStaking = await ethers.getContractFactory( + "StakerV3FacetStaking" + ); + this.StakerV3FacetPoints = await ethers.getContractFactory( + "StakerV3FacetPoints" + ); + this.StakerV3FacetBoosters = await ethers.getContractFactory( + "StakerV3FacetBoosters" + ); + this.Super721 = await ethers.getContractFactory("Super721"); + this.Super1155 = await ethers.getContractFactory("Super1155"); + this.ProxyRegistry = await ethers.getContractFactory("MockProxyRegistry"); + }); + + beforeEach(async function () { + [ + deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer, + ] = await ethers.getSigners(); + + some721 = await this.MockERC721.deploy(); + await await some721.deployed(); + + // some1155 = await this.MockERC1155.deploy(); + // some1155.deployed(); + + rewardToken = await this.MockERC20.deploy(); + await rewardToken.deployed(); + + depositToken = await this.MockERC20.deploy(); + await depositToken.deployed(); + + stakerV3FacetCore = await this.StakerV3FacetCore.deploy(); + await stakerV3FacetCore.deployed(); + + stakerV3FacetStaking = await this.StakerV3FacetStaking.deploy(); + await stakerV3FacetStaking.deployed(); + + stakerV3FacetPoints = await this.StakerV3FacetPoints.deploy(); + await stakerV3FacetPoints.deployed(); + + stakerV3FacetBoosters = await this.StakerV3FacetBoosters.deploy(); + await stakerV3FacetBoosters.deployed(); + + stakerV3FacetViews = await this.StakerV3FacetViews.deploy(); + await stakerV3FacetViews.deployed(); + + proxyRegistry = await this.ProxyRegistry.deploy(); + await proxyRegistry.deployed(); + + IOUToken = await this.MockERC721.deploy(); + await IOUToken.deployed(); + + super721 = await this.Super721.deploy( + owner.address, + "Super721", + "SIMX721", + originalUri, + originalUri721, + proxyRegistry.address + ); + await super721.deployed(); + + super1155 = await this.Super1155.deploy( + owner.address, + "Super1155", + originalUri, + originalUri1155, + proxyRegistry.address + ); + await super1155.deployed(); + + var someSelector1 = await utils.getSelector( + "function setEmissions((uint256,uint256)[],(uint256,uint256)[])" + ); + //console.log(someSelector1); + + var someSelector = await utils.getSelector("function initialize(address)"); + //console.log(someSelector); + + coreSelectors = await utils.getSelectors(stakerV3FacetCore); + addressesForSelectors = []; + // console.log(coreSelectors); + let counter = 0; + for (counter; counter < coreSelectors.length; counter++) { + addressesForSelectors.push(stakerV3FacetCore.address); + } + + oldCounter = counter; + viewsSelectors = await utils.getSelectors(stakerV3FacetViews); + for (counter; counter < viewsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetViews.address); + } + + oldCounter = counter; + pointsSelectors = await utils.getSelectors(stakerV3FacetPoints); + for (counter; counter < pointsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetPoints.address); + } + // console.log(pointsSelectors); + + oldCounter = counter; + boostersSelectors = await utils.getSelectors(stakerV3FacetBoosters); + for (counter; counter < boostersSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetBoosters.address); + } + + var oldCounter = counter; + stakingSelectors = await utils.getSelectors(stakerV3FacetStaking); + for (counter; counter < stakingSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetStaking.address); + } + //console.log(stakingSelectors); + + allSelectors = [ + ...coreSelectors, + ...viewsSelectors, + ...pointsSelectors, + ...boostersSelectors, + ...stakingSelectors, + ]; + //console.log(allSelectors); + + stakerV3dsProxy = await this.StakerV3Proxy.deploy( + stakerV3FacetCore.address, + owner.address, + rewardToken.address, + admin.address, + IOUToken.address, + stakerName, + allSelectors, + addressesForSelectors + ); + await stakerV3dsProxy.deployed(); + + some721.mint(signer1.address, 1); + + rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("1000000") + ); + + IOUToken.transferOwnership(stakerV3dsProxy.address); + + diamondStakingFacet = await ethers.getContractAt( + "StakerV3FacetStaking", + stakerV3dsProxy.address + ); + + diamondCoreFacet = await ethers.getContractAt( + "StakerV3FacetCore", + stakerV3dsProxy.address + ); + + diamondBoostersFacet = await ethers.getContractAt( + "StakerV3FacetBoosters", + stakerV3dsProxy.address + ); + + diamondPointsFacet = await ethers.getContractAt( + "StakerV3FacetPoints", + stakerV3dsProxy.address + ); + + diamondViewsFacet = await ethers.getContractAt( + "StakerV3FacetViews", + stakerV3dsProxy.address + ); + }); + + describe("Multiplie changes of booster", function () { + it("stakerv3", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 10000, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 20000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 2100, + burnType: 0, + burnData: 0, + }); + + [ + deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer, + ] = await ethers.getSigners(); + + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(1)], + amounts: [1], + IOUTokenId: [], + }); + + // turning off auto mining + console.log("disabling auto mining..."); + await network.provider.send("evm_setAutomine", [false]); + await network.provider.send("evm_setIntervalMining", [0]); + console.log("Done."); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await ethers.provider.send("evm_mine", []); + + //User2-Deposit + await diamondStakingFacet.connect(signer2).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + // +900 rewards for signer1 (900 summary) and signer 2 is starting staking + await network.provider.send("evm_setNextBlockTimestamp", [ + (await (await ethers.provider.getBlock()).timestamp) + 90, + ]); + await ethers.provider.send("evm_mine", []); + + // changing booster + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 30000, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + // +600 rewards for signer1 (1500 summary) and +300 for signer 2 + await network.provider.send("evm_setNextBlockTimestamp", [ + (await (await ethers.provider.getBlock()).timestamp) + 90, + ]); + await ethers.provider.send("evm_mine", []); + + console.log(await rewardToken.balanceOf(signer1.address)); + console.log(await rewardToken.balanceOf(signer2.address)); + + // changing booster + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 20000, + amountRequired: 1, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + // +800 rewards for signer1 (2300 summary) and +200 (500 summary) for signer 2 + await network.provider.send("evm_setNextBlockTimestamp", [ + (await (await ethers.provider.getBlock()).timestamp) + 100, + ]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).withdraw(0, [0, 1, 2]); + await diamondStakingFacet.connect(signer2).withdraw(0, [3, 4, 5]); + await diamondStakingFacet.connect(signer1).claim(0, []); + await diamondStakingFacet.connect(signer2).claim(0, []); + + // +600 rewards for signer1 (2900 summary) and +200 for signer 2(700 summary) + await network.provider.send("evm_setNextBlockTimestamp", [ + (await (await ethers.provider.getBlock()).timestamp) + 80, + ]); + await ethers.provider.send("evm_mine", []); + + expect(await rewardToken.balanceOf(signer1.address)).be.closeTo( + ethers.utils.parseEther("2900"), + ethers.utils.parseEther("0.1") + ); + expect(await rewardToken.balanceOf(signer2.address)).be.closeTo( + ethers.utils.parseEther("700"), + ethers.utils.parseEther("0.1") + ); + + console.log(await rewardToken.balanceOf(signer1.address)); + console.log(await rewardToken.balanceOf(signer2.address)); + }); + }); +}); diff --git a/test/StakerV2.test.js b/test/StakerV2.test.js index 27d82b4..b845e67 100644 --- a/test/StakerV2.test.js +++ b/test/StakerV2.test.js @@ -1,10 +1,10 @@ -const { expect } = require('chai'); -const { BigNumber } = require('ethers'); -const { mnemonicToSeed } = require('ethers/lib/utils'); -const { ethers } = require('hardhat'); -const Web3 = require('web3'); +const { expect } = require("chai"); +const { BigNumber } = require("ethers"); +const { mnemonicToSeed } = require("ethers/lib/utils"); +const { ethers } = require("hardhat"); +//const Web3 = require('web3'); -const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; const DATA = "0x02"; @@ -16,183 +16,268 @@ const DATA = "0x02"; /////////////////////////////////////////////////////////// // Start test block -describe('===Stakerv2===', function () { - let deployer, owner, paymentReceiver, signer1, signer2, signer3; - - let rewardToken, - depositToken, - stakerv2, - super721, - super1155, - proxyRegistry; - const originalUri = "://ipfs/uri/"; - const originalUri721 = "://ipfs/uri/"; - const originalUri1155 = "://ipfs/uri/"; - - - before(async function () { - this.MockERC20 = await ethers.getContractFactory("MockERC20"); - this.Staker = await ethers.getContractFactory("StakerV2"); - this.Super721 = await ethers.getContractFactory("Super721"); - this.Super1155 = await ethers.getContractFactory("Super1155"); - this.ProxyRegistry = await ethers.getContractFactory("MockProxyRegistry"); - }); +describe("===Stakerv2===", function () { + let deployer, owner, paymentReceiver, signer1, signer2, signer3; + + let rewardToken, depositToken, stakerv2, super721, super1155, proxyRegistry; + const originalUri = "://ipfs/uri/"; + const originalUri721 = "://ipfs/uri/"; + const originalUri1155 = "://ipfs/uri/"; + + before(async function () { + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.Staker = await ethers.getContractFactory("StakerV2"); + this.Super721 = await ethers.getContractFactory("Super721"); + this.Super1155 = await ethers.getContractFactory("Super1155"); + this.ProxyRegistry = await ethers.getContractFactory("MockProxyRegistry"); + }); + + beforeEach(async function () { + [deployer, owner, paymentReceiver, signer1, signer2, signer3] = + await ethers.getSigners(); + + rewardToken = await this.MockERC20.deploy(); + await rewardToken.deployed(); + + depositToken = await this.MockERC20.deploy(); + await depositToken.deployed(); + + stakerv2 = await this.Staker.deploy( + owner.address, + "firstStaker", + rewardToken.address + ); + await stakerv2.deployed(); + + proxyRegistry = await this.ProxyRegistry.deploy(); + await proxyRegistry.deployed(); + + super721 = await this.Super721.deploy( + owner.address, + "Super721", + "SIMX721", + originalUri, + originalUri721, + proxyRegistry.address + ); + await super721.deployed(); + + super1155 = await this.Super1155.deploy( + owner.address, + "Super1155", + originalUri, + originalUri1155, + proxyRegistry.address + ); + await super1155.deployed(); + }); + + // Test cases + + ////////////////////////////// + // Constructor + ////////////////////////////// + + describe("All", function () { + it("stakerv2", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await depositToken.transfer( + signer1.address, + ethers.utils.parseEther("1000") + ); + await depositToken.transfer( + signer2.address, + ethers.utils.parseEther("1000") + ); + await rewardToken.transfer( + stakerv2.address, + ethers.utils.parseEther("500000") + ); - beforeEach(async function () { - [deployer, owner, paymentReceiver, signer1, signer2, signer3] = await ethers.getSigners(); + // Note 6.6666666666 per second is equivalent to 100 per 15 seconds(15 seconds = block time according to Blocks implementation) + // Now the rewards must be set based on seconds + await stakerv2.connect(owner).setEmissions( + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await (await ethers.provider.getBlock()).timestamp, + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); - rewardToken = await this.MockERC20.deploy(); - await rewardToken.deployed(); + await stakerv2.connect(owner).configureBoostersBatch( + [0, 1], + [ + { + set: true, + multiplier: 23000, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + assetType: 2, + }, + { + set: true, + multiplier: 20000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + assetType: 2, + }, + ] + ); - depositToken = await this.MockERC20.deploy(); - await depositToken.deployed(); + await stakerv2 + .connect(owner) + .addPool(depositToken.address, 10000, 10000, [0, 1]); + await depositToken + .connect(signer1) + .approve(stakerv2.address, ethers.utils.parseEther("1000")); + await depositToken + .connect(signer2) + .approve(stakerv2.address, ethers.utils.parseEther("1000")); - stakerv2 = await this.Staker.deploy( - owner.address, - "firstStaker", - rewardToken.address + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + DATA ); - await stakerv2.deployed(); - - proxyRegistry = await this.ProxyRegistry.deploy(); - await proxyRegistry.deployed(); - - super721 = await this.Super721.deploy( - owner.address, - "Super721", - "SIMX721", - originalUri, - originalUri721, - proxyRegistry.address, + await super721.connect(signer1).setApprovalForAll(stakerv2.address, true); + + // Mint ITEMS for Signer2 + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + itemType: 0, + itemData: 0, + burnType: 0, + burnData: 0, + }); + await super1155 + .connect(owner) + .mintBatch( + signer2.address, + [shiftedItemGroupId, shiftedItemGroupId.add(1)], + [1, 1], + DATA ); - await super721.deployed(); - - super1155 = await this.Super1155.deploy( - owner.address, - "Super1155", - originalUri, - originalUri1155, - proxyRegistry.address + await super1155 + .connect(signer2) + .setApprovalForAll(stakerv2.address, true); + + //User1-Deposit + await stakerv2 + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("200")); + await network.provider.send("evm_increaseTime", [30]); + + //User2-StakeITEMS + await stakerv2 + .connect(signer2) + .stakeItemsBatch( + [shiftedItemGroupId, shiftedItemGroupId.add(1)], + [1, 1], + super1155.address, + depositToken.address, + 1 ); - await super1155.deployed(); + await network.provider.send("evm_increaseTime", [30]); - }); + //User1-StakeITEMS + await stakerv2 + .connect(signer1) + .stakeItemsBatch( + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + [1, 1, 1], + super721.address, + depositToken.address, + 0 + ); + await network.provider.send("evm_increaseTime", [15]); + + //User2-Deposit + await stakerv2 + .connect(signer2) + .deposit(depositToken.address, ethers.utils.parseEther("150")); + await network.provider.send("evm_increaseTime", [15]); + + //User1-Claims + await stakerv2.connect(signer1).claim(depositToken.address); + + //User1-UnstakeITEMS + await stakerv2 + .connect(signer1) + .unstakeItemsBatch(depositToken.address, 0); + await network.provider.send("evm_increaseTime", [15]); + + //User2-Withdraw + await stakerv2 + .connect(signer2) + .withdraw(depositToken.address, ethers.utils.parseEther("100")); + await network.provider.send("evm_increaseTime", [15]); + + //User2-Claims + await stakerv2.connect(signer2).claim(depositToken.address); + + //User1-Deposit + await stakerv2 + .connect(signer1) + .deposit(depositToken.address, ethers.utils.parseEther("150")); + await network.provider.send("evm_increaseTime", [15]); + + //User-2 && User-1 Withdraw-All and Claim + await stakerv2 + .connect(signer2) + .withdraw(depositToken.address, ethers.utils.parseEther("50")); + await stakerv2 + .connect(signer1) + .withdraw(depositToken.address, ethers.utils.parseEther("350")); + await stakerv2.connect(signer1).claim(depositToken.address); + await stakerv2.connect(signer2).claim(depositToken.address); + // console.log( + // await (await rewardToken.balanceOf(signer1.address)).toString() + // ); + // console.log( + // await (await rewardToken.balanceOf(signer2.address)).toString() + // ); + // console.log( + // await stakerv2.connect(signer3).getItemsUserInfo(signer2.address, 1) + // ); + + // Resultant must be around 900 rewards since + // (30 + 30 + 15 + 15 + 15 + 15 + 15) seconds * (6.666666666) Rate = 899.99999 - // Test cases - - ////////////////////////////// - // Constructor - ////////////////////////////// - - describe("All", function () { - it('stakerv2', async function () { - let itemGroupId = ethers.BigNumber.from(1); - let shiftedItemGroupId = itemGroupId.shl(128); - let itemGroupId2 = ethers.BigNumber.from(2); - let shiftedItemGroupId2 = itemGroupId2.shl(128); - - await depositToken.transfer(signer1.address, ethers.utils.parseEther("1000")); - await depositToken.transfer(signer2.address, ethers.utils.parseEther("1000")); - await rewardToken.transfer(stakerv2.address, ethers.utils.parseEther("500000")); - - // Note 6.6666666666 per second is equivalent to 100 per 15 seconds(15 seconds = block time according to Blocks implementation) - // Now the rewards must be set based on seconds - await stakerv2.connect(owner).setEmissions( - [{timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther("6.6666666666")}], - [{timeStamp: await (await ethers.provider.getBlock()).timestamp, rate: ethers.utils.parseEther("6.6666666666")}]); - - await stakerv2.connect(owner).configureBoostersBatch([0, 1], [{ - set: true, - multiplier: 23000, - amountRequired: 3, - groupRequired: itemGroupId2, - contractRequired: super721.address, - assetType: 2 - }, { - set: true, - multiplier: 20000, - amountRequired: 2, - groupRequired: 0, - contractRequired: super1155.address, - assetType: 2 - }]); - - await stakerv2.connect(owner).addPool(depositToken.address, 10000, 10000, [0, 1]); - await depositToken.connect(signer1).approve(stakerv2.address, ethers.utils.parseEther("1000")); - await depositToken.connect(signer2).approve(stakerv2.address, ethers.utils.parseEther("1000")); - - // Mint ITEMS for Signer1 - await super721.connect(owner).configureGroup(itemGroupId2, { - name: 'PEPSI', - supplyType: 0, - supplyData: 10, - burnType: 0, - burnData: 0 - }); - await super721.connect(owner).mintBatch(signer1.address, [shiftedItemGroupId2, shiftedItemGroupId2.add(1), shiftedItemGroupId2.add(2)], DATA); - await super721.connect(signer1).setApprovalForAll(stakerv2.address, true); - - // Mint ITEMS for Signer2 - await super1155.connect(owner).configureGroup(itemGroupId, { - name: 'PEPSI', - supplyType: 0, - supplyData: 10, - itemType: 0, - itemData: 0, - burnType: 0, - burnData: 0 - }); - await super1155.connect(owner).mintBatch(signer2.address, [shiftedItemGroupId, shiftedItemGroupId.add(1)], [1, 1], DATA); - await super1155.connect(signer2).setApprovalForAll(stakerv2.address, true); - - //User1-Deposit - await stakerv2.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("200")); - await network.provider.send("evm_increaseTime", [30]) - - //User2-StakeITEMS - await stakerv2.connect(signer2).stakeItemsBatch([shiftedItemGroupId, shiftedItemGroupId.add(1)], [1, 1], super1155.address, depositToken.address, 1); - await network.provider.send("evm_increaseTime", [30]) - - //User1-StakeITEMS - await stakerv2.connect(signer1).stakeItemsBatch([shiftedItemGroupId2, shiftedItemGroupId2.add(1), shiftedItemGroupId2.add(2)], [1, 1, 1], super721.address, depositToken.address, 0); - await network.provider.send("evm_increaseTime", [15]) - - //User2-Deposit - await stakerv2.connect(signer2).deposit(depositToken.address, ethers.utils.parseEther("150")); - await network.provider.send("evm_increaseTime", [15]) - - //User1-Claims - await stakerv2.connect(signer1).claim(depositToken.address); - - //User1-UnstakeITEMS - await stakerv2.connect(signer1).unstakeItemsBatch(depositToken.address, 0); - await network.provider.send("evm_increaseTime", [15]) - - //User2-Withdraw - await stakerv2.connect(signer2).withdraw(depositToken.address, ethers.utils.parseEther("100")); - await network.provider.send("evm_increaseTime", [15]) - - //User2-Claims - await stakerv2.connect(signer2).claim(depositToken.address); - - //User1-Deposit - await stakerv2.connect(signer1).deposit(depositToken.address, ethers.utils.parseEther("150")); - await network.provider.send("evm_increaseTime", [15]) - - //User-2 && User-1 Withdraw-All and Claim - await stakerv2.connect(signer2).withdraw(depositToken.address, ethers.utils.parseEther("50")); - await stakerv2.connect(signer1).withdraw(depositToken.address, ethers.utils.parseEther("350")); - await stakerv2.connect(signer1).claim(depositToken.address); - await stakerv2.connect(signer2).claim(depositToken.address); - console.log(await (await rewardToken.balanceOf(signer1.address)).toString()); - console.log(await (await rewardToken.balanceOf(signer2.address)).toString()); - console.log(await stakerv2.connect(signer3).getItemsUserInfo(signer2.address, 1)); - - // Resultant must be around 900 rewards since - // (30 + 30 + 15 + 15 + 15 + 15 + 15) seconds * (6.666666666) Rate = 899.99999 - - // 235011 + 655331 + 262178 + 51697 = 1204217 = 0.001204217 Ether Gas consumption for all calls above - // as shown by gas reporter. It is yet to be confirmed on Testnet. - }); + // 235011 + 655331 + 262178 + 51697 = 1204217 = 0.001204217 Ether Gas consumption for all calls above + // as shown by gas reporter. It is yet to be confirmed on Testnet. }); -}); \ No newline at end of file + }); +}); diff --git a/test/StakerV3ds.test.js b/test/StakerV3ds.test.js new file mode 100644 index 0000000..55259a4 --- /dev/null +++ b/test/StakerV3ds.test.js @@ -0,0 +1,5107 @@ +const { expect, util } = require("chai"); +const { BigNumber } = require("ethers"); +const { mnemonicToSeed, checkProperties } = require("ethers/lib/utils"); +const { ethers, network } = require("hardhat"); +//const Web3 = require('web3'); + +import * as utils from "./utils.js"; + +const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; + +const DATA = "0x02"; + +/////////////////////////////////////////////////////////// +// SEE https://hardhat.org/tutorial/testing-contracts.html +// FOR HELP WRITING TESTS +// USE https://github.com/gnosis/mock-contract FOR HELP +// WITH MOCK CONTRACT +/////////////////////////////////////////////////////////// + +// Start test block +describe("===Stakerv3ds===", function () { + let deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer; + + let coreSelectors, + stakingSelectors, + pointsSelectors, + boostersSelectors, + viewsSelectors, + addressesForSelectors, + allSelectors; + + let some721, + some1155, + rewardToken, + depositToken, + IOUToken, + super721, + super1155, + proxyRegistry, + stakerV3FacetCore, + stakerV3FacetStaking, + stakerV3FacetPoints, + stakerV3FacetBoosters, + stakerV3FacetViews, + stakerV3dsProxy, + diamondStakingFacet, + diamondCoreFacet, + diamondPointsFacet, + diamondBoostersFacet, + diamondViewFacet; + let startOfStaking; + const originalUri = "://ipfs/uri/"; + const originalUri721 = "://ipfs/uri/"; + const originalUri1155 = "://ipfs/uri/"; + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + let stakerName = "StakerV3ds"; + + before(async function () { + this.MockERC721 = await ethers.getContractFactory("TestERC721"); + this.MockERC1155 = await ethers.getContractFactory("TestERC1155"); + this.MockERC20 = await ethers.getContractFactory("MockERC20"); + this.StakerV3Proxy = await ethers.getContractFactory("StakerProxy"); + this.StakerV3FacetCore = await ethers.getContractFactory( + "StakerV3FacetCore" + ); + this.StakerV3FacetViews = await ethers.getContractFactory( + "StakerV3FacetViews" + ); + this.StakerV3FacetStaking = await ethers.getContractFactory( + "StakerV3FacetStaking" + ); + this.StakerV3FacetPoints = await ethers.getContractFactory( + "StakerV3FacetPoints" + ); + this.StakerV3FacetBoosters = await ethers.getContractFactory( + "StakerV3FacetBoosters" + ); + this.Super721 = await ethers.getContractFactory("Super721"); + this.Super1155 = await ethers.getContractFactory("Super1155"); + this.ProxyRegistry = await ethers.getContractFactory("MockProxyRegistry"); + }); + + beforeEach(async function () { + [ + deployer, + owner, + admin, + paymentReceiver, + signer1, + signer2, + signer3, + developer, + ] = await ethers.getSigners(); + + some721 = await this.MockERC721.deploy(); + await await some721.deployed(); + + // some1155 = await this.MockERC1155.deploy(); + // some1155.deployed(); + + rewardToken = await this.MockERC20.deploy(); + await rewardToken.deployed(); + + depositToken = await this.MockERC20.deploy(); + await depositToken.deployed(); + + stakerV3FacetCore = await this.StakerV3FacetCore.deploy(); + await stakerV3FacetCore.deployed(); + + stakerV3FacetStaking = await this.StakerV3FacetStaking.deploy(); + await stakerV3FacetStaking.deployed(); + + stakerV3FacetPoints = await this.StakerV3FacetPoints.deploy(); + await stakerV3FacetPoints.deployed(); + + stakerV3FacetBoosters = await this.StakerV3FacetBoosters.deploy(); + await stakerV3FacetBoosters.deployed(); + + stakerV3FacetViews = await this.StakerV3FacetViews.deploy(); + await stakerV3FacetViews.deployed(); + + proxyRegistry = await this.ProxyRegistry.deploy(); + await proxyRegistry.deployed(); + + IOUToken = await this.MockERC721.deploy(); + await IOUToken.deployed(); + + super721 = await this.Super721.deploy( + owner.address, + "Super721", + "SIMX721", + originalUri, + originalUri721, + proxyRegistry.address + ); + await super721.deployed(); + + super1155 = await this.Super1155.deploy( + owner.address, + "Super1155", + originalUri, + originalUri1155, + proxyRegistry.address + ); + await super1155.deployed(); + + var someSelector1 = await utils.getSelector( + "function setEmissions((uint256,uint256)[],(uint256,uint256)[])" + ); + //console.log(someSelector1); + + var someSelector = await utils.getSelector("function initialize(address)"); + //console.log(someSelector); + + coreSelectors = await utils.getSelectors(stakerV3FacetCore); + addressesForSelectors = []; + // console.log(coreSelectors); + let counter = 0; + for (counter; counter < coreSelectors.length; counter++) { + addressesForSelectors.push(stakerV3FacetCore.address); + } + + oldCounter = counter; + viewsSelectors = await utils.getSelectors(stakerV3FacetViews); + for (counter; counter < viewsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetViews.address); + } + + oldCounter = counter; + pointsSelectors = await utils.getSelectors(stakerV3FacetPoints); + for (counter; counter < pointsSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetPoints.address); + } + // console.log(pointsSelectors); + + oldCounter = counter; + boostersSelectors = await utils.getSelectors(stakerV3FacetBoosters); + for (counter; counter < boostersSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetBoosters.address); + } + + var oldCounter = counter; + stakingSelectors = await utils.getSelectors(stakerV3FacetStaking); + for (counter; counter < stakingSelectors.length + oldCounter; counter++) { + addressesForSelectors.push(stakerV3FacetStaking.address); + } + //console.log(stakingSelectors); + + allSelectors = [ + ...coreSelectors, + ...viewsSelectors, + ...pointsSelectors, + ...boostersSelectors, + ...stakingSelectors, + ]; + //console.log(allSelectors); + + stakerV3dsProxy = await this.StakerV3Proxy.deploy( + stakerV3FacetCore.address, + owner.address, + rewardToken.address, + admin.address, + IOUToken.address, + stakerName, + allSelectors, + addressesForSelectors + ); + await stakerV3dsProxy.deployed(); + + some721.mint(signer1.address, 1); + + IOUToken.transferOwnership(stakerV3dsProxy.address); + + diamondStakingFacet = await ethers.getContractAt( + "StakerV3FacetStaking", + stakerV3dsProxy.address + ); + + diamondCoreFacet = await ethers.getContractAt( + "StakerV3FacetCore", + stakerV3dsProxy.address + ); + + diamondBoostersFacet = await ethers.getContractAt( + "StakerV3FacetBoosters", + stakerV3dsProxy.address + ); + + diamondPointsFacet = await ethers.getContractAt( + "StakerV3FacetPoints", + stakerV3dsProxy.address + ); + + diamondViewFacet = await ethers.getContractAt( + "StakerV3FacetViews", + stakerV3dsProxy.address + ); + }); + + describe("Proxy", function () { + it("Reverts: mismatch of selector and addresses lengths of arrays at constructor", async function () { + // decrease length of selectors array by 1; + await allSelectors.pop(); + await expect( + this.StakerV3Proxy.deploy( + stakerV3FacetCore.address, + owner.address, + rewardToken.address, + admin.address, + IOUToken.address, + stakerName, + allSelectors, + addressesForSelectors + ) + ).to.be.revertedWith("ArraysLengthsMismatch()"); + }); + it("Reverts: wrong implemintation given", async function () { + await expect( + this.StakerV3Proxy.deploy( + stakerV3FacetStaking.address, + owner.address, + rewardToken.address, + admin.address, + IOUToken.address, + stakerName, + allSelectors, + addressesForSelectors + ) + ).to.be.revertedWith("DelegateCallFails()"); + }); + it("Reverts: invalid selector of the function for delegate call", async function () { + // generate data for sendTransaction with invalid selector + const invalidAbi = ["function someInvalidFunc(address _address)"]; + const invalidInterface = new ethers.utils.Interface(invalidAbi); + const callData = invalidInterface.encodeFunctionData("someInvalidFunc", [ + signer1.address, + ]); + + // executing calldata at proxy contract + await expect( + owner.sendTransaction({ + to: stakerV3dsProxy.address, + data: callData, + }) + ).to.be.revertedWith("NoImplementation()"); + }); + }); + + describe("Core Facet testings", function () { + describe("addDeveloper, lockDevelopers, updateDeveloper, getDeveloperCount", function () { + it("Reverts: addition of developers is locked", async function () { + const coreFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetCore" + ); + + await diamondCoreFacet.connect(owner).lockDevelopers(); + + await expect( + diamondCoreFacet.connect(owner).addDeveloper(developer.address, 500) + ).to.be.revertedWith("CantAlterDevs"); + }); + + it("Reverts: update developer by person with 0 share", async function () { + await expect( + diamondCoreFacet.connect(owner).updateDeveloper(signer2.address, 100) + ).to.be.revertedWith("ZeroDevShare()"); + }); + + it("should add new developer", async function () { + const developersShare = [500, 1500, 2500]; + + const viewFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetViews" + ); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(developer.address, developersShare[0]); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(signer1.address, developersShare[1]); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(signer2.address, developersShare[2]); + + // getDeveloperAddresses + let devAddresses = await diamondViewFacet + .connect(owner) + .getDeveloperAddresses(); + + expect(devAddresses[0]).to.be.eq(developer.address); + expect(devAddresses[1]).to.be.eq(signer1.address); + expect(devAddresses[2]).to.be.eq(signer2.address); + + // getDeveloperShare + let devShares = []; + + for (let i = 0; i < devAddresses.length; i++) { + devShares[i] = await diamondViewFacet + .connect(owner) + .getDeveloperShare(devAddresses[i]); + } + + expect(devShares[0]).to.be.eq(developersShare[0]); + expect(devShares[1]).to.be.eq(developersShare[1]); + expect(devShares[2]).to.be.eq(developersShare[2]); + }); + + it("Reverts: can not increase share", async function () { + await diamondCoreFacet + .connect(owner) + .addDeveloper(developer.address, 500); + + await expect( + diamondCoreFacet + .connect(developer) + .updateDeveloper(developer.address, 1000) + ).to.be.revertedWith("CantIncreaseDevShare()"); + }); + + it("Reverts: can not update developer at address with greater then 0 share", async function () { + await diamondCoreFacet + .connect(owner) + .addDeveloper(developer.address, 500); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(signer1.address, 1000); + + await expect( + diamondCoreFacet + .connect(developer) + .updateDeveloper(signer1.address, 100) + ).to.be.revertedWith("InvalidNewAddress()"); + }); + + it("should update developer address correctly", async function () { + const developersShare = [500, 1500, 2500]; + + const viewFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetViews" + ); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(developer.address, developersShare[0]); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(signer1.address, developersShare[1]); + + await diamondCoreFacet + .connect(owner) + .addDeveloper(signer2.address, developersShare[2]); + + // Updating devs + await diamondCoreFacet + .connect(developer) + .updateDeveloper(developer.address, 0); + + await diamondCoreFacet + .connect(signer1) + .updateDeveloper(signer3.address, developersShare[1]); + + await diamondCoreFacet + .connect(signer2) + .updateDeveloper(signer2.address, developersShare[2] - 1000); + + /** + * + * + * ASSERTING + * + * + */ + + // getDeveloperAddresses + let devAddresses = await diamondViewFacet + .connect(owner) + .getDeveloperAddresses(); + + expect(devAddresses).to.not.contain(developer.address); + expect(devAddresses[0]).to.be.eq(signer2.address); + expect(devAddresses[1]).to.be.eq(signer3.address); + + let newDevShares = []; + // getDeveloperShare + newDevShares[0] = await diamondViewFacet + .connect(owner) + .getDeveloperShare(devAddresses[0]); + + // getDeveloperShare + newDevShares[1] = await diamondViewFacet + .connect(owner) + .getDeveloperShare(devAddresses[1]); + + expect(newDevShares[0]).to.be.eq(developersShare[2] - 1000); + expect(newDevShares[1]).to.be.eq(developersShare[1]); + + diamondCoreFacet + .connect(signer2) + .updateDeveloper(signer2.address, developersShare[2] - 1000); + }); + }); + describe("setEmissions, lockTokenEmissions, lockPointEmissions", function () { + it("Reverts: alteration of token emission is locked", async function () { + await diamondCoreFacet.connect(owner).lockTokenEmissions(); + + // setEmissions() + await expect( + diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ) + ).to.be.revertedWith("CantAlterTokenEmissionSchedule()"); + }); + + it("Reverts: alteration of point emissions is locked", async function () { + await diamondCoreFacet.connect(owner).lockPointEmissions(); + + await expect( + diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ) + ).to.be.revertedWith("CantAlterPointEmissionSchedule()"); + }); + + it("Reverts: token emission schedule must be set", async function () { + await expect( + diamondCoreFacet.connect(owner).setEmissions([], []) + ).to.be.revertedWith("ZeroTokenEmissionEvents()"); + }); + + it("Reverts: point emission schedule must be set", async function () { + await expect( + diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [] + ) + ).to.be.revertedWith("ZeroPointEmissionEvents()"); + }); + + it("should set emissions", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + }); + + it("should set emissions of staker where earliestTokenEmission/earliestPointEmission timestamps are less", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + // Increase time so that the earliestTokenEmission/EarliestPointEmission timestamps are less + await ethers.provider.send("evm_increaseTime", [70]); + await ethers.provider.send("evm_mine", []); + + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + }); + }); + + describe("configureBoostersBatch, getBoostersCount, getBoosterInfo", function () { + it("Reverts: boost info must be set", async function () { + await expect( + diamondCoreFacet.connect(owner).configureBoostersBatch([1, 2], []) + ).to.be.revertedWith("EmptyBoostInfoArray()"); + + await expect( + diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 0, + amountRequired: 0, + groupRequired: 0, + contractRequired: ethers.constants.AddressZero, + boostType: 2, + typeOfAsset: 0, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ) + ).to.be.revertedWith("InvalidConfBoostersInputs()"); + }); + + it("Reverts: mismatch of ids and boost info arrays leghts", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2, 3], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ) + ).to.be.revertedWith("InputLengthsMismatch()"); + }); + + it("Reverts: you can not configure boost with id 0", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 0], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ) + ).to.be.revertedWith("BoosterIdZero()"); + }); + + it("Reverts: you can't set ERC20 as asset for stake for boosts", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: depositToken.address, + boostType: 2, + typeOfAsset: 0, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ) + ).to.be.revertedWith("InvalidConfBoostersAssetType()"); + }); + + it("should configure boosters correctly", async function () { + const viewFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetViews" + ); + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + const configOfBoosters = [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ]; + + await diamondCoreFacet + .connect(owner) + .configureBoostersBatch([1, 2], configOfBoosters); + + const getBoosterCountData = await diamondViewFacet + .connect(owner) + .getBoostersCount(); + + let getBoosterInfo = []; + getBoosterInfo[0] = await diamondViewFacet + .connect(owner) + .getBoosterInfo(1); + + getBoosterInfo[1] = await diamondViewFacet + .connect(owner) + .getBoosterInfo(2); + + expect(await configOfBoosters[0].multiplier).to.be.eq( + getBoosterInfo[0].multiplier + ); + expect(await configOfBoosters[1].multiplier).to.be.eq( + getBoosterInfo[1].multiplier + ); + expect(await getBoosterCountData).to.be.eq(2); + }); + + it("should change existed boosters correctly", async function () { + const viewFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetViews" + ); + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + const configOfBoosters = [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ]; + + await diamondCoreFacet + .connect(owner) + .configureBoostersBatch([1, 2], configOfBoosters); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 0, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [2], + [ + { + multiplier: 26000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + const getBoosterCountData = await diamondViewFacet + .connect(owner) + .getBoostersCount(); + + let getBoosterInfo = []; + getBoosterInfo[0] = await diamondViewFacet + .connect(owner) + .getBoosterInfo(1); + + getBoosterInfo[1] = await diamondViewFacet + .connect(owner) + .getBoosterInfo(2); + + expect(await getBoosterInfo[0].multiplier).to.be.eq(0); + expect(await getBoosterInfo[1].multiplier).to.be.eq(26000); + expect(await getBoosterCountData).to.be.eq(1); + }); + }); + + describe("addPool, overwrtite pool, getPoolCount", function () { + it("Reverts: emission schedule not defined", async function () { + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.revertedWith("EmissionNotSet()"); + }); + + it("Reverts: pool token is ERC20 token", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: rewardToken.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.reverted; + }); + + it("Reverts: mismatch typeOfAsset and real asset type", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super1155.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.revertedWith("InvalidAsset()"); + + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 2, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.revertedWith("InvalidAsset()"); + }); + + it("Reverts: token or point strength of the pool is set to 0 or less", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 0, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.revertedWith("ZeroStrength()"); + }); + + // it("Reverts: ERC20 can't be as asset at pool for stake", async function () { + // await diamondCoreFacet.connect(owner).setEmissions( + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("6.6666666666"), + // }, + // ], + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("6.6666666666"), + // }, + // ] + // ); + + // await expect(diamondCoreFacet.connect(owner).addPool({ + // id: 0, + // tokenStrength: 100, + // pointStrength: 10000, + // groupId: 0, + // tokensPerShare: 0, + // pointsPerShare: 0, + // compoundInterestThreshold: ethers.utils.parseEther("1000"), + // compoundInterestMultiplier: 5000, + // boostInfo: [1, 2], + // assetAddress: depositToken.address, + // typeOfAsset: 0, + // lockPeriod: 0, + // lockAmount: 0, + // lockMultiplier: 0, + // timeLockTypeOfBoost: 0, + // compoundTypeOfBoost: 0, + // })).to.be.revertedWith("InvalidTypeOfAsset()"); + // }); + + it("Reverts: when group id is required but it is ERC20 asset", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await expect( + diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 1, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: depositToken.address, + typeOfAsset: 0, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }) + ).to.be.revertedWith("InvalidGroupIdForERC20()"); + }); + + it("should add a new pool, overwrite it and get pool count", async function () { + const viewFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetViews" + ); + + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + let getPoolCount = await diamondViewFacet.connect(owner).getPoolCount(); + + expect(await getPoolCount).to.be.eq(1); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 12000, + pointStrength: 12000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + getPoolCount = await diamondViewFacet.connect(owner).getPoolCount(); + expect(await getPoolCount).to.be.eq(1); + }); + }); + + describe("onERC721Received", function () { + it("should work correctly", async function () { + await diamondCoreFacet + .connect(owner) + .onERC721Received(owner.address, signer1.address, 1, [0x01, 0x02]); + }); + }); + }); + + describe("Staking Facet testings", function () { + let viewFacetABI; + describe("deposit, getItemsUserInfo", function () { + beforeEach(async function () { + viewFacetABI = await hre.artifacts.readArtifact("StakerV3FacetViews"); + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + + await depositToken.transfer( + signer1.address, + ethers.utils.parseEther("1000") + ); + await depositToken.transfer( + signer2.address, + ethers.utils.parseEther("1000") + ); + await depositToken.transfer( + signer3.address, + ethers.utils.parseEther("1000") + ); + await depositToken + .connect(signer1) + .approve(stakerV3dsProxy.address, ethers.utils.parseEther("1000")); + await depositToken + .connect(signer2) + .approve(stakerV3dsProxy.address, ethers.utils.parseEther("1000")); + await depositToken + .connect(signer3) + .approve(stakerV3dsProxy.address, ethers.utils.parseEther("1000")); + await rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("500000") + ); + + //await stakerV3FacetCore.connect(owner).initialize(owner.address); + + // Note 6.6666666666 per second is equivalent to 100 per 15 seconds(15 seconds = block time according to Blocks implementation) + // Now the rewards must be set based on seconds + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721.connect(owner).configureGroup(itemGroupId3, { + name: "PEPSI2", + supplyType: 0, + supplyData: 11, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId3, + shiftedItemGroupId3.add(1), + shiftedItemGroupId3.add(2), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + // Mint ITEMS for Signer2 + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "PEPSI", + supplyType: 0, + supplyData: 100, + itemType: 2, + itemData: 20, + burnType: 0, + burnData: 0, + }); + await super1155 + .connect(owner) + .mintBatch( + signer2.address, + [shiftedItemGroupId, shiftedItemGroupId.add(1)], + [20, 10], + DATA + ); + await super1155 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + }); + + it("Reverts: deposit in pool with group requires, not an group item", async function () { + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: itemGroupId, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await expect( + diamondStakingFacet.connect(signer1).deposit( + 1, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 2, 3], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("InvalidGroupIdForStake()"); + }); + + it("Should deposit correctly with group id requires", async function () { + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: itemGroupId2, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer1).deposit( + 1, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + }); + + it("Reverts: when asset is ERC20 and amounts array length not equal 1", async function () { + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: depositToken.address, + typeOfAsset: 0, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await expect( + diamondStakingFacet.connect(signer1).deposit( + 1, + { + assetAddress: depositToken.address, + id: [1, 2], + amounts: [ethers.utils.parseEther("100"), 20], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("InvalidERC20DepositInputs()"); + }); + + it("ERC20 staking asset tests", async function () { + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: depositToken.address, + typeOfAsset: 0, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer1).deposit( + 1, + { + assetAddress: depositToken.address, + id: [1], + amounts: [ethers.utils.parseEther("100")], + IOUTokenId: [], + }, + false + ); + + startOfStaking = await utils.getCurrentTime(); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 30, + ]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).withdraw(1, [0]); + + //User2-Claims + await diamondStakingFacet.connect(signer1).claim(1, []); + + expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + ethers.utils.parseEther("103.3333"), + ethers.utils.parseEther("0.01") + ); + }); + + it("Reverts: Inactive pool", async function () { + await expect( + diamondStakingFacet.connect(signer1).deposit( + 5, + { + assetAddress: super721.address, + id: [1, 2, 3], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("InactivePool()"); + }); + + it("Reverts: wrong asset deposited", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: some721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 2, 3], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("InvalidAssetToStake()"); + }); + + it("Reverts: you can't deposit erc721 amounts other than 1", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 2, 3], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("InvalidERC721Amount()"); + }); + + it("should deposit at pool correctly", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + expect(await super721.balanceOf(signer1.address)).to.be.eq(7); + expect(await super721.ownerOf(shiftedItemGroupId2)).to.be.eq( + stakerV3dsProxy.address + ); + expect(await super721.ownerOf(shiftedItemGroupId2.add(1))).to.be.eq( + stakerV3dsProxy.address + ); + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(3); + expect(await IOUToken.ownerOf(0)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(1)).to.be.eq(signer1.address); + }); + + it("Reverts: wrong booster id for stake", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 10, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("InvalidInfoStakeForBoost()"); + }); + + it("Reverts: mismatch of id and amounts arrays lentghs", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: some721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("AssetArrayLengthsMismatch()"); + + await expect( + diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1], + IOUTokenId: [], + }, + false + ) + ).to.be.revertedWith("AssetArrayLengthsMismatch()"); + }); + + it("Reverts: check that you not eligible to stake in the pool for booster", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + + // incorrect asset + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: some721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("InvalidInfoStakeForBoost()"); + + // incorrect amounts + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + amounts: [1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("InvalidInfoStakeForBoost()"); + + // incorrect group id + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId3, + shiftedItemGroupId2.add(1), + shiftedItemGroupId3.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("InvalidInfoStakeForBoost()"); + + // setting booster multiplier to 0 + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1], + [ + { + multiplier: 0, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + // cant stake for booster with multiplier 0 + await expect( + diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }) + ).to.be.revertedWith("InvalidInfoStakeForBoost()"); + }); + + it("should stake items at pool for boosters correctly", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + expect(await super721.balanceOf(signer1.address)).to.be.eq(7); + expect(await super721.ownerOf(shiftedItemGroupId2)).to.be.eq( + stakerV3dsProxy.address + ); + expect(await super721.ownerOf(shiftedItemGroupId2.add(1))).to.be.eq( + stakerV3dsProxy.address + ); + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(0); + + let getItemsUserInfo = await diamondViewFacet + .connect(owner) + .getItemsUserInfo(signer1.address, 1); + + expect(await getItemsUserInfo.tokenIds[0]).to.be.eq( + shiftedItemGroupId2 + ); + expect(await getItemsUserInfo.tokenIds[1]).to.be.eq( + shiftedItemGroupId2.add(1) + ); + expect(await getItemsUserInfo.tokenIds[2]).to.be.eq( + shiftedItemGroupId2.add(2) + ); + }); + }); + + describe("withdraw, claim", function () { + beforeEach(async function () { + viewFacetABI = await hre.artifacts.readArtifact("StakerV3FacetViews"); + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + let itemGroupId3 = ethers.BigNumber.from(3); + let shiftedItemGroupId3 = itemGroupId3.shl(128); + + await depositToken.transfer( + signer1.address, + ethers.utils.parseEther("1000") + ); + await depositToken.transfer( + signer2.address, + ethers.utils.parseEther("1000") + ); + await rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("500000") + ); + + //await stakerV3FacetCore.connect(owner).initialize(owner.address); + + // Note 6.6666666666 per second is equivalent to 100 per 15 seconds(15 seconds = block time according to Blocks implementation) + // Now the rewards must be set based on seconds + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super1155.address, + typeOfAsset: 2, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721.connect(owner).configureGroup(itemGroupId3, { + name: "PEPSI2", + supplyType: 0, + supplyData: 11, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId3, + shiftedItemGroupId3.add(1), + shiftedItemGroupId3.add(2), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + // Mint ITEMS for Signer2 + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "PEPSI", + supplyType: 0, + supplyData: 100, + itemType: 2, + itemData: 20, + burnType: 0, + burnData: 0, + }); + await super1155 + .connect(owner) + .mintBatch( + signer2.address, + [shiftedItemGroupId, shiftedItemGroupId.add(1)], + [20, 10], + DATA + ); + await super1155 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + }); + + it("Reverts: booster not available for this user", async function () { + await expect( + diamondBoostersFacet.connect(owner).unstakeItemsBatch(0, 1) + ).to.be.revertedWith("NotStaked()"); + }); + + // it("Reverts: withdraw amount exceeds user's amount on staking", async function () { + // await expect(diamondStakingFacet + // .connect(owner) + // .withdraw(0, { + // assetAddress: super721.address, + // id: [ + // shiftedItemGroupId2.add(3), + // shiftedItemGroupId2.add(4), + // shiftedItemGroupId2.add(5), + // ], + // amounts: [1, 1, 1], + // IOUTokenId: [], + // })).to.be.revertedWith("InvalidAmount()"); + // }); + + // it("Reverts: withdraw amount exceeds user's amount on staking", async function () { + // await expect(diamondStakingFacet.connect(owner).withdraw( + // 0, + // { + // assetAddress: super721.address, + // id: [ + // shiftedItemGroupId2.add(3), + // shiftedItemGroupId2.add(4), + // shiftedItemGroupId2.add(5), + // ], + // amounts: [1, 1, 1], + // IOUTokenId: [], + // } + // )).to.be.revertedWith("InvalidAmount()"); + // }); + + // it("Reverts: balance of IOU token is zero", async function () { + // await expect(diamondStakingFacet.connect(owner).withdraw( + // 0, + // { + // assetAddress: super721.address, + // id: [ + // shiftedItemGroupId2.add(3), + // shiftedItemGroupId2.add(4), + // shiftedItemGroupId2.add(5), + // ], + // amounts: [0, 0, 0], + // IOUTokenId: [], + // } + // )).to.be.revertedWith("0x2E"); + // }); + + it("Reverts: trying to withdraw with incorrect IOUToken id", async function () { + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await expect( + diamondStakingFacet.connect(owner).withdraw(0, [0]) + ).to.be.revertedWith("NotAnOwnerOfIOUToken()"); + + await IOUToken.connect(signer1).transferFrom( + signer1.address, + signer2.address, + 0 + ); + }); + + it("Reverts: trying to withdraw with IOUToken related to other pool", async function () { + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super1155.address, + typeOfAsset: 2, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await diamondStakingFacet.connect(signer2).deposit( + 1, + { + assetAddress: super1155.address, + id: [shiftedItemGroupId, shiftedItemGroupId.add(1)], + amounts: [1, 1], + IOUTokenId: [], + }, + false + ); + + await IOUToken.connect(signer1).transferFrom( + signer1.address, + signer2.address, + 0 + ); + + await expect( + diamondStakingFacet.connect(signer2).withdraw(1, [0]) + ).to.be.revertedWith("IOUTokenFromDifferentPool()"); + }); + + it("should withdraw correctly", async function () { + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await diamondStakingFacet.connect(signer2).deposit( + 1, + { + assetAddress: super1155.address, + id: [shiftedItemGroupId, shiftedItemGroupId.add(1)], + amounts: [10, 10], + IOUTokenId: [], + }, + false + ); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(3); + expect(await IOUToken.ownerOf(0)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(1)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(2)).to.be.eq(signer1.address); + + await diamondStakingFacet.connect(signer1).withdraw(0, [0, 1, 2]); + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(0); + + await diamondBoostersFacet.connect(signer1).unstakeItemsBatch(0, 1); + + await diamondStakingFacet.connect(signer2).withdraw(1, [3, 4]); + }); + + it("should claim correctly", async function () { + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + const startOfStaking = await ( + await ethers.provider.getBlock() + ).timestamp; + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(3); + expect(await IOUToken.ownerOf(0)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(1)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(2)).to.be.eq(signer1.address); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 28, + ]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).claim(0, []); + + // expect( + // await rewardToken.connect(signer1).balanceOf(signer1.address) + // ).to.be.closeTo(ethers.utils.parseEther("1.0")); + // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // ethers.utils.parseEther("200"), + // ethers.utils.parseEther("0.01") + // ); + + await diamondBoostersFacet.connect(signer1).unstakeItemsBatch(0, 1); + + await diamondStakingFacet.connect(signer1).withdraw(0, [0, 1, 2]); + + //expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(0); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).claim(0, []); + }); + + // it("Reverts: checkpoints start time and end time must be same lengths", async function () { + // const blockTime = await utils.getCurrentTime(); + + // const signedDataHash = ethers.utils.solidityKeccak256( + // ["uint256[]", "uint256[]", "uint256[]"], + // [ + // [blockTime - 1000, blockTime], + // [blockTime + 1, blockTime + 1000], + // [3000, 2000], + // ] + // ); + + // const bytesArray = ethers.utils.arrayify(signedDataHash); + + // const flatSignature1 = await signer1.signMessage(bytesArray); + + // const signature1 = ethers.utils.splitSignature(flatSignature1); + + // let signedDataHashBytes = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(signedDataHash), + // 32 + // ); + // let vBytes = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(signature1.v), + // 32 + // ); + // let rBytes = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(signature1.r), + // 32 + // ); + // let sBytes = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(signature1.s), + // 32 + // ); + + // let lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(2), 32); + + // let startTimeBytes1 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(blockTime - 1000), + // 32 + // ); + // let startTimeBytes2 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(blockTime), + // 32 + // ); + // let endTimeBytes1 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(blockTime + 1), + // 32 + // ); + // let endTimeBytes2 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(blockTime + 1000), + // 32 + // ); + // let balanceBytes1 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(3000), + // 32 + // ); + // let balanceBytes2 = ethers.utils.hexZeroPad( + // ethers.utils.hexlify(2000), + // 32 + // ); + + // let callDataBytes = ethers.utils.hexConcat([ + // signedDataHashBytes, + // vBytes, + // rBytes, + // sBytes, + // lengthBytes, + // startTimeBytes1, + // startTimeBytes2, + // endTimeBytes1, + // endTimeBytes2, + // balanceBytes1, + // balanceBytes2, + // ]); + + // await expect(diamondStakingFacet.connect(signer1).claim( + // 0, + // callDataBytes + // // signedDataHash, + // // { + // // v: signature1.v, + // // r: signature1.r, + // // s: signature1.s, + // // }, + // // { + // // startTime: [blockTime - 1000, blockTime], + // // endTime: [blockTime + 1, blockTime + 1000], + // // balance: [3000, 2000, 1], + // // } + // )).to.be.revertedWith( + // "StakerV3FacetStaking::claim: mismatch of start time end time or balances arrays lengths." + // ); + // }); + + it("Reverts: wrong signature", async function () { + const blockTime = await utils.getCurrentTime(); + + const signedDataHash = ethers.utils.solidityKeccak256( + ["uint256[]", "uint256[]", "uint256[]"], + [ + [blockTime - 1000, blockTime], + [blockTime + 1, blockTime + 1000], + [3000, 2000], + ] + ); + + const bytesArray = ethers.utils.arrayify(signedDataHash); + + const flatSignature1 = await signer1.signMessage(bytesArray); + + const signature1 = ethers.utils.splitSignature(flatSignature1); + + let signedDataHashBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signedDataHash), + 32 + ); + let vBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.v), + 32 + ); + let rBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.r), + 32 + ); + let sBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.s), + 32 + ); + + let lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(2), 32); + + let startTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime - 1000), + 32 + ); + let startTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime), + 32 + ); + let endTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1), + 32 + ); + let endTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1000), + 32 + ); + let balanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let balanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + + let callDataBytes = ethers.utils.hexConcat([ + signedDataHashBytes, + vBytes, + rBytes, + sBytes, + lengthBytes, + startTimeBytes1, + startTimeBytes2, + endTimeBytes1, + endTimeBytes2, + balanceBytes1, + balanceBytes2, + ]); + + await expect( + diamondStakingFacet.connect(signer1).claim( + 0, + callDataBytes + // signedDataHash, + // { + // v: 0, + // r: signature1.r, + // s: signature1.s, + // }, + // { + // startTime: [blockTime - 1000, blockTime], + // endTime: [blockTime + 1, blockTime + 1000], + // balance: [3000, 2000], + // } + ) + ).to.be.revertedWith("NotAnAdmin()"); + }); + + it("Reverts: mismatch given arguments with hashed arguments", async function () { + const blockTime = await utils.getCurrentTime(); + + const signedDataHash = ethers.utils.solidityKeccak256( + ["uint256[]", "uint256[]", "uint256[]"], + [ + [blockTime - 1000, blockTime], + [blockTime + 1, blockTime + 1000], + [3000, 2000], + ] + ); + + const bytesArray = ethers.utils.arrayify(signedDataHash); + + const flatSignature1 = await admin.signMessage(bytesArray); + + const signature1 = ethers.utils.splitSignature(flatSignature1); + + let signedDataHashBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signedDataHash), + 32 + ); + let vBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.v), + 32 + ); + let rBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.r), + 32 + ); + let sBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.s), + 32 + ); + + let lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(2), 32); + + let startTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime - 100), + 32 + ); + let startTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime), + 32 + ); + let endTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1), + 32 + ); + let endTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1000), + 32 + ); + let balanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let balanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + + let callDataBytes = ethers.utils.hexConcat([ + signedDataHashBytes, + vBytes, + rBytes, + sBytes, + lengthBytes, + startTimeBytes1, + startTimeBytes2, + endTimeBytes1, + endTimeBytes2, + balanceBytes1, + balanceBytes2, + ]); + + await expect( + diamondStakingFacet.connect(admin).claim( + 0, + callDataBytes + // signedDataHash, + // { + // v: signature1.v, + // r: signature1.r, + // s: signature1.s, + // }, + // { + // startTime: [blockTime - 100, blockTime], + // endTime: [blockTime + 1, blockTime + 1000], + // balance: [3000, 2000], + // } + ) + ).to.be.revertedWith("MismatchArgumentsAndHash()"); + }); + + it("Reverts: you can't use same hash", async function () { + const blockTime = await utils.getCurrentTime(); + + const signedDataHash = ethers.utils.solidityKeccak256( + ["bytes32", "bytes32", "bytes32", "bytes32", "bytes32", "bytes32"], + [ + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [blockTime - 1000, blockTime] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [blockTime + 1, blockTime + 1000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [3000, 2000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [3000, 2000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [ + ethers.utils.parseUnits("1.0", 12), + ethers.utils.parseUnits("1.2", 12), + ] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [ + ethers.utils.parseUnits("1.0", 30), + ethers.utils.parseUnits("1.2", 30), + ] + ), + ] + ); + + const bytesArray = ethers.utils.arrayify(signedDataHash); + + const flatSignature1 = await admin.signMessage(bytesArray); + + const signature1 = ethers.utils.splitSignature(flatSignature1); + + let signedDataHashBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signedDataHash), + 32 + ); + let vBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.v), + 32 + ); + let rBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.r), + 32 + ); + let sBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.s), + 32 + ); + + let lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(2), 32); + + let startTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime - 1000), + 32 + ); + let startTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime), + 32 + ); + let endTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1), + 32 + ); + let endTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1000), + 32 + ); + let tokensBalanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let tokensBalanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + let pointsBalanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let pointsBalanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + let tpsBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.0", 12)), + 32 + ); + let tpsBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.2", 12)), + 32 + ); + let ppsBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.0", 30)), + 32 + ); + let ppsBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.2", 30)), + 32 + ); + + let callDataBytes = ethers.utils.hexConcat([ + signedDataHashBytes, + vBytes, + rBytes, + sBytes, + lengthBytes, + startTimeBytes1, + startTimeBytes2, + endTimeBytes1, + endTimeBytes2, + tokensBalanceBytes1, + tokensBalanceBytes2, + pointsBalanceBytes1, + pointsBalanceBytes2, + tpsBytes1, + tpsBytes2, + ppsBytes1, + ppsBytes2, + ]); + + await diamondStakingFacet.connect(admin).claim( + 0, + callDataBytes + // signedDataHash, + // { + // v: signature1.v, + // r: signature1.r, + // s: signature1.s, + // }, + // { + // startTime: [blockTime - 1000, blockTime], + // endTime: [blockTime + 1, blockTime + 1000], + // balance: [3000, 2000], + // } + ); + + await expect( + diamondStakingFacet.connect(admin).claim( + 0, + callDataBytes + // signedDataHash, + // { + // v: signature1.v, + // r: signature1.r, + // s: signature1.s, + // }, + // { + // startTime: [blockTime - 1000, blockTime], + // endTime: [blockTime + 1, blockTime + 1000], + // balance: [3000, 2000], + // } + ) + ).to.be.revertedWith("HashUsed()"); + }); + + it("should claim with checkpoints correctly", async function () { + const blockTime = await utils.getCurrentTime(); + + const signedDataHash = ethers.utils.solidityKeccak256( + ["bytes32", "bytes32", "bytes32", "bytes32", "bytes32", "bytes32"], + [ + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [blockTime - 1000, blockTime] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [blockTime + 1, blockTime + 1000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [3000, 2000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [3000, 2000] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [ + ethers.utils.parseUnits("1.0", 12), + ethers.utils.parseUnits("1.2", 12), + ] + ), + ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [ + ethers.utils.parseUnits("1.0", 30), + ethers.utils.parseUnits("1.2", 30), + ] + ), + ] + ); + + const bytesArray = ethers.utils.arrayify(signedDataHash); + + const flatSignature1 = await admin.signMessage(bytesArray); + + const signature1 = ethers.utils.splitSignature(flatSignature1); + + let signedDataHashBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signedDataHash), + 32 + ); + let vBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.v), + 32 + ); + let rBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.r), + 32 + ); + let sBytes = ethers.utils.hexZeroPad( + ethers.utils.hexlify(signature1.s), + 32 + ); + + let lengthBytes = ethers.utils.hexZeroPad(ethers.utils.hexlify(2), 32); + + let startTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime - 1000), + 32 + ); + let startTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime), + 32 + ); + let endTimeBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1), + 32 + ); + let endTimeBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(blockTime + 1000), + 32 + ); + let tokensBalanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let tokensBalanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + let pointsBalanceBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(3000), + 32 + ); + let pointsBalanceBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(2000), + 32 + ); + let tpsBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.0", 12)), + 32 + ); + let tpsBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.2", 12)), + 32 + ); + let ppsBytes1 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.0", 30)), + 32 + ); + let ppsBytes2 = ethers.utils.hexZeroPad( + ethers.utils.hexlify(ethers.utils.parseUnits("1.2", 30)), + 32 + ); + + let callDataBytes = ethers.utils.hexConcat([ + signedDataHashBytes, + vBytes, + rBytes, + sBytes, + lengthBytes, + startTimeBytes1, + startTimeBytes2, + endTimeBytes1, + endTimeBytes2, + tokensBalanceBytes1, + tokensBalanceBytes2, + pointsBalanceBytes1, + pointsBalanceBytes2, + tpsBytes1, + tpsBytes2, + ppsBytes1, + ppsBytes2, + ]); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).claim( + 0, + callDataBytes + // signedDataHash, + // { + // v: signature1.v, + // r: signature1.r, + // s: signature1.s, + // }, + // { + // startTime: [blockTime - 1000, blockTime], + // endTime: [blockTime + 1, blockTime + 1000], + // balance: [3000, 2000], + // } + ); + // expect(await rewardToken.balanceOf(signer1.address)).to.be.gt(0); + }); + }); + // describe("onERC721Received", function () { + // it("should work correctly", async function () { + // await stakerV3FacetStaking + // .connect(owner) + // .onERC721Received(owner.address, signer1.address, 1, [0x01, 0x02]); + // }); + // }); + + describe("approvePointSpender spendPoints, getPendingPoints, getTotalPoints", function () { + it("approve should work correctly", async function () { + await diamondPointsFacet + .connect(owner) + .approvePointSpender(signer2.address, true); + }); + + it("Reverts: spender is not approved", async function () { + await expect( + diamondPointsFacet.connect(signer1).spendPoints(signer2.address, 10) + ).to.be.revertedWith("NotApprovedPointSpender()"); + }); + + it("Reverts: amount exceeds available points", async function () { + await diamondPointsFacet + .connect(owner) + .approvePointSpender(signer2.address, true); + + await expect( + diamondPointsFacet.connect(signer2).spendPoints(signer1.address, 10) + ).to.be.revertedWith("InvalidAmount()"); + }); + + it("spendPoints should work correctly ", async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + await diamondPointsFacet + .connect(owner) + .approvePointSpender(signer2.address, true); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await diamondPointsFacet + .connect(signer2) + .spendPoints(signer1.address, 10); + }); + }); + describe("apply boost", function () { + beforeEach(async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 0, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super721.address, + boostType: 1, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + }); + it("should work correctly with different/without boosts", async function () { + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 2, { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + amounts: [1, 1], + IOUTokenId: [], + }); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(5), shiftedItemGroupId2.add(6)], + amounts: [1, 1], + IOUTokenId: [], + }, + false + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 15000, + pointStrength: 15000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer2).deposit( + 1, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(7)], + amounts: [1], + IOUTokenId: [], + }, + false + ); + }); + + it("should get total points correctly", async function () { + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 2, { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + amounts: [1, 1], + IOUTokenId: [], + }); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(5), shiftedItemGroupId2.add(6)], + amounts: [1, 1], + IOUTokenId: [], + }, + false + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 15000, + pointStrength: 15000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer2).deposit( + 1, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(7)], + amounts: [1], + IOUTokenId: [], + }, + false + ); + }); + }); + describe("getPendingTokens", function () { + beforeEach(async function () { + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 0, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super721.address, + boostType: 1, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 2, { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + amounts: [1, 1], + IOUTokenId: [], + }); + + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [shiftedItemGroupId2.add(5), shiftedItemGroupId2.add(6)], + amounts: [1, 1], + IOUTokenId: [], + }, + false + ); + }); + + it("getPendingTokens should work correctly", async function () { + const stakingFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetStaking" + ); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + let getPendingTokens = await diamondStakingFacet + .connect(owner) + .getPendingTokens(0, signer1.address); + + expect(await getPendingTokens).be.closeTo( + ethers.utils.parseEther("200"), + 10 ** 15 + ); + }); + + it("getPendingPoints should work correctly", async function () { + const stakingFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetStaking" + ); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + let getPendingPoints = await diamondStakingFacet + .connect(owner) + .getPendingPoints(0, signer1.address); + + expect(await getPendingPoints).be.closeTo( + ethers.utils.parseEther("200"), + 10 ** 15 + ); + }); + + it("getAvailablePoints and getTotalPoints should work correctly", async function () { + let startOfStaking = await utils.getCurrentTime(); + const stakingFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetStaking" + ); + const pointsFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetPoints" + ); + await diamondPointsFacet + .connect(owner) + .approvePointSpender(signer2.address, true); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 29, + ]); + await ethers.provider.send("evm_mine", []); + + await diamondPointsFacet + .connect(signer2) + .spendPoints(signer1.address, ethers.utils.parseEther("50")); + + let getAvailablePoints = await diamondPointsFacet + .connect(owner) + .getAvailablePoints(signer1.address); + + expect(getAvailablePoints).be.closeTo( + ethers.utils.parseEther("150"), + 10 ** 15 + ); + + let getTotalPoints = await diamondPointsFacet + .connect(owner) + .getTotalPoints(signer1.address); + + expect(await getTotalPoints).be.closeTo( + ethers.utils.parseEther("200"), + 10 ** 15 + ); + }); + }); + describe("some specific test cases with emission starts late", function () { + it("getPendingPoints and getPendingTokens should work correctly with emission starts late", async function () { + const stakingFacetABI = await hre.artifacts.readArtifact( + "StakerV3FacetStaking" + ); + + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: (await utils.getCurrentTime()) + 10000, + rate: ethers.utils.parseEther("6.6666666666"), + }, + ], + [ + { + timeStamp: (await utils.getCurrentTime()) + 10000, + rate: ethers.utils.parseEther("6.6666666666"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + //console.log(await utils.getCurrentTime()); + + // await network.provider.send("evm_increaseTime", [35]); + // await ethers.provider.send("evm_mine", []); + //console.log(await utils.getCurrentTime()); + + let getPendingTokens = await diamondStakingFacet + .connect(owner) + .getPendingTokens(1, signer1.address); + + expect(await getPendingTokens).be.closeTo( + ethers.utils.parseEther("0"), + 10 ** 15 + ); + + let getPendingPoints = await diamondStakingFacet + .connect(owner) + .getPendingPoints(1, signer1.address); + + expect(await getPendingPoints).be.closeTo( + ethers.utils.parseEther("0"), + 10 ** 15 + ); + }); + + it("getTotalEmittedTokens and getTotalEmittedPoints should work correctly with different emissions", async function () { + await rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("500000") + ); + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + { + timeStamp: (await utils.getCurrentTime()) + 36, + rate: ethers.utils.parseEther("2"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("6.6666666666"), + }, + { + timeStamp: (await utils.getCurrentTime()) + 30, + rate: ethers.utils.parseEther("0.1"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 1, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + await diamondStakingFacet.connect(signer1).deposit( + 1, + { + id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + amounts: [1, 1], + assetAddress: super721.address, + IOUTokenId: [], + }, + false + ); + + await diamondStakingFacet.connect(signer1).claim(1, []); + //console.log(await utils.getCurrentTime()); + + await network.provider.send("evm_increaseTime", [30]); + await ethers.provider.send("evm_mine", []); + + await diamondStakingFacet.connect(signer1).deposit( + 1, + { + id: [shiftedItemGroupId2.add(2), shiftedItemGroupId2.add(3)], + amounts: [1, 1], + assetAddress: super721.address, + IOUTokenId: [], + }, + false + ); + + // await diamondStakingFacet + // .connect(signer1) + // .deposit(1, 0, { + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // assetAddress: super721.address, + // IOUTokenId: [], + // }, + // false); + }); + }); + }); + // describe("time lock deposits testing", function () { + // beforeEach(async function () { + // await diamondCoreFacet.connect(owner).setEmissions( + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("10"), + // }, + // ], + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("10"), + // }, + // ] + // ); + // + + // await diamondCoreFacet + // .connect(owner) + // .configureBoostersBatch( + // [1, 2], + // [ + // { + // + // multiplier: 2300, + // amountRequired: 3, + // groupRequired: itemGroupId2, + // contractRequired: super721.address, + // boostType: 0, + // typeOfAsset: 1, + // }, + // { + // + // multiplier: 2000, + // amountRequired: 2, + // groupRequired: 0, + // contractRequired: super721.address, + // boostType: 1, + // typeOfAsset: 1, + // }, + // ] + // ); + // + + // await diamondCoreFacet.connect(owner).addPool({ + // id: 0, + // tokenStrength: 10000, + // pointStrength: 10000, + // groupId: 0, + // tokensPerShare: 0, + // pointsPerShare: 0, + // compoundInterestThreshold: ethers.utils.parseEther("1000"), + // compoundInterestMultiplier: 5000, + // boostInfo: [1, 2], + // assetAddress: super721.address, + // typeOfAsset: 1, + // lockPeriod: 60, + // lockAmount: 2, + // lockMultiplier: 10000, + // timeLockTypeOfBoost: 2, + // compoundTypeOfBoost: 2, + // typeOfPool: 0, + // }); + // + + // await super721.connect(owner).configureGroup(itemGroupId2, { + // name: "PEPSI", + // supplyType: 0, + // supplyData: 10, + // burnType: 0, + // burnData: 0, + // }); + // await super721 + // .connect(owner) + // .mintBatch( + // signer1.address, + // [ + // shiftedItemGroupId2, + // shiftedItemGroupId2.add(1), + // shiftedItemGroupId2.add(2), + // shiftedItemGroupId2.add(3), + // ], + // DATA + // ); + // await super721 + // .connect(owner) + // .mintBatch( + // signer3.address, + // [ + // shiftedItemGroupId2.add(4), + // shiftedItemGroupId2.add(5), + // shiftedItemGroupId2.add(6), + // ], + // DATA + // ); + // await super721 + // .connect(owner) + // .mintBatch( + // signer2.address, + // [ + // shiftedItemGroupId2.add(7), + // shiftedItemGroupId2.add(8), + // shiftedItemGroupId2.add(9), + // ], + // DATA + // ); + // await super721 + // .connect(signer1) + // .setApprovalForAll(stakerV3dsProxy.address, true); + // await super721 + // .connect(signer2) + // .setApprovalForAll(stakerV3dsProxy.address, true); + // await super721 + // .connect(signer3) + // .setApprovalForAll(stakerV3dsProxy.address, true); + + // // await diamondStakingFacet.connect(signer1).deposit( + // // 0, + // // 2, + // // { + // // assetAddress: super721.address, + // // id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + // // amounts: [1, 1], + // // IOUTokenId: [], + // // }, + // // false + // // ); + + // await rewardToken.transfer( + // stakerV3dsProxy.address, + // ethers.utils.parseEther("500000") + // ); + // }); + + // it("Reverts: invalid amount to lock", async function () { + // await expect(diamondStakingFacet.connect(signer2).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(7)], + // amounts: [1], + // IOUTokenId: [], + // }, + // true + // )).to.be.revertedWith("InvalidAmountToLock()"); + // }); + + // it("Reverts: tokens already locked", async function () { + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // await expect(diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(2), shiftedItemGroupId2.add(3)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // )).to.be.revertedWith("TokensAlreadyLocked()"); + // }); + + // it("Reverts: can't withdraw tokens are locked", async function () { + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // let startOfStaking = await utils.getCurrentTime(); + + // await expect(diamondStakingFacet.connect(signer1).withdraw( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + // amounts: [1, 1], + // IOUTokenId: [0, 1], + // } + // )).to.be.revertedWith("TokenLocked()"); + + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(2), shiftedItemGroupId2.add(3)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // false + // ); + + // await diamondStakingFacet.connect(signer1).withdraw( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + // amounts: [1, 1], + // IOUTokenId: [2, 3], + // } + // ); + + // expect(await super721.ownerOf(shiftedItemGroupId2.add(3))).to.be.eq( + // signer1.address + // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // startOfStaking + 70, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet.connect(signer1).withdraw( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(3), shiftedItemGroupId2.add(4)], + // amounts: [1, 1], + // IOUTokenId: [0, 1], + // } + // ); + + // expect(await super721.ownerOf(shiftedItemGroupId2.add(1))).to.be.eq( + // signer1.address + // ); + // }); + + // it("should work with different types of time lock boosts correctly", async function () { + // await diamondCoreFacet.connect(owner).addPool({ + // id: 1, + // tokenStrength: 10000, + // pointStrength: 10000, + // groupId: 0, + // tokensPerShare: 0, + // pointsPerShare: 0, + // compoundInterestThreshold: ethers.utils.parseEther("10"), + // compoundInterestMultiplier: 5000, + // boostInfo: [1, 2], + // assetAddress: super721.address, + // typeOfAsset: 1, + // lockPeriod: 60, + // lockAmount: 2, + // lockMultiplier: 10000, + // timeLockTypeOfBoost: 1, + // compoundTypeOfBoost: 1, + // typeOfPool: 0, + // }); + + // await diamondCoreFacet.connect(owner).addPool({ + // id: 2, + // tokenStrength: 10000, + // pointStrength: 10000, + // groupId: 0, + // tokensPerShare: 0, + // pointsPerShare: 0, + // compoundInterestThreshold: ethers.utils.parseEther("1000"), + // compoundInterestMultiplier: 5000, + // boostInfo: [1, 2], + // assetAddress: super721.address, + // typeOfAsset: 1, + // lockPeriod: 60, + // lockAmount: 2, + // lockMultiplier: 10000, + // timeLockTypeOfBoost: 0, + // compoundTypeOfBoost: 0, + // typeOfPool: 0, + // }); + + // let startOfStaking = await utils.getCurrentTime(); + // await diamondStakingFacet.connect(signer1).deposit( + // 1, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(2), shiftedItemGroupId2.add(3)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // await diamondStakingFacet.connect(signer1).deposit( + // 2, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // startOfStaking + 30, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(1, []); + // }); + + // it("complex math tests of time locks with 3 users", async function () { + // let shares = { + // sig1: 0, + // sig2: 0, + // sig3: 0, + // sum: 0, + // }; + // let rewardsPerSecond = BigNumber.from(ethers.utils.parseEther("10")), + // lockMultiplier = 2; + + // await diamondStakingFacet.connect(signer2).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(7), shiftedItemGroupId2.add(8)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // false + // ); + + // shares.sig2 = 2000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + // let signer2DepTime = await utils.getCurrentTime(); + + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + // // 2000 with time lock bonus multiplier x2 + // shares.sig1 = 2000 * lockMultiplier; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + // let signer1DepTime = await utils.getCurrentTime(); + // let signer2Rewards = BigNumber.from( + // rewardsPerSecond.mul(signer1DepTime - signer2DepTime) + // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // startOfStaking + 30, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // // helper var + // let someBig = ethers.utils.parseEther("1"); + // // signer 1 share with time lock boost is 2/3 (4000/6000) * 10(rewards per second) * + // // * 30(time from start of signer1 staked) ~= 200 + // let signer1Rewards = BigNumber.from( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul((await utils.getCurrentTime()) - signer1DepTime) + // .div(someBig) + // ); + + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // signer1Rewards, + // // 10 ** 15 + // // ); + // let signer1FirstClaimTime = await ( + // await ethers.provider.getBlock() + // ).timestamp; + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul((await utils.getCurrentTime()) - signer1DepTime) + // .div(someBig) + // ); + // let signer2FirstClaimTime = await ( + // await ethers.provider.getBlock() + // ).timestamp; + // // signer 2 share is 1/3 (2000/6000) * 10 * 31 (1 sec past from last tx) + + // // + 10(reward for 1 sec when singer2 deposited first) ~= 113.3333333 + // // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // // signer2Rewards, + // // 10 ** 15 + // // ); + + // // 3 seconds have passed since the last claim + // await diamondStakingFacet.connect(signer3).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(4)], + // amounts: [1], + // IOUTokenId: [], + // }, + // false + // ); + // let signer3DepTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3DepTime - signer1FirstClaimTime) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3DepTime - signer2FirstClaimTime) + // .div(someBig) + // ); + // shares.sig3 = 1000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // // +1 second (4 overall) + // await diamondStakingFacet.connect(signer3).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(5), shiftedItemGroupId2.add(6)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // let signer3TimeLockAt = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + // let signer3Rewards = BigNumber.from( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + + // shares.sig3 = 3000 * lockMultiplier; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // let signer1SecondClaimTime = await utils.getCurrentTime(); + + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1SecondClaimTime - signer3TimeLockAt) + // .div(someBig) + // ); + + // // 200 + 10 * 2/3 * 4(time between 1st signer1 claim and 1st signer3 deposit) + 10 * + // // * 4/7(share of signer1 at signer3 1st deposit) * 1 + 1/3(share of signer1 at signer3 2nd deposit) * + // // * 1(second past until 2nd signer1 claim) ~= 235,714285714 + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // signer1Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + + // let signer2SecondClaimTime = await utils.getCurrentTime(); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer2SecondClaimTime - signer3TimeLockAt) + // .div(someBig) + // ); + + // // 113.333333 + 10 * 1/3 * 3(one less second) + 10 * 2/7 * 1 + 1/6 * + // // * 2(+1 second from last tx) ~= 129.52380949 + // // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // // signer2Rewards, + // // 10 ** 15 + // // ); + + // // moving to 60 seconds after signer1 time locked + // await network.provider.send("evm_setNextBlockTimestamp", [ + // startOfStaking + 60, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // let signer1ThirdClaimTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1ThirdClaimTime - signer1SecondClaimTime) + // .div(someBig) + // ); + + // // 235.714285 + 10 * 1/3 * 24(time from last signer1 claim) ~= 315.714285 + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // signer1Rewards, + // // 10 ** 15 + // // ); + + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer1ThirdClaimTime - signer2SecondClaimTime) + // .div(someBig) + // ); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer1ThirdClaimTime - signer3TimeLockAt) + // .div(someBig) + // ); + + // shares.sig1 = 2000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + + // let signer2ThirdClaimTime = await utils.getCurrentTime(); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer2ThirdClaimTime - signer1ThirdClaimTime) + // .div(someBig) + // ); + + // // 129.52380949 + 10 * 1/6 * 23(time from last signer2 claim to unlock of signer1 deposit) + + // // 10 * 1/5 ~= 169.857142823 + // // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // // signer2Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer3) + // .claim(0, []); + + // let signer3FirstClaimTime = await utils.getCurrentTime(); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3FirstClaimTime - signer1ThirdClaimTime) + // .div(someBig) + // ); + + // // 10 * 1/7 + 10 * 6/12 * 25(seconds from time lock of signer3 to unlock of signer1 deposit) + 10 * + // // * 6 / 10 * 2(time from signer1 unlock) ~= + // // 10 * 1/5 ~= 138.4285714 + // // expect(await rewardToken.balanceOf(signer3.address)).to.be.closeTo( + // // signer3Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // let signer1FourthClaimTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1FourthClaimTime - signer1ThirdClaimTime) + // .div(someBig) + // ); + + // // 315.714285 + 10 * 2/10 * 3 ~= 321.714285714285 + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // signer1Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + + // let signer2FourthClaimTime = await utils.getCurrentTime(); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer2FourthClaimTime - signer2ThirdClaimTime) + // .div(someBig) + // ); + + // // 169.857142823 + 10 * 2/10 * 3 ~= 175.85714285714 + // // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // // signer2Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer3) + // .claim(0, []); + + // let signer3SecondClaimTime = await utils.getCurrentTime(); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3SecondClaimTime - signer3FirstClaimTime) + // .div(someBig) + // ); + + // // 138.428571428571 + 10 * 6/10 * 3 ~= 156.428571429 + // // expect(await rewardToken.balanceOf(signer3.address)).to.be.closeTo( + // // signer3Rewards, + // // 10 ** 15 + // // ); + + // // moving to 60 seconds after signer1 time locked + // await network.provider.send("evm_setNextBlockTimestamp", [ + // signer3TimeLockAt + 60, + // ]); + // await ethers.provider.send("evm_mine", []); + + // let signer3UnlockTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3UnlockTime - signer1FourthClaimTime) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3UnlockTime - signer2FourthClaimTime) + // .div(someBig) + // ); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3UnlockTime - signer3SecondClaimTime) + // .div(someBig) + // ); + + // shares.sig3 = 3000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + // await network.provider.send("evm_setNextBlockTimestamp", [ + // signer3TimeLockAt + 75, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // let signer1FifthClaimTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1FifthClaimTime - signer3UnlockTime) + // .div(someBig) + // ); + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // signer1Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + + // let signer2FifthClaimTime = await utils.getCurrentTime(); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer2FifthClaimTime - signer3UnlockTime) + // .div(someBig) + // ); + // // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // // signer2Rewards, + // // 10 ** 15 + // // ); + + // await diamondStakingFacet + // .connect(signer3) + // .claim(0, []); + + // let signer3ThirdClaimTime = await utils.getCurrentTime(); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3ThirdClaimTime - signer3UnlockTime) + // .div(someBig) + // ); + // // expect(await rewardToken.balanceOf(signer3.address)).to.be.closeTo( + // // signer3Rewards, + // // 10 ** 15 + // // ); + // }); + + // it("multiple unlocks should work correctly", async function () { + // let shares = { + // sig1: 0, + // sig2: 0, + // sig3: 0, + // sum: 0, + // }; + // let rewardsPerSecond = BigNumber.from(ethers.utils.parseEther("10")), + // lockMultiplier = 2; + + // await diamondStakingFacet.connect(signer2).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(7), shiftedItemGroupId2.add(8)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // false + // ); + + // shares.sig2 = 2000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + // let signer2DepTime = await utils.getCurrentTime(); + + // //deposit + // let startOfStaking = await utils.getCurrentTime(); + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2, shiftedItemGroupId2.add(1)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // // 2000 with time lock bonus multiplier x2 + // shares.sig1 = 2000 * lockMultiplier; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + // let signer1DepTime = await utils.getCurrentTime(); + // let signer2Rewards = BigNumber.from( + // rewardsPerSecond.mul(signer1DepTime - signer2DepTime) + // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // startOfStaking + 30, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // // helper var + // let someBig = ethers.utils.parseEther("1"); + // // signer 1 share with time lock boost is 2/3 (4000/6000) * 10(rewards per second) * + // // * 30(time of signer1 staked) ~= 200 + // let signer1Rewards = BigNumber.from( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul((await utils.getCurrentTime()) - signer1DepTime) + // .div(someBig) + // ); + + // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // signer1Rewards, + // 10 ** 15 + // ); + // let signer1FirstClaimTime = await ( + // await ethers.provider.getBlock() + // ).timestamp; + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + // }); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul((await utils.getCurrentTime()) - signer1DepTime) + // .div(someBig) + // ); + // let signer2FirstClaimTime = await ( + // await ethers.provider.getBlock() + // ).timestamp; + // // signer 2 share is 1/3 (2000/6000) * 10 * 31 (1 sec past from last tx) + + // // + 10(reward for 1 sec when singer2 deposited first) ~= 113.3333333 + // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // signer2Rewards, + // 10 ** 15 + // ); + + // // 3 seconds have passed since the last claim + // //deposit + // await diamondStakingFacet.connect(signer3).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(4)], + // amounts: [1], + // IOUTokenId: [], + // }, + // false + // ); + + // let signer3DepTime = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3DepTime - signer1FirstClaimTime) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3DepTime - signer2FirstClaimTime) + // .div(someBig) + // ); + // shares.sig3 = 1000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // // +1 second (4 overall) + // await diamondStakingFacet.connect(signer3).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [shiftedItemGroupId2.add(5), shiftedItemGroupId2.add(6)], + // amounts: [1, 1], + // IOUTokenId: [], + // }, + // true + // ); + + // let signer3TimeLockAt = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + // let signer3Rewards = BigNumber.from( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3TimeLockAt - signer3DepTime) + // .div(someBig) + // ); + + // shares.sig3 = 3000 * lockMultiplier; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // signer1DepTime + 200, + // ]); + + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1DepTime + 60 - signer3TimeLockAt) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer1DepTime + 60 - signer3TimeLockAt) + // .div(someBig) + // ); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer1DepTime + 60 - signer3TimeLockAt) + // .div(someBig) + // ); + + // shares.sig1 = 2000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer3TimeLockAt + 60 - (signer1DepTime + 60)) + // .div(someBig) + // ); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer3TimeLockAt + 60 - (signer1DepTime + 60)) + // .div(someBig) + // ); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3TimeLockAt + 60 - (signer1DepTime + 60)) + // .div(someBig) + // ); + + // shares.sig3 = 3000; + // shares.sum = shares.sig1 + shares.sig2 + shares.sig3; + + // // move to signer1LockTime + 200 seconds + // await ethers.provider.send("evm_mine", []); + + // await expect(IOUToken.ownerOf(2)).to.be.reverted; + // expect(await IOUToken.ownerOf(4)).to.be.eq(signer3.address); + // await expect(IOUToken.ownerOf(5)).to.be.reverted; + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + // }); + + // let signer1LastClaim = await utils.getCurrentTime(); + // signer1Rewards = signer1Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig1).div(shares.sum)) + // .mul(signer1LastClaim - (signer3TimeLockAt + 60)) + // .div(someBig) + // ); + + // expect(await IOUToken.ownerOf(2)).to.be.eq(signer1.address); + // expect(await IOUToken.ownerOf(4)).to.be.eq(signer3.address); + // expect(await IOUToken.ownerOf(5)).to.be.eq(signer3.address); + // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // signer1Rewards, + // 10 ** 15 + // ); + + // await diamondStakingFacet + // .connect(signer2) + // .claim(0, []); + // }); + + // let signer2LastClaim = await utils.getCurrentTime(); + // signer2Rewards = signer2Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig2).div(shares.sum)) + // .mul(signer2LastClaim - (signer3TimeLockAt + 60)) + // .div(someBig) + // ); + // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // signer2Rewards, + // 10 ** 15 + // ); + + // await diamondStakingFacet + // .connect(signer3) + // .claim(0, []); + // }); + + // let signer3LastClaim = await utils.getCurrentTime(); + // signer3Rewards = signer3Rewards.add( + // rewardsPerSecond + // .mul(someBig.mul(shares.sig3).div(shares.sum)) + // .mul(signer3LastClaim - (signer3TimeLockAt + 60)) + // .div(someBig) + // ); + // expect(await rewardToken.balanceOf(signer3.address)).to.be.closeTo( + // signer3Rewards, + // 10 ** 15 + // ); + // }); + // }); + // }); + + // describe("Compound interest testing", function () { + // it("Should work correctly with compound interest pools", async function () { + // await rewardToken.transfer( + // stakerV3dsProxy.address, + // ethers.utils.parseEther("500000") + // ); + + // await diamondCoreFacet.connect(owner).setEmissions( + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("10"), + // }, + // ], + // [ + // { + // timeStamp: await utils.getCurrentTime(), + // rate: ethers.utils.parseEther("10"), + // }, + // ] + // ); + + // await super721.connect(owner).configureGroup(itemGroupId2, { + // name: "PEPSI", + // supplyType: 0, + // supplyData: 10, + // burnType: 0, + // burnData: 0, + // }); + // await super721 + // .connect(owner) + // .mintBatch( + // signer1.address, + // [ + // shiftedItemGroupId2, + // shiftedItemGroupId2.add(1), + // shiftedItemGroupId2.add(2), + // shiftedItemGroupId2.add(3), + // ], + // DATA + // ); + // await super721 + // .connect(signer1) + // .setApprovalForAll(stakerV3dsProxy.address, true); + + // await diamondCoreFacet.connect(owner).addPool({ + // id: 0, + // tokenStrength: 10000, + // pointStrength: 10000, + // groupId: 0, + // tokensPerShare: 0, + // pointsPerShare: 0, + // compoundInterestThreshold: ethers.utils.parseEther("500"), + // compoundInterestMultiplier: 5000, + // boostInfo: [1, 2], + // assetAddress: super721.address, + // typeOfAsset: 1, + // lockPeriod: 0, + // lockAmount: 0, + // lockMultiplier: 0, + // timeLockTypeOfBoost: 0, + // compoundTypeOfBoost: 0, + // typeOfPool: 0, + // }); + + // let signer1DepTime = await utils.getCurrentTime(); + + // await diamondStakingFacet.connect(signer1).deposit( + // 0, + // { + // assetAddress: super721.address, + // id: [ + // shiftedItemGroupId2, + // shiftedItemGroupId2.add(1), + // shiftedItemGroupId2.add(2), + // ], + // amounts: [1, 1, 1], + // IOUTokenId: [], + // }, + // false + // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // signer1DepTime + 30, + // ]); + // await ethers.provider.send("evm_mine", []); + + // //claim + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // ethers.utils.parseEther("300"), + // // 10 ** 15 + // // ); + + // await network.provider.send("evm_setNextBlockTimestamp", [ + // signer1DepTime + 100, + // ]); + // await ethers.provider.send("evm_mine", []); + + // await diamondStakingFacet + // .connect(signer1) + // .claim(0, []); + + // // 300 + 10 * 50 + 10 * 20 * 1.5 = 1100 + // // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // // ethers.utils.parseEther("1100"), + // // 10 ** 15 + // // ); + // }); + // }); + + describe("All", function () { + it("stakerv3", async function () { + let itemGroupId = ethers.BigNumber.from(1); + let shiftedItemGroupId = itemGroupId.shl(128); + let itemGroupId2 = ethers.BigNumber.from(2); + let shiftedItemGroupId2 = itemGroupId2.shl(128); + + await depositToken.transfer( + signer1.address, + ethers.utils.parseEther("1000") + ); + await depositToken.transfer( + signer2.address, + ethers.utils.parseEther("1000") + ); + await rewardToken.transfer( + stakerV3dsProxy.address, + ethers.utils.parseEther("500000") + ); + + // addDeveloper() + await diamondCoreFacet + .connect(owner) + .addDeveloper(developer.address, 1000); + + //await diamondCoreFacet.connect(owner).initialize(owner.address); + + // Note 10 per second is equivalent to 150 per 15 seconds(15 seconds = block time according to Blocks implementation) + // Now the rewards must be set based on seconds + + await diamondCoreFacet.connect(owner).setEmissions( + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ], + [ + { + timeStamp: await utils.getCurrentTime(), + rate: ethers.utils.parseEther("10"), + }, + ] + ); + + await diamondCoreFacet.connect(owner).configureBoostersBatch( + [1, 2], + [ + { + multiplier: 2300, + amountRequired: 3, + groupRequired: itemGroupId2, + contractRequired: super721.address, + boostType: 2, + typeOfAsset: 1, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + { + multiplier: 2000, + amountRequired: 2, + groupRequired: 0, + contractRequired: super1155.address, + boostType: 2, + typeOfAsset: 2, + historyOfTokenMultipliers: [], + historyOfPointMultipliers: [], + }, + ] + ); + + await diamondCoreFacet.connect(owner).addPool({ + id: 0, + tokenStrength: 10000, + pointStrength: 10000, + groupId: 0, + tokensPerShare: 0, + pointsPerShare: 0, + compoundInterestThreshold: ethers.utils.parseEther("1000"), + compoundInterestMultiplier: 5000, + boostInfo: [1, 2], + assetAddress: super721.address, + typeOfAsset: 1, + lockPeriod: 0, + lockAmount: 0, + lockMultiplier: 0, + timeLockTypeOfBoost: 0, + compoundTypeOfBoost: 0, + typeOfPool: 0, + }); + + // Mint ITEMS for Signer1 + await super721.connect(owner).configureGroup(itemGroupId2, { + name: "PEPSI", + supplyType: 0, + supplyData: 10, + burnType: 0, + burnData: 0, + }); + await super721 + .connect(owner) + .mintBatch( + signer1.address, + [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + shiftedItemGroupId2.add(6), + ], + DATA + ); + await super721 + .connect(owner) + .mintBatch( + signer2.address, + [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + DATA + ); + await super721 + .connect(signer1) + .setApprovalForAll(stakerV3dsProxy.address, true); + await super721 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + // Mint ITEMS for Signer2 + await super1155.connect(owner).configureGroup(itemGroupId, { + name: "PEPSI", + supplyType: 0, + supplyData: 100, + itemType: 2, + itemData: 20, + burnType: 0, + burnData: 0, + }); + await super1155 + .connect(owner) + .mintBatch( + signer2.address, + [shiftedItemGroupId, shiftedItemGroupId.add(1)], + [20, 10], + DATA + ); + await super1155 + .connect(signer2) + .setApprovalForAll(stakerV3dsProxy.address, true); + + // + let startOfStaking = await utils.getCurrentTime(); + + //User1-Deposit + await diamondStakingFacet.connect(signer1).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2, + shiftedItemGroupId2.add(1), + shiftedItemGroupId2.add(2), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 30, + ]); + await ethers.provider.send("evm_mine", []); + + //User1-Claims + await diamondStakingFacet.connect(signer1).claim(0, []); + // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // ethers.utils.parseEther("297"), + // ethers.utils.parseEther("0.01") + // ); + + expect(await IOUToken.balanceOf(signer1.address)).to.be.eq(3); + expect(await IOUToken.ownerOf(0)).to.be.eq(signer1.address); + expect(await IOUToken.ownerOf(1)).to.be.eq(signer1.address); + + expect(await super721.ownerOf(shiftedItemGroupId2.add(3))).to.be.eq( + signer1.address + ); + + // +300 rewars for signer1 + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 60, + ]); + await ethers.provider.send("evm_mine", []); + + //User1-StakeITEMS + await diamondBoostersFacet.connect(signer1).stakeItemsBatch(0, 1, { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(3), + shiftedItemGroupId2.add(4), + shiftedItemGroupId2.add(5), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }); + + expect(await super721.ownerOf(shiftedItemGroupId2.add(3))).to.be.eq( + stakerV3dsProxy.address + ); + expect(await super721.ownerOf(shiftedItemGroupId2.add(5))).to.be.eq( + stakerV3dsProxy.address + ); + + //user2 stake items + await diamondBoostersFacet.connect(signer2).stakeItemsBatch(0, 2, { + assetAddress: super1155.address, + id: [shiftedItemGroupId, shiftedItemGroupId.add(1)], + amounts: [1, 1], + IOUTokenId: [], + }); + + expect( + await super1155.balanceOf(signer2.address, shiftedItemGroupId) + ).to.be.eq(19); + + // +300 rewards for signer1 (900 summary) and signer 2 is starting staking + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 90, + ]); + await ethers.provider.send("evm_mine", []); + + //User2-Deposit + await diamondStakingFacet.connect(signer2).deposit( + 0, + { + assetAddress: super721.address, + id: [ + shiftedItemGroupId2.add(7), + shiftedItemGroupId2.add(8), + shiftedItemGroupId2.add(9), + ], + amounts: [1, 1, 1], + IOUTokenId: [], + }, + false + ); + + // 900 + about 76 rewards for signer 1 - 1% for developer ~= 966.166 + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 105, + ]); + await ethers.provider.send("evm_mine", []); + + //User1-Claims + await diamondStakingFacet.connect(signer1).claim(0, []); + + // expect(await rewardToken.balanceOf(signer1.address)).to.be.closeTo( + // ethers.utils.parseEther("966.166"), + // ethers.utils.parseEther("0.001") + // ); + + expect(await super721.ownerOf(shiftedItemGroupId2.add(5))).to.be.eq( + stakerV3dsProxy.address + ); + //User1-UnstakeITEMS + await diamondBoostersFacet.connect(signer1).unstakeItemsBatch(0, 1); + + expect(await super721.ownerOf(shiftedItemGroupId2.add(5))).to.be.eq( + signer1.address + ); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 120, + ]); + await ethers.provider.send("evm_mine", []); + + //User2-Withdraw + await diamondStakingFacet.connect(signer2).withdraw(0, [3, 4, 5]); + + expect(await super721.ownerOf(shiftedItemGroupId2.add(5))).to.be.eq( + signer1.address + ); + + await network.provider.send("evm_setNextBlockTimestamp", [ + startOfStaking + 135, + ]); + await ethers.provider.send("evm_mine", []); + + //User2-Claims + await diamondStakingFacet.connect(signer2).claim(0, []); + + // its about 2 seconds until tx with user1 unstake booster will be mine, + // so rewards of signer2 = ~74(150 * 3600 / 7290 at moment of first claim of signer1) + // + 20 * 3600 / 7290(2 sec desc above) + 130 * 3600 / 6600 (after signer1 unstaked) ~= 154.859 + // - 1% for developer ~= 153.311 + // expect(await rewardToken.balanceOf(signer2.address)).to.be.closeTo( + // ethers.utils.parseEther("153.311"), + // ethers.utils.parseEther("0.01") + // ); + + // expect(await rewardToken.balanceOf(developer.address)).to.be.eq( + // ethers.utils.parseEther("13.5") + // ); + + //User2-UnstakeITEMS + await diamondBoostersFacet.connect(signer2).unstakeItemsBatch(0, 2); + + // //User1-Deposit + // await diamondStakingFacet + // .connect(signer1) + // .deposit(0, { + // assetAddress: super721.address, + // id: [ + // shiftedItemGroupId2, + // shiftedItemGroupId2.add(1), + // shiftedItemGroupId2.add(2), + // ], + // amounts: [1, 1, 1], + // IOUTokenId: [], + // }, + // false); + }); + }); +}); diff --git a/test/utils.js b/test/utils.js index fb839df..0a6c7cb 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,323 +1,346 @@ -import {ethers, network} from "hardhat"; +import { ethers, network } from "hardhat"; -export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; +export const NULL_ADDRESS = "0x0000000000000000000000000000000000000000"; -export async function getCurrentTime(){ - return ( - await ethers.provider.getBlock(await ethers.provider.getBlockNumber()) - ).timestamp; +export async function getCurrentTime() { + return ( + await ethers.provider.getBlock(await ethers.provider.getBlockNumber()) + ).timestamp; } -export async function evm_increaseTime(seconds){ - await network.provider.send("evm_increaseTime", [seconds]); - await network.provider.send("evm_mine"); +export async function evm_increaseTime(seconds) { + await network.provider.send("evm_increaseTime", [seconds]); + await network.provider.send("evm_mine"); } /*=======================MARKETPLACE===========================*/ -export const replacementPatternBuy = "0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; -export const replacementPatternSell = "0x000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"; +export const replacementPatternBuy = + "0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; +export const replacementPatternSell = + "0x000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"; export const mint = { - weth: { - bob: ethers.utils.parseEther("100"), - alice: ethers.utils.parseEther("10") + weth: { + bob: ethers.utils.parseEther("100"), + alice: ethers.utils.parseEther("10"), + }, + erc721: { + bob: 1, + alice: 2, + }, + erc1155: { + bob: { + id: 1, + amount: 5, + data: 0x0, }, - erc721:{ - bob: 1, - alice: 2 + alice: { + id: 2, + amount: 3, + data: 0x0, }, - erc1155:{ - bob: { - id: 1, - amount: 5, - data: 0x0 - }, - alice:{ - id: 2, - amount: 3, - data: 0x0 - } - } -} - + }, +}; export function makeOrder( - _basePrice, - _extra, - _listingTime, - _expirationTime, - _salt, - _fees, - _addresses, - _exchange, - _maker, - _side, - _taker, - _saleKind, - _callType, - _target, - _staticTarget, - _paymentToken, - _data, - _replacementPattern, - _staticExtraData) - { - return { - outline: { - basePrice: _basePrice, - listingTime: _listingTime, - expirationTime: _expirationTime, - exchange: _exchange, - maker: _maker, - side: _side, - taker: _taker, - saleKind: _saleKind, - target: _target, - callType: _callType, - paymentToken: _paymentToken - }, - extra: _extra, - salt: _salt, - fees: _fees, - addresses: _addresses, - staticTarget: _staticTarget, - data: _data, - replacementPattern: _replacementPattern, - staticExtradata: _staticExtraData - } + _basePrice, + _extra, + _listingTime, + _expirationTime, + _salt, + _fees, + _addresses, + _exchange, + _maker, + _side, + _taker, + _saleKind, + _callType, + _target, + _staticTarget, + _paymentToken, + _data, + _replacementPattern, + _staticExtraData +) { + return { + outline: { + basePrice: _basePrice, + listingTime: _listingTime, + expirationTime: _expirationTime, + exchange: _exchange, + maker: _maker, + side: _side, + taker: _taker, + saleKind: _saleKind, + target: _target, + callType: _callType, + paymentToken: _paymentToken, + }, + extra: _extra, + salt: _salt, + fees: _fees, + addresses: _addresses, + staticTarget: _staticTarget, + data: _data, + replacementPattern: _replacementPattern, + staticExtradata: _staticExtraData, + }; } -async function withTestTokens(){ - const TestERC1155 = await ethers.getContractFactory("TestERC1155"); - const TestERC721 = await ethers.getContractFactory("TestERC721"); - const TestWrappedEther = await ethers.getContractFactory("wETH"); +async function withTestTokens() { + const TestERC1155 = await ethers.getContractFactory("TestERC1155"); + const TestERC721 = await ethers.getContractFactory("TestERC721"); + const TestWrappedEther = await ethers.getContractFactory("wETH"); - const erc1155 = await TestERC1155.deploy(); - await erc1155.deployed() - const erc721 = await TestERC721.deploy(); - await erc721.deployed() - const weth = await TestWrappedEther.deploy(); - await weth.deployed() + const erc1155 = await TestERC1155.deploy(); + await erc1155.deployed(); + const erc721 = await TestERC721.deploy(); + await erc721.deployed(); + const weth = await TestWrappedEther.deploy(); + await weth.deployed(); - return [erc1155, erc721, weth] + return [erc1155, erc721, weth]; } -async function withProxies(){ - const Registry = await ethers.getContractFactory("SuperProxyRegistry"); - const TokenTransferProxy = await ethers.getContractFactory("SuperTokenTransferProxy"); +async function withProxies() { + const Registry = await ethers.getContractFactory("SuperProxyRegistry"); + const TokenTransferProxy = await ethers.getContractFactory( + "SuperTokenTransferProxy" + ); - const registry = await Registry.deploy(); - await registry.deployed() - const transferProxy = await TokenTransferProxy.deploy(registry.address); - await transferProxy.deployed() + const registry = await Registry.deploy(); + await registry.deployed(); + const transferProxy = await TokenTransferProxy.deploy(registry.address); + await transferProxy.deployed(); - return [registry, transferProxy] + return [registry, transferProxy]; } -export const withContracts = async function(platformFeeAddress, minimumPlatformFee, protocolFeeAddress, minimumProtocolFee){ - const [erc1155, erc721, weth] = await withTestTokens(); - const[registry, transferProxy] = await withProxies(); - - const Marketplace = await ethers.getContractFactory("SuperMarketplace"); - - const marketplace = await Marketplace.deploy( - registry.address, - ethers.utils.defaultAbiCoder.encode(["string"],["\x19Ethereum Signed Message:\n"]), - transferProxy.address, - platformFeeAddress, - minimumPlatformFee, - protocolFeeAddress, - minimumProtocolFee - ); - await marketplace.deployed() - - return [marketplace, registry, transferProxy, erc1155, erc721, weth] -} +export const withContracts = async function ( + platformFeeAddress, + minimumPlatformFee +) { + const [erc1155, erc721, weth] = await withTestTokens(); + const [registry, transferProxy] = await withProxies(); + + const Marketplace = await ethers.getContractFactory("SuperMarketplace"); + + const marketplace = await Marketplace.deploy( + registry.address, + ethers.utils.defaultAbiCoder.encode( + ["string"], + ["\x19Ethereum Signed Message:\n"] + ), + transferProxy.address, + platformFeeAddress, + minimumPlatformFee + ); + await marketplace.deployed(); + + return [marketplace, registry, transferProxy, erc1155, erc721, weth]; +}; export const OrderType = { - Order: [ - { - name: "outline", - type: "Outline" - }, - { - name: "extra", - type: "uint256[]" - }, - { - name: "salt", - type: "uint256" - }, - { - name: "fees", - type: "uint256[]" - }, - { - name: "addresses", - type: "address[]" - }, - { - name: "staticTarget", - type: "address" - }, - { - name: "data", - type: "bytes" - }, - { - name: "replacementPattern", - type: "bytes" - }, - { - name: "staticExtradata", - type: "bytes" - } - ], - Outline: [ - { - name: "basePrice", - type: "uint256" - }, - { - name: "listingTime", - type: "uint256" - }, - { - name: "expirationTime", - type: "uint256" - }, - { - name: "exchange", - type: "address" - }, - { - name: "maker", - type: "address" - }, - { - name: "side", - type: "uint8" - }, - { - name: "taker", - type: "address" - }, - { - name: "saleKind", - type: "uint8" - }, - { - name: "target", - type: "address" - }, - { - name: "callType", - type: "uint8" - }, - { - name: "paymentToken", - type: "address" - }, - ] -} + Order: [ + { + name: "outline", + type: "Outline", + }, + { + name: "extra", + type: "uint256[]", + }, + { + name: "salt", + type: "uint256", + }, + { + name: "fees", + type: "uint256[]", + }, + { + name: "addresses", + type: "address[]", + }, + { + name: "staticTarget", + type: "address", + }, + { + name: "data", + type: "bytes", + }, + { + name: "replacementPattern", + type: "bytes", + }, + { + name: "staticExtradata", + type: "bytes", + }, + ], + Outline: [ + { + name: "basePrice", + type: "uint256", + }, + { + name: "listingTime", + type: "uint256", + }, + { + name: "expirationTime", + type: "uint256", + }, + { + name: "exchange", + type: "address", + }, + { + name: "maker", + type: "address", + }, + { + name: "side", + type: "uint8", + }, + { + name: "taker", + type: "address", + }, + { + name: "saleKind", + type: "uint8", + }, + { + name: "target", + type: "address", + }, + { + name: "callType", + type: "uint8", + }, + { + name: "paymentToken", + type: "address", + }, + ], +}; /*=======================MARKETPLACE===========================*/ /*=======================MERKLE UTILS (with allowances)===========================*/ export const expandLeaves = function (balances) { - var addresses = Object.keys(balances) - addresses.sort(function(a, b) { - var al = a.toLowerCase(), bl = b.toLowerCase(); - if (al < bl) { return -1; } - if (al > bl) { return 1; } - return 0; - }); - - return addresses.map(function(a, i) { return { address: a, index: i, allowance: balances[a]}; }); -} - + var addresses = Object.keys(balances); + addresses.sort(function (a, b) { + var al = a.toLowerCase(), + bl = b.toLowerCase(); + if (al < bl) { + return -1; + } + if (al > bl) { + return 1; + } + return 0; + }); -export const hash = function(index, address, allowance) { - return ethers.utils.solidityKeccak256(["uint256", "address", "uint256"], [index, address, allowance]); + return addresses.map(function (a, i) { + return { address: a, index: i, allowance: balances[a] }; + }); +}; -} +export const hash = function (index, address, allowance) { + return ethers.utils.solidityKeccak256( + ["uint256", "address", "uint256"], + [index, address, allowance] + ); +}; // Get hashes of leaf nodes -export const getLeaves = function(balances) { - var leaves = expandLeaves(balances); - - return leaves.map(function(leaf) { - return ethers.utils.solidityKeccak256(["uint256", "address", "uint256"], [leaf.index, leaf.address, leaf.allowance]); - }); -} +export const getLeaves = function (balances) { + var leaves = expandLeaves(balances); -export const computeRootHash = function(balances) { - var leaves = getLeaves(balances); - // console.log(leaves) - while (leaves.length > 1) { - reduceMerkleBranches(leaves); + return leaves.map(function (leaf) { + return ethers.utils.solidityKeccak256( + ["uint256", "address", "uint256"], + [leaf.index, leaf.address, leaf.allowance] + ); + }); +}; + +export const computeRootHash = function (balances) { + var leaves = getLeaves(balances); + // console.log(leaves) + while (leaves.length > 1) { + reduceMerkleBranches(leaves); + } + + return leaves[0]; +}; + +export const computeMerkleProof = function (index, address) { + var leaves = getLeaves(address); + + if (index == null) { + throw new Error("address not found"); + } + + var path = index; + + var proof = []; + while (leaves.length > 1) { + if (path % 2 == 1) { + proof.push(leaves[path - 1]); + } else { + if (typeof leaves[path + 1] != "undefined") proof.push(leaves[path + 1]); + else proof.push(leaves[path]); } - return leaves[0]; -} - + // Reduce the merkle tree one level + reduceMerkleBranches(leaves); -export const computeMerkleProof = function(index, address) { - var leaves = getLeaves(address); + // Move up + path = parseInt(path / 2); + } + // console.log(proof) + return proof; +}; - if (index == null) { throw new Error('address not found'); } +export const reduceMerkleBranches = function (leaves) { + var output = []; - var path = index; + while (leaves.length) { + var left = leaves.shift(); + var right = leaves.length === 0 ? left : leaves.shift(); + output.push( + ethers.utils.solidityKeccak256(["bytes32", "bytes32"], [left, right]) + ); + } + output.forEach(function (leaf) { + leaves.push(leaf); + }); +}; - var proof = [ ]; - while (leaves.length > 1) { - if ((path % 2) == 1) { - proof.push(leaves[path - 1]) - } else { - if (typeof leaves[path + 1] != "undefined") - proof.push(leaves[path + 1]) - else - proof.push(leaves[path]) - } +export const getIndex = function (balances, address) { + // address = address.toLowerCase(); - // Reduce the merkle tree one level - reduceMerkleBranches(leaves); + var leaves = expandLeaves(balances); - // Move up - path = parseInt(path / 2); + var index = null; + for (var i = 0; i < leaves.length; i++) { + if (i != leaves[i].index) { + throw new Error("bad index mapping"); } - // console.log(proof) - return proof; -} - -export const reduceMerkleBranches = function(leaves) { - var output = []; - - while (leaves.length) { - var left = leaves.shift(); - var right = (leaves.length === 0) ? left: leaves.shift(); - output.push(ethers.utils.solidityKeccak256(["bytes32", "bytes32"], [left, right])); + if (leaves[i].address === address) { + return leaves[i].index; } - output.forEach(function(leaf) { - leaves.push(leaf); - }); -} - + } -export const getIndex = function(balances, address) { - // address = address.toLowerCase(); - - var leaves = expandLeaves(balances); - - var index = null; - for (var i = 0; i < leaves.length; i++) { - if (i != leaves[i].index) { throw new Error('bad index mapping'); } - if (leaves[i].address === address) { return leaves[i].index; } - } - - throw new Error('address not found'); -} + throw new Error("address not found"); +}; /*=======================MERKLE UTILS (with allowances)===========================*/ + /*=======================MULTICALL=================================*/ export const decodeResult = function(contractABI, func, result) { var functionABI = contractABI.abi.find((abiItem) => {return abiItem.name == func;}); @@ -357,4 +380,90 @@ export const encodeCalls = function(addresses, contractABIs, funcs, params) { return encoded; } -/*=======================MULTICALL=================================*/ \ No newline at end of file +/*=======================MULTICALL=================================*/ + + +/*===============================DIAMOND UTILS=================================== */ + +// +export const universal = + "0xffffffffffffffffffffffffffffffff00000000000000000000000000000000"; +export const mintRights = + "0xfdf81848136595c31bb5f76217767372bc4bf906663038eb38381131ea27ecba"; + +// get function selectors from ABI +export const getSelectors = function (contract) { + const signatures = Object.keys(contract.interface.functions); + const selectors = signatures.reduce((acc, val) => { + if (val !== "init(bytes)") { + acc.push(contract.interface.getSighash(val)); + } + return acc; + }, []); + selectors.contract = contract; + selectors.remove = remove; + selectors.get = get; + return selectors; +}; + +// get function selector from function signature +export const getSelector = function (func) { + const abiInterface = new ethers.utils.Interface([func]); + return abiInterface.getSighash(ethers.utils.Fragment.from(func)); +}; + +// used with getSelectors to remove selectors from an array of selectors +// functionNames argument is an array of function signatures +function remove(functionNames) { + const selectors = this.filter((v) => { + for (const functionName of functionNames) { + if (v === this.contract.interface.getSighash(functionName)) { + return false; + } + } + return true; + }); + selectors.contract = this.contract; + selectors.remove = this.remove; + selectors.get = this.get; + return selectors; +} + +// used with getSelectors to get selectors from an array of selectors +// functionNames argument is an array of function signatures +function get(functionNames) { + const selectors = this.filter((v) => { + for (const functionName of functionNames) { + if (v === this.contract.interface.getSighash(functionName)) { + return true; + } + } + return false; + }); + selectors.contract = this.contract; + selectors.remove = this.remove; + selectors.get = this.get; + return selectors; +} + +// remove selectors using an array of signatures +function removeSelectors(selectors, signatures) { + const iface = new ethers.utils.Interface( + signatures.map((v) => "function " + v) + ); + const removeSelectors = signatures.map((v) => iface.getSighash(v)); + selectors = selectors.filter((v) => !removeSelectors.includes(v)); + return selectors; +} + +// find a particular address position in the return value of diamondLoupeFacet.facets() +function findAddressPositionInFacets(facetAddress, facets) { + for (let i = 0; i < facets.length; i++) { + if (facets[i].facetAddress === facetAddress) { + return i; + } + } +} + +/*===============================DIAMOND UTILS=================================== */ + diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..9d7fd7b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,11772 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + "integrity" "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==" + "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": + "integrity" "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/code-frame@7.12.11": + "integrity" "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + "version" "7.12.11" + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0": + "integrity" "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==" + "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz" + "version" "7.17.0" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.4.0-0": + "integrity" "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz" + "version" "7.17.5" + 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" + +"@babel/generator@^7.17.3": + "integrity" "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==" + "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz" + "version" "7.17.3" + dependencies: + "@babel/types" "^7.17.0" + "jsesc" "^2.5.1" + "source-map" "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.16.7": + "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" + "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": + "integrity" "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==" + "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-explode-assignable-expression" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": + "integrity" "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==" + "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + "browserslist" "^4.17.5" + "semver" "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6": + "integrity" "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz" + "version" "7.17.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + +"@babel/helper-create-regexp-features-plugin@^7.16.7": + "integrity" "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz" + "version" "7.17.0" + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "regexpu-core" "^5.0.1" + +"@babel/helper-define-polyfill-provider@^0.3.1": + "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" + "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" + "semver" "^6.1.2" + +"@babel/helper-environment-visitor@^7.16.7": + "integrity" "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==" + "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-explode-assignable-expression@^7.16.7": + "integrity" "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + "integrity" "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==" + "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + "integrity" "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==" + "resolved" "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + "integrity" "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==" + "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-member-expression-to-functions@^7.16.7": + "integrity" "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": + "integrity" "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + "integrity" "sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz" + "version" "7.17.6" + 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.17.3" + "@babel/types" "^7.17.0" + +"@babel/helper-optimise-call-expression@^7.16.7": + "integrity" "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==" + "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + "integrity" "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-remap-async-to-generator@^7.16.8": + "integrity" "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-wrap-function" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helper-replace-supers@^7.16.7": + "integrity" "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==" + "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-simple-access@^7.16.7": + "integrity" "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==" + "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + "integrity" "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==" + "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz" + "version" "7.16.0" + dependencies: + "@babel/types" "^7.16.0" + +"@babel/helper-split-export-declaration@^7.16.7": + "integrity" "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==" + "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + "integrity" "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-validator-option@^7.16.7": + "integrity" "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz" + "version" "7.16.7" + +"@babel/helper-wrap-function@^7.16.8": + "integrity" "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==" + "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-function-name" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + +"@babel/helpers@^7.17.2": + "integrity" "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==" + "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz" + "version" "7.17.2" + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7": + "integrity" "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" + "version" "7.16.10" + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" + +"@babel/parser@^7.16.7", "@babel/parser@^7.17.3": + "integrity" "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==" + "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz" + "version" "7.17.3" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": + "integrity" "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": + "integrity" "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + +"@babel/plugin-proposal-async-generator-functions@^7.16.8": + "integrity" "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.16.7": + "integrity" "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-class-static-block@^7.16.7": + "integrity" "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz" + "version" "7.17.6" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.17.6" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.16.7": + "integrity" "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.16.7": + "integrity" "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.16.7": + "integrity" "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": + "integrity" "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": + "integrity" "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.16.7": + "integrity" "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.16.7": + "integrity" "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz" + "version" "7.17.3" + dependencies: + "@babel/compat-data" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.16.7": + "integrity" "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.16.7": + "integrity" "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.16.11": + "integrity" "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz" + "version" "7.16.11" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.10" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-private-property-in-object@^7.16.7": + "integrity" "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + "integrity" "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-syntax-async-generators@^7.8.4": + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-json-strings@^7.8.3": + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-transform-arrow-functions@^7.16.7": + "integrity" "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-async-to-generator@^7.16.8": + "integrity" "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-remap-async-to-generator" "^7.16.8" + +"@babel/plugin-transform-block-scoped-functions@^7.16.7": + "integrity" "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoping@^7.16.7": + "integrity" "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-classes@^7.16.7": + "integrity" "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "globals" "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.16.7": + "integrity" "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-destructuring@^7.16.7": + "integrity" "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz" + "version" "7.17.3" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": + "integrity" "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-duplicate-keys@^7.16.7": + "integrity" "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-exponentiation-operator@^7.16.7": + "integrity" "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-for-of@^7.16.7": + "integrity" "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-function-name@^7.16.7": + "integrity" "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-literals@^7.16.7": + "integrity" "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-member-expression-literals@^7.16.7": + "integrity" "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-modules-amd@^7.16.7": + "integrity" "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.16.8": + "integrity" "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.16.7": + "integrity" "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.16.7": + "integrity" "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": + "integrity" "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz" + "version" "7.16.8" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + +"@babel/plugin-transform-new-target@^7.16.7": + "integrity" "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-object-super@^7.16.7": + "integrity" "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + +"@babel/plugin-transform-parameters@^7.16.7": + "integrity" "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-property-literals@^7.16.7": + "integrity" "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-regenerator@^7.16.7": + "integrity" "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "regenerator-transform" "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.16.7": + "integrity" "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-runtime@^7.11.5": + "integrity" "sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz" + "version" "7.17.0" + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "semver" "^6.3.0" + +"@babel/plugin-transform-shorthand-properties@^7.16.7": + "integrity" "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.16.7": + "integrity" "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-sticky-regex@^7.16.7": + "integrity" "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-template-literals@^7.16.7": + "integrity" "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-typeof-symbol@^7.16.7": + "integrity" "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-escapes@^7.16.7": + "integrity" "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-unicode-regex@^7.16.7": + "integrity" "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/preset-env@^7.11.5": + "integrity" "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==" + "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz" + "version" "7.16.11" + dependencies: + "@babel/compat-data" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-validator-option" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-async-generator-functions" "^7.16.8" + "@babel/plugin-proposal-class-properties" "^7.16.7" + "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-proposal-dynamic-import" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.16.7" + "@babel/plugin-proposal-json-strings" "^7.16.7" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-numeric-separator" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-private-methods" "^7.16.11" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.7" + "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-block-scoped-functions" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.16.7" + "@babel/plugin-transform-classes" "^7.16.7" + "@babel/plugin-transform-computed-properties" "^7.16.7" + "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-dotall-regex" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-exponentiation-operator" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-function-name" "^7.16.7" + "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-member-expression-literals" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.16.7" + "@babel/plugin-transform-modules-commonjs" "^7.16.8" + "@babel/plugin-transform-modules-systemjs" "^7.16.7" + "@babel/plugin-transform-modules-umd" "^7.16.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" + "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-object-super" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-property-literals" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.16.7" + "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-shorthand-properties" "^7.16.7" + "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-sticky-regex" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.16.7" + "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-unicode-escapes" "^7.16.7" + "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.8" + "babel-plugin-polyfill-corejs2" "^0.3.0" + "babel-plugin-polyfill-corejs3" "^0.5.0" + "babel-plugin-polyfill-regenerator" "^0.3.0" + "core-js-compat" "^3.20.2" + "semver" "^6.3.0" + +"@babel/preset-modules@^0.1.5": + "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" + "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + "version" "0.1.5" + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + "esutils" "^2.0.2" + +"@babel/register@^7.11.5": + "integrity" "sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg==" + "resolved" "https://registry.npmjs.org/@babel/register/-/register-7.17.0.tgz" + "version" "7.17.0" + dependencies: + "clone-deep" "^4.0.1" + "find-cache-dir" "^2.0.0" + "make-dir" "^2.1.0" + "pirates" "^4.0.5" + "source-map-support" "^0.5.16" + +"@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4": + "integrity" "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==" + "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz" + "version" "7.17.2" + dependencies: + "regenerator-runtime" "^0.13.4" + +"@babel/template@^7.16.7": + "integrity" "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==" + "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz" + "version" "7.16.7" + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": + "integrity" "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==" + "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz" + "version" "7.17.3" + 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" + +"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.4.4": + "integrity" "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==" + "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" + "version" "7.17.0" + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + "to-fast-properties" "^2.0.0" + +"@chainlink/contracts@^0.2.1": + "integrity" "sha512-hf4b8OEfEqfjC9addvXCrE2SEybNwN1r971vxFYhL/l/yDTTMAk0jmGZYtfUPDOB/qY7FfrOXuxlEVQ+ojZgZw==" + "resolved" "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.3.tgz" + "version" "0.2.3" + +"@ensdomains/ens@^0.4.4": + "integrity" "sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==" + "resolved" "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz" + "version" "0.4.5" + dependencies: + "bluebird" "^3.5.2" + "eth-ens-namehash" "^2.0.8" + "solc" "^0.4.20" + "testrpc" "0.0.1" + "web3-utils" "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + "integrity" "sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA==" + "resolved" "https://registry.npmjs.org/@ensdomains/resolver/-/resolver-0.2.4.tgz" + "version" "0.2.4" + +"@eslint/eslintrc@^0.4.3": + "integrity" "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==" + "resolved" "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" + "version" "0.4.3" + dependencies: + "ajv" "^6.12.4" + "debug" "^4.1.1" + "espree" "^7.3.0" + "globals" "^13.9.0" + "ignore" "^4.0.6" + "import-fresh" "^3.2.1" + "js-yaml" "^3.13.1" + "minimatch" "^3.0.4" + "strip-json-comments" "^3.1.1" + +"@ethereum-waffle/chai@^3.4.0": + "integrity" "sha512-yu1DCuyuEvoQFP9PCbHqiycGxwKUrZ24yc/DsjkBlLAQ3OSLhbmlbMiz804YFymWCNsFmobEATp6kBuUDexo7w==" + "resolved" "https://registry.npmjs.org/@ethereum-waffle/chai/-/chai-3.4.3.tgz" + "version" "3.4.3" + dependencies: + "@ethereum-waffle/provider" "^3.4.1" + "ethers" "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.0": + "integrity" "sha512-a2wxGOoB9F1QFRE+Om7Cz2wn+pxM/o7a0a6cbwhaS2lECJgFzeN9xEkVrKahRkF4gEfXGcuORg4msP0Asxezlw==" + "resolved" "https://registry.npmjs.org/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz" + "version" "3.4.0" + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + "ethers" "^5.0.1" + "mkdirp" "^0.5.1" + "node-fetch" "^2.6.1" + "solc" "^0.6.3" + "ts-generator" "^0.1.1" + "typechain" "^3.0.0" + +"@ethereum-waffle/ens@^3.3.1": + "integrity" "sha512-xSjNWnT2Iwii3J3XGqD+F5yLEOzQzLHNLGfI5KIXdtQ4FHgReW/AMGRgPPLi+n+SP08oEQWJ3sEKrvbFlwJuaA==" + "resolved" "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.3.1.tgz" + "version" "3.3.1" + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + "ethers" "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.3.0": + "integrity" "sha512-h9yChF7IkpJLODg/o9/jlwKwTcXJLSEIq3gewgwUJuBHnhPkJGekcZvsTbximYc+e42QUZrDUATSuTCIryeCEA==" + "resolved" "https://registry.npmjs.org/@ethereum-waffle/mock-contract/-/mock-contract-3.3.1.tgz" + "version" "3.3.1" + dependencies: + "@ethersproject/abi" "^5.5.0" + "ethers" "^5.5.2" + +"@ethereum-waffle/provider@^3.4.0", "@ethereum-waffle/provider@^3.4.1": + "integrity" "sha512-5iDte7c9g9N1rTRE/P4npwk1Hus/wA2yH850X6sP30mr1IrwSG9NKn6/2SOQkAVJnh9jqyLVg2X9xCODWL8G4A==" + "resolved" "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.4.1.tgz" + "version" "3.4.1" + dependencies: + "@ethereum-waffle/ens" "^3.3.1" + "ethers" "^5.5.2" + "ganache-core" "^2.13.2" + "patch-package" "^6.2.2" + "postinstall-postinstall" "^2.1.0" + +"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0", "@ethereumjs/block@^3.6.1": + "integrity" "sha512-o5d/zpGl4SdVfdTfrsq9ZgYMXddc0ucKMiFW5OphBCX+ep4xzYnSjboFcZXT2V/tcSBr84VrKWWp21CGVb3DGw==" + "resolved" "https://registry.npmjs.org/@ethereumjs/block/-/block-3.6.1.tgz" + "version" "3.6.1" + dependencies: + "@ethereumjs/common" "^2.6.1" + "@ethereumjs/tx" "^3.5.0" + "ethereumjs-util" "^7.1.4" + "merkle-patricia-tree" "^4.2.3" + +"@ethereumjs/blockchain@^5.5.0", "@ethereumjs/blockchain@^5.5.1": + "integrity" "sha512-JS2jeKxl3tlaa5oXrZ8mGoVBCz6YqsGG350XVNtHAtNZXKk7pU3rH4xzF2ru42fksMMqzFLzKh9l4EQzmNWDqA==" + "resolved" "https://registry.npmjs.org/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz" + "version" "5.5.1" + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/ethash" "^1.1.0" + "debug" "^2.2.0" + "ethereumjs-util" "^7.1.3" + "level-mem" "^5.0.1" + "lru-cache" "^5.1.1" + "semaphore-async-await" "^1.5.1" + +"@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.0", "@ethereumjs/common@^2.6.1", "@ethereumjs/common@^2.6.2": + "integrity" "sha512-vDwye5v0SVeuDky4MtKsu+ogkH2oFUV8pBKzH/eNBzT8oI91pKa8WyzDuYuxOQsgNgv5R34LfFDh2aaw3H4HbQ==" + "resolved" "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.2.tgz" + "version" "2.6.2" + dependencies: + "crc-32" "^1.2.0" + "ethereumjs-util" "^7.1.4" + +"@ethereumjs/ethash@^1.1.0": + "integrity" "sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA==" + "resolved" "https://registry.npmjs.org/@ethereumjs/ethash/-/ethash-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "@ethereumjs/block" "^3.5.0" + "@types/levelup" "^4.3.0" + "buffer-xor" "^2.0.1" + "ethereumjs-util" "^7.1.1" + "miller-rabin" "^4.0.0" + +"@ethereumjs/tx@^3.2.1", "@ethereumjs/tx@^3.4.0", "@ethereumjs/tx@^3.5.0": + "integrity" "sha512-/+ZNbnJhQhXC83Xuvy6I9k4jT5sXiV0tMR9C+AzSSpcCV64+NB8dTE1m3x98RYMqb8+TLYWA+HML4F5lfXTlJw==" + "resolved" "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.0.tgz" + "version" "3.5.0" + dependencies: + "@ethereumjs/common" "^2.6.1" + "ethereumjs-util" "^7.1.4" + +"@ethereumjs/vm@^5.6.0": + "integrity" "sha512-NiFm5FMaeDGZ9ojBL+Y9Y/xhW6S4Fgez+zPBM402T5kLsfeAR9mrRVckYhvkGVJ6FMwsY820CLjYP5OVwMjLTg==" + "resolved" "https://registry.npmjs.org/@ethereumjs/vm/-/vm-5.7.1.tgz" + "version" "5.7.1" + dependencies: + "@ethereumjs/block" "^3.6.1" + "@ethereumjs/blockchain" "^5.5.1" + "@ethereumjs/common" "^2.6.2" + "@ethereumjs/tx" "^3.5.0" + "async-eventemitter" "^0.2.4" + "core-js-pure" "^3.0.1" + "debug" "^4.3.3" + "ethereumjs-util" "^7.1.4" + "functional-red-black-tree" "^1.0.1" + "mcl-wasm" "^0.7.1" + "merkle-patricia-tree" "^4.2.3" + "rustbn.js" "~0.2.0" + +"@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@5.5.0": + "integrity" "sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w==" + "resolved" "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/abi@5.0.0-beta.153": + "integrity" "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==" + "resolved" "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz" + "version" "5.0.0-beta.153" + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.0.7": + "integrity" "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==" + "resolved" "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz" + "version" "5.0.7" + 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" + +"@ethersproject/abstract-provider@^5.5.0", "@ethersproject/abstract-provider@5.5.1": + "integrity" "sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg==" + "resolved" "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz" + "version" "5.5.1" + 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" + +"@ethersproject/abstract-signer@^5.5.0", "@ethersproject/abstract-signer@5.5.0": + "integrity" "sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA==" + "resolved" "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@5.5.0": + "integrity" "sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw==" + "resolved" "https://registry.npmjs.org/@ethersproject/address/-/address-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/base64@^5.5.0", "@ethersproject/base64@5.5.0": + "integrity" "sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA==" + "resolved" "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + +"@ethersproject/basex@^5.5.0", "@ethersproject/basex@5.5.0": + "integrity" "sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ==" + "resolved" "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@5.5.0": + "integrity" "sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg==" + "resolved" "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "bn.js" "^4.11.9" + +"@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@5.5.0": + "integrity" "sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog==" + "resolved" "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@5.5.0": + "integrity" "sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ==" + "resolved" "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bignumber" "^5.5.0" + +"@ethersproject/contracts@5.5.0": + "integrity" "sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg==" + "resolved" "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@5.5.0": + "integrity" "sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg==" + "resolved" "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/hdnode@^5.5.0", "@ethersproject/hdnode@5.5.0": + "integrity" "sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q==" + "resolved" "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/json-wallets@^5.5.0", "@ethersproject/json-wallets@5.5.0": + "integrity" "sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ==" + "resolved" "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@5.5.0": + "integrity" "sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg==" + "resolved" "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "js-sha3" "0.8.0" + +"@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@5.5.0": + "integrity" "sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg==" + "resolved" "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.5.0.tgz" + "version" "5.5.0" + +"@ethersproject/networks@^5.5.0", "@ethersproject/networks@5.5.2": + "integrity" "sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ==" + "resolved" "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.5.2.tgz" + "version" "5.5.2" + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/pbkdf2@^5.5.0", "@ethersproject/pbkdf2@5.5.0": + "integrity" "sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg==" + "resolved" "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + +"@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@5.5.0": + "integrity" "sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA==" + "resolved" "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/providers@5.5.3": + "integrity" "sha512-ZHXxXXXWHuwCQKrgdpIkbzMNJMvs+9YWemanwp1fA7XZEv7QlilseysPvQe0D7Q7DlkJX/w/bGA1MdgK2TbGvA==" + "resolved" "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.5.3.tgz" + "version" "5.5.3" + 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" + +"@ethersproject/random@^5.5.0", "@ethersproject/random@5.5.1": + "integrity" "sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA==" + "resolved" "https://registry.npmjs.org/@ethersproject/random/-/random-5.5.1.tgz" + "version" "5.5.1" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/rlp@^5.5.0", "@ethersproject/rlp@5.5.0": + "integrity" "sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA==" + "resolved" "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/sha2@^5.5.0", "@ethersproject/sha2@5.5.0": + "integrity" "sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA==" + "resolved" "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "hash.js" "1.1.7" + +"@ethersproject/signing-key@^5.5.0", "@ethersproject/signing-key@5.5.0": + "integrity" "sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng==" + "resolved" "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/solidity@5.5.0": + "integrity" "sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw==" + "resolved" "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@5.5.0": + "integrity" "sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ==" + "resolved" "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0", "@ethersproject/transactions@5.5.0": + "integrity" "sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA==" + "resolved" "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/units@5.5.0": + "integrity" "sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag==" + "resolved" "https://registry.npmjs.org/@ethersproject/units/-/units-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/wallet@5.5.0": + "integrity" "sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q==" + "resolved" "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@ethersproject/web@^5.5.0", "@ethersproject/web@5.5.1": + "integrity" "sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg==" + "resolved" "https://registry.npmjs.org/@ethersproject/web/-/web-5.5.1.tgz" + "version" "5.5.1" + 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" + +"@ethersproject/wordlists@^5.5.0", "@ethersproject/wordlists@5.5.0": + "integrity" "sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q==" + "resolved" "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.5.0.tgz" + "version" "5.5.0" + 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" + +"@humanwhocodes/config-array@^0.5.0": + "integrity" "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==" + "resolved" "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" + "version" "0.5.0" + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + "debug" "^4.1.1" + "minimatch" "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + "integrity" "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "resolved" "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + "version" "1.2.1" + +"@jridgewell/resolve-uri@^3.0.3": + "integrity" "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==" + "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz" + "version" "3.0.5" + +"@jridgewell/sourcemap-codec@^1.4.10": + "integrity" "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" + "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz" + "version" "1.4.11" + +"@jridgewell/trace-mapping@^0.3.0": + "integrity" "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==" + "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz" + "version" "0.3.4" + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@metamask/eth-sig-util@^4.0.0": + "integrity" "sha512-LczOjjxY4A7XYloxzyxJIHONELmUxVZncpOLoClpEcTiebiVdM46KRPYXGuULro9oNNR2xdVx3yoKiQjdfWmoA==" + "resolved" "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ethereumjs-abi" "^0.6.8" + "ethereumjs-util" "^6.2.1" + "ethjs-util" "^0.1.6" + "tweetnacl" "^1.0.3" + "tweetnacl-util" "^0.15.1" + +"@nodelib/fs.scandir@2.1.5": + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" + dependencies: + "@nodelib/fs.stat" "2.0.5" + "run-parallel" "^1.1.9" + +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" + +"@nodelib/fs.walk@^1.2.3": + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" + dependencies: + "@nodelib/fs.scandir" "2.1.5" + "fastq" "^1.6.0" + +"@nomiclabs/hardhat-ethers@^2.0.0": + "integrity" "sha512-A2gZAGB6kUvLx+kzM92HKuUF33F1FSe90L0TmkXkT2Hh0OKRpvWZURUSU2nghD2yC4DzfEZ3DftfeHGvZ2JTUw==" + "resolved" "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.5.tgz" + "version" "2.0.5" + +"@nomiclabs/hardhat-etherscan@^2.1.1": + "integrity" "sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA==" + "resolved" "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz" + "version" "2.1.8" + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + "cbor" "^5.0.2" + "debug" "^4.1.1" + "fs-extra" "^7.0.1" + "node-fetch" "^2.6.0" + "semver" "^6.3.0" + +"@nomiclabs/hardhat-ganache@^2.0.0": + "integrity" "sha512-Q3D8iTtsvQVkJd1EzhhYYvXAFY8fF/JEUt6l6jW7tduhFDRCKvyoSMCw+lH/3nBOHsBolr80pF76NHZ2mYCMeQ==" + "resolved" "https://registry.npmjs.org/@nomiclabs/hardhat-ganache/-/hardhat-ganache-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "debug" "^4.1.1" + "ganache-core" "^2.7.0" + "ts-interface-checker" "^0.1.9" + +"@nomiclabs/hardhat-waffle@^2.0.0": + "integrity" "sha512-dnhry6Bj15O8L3pBksTuXfr4RAUIf+BxRxWJXiu+ioSawcQaOcNF4gfMxn6ik0auk3zrsAJLA6m9vqe87d4xvg==" + "resolved" "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + +"@oclif/command@^1.8.0": + "integrity" "sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w==" + "resolved" "https://registry.npmjs.org/@oclif/command/-/command-1.8.16.tgz" + "version" "1.8.16" + dependencies: + "@oclif/config" "^1.18.2" + "@oclif/errors" "^1.3.5" + "@oclif/help" "^1.0.1" + "@oclif/parser" "^3.8.6" + "debug" "^4.1.1" + "semver" "^7.3.2" + +"@oclif/command@^1.8.15": + "integrity" "sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w==" + "resolved" "https://registry.npmjs.org/@oclif/command/-/command-1.8.16.tgz" + "version" "1.8.16" + dependencies: + "@oclif/config" "^1.18.2" + "@oclif/errors" "^1.3.5" + "@oclif/help" "^1.0.1" + "@oclif/parser" "^3.8.6" + "debug" "^4.1.1" + "semver" "^7.3.2" + +"@oclif/config@^1.17.0", "@oclif/config@^1.18.2": + "integrity" "sha512-sBpko86IrTscc39EvHUhL+c++81BVTsIZ3ETu/vG+cCdi0N6vb2DoahR67A9FI2CGnxRRHjnTfa3m6LulwNATA==" + "resolved" "https://registry.npmjs.org/@oclif/config/-/config-1.18.3.tgz" + "version" "1.18.3" + dependencies: + "@oclif/errors" "^1.3.5" + "@oclif/parser" "^3.8.0" + "debug" "^4.1.1" + "globby" "^11.0.1" + "is-wsl" "^2.1.1" + "tslib" "^2.3.1" + +"@oclif/config@1.18.2": + "integrity" "sha512-cE3qfHWv8hGRCP31j7fIS7BfCflm/BNZ2HNqHexH+fDrdF2f1D5S8VmXWLC77ffv3oDvWyvE9AZeR0RfmHCCaA==" + "resolved" "https://registry.npmjs.org/@oclif/config/-/config-1.18.2.tgz" + "version" "1.18.2" + dependencies: + "@oclif/errors" "^1.3.3" + "@oclif/parser" "^3.8.0" + "debug" "^4.1.1" + "globby" "^11.0.1" + "is-wsl" "^2.1.1" + "tslib" "^2.0.0" + +"@oclif/errors@^1.3.3", "@oclif/errors@^1.3.5", "@oclif/errors@1.3.5": + "integrity" "sha512-OivucXPH/eLLlOT7FkCMoZXiaVYf8I/w1eTAM1+gKzfhALwWTusxEx7wBmW0uzvkSg/9ovWLycPaBgJbM3LOCQ==" + "resolved" "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.5.tgz" + "version" "1.3.5" + dependencies: + "clean-stack" "^3.0.0" + "fs-extra" "^8.1" + "indent-string" "^4.0.0" + "strip-ansi" "^6.0.0" + "wrap-ansi" "^7.0.0" + +"@oclif/help@^1.0.1": + "integrity" "sha512-8rsl4RHL5+vBUAKBL6PFI3mj58hjPCp2VYyXD4TAa7IMStikFfOH2gtWmqLzIlxAED2EpD0dfYwo9JJxYsH7Aw==" + "resolved" "https://registry.npmjs.org/@oclif/help/-/help-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "@oclif/config" "1.18.2" + "@oclif/errors" "1.3.5" + "chalk" "^4.1.2" + "indent-string" "^4.0.0" + "lodash" "^4.17.21" + "string-width" "^4.2.0" + "strip-ansi" "^6.0.0" + "widest-line" "^3.1.0" + "wrap-ansi" "^6.2.0" + +"@oclif/linewrap@^1.0.0": + "integrity" "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==" + "resolved" "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz" + "version" "1.0.0" + +"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.6": + "integrity" "sha512-b11xBmIUK+LuuwVGJpFs4LwQN2xj2cBWj2c4z1FtiXGrJ85h9xV6q+k136Hw0tGg1jQoRXuvuBnqQ7es7vO9/Q==" + "resolved" "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.7.tgz" + "version" "3.8.7" + dependencies: + "@oclif/errors" "^1.3.5" + "@oclif/linewrap" "^1.0.0" + "chalk" "^4.1.0" + "tslib" "^2.3.1" + +"@oclif/plugin-help@^3.2.0": + "integrity" "sha512-QuSiseNRJygaqAdABYFWn/H1CwIZCp9zp/PLid6yXvy6VcQV7OenEFF5XuYaCvSARe2Tg9r8Jqls5+fw1A9CbQ==" + "resolved" "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.3.1.tgz" + "version" "3.3.1" + dependencies: + "@oclif/command" "^1.8.15" + "@oclif/config" "1.18.2" + "@oclif/errors" "1.3.5" + "@oclif/help" "^1.0.1" + "chalk" "^4.1.2" + "indent-string" "^4.0.0" + "lodash" "^4.17.21" + "string-width" "^4.2.0" + "strip-ansi" "^6.0.0" + "widest-line" "^3.1.0" + "wrap-ansi" "^6.2.0" + +"@openzeppelin/contracts-upgradeable@^4.5.1": + "integrity" "sha512-xcKycsSyFauIGMhSeeTJW/Jzz9jZUJdiFNP9Wo/9VhMhw8t5X0M92RY6x176VfcIWsxURMHFWOJVTlFA78HI/w==" + "resolved" "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.1.tgz" + "version" "4.5.1" + +"@openzeppelin/contracts@^4.3.1": + "integrity" "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==" + "resolved" "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz" + "version" "4.5.0" + +"@resolver-engine/core@^0.3.3": + "integrity" "sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ==" + "resolved" "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz" + "version" "0.3.3" + dependencies: + "debug" "^3.1.0" + "is-url" "^1.2.4" + "request" "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + "integrity" "sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ==" + "resolved" "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.3.3.tgz" + "version" "0.3.3" + dependencies: + "@resolver-engine/core" "^0.3.3" + "debug" "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + "integrity" "sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA==" + "resolved" "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz" + "version" "0.3.3" + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + "debug" "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + "integrity" "sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q==" + "resolved" "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.3.3.tgz" + "version" "0.3.3" + dependencies: + "@resolver-engine/core" "^0.3.3" + "debug" "^3.1.0" + "hosted-git-info" "^2.6.0" + "path-browserify" "^1.0.0" + "url" "^0.11.0" + +"@sentry/core@5.30.0": + "integrity" "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==" + "resolved" "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + "tslib" "^1.9.3" + +"@sentry/hub@5.30.0": + "integrity" "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==" + "resolved" "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + "tslib" "^1.9.3" + +"@sentry/minimal@5.30.0": + "integrity" "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==" + "resolved" "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + "tslib" "^1.9.3" + +"@sentry/node@^5.18.1": + "integrity" "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==" + "resolved" "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + "cookie" "^0.4.1" + "https-proxy-agent" "^5.0.0" + "lru_map" "^0.3.3" + "tslib" "^1.9.3" + +"@sentry/tracing@5.30.0": + "integrity" "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==" + "resolved" "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + "tslib" "^1.9.3" + +"@sentry/types@5.30.0": + "integrity" "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==" + "resolved" "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz" + "version" "5.30.0" + +"@sentry/utils@5.30.0": + "integrity" "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==" + "resolved" "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz" + "version" "5.30.0" + dependencies: + "@sentry/types" "5.30.0" + "tslib" "^1.9.3" + +"@sindresorhus/is@^0.14.0": + "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + "version" "0.14.0" + +"@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": + "integrity" "sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw==" + "resolved" "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.1.tgz" + "version" "0.14.1" + dependencies: + "antlr4ts" "^0.5.0-alpha.4" + +"@szmarczak/http-timer@^1.1.2": + "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" + "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "defer-to-connect" "^1.0.1" + +"@truffle/error@^0.1.0": + "integrity" "sha512-RbUfp5VreNhsa2Q4YbBjz18rOQI909pG32bghl1hulO7IpvcqTS+C3Ge5cNbiWQ1WGzy1wIeKLW0tmQtHFB7qg==" + "resolved" "https://registry.npmjs.org/@truffle/error/-/error-0.1.0.tgz" + "version" "0.1.0" + +"@truffle/interface-adapter@^0.5.11": + "integrity" "sha512-HXLm+r1KdT8nHzJht1iK6EnHBKIjSYHdDfebBMCqmRCsMoUXvUJ0KsIxvDG758MafB12pjx5gsNn4XzzfksSBQ==" + "resolved" "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.5.11.tgz" + "version" "0.5.11" + dependencies: + "bn.js" "^5.1.3" + "ethers" "^4.0.32" + "web3" "1.5.3" + +"@truffle/provider@^0.2.24": + "integrity" "sha512-Y9VRLsdMcfEicZjxxcwA0y9pqnwJx0JX/UDeHDHZmymx3KIJwI3VpxRPighfHAmvDRksic6Yj4iL0CmiEDR5kg==" + "resolved" "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.47.tgz" + "version" "0.2.47" + dependencies: + "@truffle/error" "^0.1.0" + "@truffle/interface-adapter" "^0.5.11" + "web3" "1.5.3" + +"@typechain/ethers-v5@^2.0.0": + "integrity" "sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw==" + "resolved" "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ethers" "^5.0.2" + +"@types/abstract-leveldown@*": + "integrity" "sha512-q5veSX6zjUy/DlDhR4Y4cU0k2Ar+DT2LUraP00T19WLmTO6Se1djepCCaqU6nQrwcJ5Hyo/CWqxTzrrFg8eqbQ==" + "resolved" "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz" + "version" "7.2.0" + +"@types/bn.js@*": + "integrity" "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==" + "resolved" "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + "integrity" "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==" + "resolved" "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz" + "version" "4.11.6" + dependencies: + "@types/node" "*" + +"@types/bn.js@^5.1.0": + "integrity" "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==" + "resolved" "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "@types/node" "*" + +"@types/chai@*": + "integrity" "sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==" + "resolved" "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz" + "version" "4.3.0" + +"@types/concat-stream@^1.6.0": + "integrity" "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==" + "resolved" "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz" + "version" "1.6.1" + dependencies: + "@types/node" "*" + +"@types/form-data@0.0.33": + "integrity" "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=" + "resolved" "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz" + "version" "0.0.33" + dependencies: + "@types/node" "*" + +"@types/glob@^7.1.1": + "integrity" "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==" + "resolved" "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/json5@^0.0.29": + "integrity" "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + "resolved" "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" + "version" "0.0.29" + +"@types/level-errors@*": + "integrity" "sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ==" + "resolved" "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz" + "version" "3.0.0" + +"@types/levelup@^4.3.0": + "integrity" "sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA==" + "resolved" "https://registry.npmjs.org/@types/levelup/-/levelup-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "@types/abstract-leveldown" "*" + "@types/level-errors" "*" + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + "integrity" "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + "resolved" "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + +"@types/minimatch@*": + "integrity" "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + "resolved" "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" + "version" "3.0.5" + +"@types/mkdirp@^0.5.2": + "integrity" "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==" + "resolved" "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "@types/node" "*" + +"@types/mocha@^9.1.0": + "integrity" "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==" + "resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz" + "version" "9.1.0" + +"@types/node-fetch@^2.5.5": + "integrity" "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==" + "resolved" "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz" + "version" "2.6.1" + dependencies: + "@types/node" "*" + "form-data" "^3.0.0" + +"@types/node@*": + "integrity" "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz" + "version" "17.0.21" + +"@types/node@^10.0.3": + "integrity" "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz" + "version" "10.17.60" + +"@types/node@^12.12.6": + "integrity" "sha512-cPjLXj8d6anFPzFvOPxS3fvly3Shm5nTfl6g8X5smexixbuGUf7hfr21J5tX9JW+UPStp/5P5R8qrKL5IyVJ+A==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-12.20.46.tgz" + "version" "12.20.46" + +"@types/node@^8.0.0": + "integrity" "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz" + "version" "8.10.66" + +"@types/parse-json@^4.0.0": + "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "resolved" "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" + +"@types/pbkdf2@^3.0.0": + "integrity" "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==" + "resolved" "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1": + "integrity" "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==" + "resolved" "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz" + "version" "2.4.4" + +"@types/qs@^6.2.31": + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"@types/resolve@^0.0.8": + "integrity" "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==" + "resolved" "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz" + "version" "0.0.8" + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + "integrity" "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==" + "resolved" "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "@types/node" "*" + +"@types/sinon-chai@^3.2.3": + "integrity" "sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g==" + "resolved" "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.8.tgz" + "version" "3.2.8" + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + "integrity" "sha512-dmZsHlBsKUtBpHriNjlK0ndlvEh8dcb9uV9Afsbt89QIyydpC7NcR+nWlAhASfy3GHnxTl4FX/aKE7XZUt/B4g==" + "resolved" "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.11.tgz" + "version" "10.0.11" + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + "integrity" "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==" + "resolved" "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz" + "version" "8.1.1" + +"@types/underscore@*": + "integrity" "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg==" + "resolved" "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz" + "version" "1.11.4" + +"@types/web3@1.0.19": + "integrity" "sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A==" + "resolved" "https://registry.npmjs.org/@types/web3/-/web3-1.0.19.tgz" + "version" "1.0.19" + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + +"@ungap/promise-all-settled@1.1.2": + "integrity" "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" + "resolved" "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + "version" "1.1.2" + +"@uniswap/lib@^1.1.4": + "integrity" "sha512-5una/3a2dPzPN0moDBsa9LfTxCjZjEiLEkN75wjwplmDU4oFqneVAzVA3Heq+DadEk3k17cszAbSMcaIu7hLfg==" + "resolved" "https://registry.npmjs.org/@uniswap/lib/-/lib-1.1.4.tgz" + "version" "1.1.4" + +"@uniswap/lib@1.1.1": + "integrity" "sha512-2yK7sLpKIT91TiS5sewHtOa7YuM8IuBXVl4GZv2jZFys4D2sY7K5vZh6MqD25TPA95Od+0YzCVq6cTF2IKrOmg==" + "resolved" "https://registry.npmjs.org/@uniswap/lib/-/lib-1.1.1.tgz" + "version" "1.1.1" + +"@uniswap/v2-core@^1.0.1": + "integrity" "sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q==" + "resolved" "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.1.tgz" + "version" "1.0.1" + +"@uniswap/v2-core@1.0.0": + "integrity" "sha512-BJiXrBGnN8mti7saW49MXwxDBRFiWemGetE58q8zgfnPPzQKq55ADltEILqOt6VFZ22kVeVKbF8gVd8aY3l7pA==" + "resolved" "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.0.tgz" + "version" "1.0.0" + +"@uniswap/v2-periphery@^1.1.0-beta.0": + "integrity" "sha512-6dkwAMKza8nzqYiXEr2D86dgW3TTavUvCR0w2Tu33bAbM8Ah43LKAzH7oKKPRT5VJQaMi1jtkGs1E8JPor1n5g==" + "resolved" "https://registry.npmjs.org/@uniswap/v2-periphery/-/v2-periphery-1.1.0-beta.0.tgz" + "version" "1.1.0-beta.0" + dependencies: + "@uniswap/lib" "1.1.1" + "@uniswap/v2-core" "1.0.0" + +"@yarnpkg/lockfile@^1.1.0": + "integrity" "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + "resolved" "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" + "version" "1.1.0" + +"abbrev@1.0.x": + "integrity" "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + "resolved" "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + "version" "1.0.9" + +"abbrev@1": + "integrity" "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "resolved" "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + "version" "1.1.1" + +"abort-controller@^3.0.0": + "integrity" "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==" + "resolved" "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "event-target-shim" "^5.0.0" + +"abstract-leveldown@^2.4.1": + "integrity" "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz" + "version" "2.7.2" + dependencies: + "xtend" "~4.0.0" + +"abstract-leveldown@^5.0.0", "abstract-leveldown@~5.0.0": + "integrity" "sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "xtend" "~4.0.0" + +"abstract-leveldown@^6.2.1": + "integrity" "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz" + "version" "6.3.0" + dependencies: + "buffer" "^5.5.0" + "immediate" "^3.2.3" + "level-concat-iterator" "~2.0.0" + "level-supports" "~1.0.0" + "xtend" "~4.0.0" + +"abstract-leveldown@~2.6.0": + "integrity" "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz" + "version" "2.6.3" + dependencies: + "xtend" "~4.0.0" + +"abstract-leveldown@~2.7.1": + "integrity" "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz" + "version" "2.7.2" + dependencies: + "xtend" "~4.0.0" + +"abstract-leveldown@~6.2.1": + "integrity" "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz" + "version" "6.2.3" + dependencies: + "buffer" "^5.5.0" + "immediate" "^3.2.3" + "level-concat-iterator" "~2.0.0" + "level-supports" "~1.0.0" + "xtend" "~4.0.0" + +"abstract-leveldown@3.0.0": + "integrity" "sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ==" + "resolved" "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "xtend" "~4.0.0" + +"accepts@~1.3.8": + "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" + "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + "version" "1.3.8" + dependencies: + "mime-types" "~2.1.34" + "negotiator" "0.6.3" + +"acorn-jsx@^5.3.1": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^7.4.0": + "integrity" "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + "version" "7.4.1" + +"address@^1.0.1": + "integrity" "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + "resolved" "https://registry.npmjs.org/address/-/address-1.1.2.tgz" + "version" "1.1.2" + +"adm-zip@^0.4.16": + "integrity" "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==" + "resolved" "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz" + "version" "0.4.16" + +"aes-js@^3.1.1": + "integrity" "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" + "resolved" "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz" + "version" "3.1.2" + +"aes-js@3.0.0": + "integrity" "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + "resolved" "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" + "version" "3.0.0" + +"agent-base@6": + "integrity" "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==" + "resolved" "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "debug" "4" + +"aggregate-error@^3.0.0": + "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" + "resolved" "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "clean-stack" "^2.0.0" + "indent-string" "^4.0.0" + +"ajv@^6.10.0", "ajv@^6.12.3", "ajv@^6.12.4": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + 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" + +"ajv@^8.0.1": + "integrity" "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz" + "version" "8.10.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"amdefine@>=0.0.4": + "integrity" "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "resolved" "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + "version" "1.0.1" + +"ansi-colors@^4.1.1": + "integrity" "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + "version" "4.1.1" + +"ansi-colors@3.2.3": + "integrity" "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" + "version" "3.2.3" + +"ansi-colors@4.1.1": + "integrity" "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + "version" "4.1.1" + +"ansi-escapes@^4.3.0": + "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==" + "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + "version" "4.3.2" + dependencies: + "type-fest" "^0.21.3" + +"ansi-regex@^2.0.0": + "integrity" "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + "version" "2.1.1" + +"ansi-regex@^3.0.0": + "integrity" "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz" + "version" "3.0.0" + +"ansi-regex@^4.1.0": + "integrity" "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" + "version" "4.1.0" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-styles@^2.2.1": + "integrity" "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + "version" "2.2.1" + +"ansi-styles@^3.2.0": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"antlr4ts@^0.5.0-alpha.4": + "integrity" "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" + "resolved" "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz" + "version" "0.5.0-alpha.4" + +"anymatch@~3.1.1", "anymatch@~3.1.2": + "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" + "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"argparse@^1.0.7": + "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "sprintf-js" "~1.0.2" + +"argparse@^2.0.1": + "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + "version" "2.0.1" + +"arr-diff@^4.0.0": + "integrity" "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "resolved" "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" + "version" "4.0.0" + +"arr-flatten@^1.1.0": + "integrity" "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "resolved" "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" + "version" "1.1.0" + +"arr-union@^3.1.0": + "integrity" "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "resolved" "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" + "version" "3.1.0" + +"array-back@^1.0.3", "array-back@^1.0.4": + "integrity" "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=" + "resolved" "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "typical" "^2.6.0" + +"array-back@^2.0.0": + "integrity" "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==" + "resolved" "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "typical" "^2.6.1" + +"array-flatten@1.1.1": + "integrity" "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "version" "1.1.1" + +"array-includes@^3.1.4": + "integrity" "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==" + "resolved" "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz" + "version" "3.1.4" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + "get-intrinsic" "^1.1.1" + "is-string" "^1.0.7" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"array-uniq@1.0.3": + "integrity" "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "resolved" "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + "version" "1.0.3" + +"array-unique@^0.3.2": + "integrity" "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "resolved" "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" + "version" "0.3.2" + +"array.prototype.flat@^1.2.5": + "integrity" "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==" + "resolved" "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz" + "version" "1.2.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.0" + +"asap@~2.0.6": + "integrity" "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + "version" "2.0.6" + +"asn1.js@^5.2.0": + "integrity" "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==" + "resolved" "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" + "version" "5.4.1" + dependencies: + "bn.js" "^4.0.0" + "inherits" "^2.0.1" + "minimalistic-assert" "^1.0.0" + "safer-buffer" "^2.1.0" + +"asn1@~0.2.3": + "integrity" "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==" + "resolved" "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" + "version" "0.2.6" + dependencies: + "safer-buffer" "~2.1.0" + +"assert-plus@^1.0.0", "assert-plus@1.0.0": + "integrity" "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "resolved" "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "version" "1.0.0" + +"assertion-error@^1.1.0": + "integrity" "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + "resolved" "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + "version" "1.1.0" + +"assign-symbols@^1.0.0": + "integrity" "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "resolved" "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" + "version" "1.0.0" + +"astral-regex@^2.0.0": + "integrity" "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "resolved" "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + "version" "2.0.0" + +"async-eventemitter@^0.2.2", "async-eventemitter@^0.2.4": + "integrity" "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==" + "resolved" "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz" + "version" "0.2.4" + dependencies: + "async" "^2.4.0" + +"async-limiter@~1.0.0": + "integrity" "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + "resolved" "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" + "version" "1.0.1" + +"async@^1.4.2": + "integrity" "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "resolved" "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + "version" "1.5.2" + +"async@^2.0.1", "async@^2.1.2", "async@^2.4.0", "async@^2.5.0", "async@^2.6.1": + "integrity" "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==" + "resolved" "https://registry.npmjs.org/async/-/async-2.6.3.tgz" + "version" "2.6.3" + dependencies: + "lodash" "^4.17.14" + +"async@1.x": + "integrity" "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "resolved" "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + "version" "1.5.2" + +"async@2.6.2": + "integrity" "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==" + "resolved" "https://registry.npmjs.org/async/-/async-2.6.2.tgz" + "version" "2.6.2" + dependencies: + "lodash" "^4.17.11" + +"asynckit@^0.4.0": + "integrity" "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "resolved" "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + "version" "0.4.0" + +"atob@^2.1.2": + "integrity" "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "resolved" "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + "version" "2.1.2" + +"available-typed-arrays@^1.0.5": + "integrity" "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + "resolved" "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" + "version" "1.0.5" + +"aws-sign2@~0.7.0": + "integrity" "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "resolved" "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" + "version" "0.7.0" + +"aws4@^1.8.0": + "integrity" "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "resolved" "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" + "version" "1.11.0" + +"axios@^0.21.1": + "integrity" "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" + "version" "0.21.4" + dependencies: + "follow-redirects" "^1.14.0" + +"babel-code-frame@^6.26.0": + "integrity" "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=" + "resolved" "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "chalk" "^1.1.3" + "esutils" "^2.0.2" + "js-tokens" "^3.0.2" + +"babel-core@^6.0.14", "babel-core@^6.26.0": + "integrity" "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==" + "resolved" "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz" + "version" "6.26.3" + dependencies: + "babel-code-frame" "^6.26.0" + "babel-generator" "^6.26.0" + "babel-helpers" "^6.24.1" + "babel-messages" "^6.23.0" + "babel-register" "^6.26.0" + "babel-runtime" "^6.26.0" + "babel-template" "^6.26.0" + "babel-traverse" "^6.26.0" + "babel-types" "^6.26.0" + "babylon" "^6.18.0" + "convert-source-map" "^1.5.1" + "debug" "^2.6.9" + "json5" "^0.5.1" + "lodash" "^4.17.4" + "minimatch" "^3.0.4" + "path-is-absolute" "^1.0.1" + "private" "^0.1.8" + "slash" "^1.0.0" + "source-map" "^0.5.7" + +"babel-generator@^6.26.0": + "integrity" "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==" + "resolved" "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz" + "version" "6.26.1" + 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" + +"babel-helper-builder-binary-assignment-operator-visitor@^6.24.1": + "integrity" "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=" + "resolved" "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-explode-assignable-expression" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-helper-call-delegate@^6.24.1": + "integrity" "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=" + "resolved" "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-hoist-variables" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-helper-define-map@^6.24.1": + "integrity" "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=" + "resolved" "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-helper-function-name" "^6.24.1" + "babel-runtime" "^6.26.0" + "babel-types" "^6.26.0" + "lodash" "^4.17.4" + +"babel-helper-explode-assignable-expression@^6.24.1": + "integrity" "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=" + "resolved" "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-helper-function-name@^6.24.1": + "integrity" "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=" + "resolved" "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-get-function-arity" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-helper-get-function-arity@^6.24.1": + "integrity" "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=" + "resolved" "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-helper-hoist-variables@^6.24.1": + "integrity" "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=" + "resolved" "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-helper-optimise-call-expression@^6.24.1": + "integrity" "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=" + "resolved" "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-helper-regex@^6.24.1": + "integrity" "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=" + "resolved" "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-runtime" "^6.26.0" + "babel-types" "^6.26.0" + "lodash" "^4.17.4" + +"babel-helper-remap-async-to-generator@^6.24.1": + "integrity" "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=" + "resolved" "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-function-name" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-helper-replace-supers@^6.24.1": + "integrity" "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=" + "resolved" "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-optimise-call-expression" "^6.24.1" + "babel-messages" "^6.23.0" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-helpers@^6.24.1": + "integrity" "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=" + "resolved" "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + +"babel-messages@^6.23.0": + "integrity" "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=" + "resolved" "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz" + "version" "6.23.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-check-es2015-constants@^6.22.0": + "integrity" "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=" + "resolved" "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-dynamic-import-node@^2.3.3": + "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + "version" "2.3.3" + dependencies: + "object.assign" "^4.1.0" + +"babel-plugin-polyfill-corejs2@^0.3.0": + "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + "semver" "^6.1.1" + +"babel-plugin-polyfill-corejs3@^0.5.0": + "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + "core-js-compat" "^3.21.0" + +"babel-plugin-polyfill-regenerator@^0.3.0": + "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + +"babel-plugin-syntax-async-functions@^6.8.0": + "integrity" "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + "resolved" "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz" + "version" "6.13.0" + +"babel-plugin-syntax-exponentiation-operator@^6.8.0": + "integrity" "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + "resolved" "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz" + "version" "6.13.0" + +"babel-plugin-syntax-trailing-function-commas@^6.22.0": + "integrity" "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + "resolved" "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz" + "version" "6.22.0" + +"babel-plugin-transform-async-to-generator@^6.22.0": + "integrity" "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-remap-async-to-generator" "^6.24.1" + "babel-plugin-syntax-async-functions" "^6.8.0" + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-arrow-functions@^6.22.0": + "integrity" "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-block-scoped-functions@^6.22.0": + "integrity" "sha1-u8UbSflk1wy42OC5ToICRs46YUE=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-block-scoping@^6.23.0": + "integrity" "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-runtime" "^6.26.0" + "babel-template" "^6.26.0" + "babel-traverse" "^6.26.0" + "babel-types" "^6.26.0" + "lodash" "^4.17.4" + +"babel-plugin-transform-es2015-classes@^6.23.0": + "integrity" "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-define-map" "^6.24.1" + "babel-helper-function-name" "^6.24.1" + "babel-helper-optimise-call-expression" "^6.24.1" + "babel-helper-replace-supers" "^6.24.1" + "babel-messages" "^6.23.0" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-computed-properties@^6.22.0": + "integrity" "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + +"babel-plugin-transform-es2015-destructuring@^6.23.0": + "integrity" "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz" + "version" "6.23.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-duplicate-keys@^6.22.0": + "integrity" "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-for-of@^6.23.0": + "integrity" "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz" + "version" "6.23.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-function-name@^6.22.0": + "integrity" "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-function-name" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-literals@^6.22.0": + "integrity" "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-modules-amd@^6.22.0", "babel-plugin-transform-es2015-modules-amd@^6.24.1": + "integrity" "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-plugin-transform-es2015-modules-commonjs" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + +"babel-plugin-transform-es2015-modules-commonjs@^6.23.0", "babel-plugin-transform-es2015-modules-commonjs@^6.24.1": + "integrity" "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz" + "version" "6.26.2" + dependencies: + "babel-plugin-transform-strict-mode" "^6.24.1" + "babel-runtime" "^6.26.0" + "babel-template" "^6.26.0" + "babel-types" "^6.26.0" + +"babel-plugin-transform-es2015-modules-systemjs@^6.23.0": + "integrity" "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-hoist-variables" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + +"babel-plugin-transform-es2015-modules-umd@^6.23.0": + "integrity" "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-plugin-transform-es2015-modules-amd" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + +"babel-plugin-transform-es2015-object-super@^6.22.0": + "integrity" "sha1-JM72muIcuDp/hgPa0CH1cusnj40=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-replace-supers" "^6.24.1" + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-parameters@^6.23.0": + "integrity" "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-call-delegate" "^6.24.1" + "babel-helper-get-function-arity" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-template" "^6.24.1" + "babel-traverse" "^6.24.1" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-shorthand-properties@^6.22.0": + "integrity" "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-spread@^6.22.0": + "integrity" "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-sticky-regex@^6.22.0": + "integrity" "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-regex" "^6.24.1" + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-plugin-transform-es2015-template-literals@^6.22.0": + "integrity" "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz" + "version" "6.22.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-typeof-symbol@^6.23.0": + "integrity" "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz" + "version" "6.23.0" + dependencies: + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-es2015-unicode-regex@^6.22.0": + "integrity" "sha1-04sS9C6nMj9yk4fxinxa4frrNek=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-regex" "^6.24.1" + "babel-runtime" "^6.22.0" + "regexpu-core" "^2.0.0" + +"babel-plugin-transform-exponentiation-operator@^6.22.0": + "integrity" "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-helper-builder-binary-assignment-operator-visitor" "^6.24.1" + "babel-plugin-syntax-exponentiation-operator" "^6.8.0" + "babel-runtime" "^6.22.0" + +"babel-plugin-transform-regenerator@^6.22.0": + "integrity" "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "regenerator-transform" "^0.10.0" + +"babel-plugin-transform-strict-mode@^6.24.1": + "integrity" "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz" + "version" "6.24.1" + dependencies: + "babel-runtime" "^6.22.0" + "babel-types" "^6.24.1" + +"babel-preset-env@^1.7.0": + "integrity" "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==" + "resolved" "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "babel-plugin-check-es2015-constants" "^6.22.0" + "babel-plugin-syntax-trailing-function-commas" "^6.22.0" + "babel-plugin-transform-async-to-generator" "^6.22.0" + "babel-plugin-transform-es2015-arrow-functions" "^6.22.0" + "babel-plugin-transform-es2015-block-scoped-functions" "^6.22.0" + "babel-plugin-transform-es2015-block-scoping" "^6.23.0" + "babel-plugin-transform-es2015-classes" "^6.23.0" + "babel-plugin-transform-es2015-computed-properties" "^6.22.0" + "babel-plugin-transform-es2015-destructuring" "^6.23.0" + "babel-plugin-transform-es2015-duplicate-keys" "^6.22.0" + "babel-plugin-transform-es2015-for-of" "^6.23.0" + "babel-plugin-transform-es2015-function-name" "^6.22.0" + "babel-plugin-transform-es2015-literals" "^6.22.0" + "babel-plugin-transform-es2015-modules-amd" "^6.22.0" + "babel-plugin-transform-es2015-modules-commonjs" "^6.23.0" + "babel-plugin-transform-es2015-modules-systemjs" "^6.23.0" + "babel-plugin-transform-es2015-modules-umd" "^6.23.0" + "babel-plugin-transform-es2015-object-super" "^6.22.0" + "babel-plugin-transform-es2015-parameters" "^6.23.0" + "babel-plugin-transform-es2015-shorthand-properties" "^6.22.0" + "babel-plugin-transform-es2015-spread" "^6.22.0" + "babel-plugin-transform-es2015-sticky-regex" "^6.22.0" + "babel-plugin-transform-es2015-template-literals" "^6.22.0" + "babel-plugin-transform-es2015-typeof-symbol" "^6.23.0" + "babel-plugin-transform-es2015-unicode-regex" "^6.22.0" + "babel-plugin-transform-exponentiation-operator" "^6.22.0" + "babel-plugin-transform-regenerator" "^6.22.0" + "browserslist" "^3.2.6" + "invariant" "^2.2.2" + "semver" "^5.3.0" + +"babel-register@^6.26.0": + "integrity" "sha1-btAhFz4vy0htestFxgCahW9kcHE=" + "resolved" "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-core" "^6.26.0" + "babel-runtime" "^6.26.0" + "core-js" "^2.5.0" + "home-or-tmp" "^2.0.0" + "lodash" "^4.17.4" + "mkdirp" "^0.5.1" + "source-map-support" "^0.4.15" + +"babel-runtime@^6.18.0", "babel-runtime@^6.22.0", "babel-runtime@^6.26.0": + "integrity" "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=" + "resolved" "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "core-js" "^2.4.0" + "regenerator-runtime" "^0.11.0" + +"babel-template@^6.24.1", "babel-template@^6.26.0": + "integrity" "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=" + "resolved" "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-runtime" "^6.26.0" + "babel-traverse" "^6.26.0" + "babel-types" "^6.26.0" + "babylon" "^6.18.0" + "lodash" "^4.17.4" + +"babel-traverse@^6.24.1", "babel-traverse@^6.26.0": + "integrity" "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=" + "resolved" "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz" + "version" "6.26.0" + 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" + +"babel-types@^6.19.0", "babel-types@^6.24.1", "babel-types@^6.26.0": + "integrity" "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=" + "resolved" "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz" + "version" "6.26.0" + dependencies: + "babel-runtime" "^6.26.0" + "esutils" "^2.0.2" + "lodash" "^4.17.4" + "to-fast-properties" "^1.0.3" + +"babelify@^7.3.0": + "integrity" "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=" + "resolved" "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz" + "version" "7.3.0" + dependencies: + "babel-core" "^6.0.14" + "object-assign" "^4.0.0" + +"babylon@^6.18.0": + "integrity" "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + "resolved" "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz" + "version" "6.18.0" + +"backoff@^2.5.0": + "integrity" "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=" + "resolved" "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "precond" "0.2" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"base-x@^3.0.2", "base-x@^3.0.8": + "integrity" "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==" + "resolved" "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz" + "version" "3.0.9" + dependencies: + "safe-buffer" "^5.0.1" + +"base@^0.11.1": + "integrity" "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==" + "resolved" "https://registry.npmjs.org/base/-/base-0.11.2.tgz" + "version" "0.11.2" + dependencies: + "cache-base" "^1.0.1" + "class-utils" "^0.3.5" + "component-emitter" "^1.2.1" + "define-property" "^1.0.0" + "isobject" "^3.0.1" + "mixin-deep" "^1.2.0" + "pascalcase" "^0.1.1" + +"base64-js@^1.3.1": + "integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "resolved" "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + "version" "1.5.1" + +"bcrypt-pbkdf@^1.0.0": + "integrity" "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=" + "resolved" "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "tweetnacl" "^0.14.3" + +"bech32@1.1.4": + "integrity" "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "resolved" "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" + "version" "1.1.4" + +"bignumber.js@^9.0.0", "bignumber.js@^9.0.1": + "integrity" "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + "resolved" "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz" + "version" "9.0.2" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"bindings@^1.5.0": + "integrity" "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==" + "resolved" "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" + "version" "1.5.0" + dependencies: + "file-uri-to-path" "1.0.0" + +"bip39@2.5.0": + "integrity" "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==" + "resolved" "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "create-hash" "^1.1.0" + "pbkdf2" "^3.0.9" + "randombytes" "^2.0.1" + "safe-buffer" "^5.0.1" + "unorm" "^1.3.3" + +"bip66@^1.1.5": + "integrity" "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=" + "resolved" "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "safe-buffer" "^5.0.1" + +"blakejs@^1.1.0": + "integrity" "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==" + "resolved" "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz" + "version" "1.1.1" + +"bluebird@^3.5.0", "bluebird@^3.5.2": + "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + "version" "3.7.2" + +"bn.js@^4.0.0", "bn.js@^4.1.0", "bn.js@^4.10.0", "bn.js@^4.11.0", "bn.js@^4.11.6", "bn.js@^4.11.8", "bn.js@^4.11.9", "bn.js@^4.8.0": + "integrity" "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + "version" "4.12.0" + +"bn.js@^5.0.0": + "integrity" "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + "version" "5.2.0" + +"bn.js@^5.1.1": + "integrity" "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + "version" "5.2.0" + +"bn.js@^5.1.2": + "integrity" "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + "version" "5.2.0" + +"bn.js@^5.1.3": + "integrity" "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + "version" "5.2.0" + +"bn.js@^5.2.0": + "integrity" "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" + "version" "5.2.0" + +"bn.js@4.11.6": + "integrity" "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" + "version" "4.11.6" + +"body-parser@^1.16.0", "body-parser@1.19.2": + "integrity" "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==" + "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" + dependencies: + "bytes" "3.1.2" + "content-type" "~1.0.4" + "debug" "2.6.9" + "depd" "~1.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "on-finished" "~2.3.0" + "qs" "6.9.7" + "raw-body" "2.4.3" + "type-is" "~1.6.18" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^2.3.1": + "integrity" "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==" + "resolved" "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" + "version" "2.3.2" + dependencies: + "arr-flatten" "^1.1.0" + "array-unique" "^0.3.2" + "extend-shallow" "^2.0.1" + "fill-range" "^4.0.0" + "isobject" "^3.0.1" + "repeat-element" "^1.1.2" + "snapdragon" "^0.8.1" + "snapdragon-node" "^2.0.1" + "split-string" "^3.0.2" + "to-regex" "^3.0.1" + +"braces@^3.0.1", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"brorand@^1.0.1", "brorand@^1.1.0": + "integrity" "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "resolved" "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + "version" "1.1.0" + +"browser-stdout@1.3.1": + "integrity" "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "resolved" "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + "version" "1.3.1" + +"browserify-aes@^1.0.0", "browserify-aes@^1.0.4", "browserify-aes@^1.0.6", "browserify-aes@^1.2.0": + "integrity" "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==" + "resolved" "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "buffer-xor" "^1.0.3" + "cipher-base" "^1.0.0" + "create-hash" "^1.1.0" + "evp_bytestokey" "^1.0.3" + "inherits" "^2.0.1" + "safe-buffer" "^5.0.1" + +"browserify-cipher@^1.0.0": + "integrity" "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==" + "resolved" "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "browserify-aes" "^1.0.4" + "browserify-des" "^1.0.0" + "evp_bytestokey" "^1.0.0" + +"browserify-des@^1.0.0": + "integrity" "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==" + "resolved" "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "cipher-base" "^1.0.1" + "des.js" "^1.0.0" + "inherits" "^2.0.1" + "safe-buffer" "^5.1.2" + +"browserify-rsa@^4.0.0", "browserify-rsa@^4.0.1": + "integrity" "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==" + "resolved" "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "bn.js" "^5.0.0" + "randombytes" "^2.0.1" + +"browserify-sign@^4.0.0": + "integrity" "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==" + "resolved" "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" + "version" "4.2.1" + 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" + +"browserslist@^3.2.6": + "integrity" "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz" + "version" "3.2.8" + dependencies: + "caniuse-lite" "^1.0.30000844" + "electron-to-chromium" "^1.3.47" + +"browserslist@^4.17.5", "browserslist@^4.19.1": + "integrity" "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz" + "version" "4.19.3" + dependencies: + "caniuse-lite" "^1.0.30001312" + "electron-to-chromium" "^1.4.71" + "escalade" "^3.1.1" + "node-releases" "^2.0.2" + "picocolors" "^1.0.0" + +"bs58@^4.0.0": + "integrity" "sha1-vhYedsNU9veIrkBx9j806MTwpCo=" + "resolved" "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "base-x" "^3.0.2" + +"bs58check@^2.1.2": + "integrity" "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==" + "resolved" "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "bs58" "^4.0.0" + "create-hash" "^1.1.0" + "safe-buffer" "^5.1.2" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"buffer-to-arraybuffer@^0.0.5": + "integrity" "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + "resolved" "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz" + "version" "0.0.5" + +"buffer-xor@^1.0.3": + "integrity" "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + "resolved" "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" + "version" "1.0.3" + +"buffer-xor@^2.0.1": + "integrity" "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==" + "resolved" "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "safe-buffer" "^5.1.1" + +"buffer@^5.0.5", "buffer@^5.2.1", "buffer@^5.5.0", "buffer@^5.6.0": + "integrity" "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==" + "resolved" "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + "version" "5.7.1" + dependencies: + "base64-js" "^1.3.1" + "ieee754" "^1.1.13" + +"bufferutil@^4.0.1": + "integrity" "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==" + "resolved" "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz" + "version" "4.0.6" + dependencies: + "node-gyp-build" "^4.3.0" + +"bytes@3.1.2": + "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + "version" "3.1.2" + +"bytewise-core@^1.2.2": + "integrity" "sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI=" + "resolved" "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz" + "version" "1.2.3" + dependencies: + "typewise-core" "^1.2" + +"bytewise@~1.1.0": + "integrity" "sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4=" + "resolved" "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "bytewise-core" "^1.2.2" + "typewise" "^1.0.3" + +"cache-base@^1.0.1": + "integrity" "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==" + "resolved" "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "collection-visit" "^1.0.0" + "component-emitter" "^1.2.1" + "get-value" "^2.0.6" + "has-value" "^1.0.0" + "isobject" "^3.0.1" + "set-value" "^2.0.0" + "to-object-path" "^0.3.0" + "union-value" "^1.0.0" + "unset-value" "^1.0.0" + +"cacheable-request@^6.0.0": + "integrity" "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==" + "resolved" "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + "version" "6.1.0" + 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" + +"cachedown@1.0.0": + "integrity" "sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU=" + "resolved" "https://registry.npmjs.org/cachedown/-/cachedown-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "abstract-leveldown" "^2.4.1" + "lru-cache" "^3.2.0" + +"call-bind@^1.0.0", "call-bind@^1.0.2", "call-bind@~1.0.2": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camelcase@^3.0.0": + "integrity" "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + "version" "3.0.0" + +"camelcase@^5.0.0": + "integrity" "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + "version" "5.3.1" + +"camelcase@^6.0.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-lite@^1.0.30000844", "caniuse-lite@^1.0.30001312": + "integrity" "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz" + "version" "1.0.30001312" + +"caseless@^0.12.0", "caseless@~0.12.0": + "integrity" "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "resolved" "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" + "version" "0.12.0" + +"cbor@^5.0.2": + "integrity" "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==" + "resolved" "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "bignumber.js" "^9.0.1" + "nofilter" "^1.0.4" + +"chai@^4.2.0": + "integrity" "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==" + "resolved" "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz" + "version" "4.3.6" + dependencies: + "assertion-error" "^1.1.0" + "check-error" "^1.0.2" + "deep-eql" "^3.0.1" + "get-func-name" "^2.0.0" + "loupe" "^2.3.1" + "pathval" "^1.1.1" + "type-detect" "^4.0.5" + +"chalk@^1.1.3": + "integrity" "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + "version" "1.1.3" + 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" + +"chalk@^2.0.0", "chalk@^2.4.1", "chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.0.0": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"chalk@^4.1.0": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"chalk@^4.1.2": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"charenc@>= 0.0.1": + "integrity" "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + "resolved" "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz" + "version" "0.0.2" + +"check-error@^1.0.2": + "integrity" "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + "resolved" "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + "version" "1.0.2" + +"checkpoint-store@^1.1.0": + "integrity" "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=" + "resolved" "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "functional-red-black-tree" "^1.0.1" + +"chokidar@^3.4.0", "chokidar@3.5.3": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + dependencies: + "anymatch" "~3.1.2" + "braces" "~3.0.2" + "glob-parent" "~5.1.2" + "is-binary-path" "~2.1.0" + "is-glob" "~4.0.1" + "normalize-path" "~3.0.0" + "readdirp" "~3.6.0" + optionalDependencies: + "fsevents" "~2.3.2" + +"chokidar@3.3.0": + "integrity" "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz" + "version" "3.3.0" + 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.2.0" + optionalDependencies: + "fsevents" "~2.1.1" + +"chownr@^1.1.4": + "integrity" "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "resolved" "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" + "version" "1.1.4" + +"ci-info@^2.0.0": + "integrity" "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + "version" "2.0.0" + +"cids@^0.7.1": + "integrity" "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==" + "resolved" "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz" + "version" "0.7.5" + dependencies: + "buffer" "^5.5.0" + "class-is" "^1.1.0" + "multibase" "~0.6.0" + "multicodec" "^1.0.0" + "multihashes" "~0.4.15" + +"cipher-base@^1.0.0", "cipher-base@^1.0.1", "cipher-base@^1.0.3": + "integrity" "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==" + "resolved" "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "inherits" "^2.0.1" + "safe-buffer" "^5.0.1" + +"class-is@^1.1.0": + "integrity" "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" + "resolved" "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz" + "version" "1.1.0" + +"class-utils@^0.3.5": + "integrity" "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==" + "resolved" "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" + "version" "0.3.6" + dependencies: + "arr-union" "^3.1.0" + "define-property" "^0.2.5" + "isobject" "^3.0.0" + "static-extend" "^0.1.1" + +"clean-stack@^2.0.0": + "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + "version" "2.2.0" + +"clean-stack@^3.0.0": + "integrity" "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==" + "resolved" "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "escape-string-regexp" "4.0.0" + +"cli-table3@^0.5.0": + "integrity" "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==" + "resolved" "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz" + "version" "0.5.1" + dependencies: + "object-assign" "^4.1.0" + "string-width" "^2.1.1" + optionalDependencies: + "colors" "^1.1.2" + +"cli-table3@^0.6.0": + "integrity" "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==" + "resolved" "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz" + "version" "0.6.1" + dependencies: + "string-width" "^4.2.0" + optionalDependencies: + "colors" "1.4.0" + +"cliui@^3.2.0": + "integrity" "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=" + "resolved" "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "string-width" "^1.0.1" + "strip-ansi" "^3.0.1" + "wrap-ansi" "^2.0.0" + +"cliui@^5.0.0": + "integrity" "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==" + "resolved" "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "string-width" "^3.1.0" + "strip-ansi" "^5.2.0" + "wrap-ansi" "^5.1.0" + +"cliui@^7.0.2": + "integrity" "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==" + "resolved" "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + "version" "7.0.4" + dependencies: + "string-width" "^4.2.0" + "strip-ansi" "^6.0.0" + "wrap-ansi" "^7.0.0" + +"clone-deep@^4.0.1": + "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" + "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-plain-object" "^2.0.4" + "kind-of" "^6.0.2" + "shallow-clone" "^3.0.0" + +"clone-response@^1.0.2": + "integrity" "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=" + "resolved" "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "mimic-response" "^1.0.0" + +"clone@^2.0.0", "clone@2.1.2": + "integrity" "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + "resolved" "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz" + "version" "2.1.2" + +"code-point-at@^1.0.0": + "integrity" "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "resolved" "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + "version" "1.1.0" + +"collection-visit@^1.0.0": + "integrity" "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=" + "resolved" "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "map-visit" "^1.0.0" + "object-visit" "^1.0.0" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colors@^1.1.2", "colors@1.4.0": + "integrity" "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "resolved" "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" + "version" "1.4.0" + +"combined-stream@^1.0.6", "combined-stream@^1.0.8", "combined-stream@~1.0.6": + "integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==" + "resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + "version" "1.0.8" + dependencies: + "delayed-stream" "~1.0.0" + +"command-exists@^1.2.8": + "integrity" "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + "resolved" "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" + "version" "1.2.9" + +"command-line-args@^4.0.7": + "integrity" "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==" + "resolved" "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz" + "version" "4.0.7" + dependencies: + "array-back" "^2.0.0" + "find-replace" "^1.0.3" + "typical" "^2.6.1" + +"commander@3.0.2": + "integrity" "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" + "resolved" "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" + "version" "3.0.2" + +"commondir@^1.0.1": + "integrity" "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + "version" "1.0.1" + +"compare-versions@^3.6.0": + "integrity" "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==" + "resolved" "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz" + "version" "3.6.0" + +"component-emitter@^1.2.1": + "integrity" "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "resolved" "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" + "version" "1.3.0" + +"concat-map@0.0.1": + "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"concat-stream@^1.5.1", "concat-stream@^1.6.0", "concat-stream@^1.6.2": + "integrity" "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==" + "resolved" "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" + "version" "1.6.2" + dependencies: + "buffer-from" "^1.0.0" + "inherits" "^2.0.3" + "readable-stream" "^2.2.2" + "typedarray" "^0.0.6" + +"content-disposition@0.5.4": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"content-hash@^2.5.2": + "integrity" "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==" + "resolved" "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz" + "version" "2.5.2" + dependencies: + "cids" "^0.7.1" + "multicodec" "^0.5.5" + "multihashes" "^0.4.15" + +"content-type@~1.0.4": + "integrity" "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + "version" "1.0.4" + +"convert-source-map@^1.5.1", "convert-source-map@^1.7.0": + "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "safe-buffer" "~5.1.1" + +"cookie-signature@1.0.6": + "integrity" "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "version" "1.0.6" + +"cookie@^0.4.1", "cookie@0.4.2": + "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + "version" "0.4.2" + +"cookiejar@^2.1.1": + "integrity" "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + "resolved" "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz" + "version" "2.1.3" + +"copy-descriptor@^0.1.0": + "integrity" "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "resolved" "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" + "version" "0.1.1" + +"core-js-compat@^3.20.2", "core-js-compat@^3.21.0": + "integrity" "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==" + "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz" + "version" "3.21.1" + dependencies: + "browserslist" "^4.19.1" + "semver" "7.0.0" + +"core-js-pure@^3.0.1": + "integrity" "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==" + "resolved" "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz" + "version" "3.21.1" + +"core-js@^2.4.0", "core-js@^2.5.0": + "integrity" "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + "resolved" "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" + "version" "2.6.12" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"core-util-is@1.0.2": + "integrity" "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + "version" "1.0.2" + +"cors@^2.8.1": + "integrity" "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==" + "resolved" "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" + "version" "2.8.5" + dependencies: + "object-assign" "^4" + "vary" "^1" + +"cosmiconfig@^7.0.0": + "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "@types/parse-json" "^4.0.0" + "import-fresh" "^3.2.1" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.10.0" + +"crc-32@^1.2.0": + "integrity" "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==" + "resolved" "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "exit-on-epipe" "~1.0.1" + "printj" "~1.3.1" + +"create-ecdh@^4.0.0": + "integrity" "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==" + "resolved" "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "bn.js" "^4.1.0" + "elliptic" "^6.5.3" + +"create-hash@^1.1.0", "create-hash@^1.1.2", "create-hash@^1.2.0": + "integrity" "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==" + "resolved" "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "cipher-base" "^1.0.1" + "inherits" "^2.0.1" + "md5.js" "^1.3.4" + "ripemd160" "^2.0.1" + "sha.js" "^2.4.0" + +"create-hmac@^1.1.0", "create-hmac@^1.1.4", "create-hmac@^1.1.7": + "integrity" "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==" + "resolved" "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + "version" "1.1.7" + dependencies: + "cipher-base" "^1.0.3" + "create-hash" "^1.1.0" + "inherits" "^2.0.1" + "ripemd160" "^2.0.0" + "safe-buffer" "^5.0.1" + "sha.js" "^2.4.8" + +"cross-fetch@^2.1.0", "cross-fetch@^2.1.1": + "integrity" "sha512-xqYAhQb4NhCJSRym03dwxpP1bYXpK3y7UN83Bo2WFi3x1Zmzn0SL/6xGoPr+gpt4WmNrgCCX3HPysvOwFOW36w==" + "resolved" "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.5.tgz" + "version" "2.2.5" + dependencies: + "node-fetch" "2.6.1" + "whatwg-fetch" "2.0.4" + +"cross-spawn@^6.0.5": + "integrity" "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" + "version" "6.0.5" + dependencies: + "nice-try" "^1.0.4" + "path-key" "^2.0.1" + "semver" "^5.5.0" + "shebang-command" "^1.2.0" + "which" "^1.2.9" + +"cross-spawn@^7.0.2": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"crypt@>= 0.0.1": + "integrity" "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + "resolved" "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz" + "version" "0.0.2" + +"crypto-browserify@3.12.0": + "integrity" "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==" + "resolved" "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" + "version" "3.12.0" + 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" + +"csv-writer@^1.6.0": + "integrity" "sha512-NOx7YDFWEsM/fTRAJjRpPp8t+MKRVvniAg9wQlUKx20MFrPs73WLJhFf5iteqrxNYnsy924K3Iroh3yNHeYd2g==" + "resolved" "https://registry.npmjs.org/csv-writer/-/csv-writer-1.6.0.tgz" + "version" "1.6.0" + +"d@^1.0.1", "d@1": + "integrity" "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==" + "resolved" "https://registry.npmjs.org/d/-/d-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "es5-ext" "^0.10.50" + "type" "^1.0.1" + +"dashdash@^1.12.0": + "integrity" "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=" + "resolved" "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" + "version" "1.14.1" + dependencies: + "assert-plus" "^1.0.0" + +"death@^1.1.0": + "integrity" "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" + "resolved" "https://registry.npmjs.org/death/-/death-1.1.0.tgz" + "version" "1.1.0" + +"debug@^2.2.0": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^2.3.3": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^2.6.0": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^2.6.8": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.1.0": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^3.2.7": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.3", "debug@4", "debug@4.3.3": + "integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz" + "version" "4.3.3" + dependencies: + "ms" "2.1.2" + +"debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@3.2.6": + "integrity" "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" + "version" "3.2.6" + dependencies: + "ms" "^2.1.1" + +"decamelize@^1.1.1", "decamelize@^1.2.0": + "integrity" "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "resolved" "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + "version" "1.2.0" + +"decamelize@^4.0.0": + "integrity" "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" + "resolved" "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + "version" "4.0.0" + +"decode-uri-component@^0.2.0": + "integrity" "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "resolved" "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" + "version" "0.2.0" + +"decompress-response@^3.2.0", "decompress-response@^3.3.0": + "integrity" "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=" + "resolved" "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "mimic-response" "^1.0.0" + +"deep-eql@^3.0.1": + "integrity" "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==" + "resolved" "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "type-detect" "^4.0.0" + +"deep-equal@~1.1.1": + "integrity" "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==" + "resolved" "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "is-arguments" "^1.0.4" + "is-date-object" "^1.0.1" + "is-regex" "^1.0.4" + "object-is" "^1.0.1" + "object-keys" "^1.1.1" + "regexp.prototype.flags" "^1.2.0" + +"deep-is@^0.1.3", "deep-is@~0.1.3": + "integrity" "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "resolved" "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + "version" "0.1.4" + +"defer-to-connect@^1.0.1": + "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + "version" "1.1.3" + +"deferred-leveldown@~1.2.1": + "integrity" "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==" + "resolved" "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz" + "version" "1.2.2" + dependencies: + "abstract-leveldown" "~2.6.0" + +"deferred-leveldown@~4.0.0": + "integrity" "sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww==" + "resolved" "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "abstract-leveldown" "~5.0.0" + "inherits" "^2.0.3" + +"deferred-leveldown@~5.3.0": + "integrity" "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==" + "resolved" "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "abstract-leveldown" "~6.2.1" + "inherits" "^2.0.3" + +"define-properties@^1.1.2", "define-properties@^1.1.3": + "integrity" "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==" + "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "object-keys" "^1.0.12" + +"define-property@^0.2.5": + "integrity" "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "resolved" "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + "version" "0.2.5" + dependencies: + "is-descriptor" "^0.1.0" + +"define-property@^1.0.0": + "integrity" "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=" + "resolved" "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-descriptor" "^1.0.0" + +"define-property@^2.0.2": + "integrity" "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==" + "resolved" "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "is-descriptor" "^1.0.2" + "isobject" "^3.0.1" + +"defined@~1.0.0": + "integrity" "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + "resolved" "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz" + "version" "1.0.0" + +"delayed-stream@~1.0.0": + "integrity" "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "resolved" "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + "version" "1.0.0" + +"depd@~1.1.2": + "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + "version" "1.1.2" + +"depd@2.0.0": + "integrity" "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "resolved" "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + "version" "2.0.0" + +"des.js@^1.0.0": + "integrity" "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==" + "resolved" "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "inherits" "^2.0.1" + "minimalistic-assert" "^1.0.0" + +"destroy@~1.0.4": + "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "version" "1.0.4" + +"detect-indent@^4.0.0": + "integrity" "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=" + "resolved" "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "repeating" "^2.0.0" + +"detect-port@^1.3.0": + "integrity" "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==" + "resolved" "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "address" "^1.0.1" + "debug" "^2.6.0" + +"diff@3.5.0": + "integrity" "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + "resolved" "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz" + "version" "3.5.0" + +"diff@5.0.0": + "integrity" "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" + "resolved" "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + "version" "5.0.0" + +"diffie-hellman@^5.0.0": + "integrity" "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==" + "resolved" "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "bn.js" "^4.1.0" + "miller-rabin" "^4.0.0" + "randombytes" "^2.0.0" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"doctrine@^2.1.0": + "integrity" "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==" + "resolved" "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "esutils" "^2.0.2" + +"doctrine@^3.0.0": + "integrity" "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==" + "resolved" "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "esutils" "^2.0.2" + +"dom-serializer@^1.0.1": + "integrity" "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-walk@^0.1.0": + "integrity" "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + "resolved" "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz" + "version" "0.1.2" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0": + "integrity" "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz" + "version" "2.2.0" + +"domhandler@^4.2.0", "domhandler@^4.2.2": + "integrity" "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "domelementtype" "^2.2.0" + +"domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"dotenv@^8.2.0": + "integrity" "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + "resolved" "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz" + "version" "8.6.0" + +"dotignore@~0.1.2": + "integrity" "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==" + "resolved" "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "minimatch" "^3.0.4" + +"drbg.js@^1.0.1": + "integrity" "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=" + "resolved" "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "browserify-aes" "^1.0.6" + "create-hash" "^1.1.2" + "create-hmac" "^1.1.4" + +"duplexer3@^0.1.4": + "integrity" "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "resolved" "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" + "version" "0.1.4" + +"ecc-jsbn@~0.1.1": + "integrity" "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=" + "resolved" "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "jsbn" "~0.1.0" + "safer-buffer" "^2.1.0" + +"ee-first@1.1.1": + "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"electron-to-chromium@^1.3.47", "electron-to-chromium@^1.4.71": + "integrity" "sha512-DvQ20M0I4dIH8KcAo7n7E4OEeNafZ1N8z6g6ck+ALCM0ZoV6mpjaX6ekjs31zKlqPzacU3lmjG9PZEa1mQhEpQ==" + "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.74.tgz" + "version" "1.4.74" + +"elliptic@^6.4.0", "elliptic@^6.5.2", "elliptic@^6.5.3", "elliptic@^6.5.4", "elliptic@6.5.4": + "integrity" "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==" + "resolved" "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" + "version" "6.5.4" + 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" + +"emoji-regex@^7.0.1": + "integrity" "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" + "version" "7.0.3" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"encodeurl@~1.0.2": + "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"encoding-down@^6.3.0": + "integrity" "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==" + "resolved" "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz" + "version" "6.3.0" + dependencies: + "abstract-leveldown" "^6.2.1" + "inherits" "^2.0.3" + "level-codec" "^9.0.0" + "level-errors" "^2.0.0" + +"encoding-down@~5.0.0", "encoding-down@5.0.4": + "integrity" "sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw==" + "resolved" "https://registry.npmjs.org/encoding-down/-/encoding-down-5.0.4.tgz" + "version" "5.0.4" + dependencies: + "abstract-leveldown" "^5.0.0" + "inherits" "^2.0.3" + "level-codec" "^9.0.0" + "level-errors" "^2.0.0" + "xtend" "^4.0.1" + +"encoding@^0.1.0", "encoding@^0.1.11": + "integrity" "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==" + "resolved" "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" + "version" "0.1.13" + dependencies: + "iconv-lite" "^0.6.2" + +"end-of-stream@^1.1.0": + "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" + "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + "version" "1.4.4" + dependencies: + "once" "^1.4.0" + +"enquirer@^2.3.0", "enquirer@^2.3.5": + "integrity" "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==" + "resolved" "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + "version" "2.3.6" + dependencies: + "ansi-colors" "^4.1.1" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^3.0.1": + "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" + "version" "3.0.1" + +"env-paths@^2.2.0": + "integrity" "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + "resolved" "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" + "version" "2.2.1" + +"errno@~0.1.1": + "integrity" "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==" + "resolved" "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" + "version" "0.1.8" + dependencies: + "prr" "~1.0.1" + +"error-ex@^1.2.0", "error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-abstract@^1.18.5", "es-abstract@^1.19.0", "es-abstract@^1.19.1": + "integrity" "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==" + "resolved" "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz" + "version" "1.19.1" + 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" + +"es-to-primitive@^1.2.1": + "integrity" "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==" + "resolved" "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "is-callable" "^1.1.4" + "is-date-object" "^1.0.1" + "is-symbol" "^1.0.2" + +"es5-ext@^0.10.35", "es5-ext@^0.10.50": + "integrity" "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==" + "resolved" "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz" + "version" "0.10.53" + dependencies: + "es6-iterator" "~2.0.3" + "es6-symbol" "~3.1.3" + "next-tick" "~1.0.0" + +"es6-iterator@~2.0.3": + "integrity" "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=" + "resolved" "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" + "version" "2.0.3" + dependencies: + "d" "1" + "es5-ext" "^0.10.35" + "es6-symbol" "^3.1.1" + +"es6-symbol@^3.1.1", "es6-symbol@~3.1.3": + "integrity" "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==" + "resolved" "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" + "version" "3.1.3" + dependencies: + "d" "^1.0.1" + "ext" "^1.1.2" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-html@~1.0.3": + "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.2", "escape-string-regexp@^1.0.5", "escape-string-regexp@1.0.5": + "integrity" "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"escape-string-regexp@4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"escodegen@1.8.x": + "integrity" "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=" + "resolved" "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "esprima" "^2.7.1" + "estraverse" "^1.9.1" + "esutils" "^2.0.2" + "optionator" "^0.8.1" + optionalDependencies: + "source-map" "~0.2.0" + +"eslint-import-resolver-node@^0.3.6": + "integrity" "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==" + "resolved" "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz" + "version" "0.3.6" + dependencies: + "debug" "^3.2.7" + "resolve" "^1.20.0" + +"eslint-module-utils@^2.7.2": + "integrity" "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==" + "resolved" "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz" + "version" "2.7.3" + dependencies: + "debug" "^3.2.7" + "find-up" "^2.1.0" + +"eslint-plugin-es@^3.0.0": + "integrity" "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==" + "resolved" "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "eslint-utils" "^2.0.0" + "regexpp" "^3.0.0" + +"eslint-plugin-html@^6.1.0": + "integrity" "sha512-vi3NW0E8AJombTvt8beMwkL1R/fdRWl4QSNRNMhVQKWm36/X0KF0unGNAY4mqUF06mnwVWZcIcerrCnfn9025g==" + "resolved" "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "htmlparser2" "^7.1.2" + +"eslint-plugin-import@^2.22.1": + "integrity" "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==" + "resolved" "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz" + "version" "2.25.4" + dependencies: + "array-includes" "^3.1.4" + "array.prototype.flat" "^1.2.5" + "debug" "^2.6.9" + "doctrine" "^2.1.0" + "eslint-import-resolver-node" "^0.3.6" + "eslint-module-utils" "^2.7.2" + "has" "^1.0.3" + "is-core-module" "^2.8.0" + "is-glob" "^4.0.3" + "minimatch" "^3.0.4" + "object.values" "^1.1.5" + "resolve" "^1.20.0" + "tsconfig-paths" "^3.12.0" + +"eslint-plugin-node@^11.1.0": + "integrity" "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==" + "resolved" "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "eslint-plugin-es" "^3.0.0" + "eslint-utils" "^2.0.0" + "ignore" "^5.1.1" + "minimatch" "^3.0.4" + "resolve" "^1.10.1" + "semver" "^6.1.0" + +"eslint-plugin-promise@^4.2.1": + "integrity" "sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==" + "resolved" "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz" + "version" "4.3.1" + +"eslint-plugin-standard@^4.0.1": + "integrity" "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==" + "resolved" "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz" + "version" "4.1.0" + +"eslint-scope@^5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"eslint-utils@^2.0.0", "eslint-utils@^2.1.0": + "integrity" "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==" + "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "eslint-visitor-keys" "^1.1.0" + +"eslint-visitor-keys@^1.1.0", "eslint-visitor-keys@^1.3.0": + "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + "version" "1.3.0" + +"eslint-visitor-keys@^2.0.0": + "integrity" "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + "version" "2.1.0" + +"eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^7.10.0", "eslint@>=4.19.1", "eslint@>=5.0.0", "eslint@>=5.16.0": + "integrity" "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==" + "resolved" "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz" + "version" "7.32.0" + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + "ajv" "^6.10.0" + "chalk" "^4.0.0" + "cross-spawn" "^7.0.2" + "debug" "^4.0.1" + "doctrine" "^3.0.0" + "enquirer" "^2.3.5" + "escape-string-regexp" "^4.0.0" + "eslint-scope" "^5.1.1" + "eslint-utils" "^2.1.0" + "eslint-visitor-keys" "^2.0.0" + "espree" "^7.3.1" + "esquery" "^1.4.0" + "esutils" "^2.0.2" + "fast-deep-equal" "^3.1.3" + "file-entry-cache" "^6.0.1" + "functional-red-black-tree" "^1.0.1" + "glob-parent" "^5.1.2" + "globals" "^13.6.0" + "ignore" "^4.0.6" + "import-fresh" "^3.0.0" + "imurmurhash" "^0.1.4" + "is-glob" "^4.0.0" + "js-yaml" "^3.13.1" + "json-stable-stringify-without-jsonify" "^1.0.1" + "levn" "^0.4.1" + "lodash.merge" "^4.6.2" + "minimatch" "^3.0.4" + "natural-compare" "^1.4.0" + "optionator" "^0.9.1" + "progress" "^2.0.0" + "regexpp" "^3.1.0" + "semver" "^7.2.1" + "strip-ansi" "^6.0.0" + "strip-json-comments" "^3.1.0" + "table" "^6.0.9" + "text-table" "^0.2.0" + "v8-compile-cache" "^2.0.3" + +"espree@^7.3.0", "espree@^7.3.1": + "integrity" "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==" + "resolved" "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + "version" "7.3.1" + dependencies: + "acorn" "^7.4.0" + "acorn-jsx" "^5.3.1" + "eslint-visitor-keys" "^1.3.0" + +"esprima@^2.7.1", "esprima@2.7.x": + "integrity" "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" + "version" "2.7.3" + +"esprima@^4.0.0": + "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + "version" "4.0.1" + +"esquery@^1.4.0": + "integrity" "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==" + "resolved" "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "estraverse" "^5.1.0" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^1.9.1": + "integrity" "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" + "version" "1.9.3" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.1.0", "estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"etag@~1.8.1": + "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"eth-block-tracker@^3.0.0": + "integrity" "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==" + "resolved" "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "eth-query" "^2.1.0" + "ethereumjs-tx" "^1.3.3" + "ethereumjs-util" "^5.1.3" + "ethjs-util" "^0.1.3" + "json-rpc-engine" "^3.6.0" + "pify" "^2.3.0" + "tape" "^4.6.3" + +"eth-ens-namehash@^2.0.8", "eth-ens-namehash@2.0.8": + "integrity" "sha1-IprEbsqG1S4MmR58sq74P/D2i88=" + "resolved" "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz" + "version" "2.0.8" + dependencies: + "idna-uts46-hx" "^2.3.1" + "js-sha3" "^0.5.7" + +"eth-gas-reporter@^0.2.24": + "integrity" "sha512-RbXLC2bnuPHzIMU/rnLXXlb6oiHEEKu7rq2UrAX/0mfo0Lzrr/kb9QTjWjfz8eNvc+uu6J8AuBwI++b+MLNI2w==" + "resolved" "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.24.tgz" + "version" "0.2.24" + dependencies: + "@ethersproject/abi" "^5.0.0-beta.146" + "@solidity-parser/parser" "^0.14.0" + "cli-table3" "^0.5.0" + "colors" "1.4.0" + "ethereumjs-util" "6.2.0" + "ethers" "^4.0.40" + "fs-readdir-recursive" "^1.1.0" + "lodash" "^4.17.14" + "markdown-table" "^1.1.3" + "mocha" "^7.1.1" + "req-cwd" "^2.0.0" + "request" "^2.88.0" + "request-promise-native" "^1.0.5" + "sha1" "^1.1.1" + "sync-request" "^6.0.0" + +"eth-json-rpc-infura@^3.1.0": + "integrity" "sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw==" + "resolved" "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "cross-fetch" "^2.1.1" + "eth-json-rpc-middleware" "^1.5.0" + "json-rpc-engine" "^3.4.0" + "json-rpc-error" "^2.0.0" + +"eth-json-rpc-middleware@^1.5.0": + "integrity" "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==" + "resolved" "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "async" "^2.5.0" + "eth-query" "^2.1.2" + "eth-tx-summary" "^3.1.2" + "ethereumjs-block" "^1.6.0" + "ethereumjs-tx" "^1.3.3" + "ethereumjs-util" "^5.1.2" + "ethereumjs-vm" "^2.1.0" + "fetch-ponyfill" "^4.0.0" + "json-rpc-engine" "^3.6.0" + "json-rpc-error" "^2.0.0" + "json-stable-stringify" "^1.0.1" + "promise-to-callback" "^1.0.0" + "tape" "^4.6.3" + +"eth-lib@^0.1.26": + "integrity" "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==" + "resolved" "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz" + "version" "0.1.29" + 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" + +"eth-lib@0.2.8": + "integrity" "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==" + "resolved" "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz" + "version" "0.2.8" + dependencies: + "bn.js" "^4.11.6" + "elliptic" "^6.4.0" + "xhr-request-promise" "^0.1.2" + +"eth-query@^2.0.2", "eth-query@^2.1.0", "eth-query@^2.1.2": + "integrity" "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=" + "resolved" "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "json-rpc-random-id" "^1.0.0" + "xtend" "^4.0.1" + +"eth-sig-util@^1.4.2": + "integrity" "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=" + "resolved" "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "ethereumjs-abi" "git+https://github.com/ethereumjs/ethereumjs-abi.git" + "ethereumjs-util" "^5.1.1" + +"eth-sig-util@3.0.0": + "integrity" "sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ==" + "resolved" "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "buffer" "^5.2.1" + "elliptic" "^6.4.0" + "ethereumjs-abi" "0.6.5" + "ethereumjs-util" "^5.1.1" + "tweetnacl" "^1.0.0" + "tweetnacl-util" "^0.15.0" + +"eth-tx-summary@^3.1.2": + "integrity" "sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg==" + "resolved" "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz" + "version" "3.2.4" + dependencies: + "async" "^2.1.2" + "clone" "^2.0.0" + "concat-stream" "^1.5.1" + "end-of-stream" "^1.1.0" + "eth-query" "^2.0.2" + "ethereumjs-block" "^1.4.1" + "ethereumjs-tx" "^1.1.1" + "ethereumjs-util" "^5.0.1" + "ethereumjs-vm" "^2.6.0" + "through2" "^2.0.3" + +"ethashjs@~0.0.7": + "integrity" "sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw==" + "resolved" "https://registry.npmjs.org/ethashjs/-/ethashjs-0.0.8.tgz" + "version" "0.0.8" + dependencies: + "async" "^2.1.2" + "buffer-xor" "^2.0.1" + "ethereumjs-util" "^7.0.2" + "miller-rabin" "^4.0.0" + +"ethereum-bloom-filters@^1.0.6": + "integrity" "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==" + "resolved" "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "js-sha3" "^0.8.0" + +"ethereum-common@^0.0.18": + "integrity" "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + "resolved" "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz" + "version" "0.0.18" + +"ethereum-common@0.2.0": + "integrity" "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + "resolved" "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz" + "version" "0.2.0" + +"ethereum-cryptography@^0.1.2", "ethereum-cryptography@^0.1.3": + "integrity" "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==" + "resolved" "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz" + "version" "0.1.3" + 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" + +"ethereum-waffle@^3.1.1", "ethereum-waffle@^3.2.0": + "integrity" "sha512-ADBqZCkoSA5Isk486ntKJVjFEawIiC+3HxNqpJqONvh3YXBTNiRfXvJtGuAFLXPG91QaqkGqILEHANAo7j/olQ==" + "resolved" "https://registry.npmjs.org/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz" + "version" "3.4.0" + dependencies: + "@ethereum-waffle/chai" "^3.4.0" + "@ethereum-waffle/compiler" "^3.4.0" + "@ethereum-waffle/mock-contract" "^3.3.0" + "@ethereum-waffle/provider" "^3.4.0" + "ethers" "^5.0.1" + +"ethereumjs-abi@^0.6.8", "ethereumjs-abi@0.6.8": + "integrity" "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==" + "resolved" "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz" + "version" "0.6.8" + dependencies: + "bn.js" "^4.11.8" + "ethereumjs-util" "^6.0.0" + +"ethereumjs-abi@0.6.5": + "integrity" "sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE=" + "resolved" "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz" + "version" "0.6.5" + dependencies: + "bn.js" "^4.10.0" + "ethereumjs-util" "^4.3.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + "version" "0.6.8" + dependencies: + "bn.js" "^4.11.8" + "ethereumjs-util" "^6.0.0" + +"ethereumjs-account@^2.0.3": + "integrity" "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==" + "resolved" "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz" + "version" "2.0.5" + dependencies: + "ethereumjs-util" "^5.0.0" + "rlp" "^2.0.0" + "safe-buffer" "^5.1.1" + +"ethereumjs-account@^3.0.0", "ethereumjs-account@3.0.0": + "integrity" "sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA==" + "resolved" "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ethereumjs-util" "^6.0.0" + "rlp" "^2.2.1" + "safe-buffer" "^5.1.1" + +"ethereumjs-block@^1.2.2": + "integrity" "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==" + "resolved" "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz" + "version" "1.7.1" + dependencies: + "async" "^2.0.1" + "ethereum-common" "0.2.0" + "ethereumjs-tx" "^1.2.2" + "ethereumjs-util" "^5.0.0" + "merkle-patricia-tree" "^2.1.2" + +"ethereumjs-block@^1.4.1": + "integrity" "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==" + "resolved" "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz" + "version" "1.7.1" + dependencies: + "async" "^2.0.1" + "ethereum-common" "0.2.0" + "ethereumjs-tx" "^1.2.2" + "ethereumjs-util" "^5.0.0" + "merkle-patricia-tree" "^2.1.2" + +"ethereumjs-block@^1.6.0": + "integrity" "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==" + "resolved" "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz" + "version" "1.7.1" + dependencies: + "async" "^2.0.1" + "ethereum-common" "0.2.0" + "ethereumjs-tx" "^1.2.2" + "ethereumjs-util" "^5.0.0" + "merkle-patricia-tree" "^2.1.2" + +"ethereumjs-block@^2.2.2", "ethereumjs-block@~2.2.0", "ethereumjs-block@~2.2.2", "ethereumjs-block@2.2.2": + "integrity" "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==" + "resolved" "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "async" "^2.0.1" + "ethereumjs-common" "^1.5.0" + "ethereumjs-tx" "^2.1.1" + "ethereumjs-util" "^5.0.0" + "merkle-patricia-tree" "^2.1.2" + +"ethereumjs-blockchain@^4.0.3": + "integrity" "sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ==" + "resolved" "https://registry.npmjs.org/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "async" "^2.6.1" + "ethashjs" "~0.0.7" + "ethereumjs-block" "~2.2.2" + "ethereumjs-common" "^1.5.0" + "ethereumjs-util" "^6.1.0" + "flow-stoplight" "^1.0.0" + "level-mem" "^3.0.1" + "lru-cache" "^5.1.1" + "rlp" "^2.2.2" + "semaphore" "^1.1.0" + +"ethereumjs-common@^1.1.0", "ethereumjs-common@^1.5.0": + "integrity" "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==" + "resolved" "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz" + "version" "1.5.2" + +"ethereumjs-common@^1.3.2": + "integrity" "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==" + "resolved" "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz" + "version" "1.5.2" + +"ethereumjs-common@1.5.0": + "integrity" "sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ==" + "resolved" "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz" + "version" "1.5.0" + +"ethereumjs-tx@^1.1.1", "ethereumjs-tx@^1.2.0", "ethereumjs-tx@^1.2.2", "ethereumjs-tx@^1.3.3": + "integrity" "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==" + "resolved" "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz" + "version" "1.3.7" + dependencies: + "ethereum-common" "^0.0.18" + "ethereumjs-util" "^5.0.0" + +"ethereumjs-tx@^2.1.1", "ethereumjs-tx@^2.1.2", "ethereumjs-tx@2.1.2": + "integrity" "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==" + "resolved" "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "ethereumjs-common" "^1.5.0" + "ethereumjs-util" "^6.0.0" + +"ethereumjs-util@^4.3.0": + "integrity" "sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz" + "version" "4.5.1" + dependencies: + "bn.js" "^4.8.0" + "create-hash" "^1.1.2" + "elliptic" "^6.5.2" + "ethereum-cryptography" "^0.1.3" + "rlp" "^2.0.0" + +"ethereumjs-util@^5.0.0", "ethereumjs-util@^5.0.1", "ethereumjs-util@^5.1.1", "ethereumjs-util@^5.1.2", "ethereumjs-util@^5.1.3", "ethereumjs-util@^5.1.5": + "integrity" "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz" + "version" "5.2.1" + 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" + +"ethereumjs-util@^5.2.0": + "integrity" "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz" + "version" "5.2.1" + 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" + +"ethereumjs-util@^6.0.0", "ethereumjs-util@^6.2.0", "ethereumjs-util@6.2.1": + "integrity" "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "@types/bn.js" "^4.11.3" + "bn.js" "^4.11.0" + "create-hash" "^1.1.2" + "elliptic" "^6.5.2" + "ethereum-cryptography" "^0.1.3" + "ethjs-util" "0.1.6" + "rlp" "^2.2.3" + +"ethereumjs-util@^6.1.0": + "integrity" "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "@types/bn.js" "^4.11.3" + "bn.js" "^4.11.0" + "create-hash" "^1.1.2" + "elliptic" "^6.5.2" + "ethereum-cryptography" "^0.1.3" + "ethjs-util" "0.1.6" + "rlp" "^2.2.3" + +"ethereumjs-util@^6.2.1": + "integrity" "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" + "version" "6.2.1" + dependencies: + "@types/bn.js" "^4.11.3" + "bn.js" "^4.11.0" + "create-hash" "^1.1.2" + "elliptic" "^6.5.2" + "ethereum-cryptography" "^0.1.3" + "ethjs-util" "0.1.6" + "rlp" "^2.2.3" + +"ethereumjs-util@^7.0.10": + "integrity" "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + "version" "7.1.4" + 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" + +"ethereumjs-util@^7.0.2": + "integrity" "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + "version" "7.1.4" + 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" + +"ethereumjs-util@^7.1.0": + "integrity" "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + "version" "7.1.4" + 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" + +"ethereumjs-util@^7.1.1": + "integrity" "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + "version" "7.1.4" + 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" + +"ethereumjs-util@^7.1.3", "ethereumjs-util@^7.1.4": + "integrity" "sha512-p6KmuPCX4mZIqsQzXfmSx9Y0l2hqf+VkAiwSisW3UKUFdk8ZkAt+AYaor83z2nSi6CU2zSsXMlD80hAbNEGM0A==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.4.tgz" + "version" "7.1.4" + 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" + +"ethereumjs-util@6.2.0": + "integrity" "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==" + "resolved" "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "@types/bn.js" "^4.11.3" + "bn.js" "^4.11.0" + "create-hash" "^1.1.2" + "ethjs-util" "0.1.6" + "keccak" "^2.0.0" + "rlp" "^2.2.3" + "secp256k1" "^3.0.1" + +"ethereumjs-vm@^2.1.0", "ethereumjs-vm@^2.3.4", "ethereumjs-vm@^2.6.0": + "integrity" "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==" + "resolved" "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz" + "version" "2.6.0" + dependencies: + "async" "^2.1.2" + "async-eventemitter" "^0.2.2" + "ethereumjs-account" "^2.0.3" + "ethereumjs-block" "~2.2.0" + "ethereumjs-common" "^1.1.0" + "ethereumjs-util" "^6.0.0" + "fake-merkle-patricia-tree" "^1.0.1" + "functional-red-black-tree" "^1.0.1" + "merkle-patricia-tree" "^2.3.2" + "rustbn.js" "~0.2.0" + "safe-buffer" "^5.1.1" + +"ethereumjs-vm@4.2.0": + "integrity" "sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==" + "resolved" "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "async" "^2.1.2" + "async-eventemitter" "^0.2.2" + "core-js-pure" "^3.0.1" + "ethereumjs-account" "^3.0.0" + "ethereumjs-block" "^2.2.2" + "ethereumjs-blockchain" "^4.0.3" + "ethereumjs-common" "^1.5.0" + "ethereumjs-tx" "^2.1.2" + "ethereumjs-util" "^6.2.0" + "fake-merkle-patricia-tree" "^1.0.1" + "functional-red-black-tree" "^1.0.1" + "merkle-patricia-tree" "^2.3.2" + "rustbn.js" "~0.2.0" + "safe-buffer" "^5.1.1" + "util.promisify" "^1.0.0" + +"ethereumjs-wallet@0.6.5": + "integrity" "sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA==" + "resolved" "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz" + "version" "0.6.5" + dependencies: + "aes-js" "^3.1.1" + "bs58check" "^2.1.2" + "ethereum-cryptography" "^0.1.3" + "ethereumjs-util" "^6.0.0" + "randombytes" "^2.0.6" + "safe-buffer" "^5.1.2" + "scryptsy" "^1.2.1" + "utf8" "^3.0.0" + "uuid" "^3.3.2" + +"ethers@^4.0.32": + "integrity" "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==" + "resolved" "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz" + "version" "4.0.49" + 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" + +"ethers@^4.0.40": + "integrity" "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==" + "resolved" "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz" + "version" "4.0.49" + 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" + +"ethers@^5.0.0", "ethers@^5.0.1", "ethers@^5.0.2", "ethers@^5.4.0", "ethers@^5.5.2": + "integrity" "sha512-N9IAXsF8iKhgHIC6pquzRgPBJEzc9auw3JoRkaKe+y4Wl/LFBtDDunNe7YmdomontECAcC5APaAgWZBiu1kirw==" + "resolved" "https://registry.npmjs.org/ethers/-/ethers-5.5.4.tgz" + "version" "5.5.4" + 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" + +"ethjs-unit@0.1.6": + "integrity" "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=" + "resolved" "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "bn.js" "4.11.6" + "number-to-bn" "1.7.0" + +"ethjs-util@^0.1.3", "ethjs-util@^0.1.6", "ethjs-util@0.1.6": + "integrity" "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==" + "resolved" "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "is-hex-prefixed" "1.0.0" + "strip-hex-prefix" "1.0.0" + +"event-target-shim@^5.0.0": + "integrity" "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + "resolved" "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" + "version" "5.0.1" + +"eventemitter3@4.0.4": + "integrity" "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" + "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz" + "version" "4.0.4" + +"events@^3.0.0": + "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + "version" "3.3.0" + +"evp_bytestokey@^1.0.0", "evp_bytestokey@^1.0.3": + "integrity" "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==" + "resolved" "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "md5.js" "^1.3.4" + "safe-buffer" "^5.1.1" + +"exit-on-epipe@~1.0.1": + "integrity" "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + "resolved" "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz" + "version" "1.0.1" + +"expand-brackets@^2.1.4": + "integrity" "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=" + "resolved" "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "debug" "^2.3.3" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "posix-character-classes" "^0.1.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"express@^4.14.0": + "integrity" "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==" + "resolved" "https://registry.npmjs.org/express/-/express-4.17.3.tgz" + "version" "4.17.3" + dependencies: + "accepts" "~1.3.8" + "array-flatten" "1.1.1" + "body-parser" "1.19.2" + "content-disposition" "0.5.4" + "content-type" "~1.0.4" + "cookie" "0.4.2" + "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.7" + "qs" "6.9.7" + "range-parser" "~1.2.1" + "safe-buffer" "5.2.1" + "send" "0.17.2" + "serve-static" "1.14.2" + "setprototypeof" "1.2.0" + "statuses" "~1.5.0" + "type-is" "~1.6.18" + "utils-merge" "1.0.1" + "vary" "~1.1.2" + +"ext@^1.1.2": + "integrity" "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==" + "resolved" "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "type" "^2.5.0" + +"extend-shallow@^2.0.1": + "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend-shallow@^3.0.0": + "integrity" "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "assign-symbols" "^1.0.0" + "is-extendable" "^1.0.1" + +"extend-shallow@^3.0.2": + "integrity" "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=" + "resolved" "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "assign-symbols" "^1.0.0" + "is-extendable" "^1.0.1" + +"extend@~3.0.2": + "integrity" "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + "version" "3.0.2" + +"extglob@^2.0.4": + "integrity" "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==" + "resolved" "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "array-unique" "^0.3.2" + "define-property" "^1.0.0" + "expand-brackets" "^2.1.4" + "extend-shallow" "^2.0.1" + "fragment-cache" "^0.2.1" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"extsprintf@^1.2.0": + "integrity" "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==" + "resolved" "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" + "version" "1.4.1" + +"extsprintf@1.3.0": + "integrity" "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "resolved" "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + "version" "1.3.0" + +"fake-merkle-patricia-tree@^1.0.1": + "integrity" "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=" + "resolved" "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "checkpoint-store" "^1.1.0" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-glob@^3.0.3", "fast-glob@^3.2.9": + "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" + "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + "version" "3.2.11" + 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" + +"fast-json-stable-stringify@^2.0.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-levenshtein@^2.0.6", "fast-levenshtein@~2.0.6": + "integrity" "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "resolved" "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + "version" "2.0.6" + +"fastq@^1.6.0": + "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" + "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + "version" "1.13.0" + dependencies: + "reusify" "^1.0.4" + +"fetch-ponyfill@^4.0.0": + "integrity" "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=" + "resolved" "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "node-fetch" "~1.7.1" + +"file-entry-cache@^6.0.1": + "integrity" "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==" + "resolved" "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "flat-cache" "^3.0.4" + +"file-uri-to-path@1.0.0": + "integrity" "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "resolved" "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" + "version" "1.0.0" + +"fill-range@^4.0.0": + "integrity" "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + "to-regex-range" "^2.1.0" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@~1.1.2": + "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" + "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + "version" "1.1.2" + 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" + +"find-cache-dir@^2.0.0": + "integrity" "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==" + "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "commondir" "^1.0.1" + "make-dir" "^2.0.0" + "pkg-dir" "^3.0.0" + +"find-replace@^1.0.3": + "integrity" "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=" + "resolved" "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "array-back" "^1.0.4" + "test-value" "^2.1.0" + +"find-up@^1.0.0": + "integrity" "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "path-exists" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"find-up@^2.1.0": + "integrity" "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "locate-path" "^2.0.0" + +"find-up@^3.0.0", "find-up@3.0.0": + "integrity" "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "locate-path" "^3.0.0" + +"find-up@^5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"find-up@5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"find-versions@^4.0.0": + "integrity" "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==" + "resolved" "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "semver-regex" "^3.1.2" + +"find-yarn-workspace-root@^1.2.1": + "integrity" "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==" + "resolved" "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "fs-extra" "^4.0.3" + "micromatch" "^3.1.4" + +"find-yarn-workspace-root@^2.0.0": + "integrity" "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==" + "resolved" "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "micromatch" "^4.0.2" + +"flat-cache@^3.0.4": + "integrity" "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==" + "resolved" "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "flatted" "^3.1.0" + "rimraf" "^3.0.2" + +"flat@^4.1.0": + "integrity" "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==" + "resolved" "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "is-buffer" "~2.0.3" + +"flat@^5.0.2": + "integrity" "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" + "resolved" "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + "version" "5.0.2" + +"flatted@^3.1.0": + "integrity" "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + "resolved" "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" + "version" "3.2.5" + +"flow-stoplight@^1.0.0": + "integrity" "sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=" + "resolved" "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz" + "version" "1.0.0" + +"follow-redirects@^1.12.1", "follow-redirects@^1.14.0": + "integrity" "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz" + "version" "1.14.9" + +"for-each@^0.3.3", "for-each@~0.3.3": + "integrity" "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==" + "resolved" "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + "version" "0.3.3" + dependencies: + "is-callable" "^1.1.3" + +"for-in@^1.0.2": + "integrity" "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "resolved" "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + "version" "1.0.2" + +"foreach@^2.0.5": + "integrity" "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "resolved" "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" + "version" "2.0.5" + +"forever-agent@~0.6.1": + "integrity" "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "resolved" "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + "version" "0.6.1" + +"form-data@^2.2.0": + "integrity" "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==" + "resolved" "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" + "version" "2.5.1" + dependencies: + "asynckit" "^0.4.0" + "combined-stream" "^1.0.6" + "mime-types" "^2.1.12" + +"form-data@^3.0.0": + "integrity" "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==" + "resolved" "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "asynckit" "^0.4.0" + "combined-stream" "^1.0.8" + "mime-types" "^2.1.12" + +"form-data@~2.3.2": + "integrity" "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==" + "resolved" "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" + "version" "2.3.3" + dependencies: + "asynckit" "^0.4.0" + "combined-stream" "^1.0.6" + "mime-types" "^2.1.12" + +"forwarded@0.2.0": + "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + "version" "0.2.0" + +"fp-ts@^1.0.0": + "integrity" "sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A==" + "resolved" "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.5.tgz" + "version" "1.19.5" + +"fp-ts@1.19.3": + "integrity" "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" + "resolved" "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz" + "version" "1.19.3" + +"fragment-cache@^0.2.1": + "integrity" "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=" + "resolved" "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" + "version" "0.2.1" + dependencies: + "map-cache" "^0.2.2" + +"fresh@0.5.2": + "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs-extra@^0.30.0": + "integrity" "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz" + "version" "0.30.0" + dependencies: + "graceful-fs" "^4.1.2" + "jsonfile" "^2.1.0" + "klaw" "^1.0.0" + "path-is-absolute" "^1.0.0" + "rimraf" "^2.2.8" + +"fs-extra@^4.0.2": + "integrity" "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "graceful-fs" "^4.1.2" + "jsonfile" "^4.0.0" + "universalify" "^0.1.0" + +"fs-extra@^4.0.3": + "integrity" "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "graceful-fs" "^4.1.2" + "jsonfile" "^4.0.0" + "universalify" "^0.1.0" + +"fs-extra@^7.0.0", "fs-extra@^7.0.1": + "integrity" "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "graceful-fs" "^4.1.2" + "jsonfile" "^4.0.0" + "universalify" "^0.1.0" + +"fs-extra@^8.1.0": + "integrity" "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" + "version" "8.1.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^4.0.0" + "universalify" "^0.1.0" + +"fs-extra@^8.1": + "integrity" "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==" + "resolved" "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" + "version" "8.1.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^4.0.0" + "universalify" "^0.1.0" + +"fs-minipass@^1.2.7": + "integrity" "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==" + "resolved" "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz" + "version" "1.2.7" + dependencies: + "minipass" "^2.6.0" + +"fs-readdir-recursive@^1.1.0": + "integrity" "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + "resolved" "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz" + "version" "1.1.0" + +"fs.realpath@^1.0.0": + "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"functional-red-black-tree@^1.0.1", "functional-red-black-tree@~1.0.1": + "integrity" "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "resolved" "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + "version" "1.0.1" + +"ganache-core@^2.13.2", "ganache-core@^2.7.0": + "integrity" "sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw==" + "resolved" "https://registry.npmjs.org/ganache-core/-/ganache-core-2.13.2.tgz" + "version" "2.13.2" + dependencies: + "abstract-leveldown" "3.0.0" + "async" "2.6.2" + "bip39" "2.5.0" + "cachedown" "1.0.0" + "clone" "2.1.2" + "debug" "3.2.6" + "encoding-down" "5.0.4" + "eth-sig-util" "3.0.0" + "ethereumjs-abi" "0.6.8" + "ethereumjs-account" "3.0.0" + "ethereumjs-block" "2.2.2" + "ethereumjs-common" "1.5.0" + "ethereumjs-tx" "2.1.2" + "ethereumjs-util" "6.2.1" + "ethereumjs-vm" "4.2.0" + "heap" "0.2.6" + "keccak" "3.0.1" + "level-sublevel" "6.6.4" + "levelup" "3.1.1" + "lodash" "4.17.20" + "lru-cache" "5.1.1" + "merkle-patricia-tree" "3.0.0" + "patch-package" "6.2.2" + "seedrandom" "3.0.1" + "source-map-support" "0.5.12" + "tmp" "0.1.0" + "web3-provider-engine" "14.2.1" + "websocket" "1.0.32" + optionalDependencies: + "ethereumjs-wallet" "0.6.5" + "web3" "1.2.11" + +"gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-caller-file@^1.0.1": + "integrity" "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz" + "version" "1.0.3" + +"get-caller-file@^2.0.1", "get-caller-file@^2.0.5": + "integrity" "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + "version" "2.0.5" + +"get-func-name@^2.0.0": + "integrity" "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + "resolved" "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" + "version" "2.0.0" + +"get-intrinsic@^1.0.2", "get-intrinsic@^1.1.0", "get-intrinsic@^1.1.1": + "integrity" "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==" + "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-symbols" "^1.0.1" + +"get-port@^3.1.0": + "integrity" "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" + "resolved" "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz" + "version" "3.2.0" + +"get-stream@^3.0.0": + "integrity" "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz" + "version" "3.0.0" + +"get-stream@^4.1.0": + "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^5.1.0": + "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "pump" "^3.0.0" + +"get-symbol-description@^1.0.0": + "integrity" "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==" + "resolved" "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "call-bind" "^1.0.2" + "get-intrinsic" "^1.1.1" + +"get-value@^2.0.3", "get-value@^2.0.6": + "integrity" "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "resolved" "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" + "version" "2.0.6" + +"getpass@^0.1.1": + "integrity" "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=" + "resolved" "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" + "version" "0.1.7" + dependencies: + "assert-plus" "^1.0.0" + +"ghost-testrpc@^0.0.2": + "integrity" "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==" + "resolved" "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz" + "version" "0.0.2" + dependencies: + "chalk" "^2.4.2" + "node-emoji" "^1.10.0" + +"glob-parent@^5.1.2", "glob-parent@~5.1.0", "glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob@^5.0.15": + "integrity" "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=" + "resolved" "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" + "version" "5.0.15" + dependencies: + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "2 || 3" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"glob@^7.0.0", "glob@^7.1.2", "glob@^7.1.3", "glob@~7.2.0", "glob@7.2.0": + "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + 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" + +"glob@7.1.3": + "integrity" "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz" + "version" "7.1.3" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"global-modules@^2.0.0": + "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" + "resolved" "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "global-prefix" "^3.0.0" + +"global-prefix@^3.0.0": + "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" + "resolved" "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "^1.3.5" + "kind-of" "^6.0.2" + "which" "^1.3.1" + +"global@~4.4.0": + "integrity" "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==" + "resolved" "https://registry.npmjs.org/global/-/global-4.4.0.tgz" + "version" "4.4.0" + dependencies: + "min-document" "^2.19.0" + "process" "^0.11.10" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globals@^13.6.0": + "integrity" "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==" + "resolved" "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz" + "version" "13.12.1" + dependencies: + "type-fest" "^0.20.2" + +"globals@^13.9.0": + "integrity" "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==" + "resolved" "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz" + "version" "13.12.1" + dependencies: + "type-fest" "^0.20.2" + +"globals@^9.18.0": + "integrity" "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + "resolved" "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz" + "version" "9.18.0" + +"globby@^10.0.1": + "integrity" "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==" + "resolved" "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz" + "version" "10.0.2" + 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" + +"globby@^11.0.0", "globby@^11.0.1": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"got@^7.1.0": + "integrity" "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==" + "resolved" "https://registry.npmjs.org/got/-/got-7.1.0.tgz" + "version" "7.1.0" + 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" + +"got@9.6.0": + "integrity" "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==" + "resolved" "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + "version" "9.6.0" + 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" + +"graceful-fs@^4.1.11", "graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.1.9", "graceful-fs@^4.2.0": + "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + "version" "4.2.9" + +"growl@1.10.5": + "integrity" "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + "resolved" "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz" + "version" "1.10.5" + +"handlebars@^4.0.1", "handlebars@^4.7.6": + "integrity" "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==" + "resolved" "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz" + "version" "4.7.7" + dependencies: + "minimist" "^1.2.5" + "neo-async" "^2.6.0" + "source-map" "^0.6.1" + "wordwrap" "^1.0.0" + optionalDependencies: + "uglify-js" "^3.1.4" + +"har-schema@^2.0.0": + "integrity" "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "resolved" "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" + "version" "2.0.0" + +"har-validator@~5.1.3": + "integrity" "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==" + "resolved" "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" + "version" "5.1.5" + dependencies: + "ajv" "^6.12.3" + "har-schema" "^2.0.0" + +"hardhat-contract-sizer@^2.1.1": + "integrity" "sha512-579Bm3QjrGyInL4RuPFPV/2jLDekw+fGmeLQ85GeiBciIKPHVS3ZYuZJDrp7E9J6A4Czk+QVCRA9YPT2Svn7lQ==" + "resolved" "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "chalk" "^4.0.0" + "cli-table3" "^0.6.0" + +"hardhat-gas-reporter@^1.0.8": + "integrity" "sha512-1G5thPnnhcwLHsFnl759f2tgElvuwdkzxlI65fC9PwxYMEe9cmjkVAAWTf3/3y8uP6ZSPiUiOW8PgZnykmZe0g==" + "resolved" "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.8.tgz" + "version" "1.0.8" + dependencies: + "array-uniq" "1.0.3" + "eth-gas-reporter" "^0.2.24" + "sha1" "^1.1.1" + +"hardhat@^2.0.0", "hardhat@^2.0.2", "hardhat@^2.0.4", "hardhat@^2.9.3": + "integrity" "sha512-7Vw99RbYbMZ15UzegOR/nqIYIqddZXvLwJGaX5sX4G5bydILnbjmDU6g3jMKJSiArEixS3vHAEaOs5CW1JQ3hg==" + "resolved" "https://registry.npmjs.org/hardhat/-/hardhat-2.9.3.tgz" + "version" "2.9.3" + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + "@ethereumjs/vm" "^5.6.0" + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + "abort-controller" "^3.0.0" + "adm-zip" "^0.4.16" + "aggregate-error" "^3.0.0" + "ansi-escapes" "^4.3.0" + "chalk" "^2.4.2" + "chokidar" "^3.4.0" + "ci-info" "^2.0.0" + "debug" "^4.1.1" + "enquirer" "^2.3.0" + "env-paths" "^2.2.0" + "ethereum-cryptography" "^0.1.2" + "ethereumjs-abi" "^0.6.8" + "ethereumjs-util" "^7.1.3" + "find-up" "^2.1.0" + "fp-ts" "1.19.3" + "fs-extra" "^7.0.1" + "glob" "^7.1.3" + "immutable" "^4.0.0-rc.12" + "io-ts" "1.10.4" + "lodash" "^4.17.11" + "merkle-patricia-tree" "^4.2.2" + "mnemonist" "^0.38.0" + "mocha" "^9.2.0" + "p-map" "^4.0.0" + "qs" "^6.7.0" + "raw-body" "^2.4.1" + "resolve" "1.17.0" + "semver" "^6.3.0" + "slash" "^3.0.0" + "solc" "0.7.3" + "source-map-support" "^0.5.13" + "stacktrace-parser" "^0.1.10" + "true-case-path" "^2.2.1" + "tsort" "0.0.1" + "undici" "^4.14.1" + "uuid" "^8.3.2" + "ws" "^7.4.6" + +"has-ansi@^2.0.0": + "integrity" "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" + "resolved" "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ansi-regex" "^2.0.0" + +"has-bigints@^1.0.1": + "integrity" "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + "resolved" "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" + "version" "1.0.1" + +"has-flag@^1.0.0": + "integrity" "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" + "version" "1.0.0" + +"has-flag@^3.0.0": + "integrity" "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-symbol-support-x@^1.4.1": + "integrity" "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + "resolved" "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz" + "version" "1.4.2" + +"has-symbols@^1.0.0", "has-symbols@^1.0.1", "has-symbols@^1.0.2": + "integrity" "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" + "version" "1.0.2" + +"has-to-string-tag-x@^1.2.0": + "integrity" "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==" + "resolved" "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "has-symbol-support-x" "^1.4.1" + +"has-tostringtag@^1.0.0": + "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" + "resolved" "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-symbols" "^1.0.2" + +"has-value@^0.3.1": + "integrity" "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=" + "resolved" "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "get-value" "^2.0.3" + "has-values" "^0.1.4" + "isobject" "^2.0.0" + +"has-value@^1.0.0": + "integrity" "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=" + "resolved" "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "get-value" "^2.0.6" + "has-values" "^1.0.0" + "isobject" "^3.0.0" + +"has-values@^0.1.4": + "integrity" "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "resolved" "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" + "version" "0.1.4" + +"has-values@^1.0.0": + "integrity" "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=" + "resolved" "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-number" "^3.0.0" + "kind-of" "^4.0.0" + +"has@^1.0.3", "has@~1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"hash-base@^3.0.0": + "integrity" "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==" + "resolved" "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "inherits" "^2.0.4" + "readable-stream" "^3.6.0" + "safe-buffer" "^5.2.0" + +"hash.js@^1.0.0", "hash.js@^1.0.3", "hash.js@^1.1.7", "hash.js@1.1.7": + "integrity" "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==" + "resolved" "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + "version" "1.1.7" + dependencies: + "inherits" "^2.0.3" + "minimalistic-assert" "^1.0.1" + +"hash.js@1.1.3": + "integrity" "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==" + "resolved" "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "inherits" "^2.0.3" + "minimalistic-assert" "^1.0.0" + +"he@1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + "version" "1.2.0" + +"heap@0.2.6": + "integrity" "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + "resolved" "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz" + "version" "0.2.6" + +"hmac-drbg@^1.0.1": + "integrity" "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=" + "resolved" "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "hash.js" "^1.0.3" + "minimalistic-assert" "^1.0.0" + "minimalistic-crypto-utils" "^1.0.1" + +"home-or-tmp@^2.0.0": + "integrity" "sha1-42w/LSyufXRqhX440Y1fMqeILbg=" + "resolved" "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "os-homedir" "^1.0.0" + "os-tmpdir" "^1.0.1" + +"hosted-git-info@^2.1.4", "hosted-git-info@^2.6.0": + "integrity" "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "resolved" "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + "version" "2.8.9" + +"htmlparser2@^7.1.2": + "integrity" "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.2" + "domutils" "^2.8.0" + "entities" "^3.0.1" + +"http-basic@^8.1.1": + "integrity" "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==" + "resolved" "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz" + "version" "8.1.3" + dependencies: + "caseless" "^0.12.0" + "concat-stream" "^1.6.2" + "http-response-object" "^3.0.1" + "parse-cache-control" "^1.0.1" + +"http-cache-semantics@^4.0.0": + "integrity" "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "resolved" "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" + "version" "4.1.0" + +"http-errors@1.8.1": + "integrity" "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" ">= 1.5.0 < 2" + "toidentifier" "1.0.1" + +"http-errors@2.0.0": + "integrity" "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "depd" "2.0.0" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" "2.0.1" + "toidentifier" "1.0.1" + +"http-https@^1.0.0": + "integrity" "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" + "resolved" "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz" + "version" "1.0.0" + +"http-response-object@^3.0.1": + "integrity" "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==" + "resolved" "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "@types/node" "^10.0.3" + +"http-signature@~1.2.0": + "integrity" "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=" + "resolved" "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "assert-plus" "^1.0.0" + "jsprim" "^1.2.2" + "sshpk" "^1.7.0" + +"https-proxy-agent@^5.0.0": + "integrity" "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==" + "resolved" "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "agent-base" "6" + "debug" "4" + +"husky@^4.3.0": + "integrity" "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==" + "resolved" "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz" + "version" "4.3.8" + dependencies: + "chalk" "^4.0.0" + "ci-info" "^2.0.0" + "compare-versions" "^3.6.0" + "cosmiconfig" "^7.0.0" + "find-versions" "^4.0.0" + "opencollective-postinstall" "^2.0.2" + "pkg-dir" "^5.0.0" + "please-upgrade-node" "^3.2.0" + "slash" "^3.0.0" + "which-pm-runs" "^1.0.0" + +"iconv-lite@^0.6.2": + "integrity" "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + "version" "0.6.3" + dependencies: + "safer-buffer" ">= 2.1.2 < 3.0.0" + +"iconv-lite@0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"idna-uts46-hx@^2.3.1": + "integrity" "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==" + "resolved" "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "punycode" "2.1.0" + +"ieee754@^1.1.13": + "integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "resolved" "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + "version" "1.2.1" + +"ignore@^4.0.6": + "integrity" "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + "version" "4.0.6" + +"ignore@^5.1.1", "ignore@^5.2.0": + "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + "version" "5.2.0" + +"immediate@^3.2.3": + "integrity" "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" + "resolved" "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz" + "version" "3.3.0" + +"immediate@~3.2.3": + "integrity" "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + "resolved" "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz" + "version" "3.2.3" + +"immutable@^4.0.0-rc.12": + "integrity" "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==" + "resolved" "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz" + "version" "4.0.0" + +"import-fresh@^3.0.0", "import-fresh@^3.2.1": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"imurmurhash@^0.1.4": + "integrity" "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"indent-string@^4.0.0": + "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "resolved" "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + "version" "4.0.0" + +"inflight@^1.0.4": + "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.1", "inherits@^2.0.3", "inherits@^2.0.4", "inherits@~2.0.1", "inherits@~2.0.3", "inherits@~2.0.4", "inherits@2", "inherits@2.0.4": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"ini@^1.3.5": + "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + "version" "1.3.8" + +"internal-slot@^1.0.3": + "integrity" "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==" + "resolved" "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "get-intrinsic" "^1.1.0" + "has" "^1.0.3" + "side-channel" "^1.0.4" + +"interpret@^1.0.0": + "integrity" "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "resolved" "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" + "version" "1.4.0" + +"invariant@^2.2.2": + "integrity" "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==" + "resolved" "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" + "version" "2.2.4" + dependencies: + "loose-envify" "^1.0.0" + +"invert-kv@^1.0.0": + "integrity" "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "resolved" "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" + "version" "1.0.0" + +"io-ts@1.10.4": + "integrity" "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==" + "resolved" "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz" + "version" "1.10.4" + dependencies: + "fp-ts" "^1.0.0" + +"ipaddr.js@1.9.1": + "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + "version" "1.9.1" + +"is-accessor-descriptor@^0.1.6": + "integrity" "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=" + "resolved" "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "kind-of" "^3.0.2" + +"is-accessor-descriptor@^1.0.0": + "integrity" "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==" + "resolved" "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-arguments@^1.0.4": + "integrity" "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" + "resolved" "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-bigint@^1.0.1": + "integrity" "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==" + "resolved" "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "has-bigints" "^1.0.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-boolean-object@^1.1.0": + "integrity" "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==" + "resolved" "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-buffer@^1.1.5": + "integrity" "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + "version" "1.1.6" + +"is-buffer@~2.0.3": + "integrity" "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + "resolved" "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + "version" "2.0.5" + +"is-callable@^1.1.3", "is-callable@^1.1.4", "is-callable@^1.2.4": + "integrity" "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "resolved" "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" + "version" "1.2.4" + +"is-ci@^2.0.0": + "integrity" "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==" + "resolved" "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ci-info" "^2.0.0" + +"is-core-module@^2.8.0", "is-core-module@^2.8.1": + "integrity" "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==" + "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" + "version" "2.8.1" + dependencies: + "has" "^1.0.3" + +"is-data-descriptor@^0.1.4": + "integrity" "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=" + "resolved" "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" + "version" "0.1.4" + dependencies: + "kind-of" "^3.0.2" + +"is-data-descriptor@^1.0.0": + "integrity" "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==" + "resolved" "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-date-object@^1.0.1": + "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" + "resolved" "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-descriptor@^0.1.0": + "integrity" "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==" + "resolved" "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "is-accessor-descriptor" "^0.1.6" + "is-data-descriptor" "^0.1.4" + "kind-of" "^5.0.0" + +"is-descriptor@^1.0.0", "is-descriptor@^1.0.2": + "integrity" "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==" + "resolved" "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-accessor-descriptor" "^1.0.0" + "is-data-descriptor" "^1.0.0" + "kind-of" "^6.0.2" + +"is-docker@^2.0.0": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-extendable@^0.1.0", "is-extendable@^0.1.1": + "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extendable@^1.0.1": + "integrity" "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==" + "resolved" "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "is-plain-object" "^2.0.4" + +"is-extglob@^2.1.1": + "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-finite@^1.0.0": + "integrity" "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + "resolved" "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz" + "version" "1.1.0" + +"is-fn@^1.0.0": + "integrity" "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=" + "resolved" "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz" + "version" "1.0.0" + +"is-fullwidth-code-point@^1.0.0": + "integrity" "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "number-is-nan" "^1.0.0" + +"is-fullwidth-code-point@^2.0.0": + "integrity" "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + "version" "2.0.0" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-function@^1.0.1": + "integrity" "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + "resolved" "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz" + "version" "1.0.2" + +"is-generator-function@^1.0.7": + "integrity" "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==" + "resolved" "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-glob@^4.0.0", "is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-hex-prefixed@1.0.0": + "integrity" "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + "resolved" "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" + "version" "1.0.0" + +"is-negative-zero@^2.0.1": + "integrity" "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + "resolved" "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + "version" "2.0.2" + +"is-number-object@^1.0.4": + "integrity" "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==" + "resolved" "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-number@^3.0.0": + "integrity" "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "kind-of" "^3.0.2" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-object@^1.0.1": + "integrity" "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" + "resolved" "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz" + "version" "1.0.2" + +"is-plain-obj@^1.1.0": + "integrity" "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + "version" "1.1.0" + +"is-plain-obj@^2.1.0": + "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + "version" "2.1.0" + +"is-plain-object@^2.0.3", "is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-regex@^1.0.4", "is-regex@^1.1.4", "is-regex@~1.1.4": + "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" + "resolved" "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-retry-allowed@^1.0.0": + "integrity" "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + "resolved" "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz" + "version" "1.2.0" + +"is-shared-array-buffer@^1.0.1": + "integrity" "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" + "resolved" "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz" + "version" "1.0.1" + +"is-stream@^1.0.0", "is-stream@^1.0.1": + "integrity" "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + "version" "1.1.0" + +"is-string@^1.0.5", "is-string@^1.0.7": + "integrity" "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==" + "resolved" "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + "version" "1.0.7" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-symbol@^1.0.2", "is-symbol@^1.0.3": + "integrity" "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==" + "resolved" "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "has-symbols" "^1.0.2" + +"is-typed-array@^1.1.3", "is-typed-array@^1.1.7": + "integrity" "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==" + "resolved" "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz" + "version" "1.1.8" + 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-typedarray@^1.0.0", "is-typedarray@~1.0.0": + "integrity" "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "version" "1.0.0" + +"is-unicode-supported@^0.1.0": + "integrity" "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + "resolved" "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + "version" "0.1.0" + +"is-url@^1.2.4": + "integrity" "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + "resolved" "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz" + "version" "1.2.4" + +"is-utf8@^0.2.0": + "integrity" "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + "resolved" "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + "version" "0.2.1" + +"is-weakref@^1.0.1": + "integrity" "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==" + "resolved" "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "call-bind" "^1.0.2" + +"is-windows@^1.0.2": + "integrity" "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "resolved" "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" + "version" "1.0.2" + +"is-wsl@^2.1.1": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"isarray@~1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isarray@0.0.1": + "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "version" "0.0.1" + +"isarray@1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isexe@^2.0.0": + "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^2.0.0": + "integrity" "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "isarray" "1.0.0" + +"isobject@^3.0.0", "isobject@^3.0.1": + "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"isstream@~0.1.2": + "integrity" "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "resolved" "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + "version" "0.1.2" + +"isurl@^1.0.0-alpha5": + "integrity" "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==" + "resolved" "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-to-string-tag-x" "^1.2.0" + "is-object" "^1.0.1" + +"js-sha3@^0.5.7": + "integrity" "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz" + "version" "0.5.7" + +"js-sha3@^0.8.0", "js-sha3@0.8.0": + "integrity" "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" + "version" "0.8.0" + +"js-sha3@0.5.7": + "integrity" "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz" + "version" "0.5.7" + +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-tokens@^3.0.2": + "integrity" "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz" + "version" "3.0.2" + +"js-yaml@^3.13.1", "js-yaml@3.x": + "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + "version" "3.14.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"js-yaml@3.13.1": + "integrity" "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz" + "version" "3.13.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"js-yaml@4.1.0": + "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "argparse" "^2.0.1" + +"jsbn@~0.1.0": + "integrity" "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "resolved" "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + "version" "0.1.1" + +"jsesc@^1.3.0": + "integrity" "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz" + "version" "1.3.0" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-buffer@3.0.0": + "integrity" "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + "resolved" "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" + "version" "3.0.0" + +"json-parse-better-errors@^1.0.1": + "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + "version" "1.0.2" + +"json-parse-even-better-errors@^2.3.0": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-rpc-engine@^3.4.0", "json-rpc-engine@^3.6.0": + "integrity" "sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==" + "resolved" "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz" + "version" "3.8.0" + dependencies: + "async" "^2.0.1" + "babel-preset-env" "^1.7.0" + "babelify" "^7.3.0" + "json-rpc-error" "^2.0.0" + "promise-to-callback" "^1.0.0" + "safe-event-emitter" "^1.0.1" + +"json-rpc-error@^2.0.0": + "integrity" "sha1-p6+cICg4tekFxyUOVH8a/3cligI=" + "resolved" "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "inherits" "^2.0.1" + +"json-rpc-random-id@^1.0.0": + "integrity" "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=" + "resolved" "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz" + "version" "1.0.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json-schema@0.4.0": + "integrity" "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "resolved" "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" + "version" "0.4.0" + +"json-stable-stringify-without-jsonify@^1.0.1": + "integrity" "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "resolved" "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + "version" "1.0.1" + +"json-stable-stringify@^1.0.1": + "integrity" "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=" + "resolved" "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "jsonify" "~0.0.0" + +"json-stringify-safe@~5.0.1": + "integrity" "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "resolved" "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + "version" "5.0.1" + +"json5@^0.5.1": + "integrity" "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + "resolved" "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" + "version" "0.5.1" + +"json5@^1.0.1": + "integrity" "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==" + "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "minimist" "^1.2.0" + +"json5@^2.1.2", "json5@^2.1.3": + "integrity" "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "minimist" "^1.2.5" + +"jsonfile@^2.1.0": + "integrity" "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=" + "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" + "version" "2.4.0" + optionalDependencies: + "graceful-fs" "^4.1.6" + +"jsonfile@^4.0.0": + "integrity" "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=" + "resolved" "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + "version" "4.0.0" + optionalDependencies: + "graceful-fs" "^4.1.6" + +"jsonify@~0.0.0": + "integrity" "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + "resolved" "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + "version" "0.0.0" + +"jsonschema@^1.2.4": + "integrity" "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==" + "resolved" "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz" + "version" "1.4.0" + +"jsprim@^1.2.2": + "integrity" "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==" + "resolved" "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "assert-plus" "1.0.0" + "extsprintf" "1.3.0" + "json-schema" "0.4.0" + "verror" "1.10.0" + +"keccak@^2.0.0": + "integrity" "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==" + "resolved" "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "bindings" "^1.5.0" + "inherits" "^2.0.4" + "nan" "^2.14.0" + "safe-buffer" "^5.2.0" + +"keccak@^3.0.0": + "integrity" "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==" + "resolved" "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "node-addon-api" "^2.0.0" + "node-gyp-build" "^4.2.0" + "readable-stream" "^3.6.0" + +"keccak@3.0.1": + "integrity" "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==" + "resolved" "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "node-addon-api" "^2.0.0" + "node-gyp-build" "^4.2.0" + +"keyv@^3.0.0": + "integrity" "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==" + "resolved" "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "json-buffer" "3.0.0" + +"kind-of@^3.0.2": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^3.0.3": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^3.2.0": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^4.0.0": + "integrity" "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^5.0.0": + "integrity" "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + "version" "5.1.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"klaw-sync@^6.0.0": + "integrity" "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==" + "resolved" "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "graceful-fs" "^4.1.11" + +"klaw@^1.0.0": + "integrity" "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=" + "resolved" "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" + "version" "1.3.1" + optionalDependencies: + "graceful-fs" "^4.1.9" + +"lcid@^1.0.0": + "integrity" "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=" + "resolved" "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "invert-kv" "^1.0.0" + +"level-codec@^9.0.0": + "integrity" "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==" + "resolved" "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz" + "version" "9.0.2" + dependencies: + "buffer" "^5.6.0" + +"level-codec@~7.0.0": + "integrity" "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + "resolved" "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz" + "version" "7.0.1" + +"level-concat-iterator@~2.0.0": + "integrity" "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==" + "resolved" "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz" + "version" "2.0.1" + +"level-errors@^1.0.3": + "integrity" "sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w==" + "resolved" "https://registry.npmjs.org/level-errors/-/level-errors-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "errno" "~0.1.1" + +"level-errors@^2.0.0", "level-errors@~2.0.0": + "integrity" "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==" + "resolved" "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "errno" "~0.1.1" + +"level-errors@~1.0.3": + "integrity" "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==" + "resolved" "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "errno" "~0.1.1" + +"level-iterator-stream@^2.0.3": + "integrity" "sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig==" + "resolved" "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz" + "version" "2.0.3" + dependencies: + "inherits" "^2.0.1" + "readable-stream" "^2.0.5" + "xtend" "^4.0.0" + +"level-iterator-stream@~1.3.0": + "integrity" "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=" + "resolved" "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "inherits" "^2.0.1" + "level-errors" "^1.0.3" + "readable-stream" "^1.0.33" + "xtend" "^4.0.0" + +"level-iterator-stream@~3.0.0": + "integrity" "sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g==" + "resolved" "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "inherits" "^2.0.1" + "readable-stream" "^2.3.6" + "xtend" "^4.0.0" + +"level-iterator-stream@~4.0.0": + "integrity" "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==" + "resolved" "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "inherits" "^2.0.4" + "readable-stream" "^3.4.0" + "xtend" "^4.0.2" + +"level-mem@^3.0.1": + "integrity" "sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg==" + "resolved" "https://registry.npmjs.org/level-mem/-/level-mem-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "level-packager" "~4.0.0" + "memdown" "~3.0.0" + +"level-mem@^5.0.1": + "integrity" "sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==" + "resolved" "https://registry.npmjs.org/level-mem/-/level-mem-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "level-packager" "^5.0.3" + "memdown" "^5.0.0" + +"level-packager@^5.0.3": + "integrity" "sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==" + "resolved" "https://registry.npmjs.org/level-packager/-/level-packager-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "encoding-down" "^6.3.0" + "levelup" "^4.3.2" + +"level-packager@~4.0.0": + "integrity" "sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q==" + "resolved" "https://registry.npmjs.org/level-packager/-/level-packager-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "encoding-down" "~5.0.0" + "levelup" "^3.0.0" + +"level-post@^1.0.7": + "integrity" "sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew==" + "resolved" "https://registry.npmjs.org/level-post/-/level-post-1.0.7.tgz" + "version" "1.0.7" + dependencies: + "ltgt" "^2.1.2" + +"level-sublevel@6.6.4": + "integrity" "sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA==" + "resolved" "https://registry.npmjs.org/level-sublevel/-/level-sublevel-6.6.4.tgz" + "version" "6.6.4" + dependencies: + "bytewise" "~1.1.0" + "level-codec" "^9.0.0" + "level-errors" "^2.0.0" + "level-iterator-stream" "^2.0.3" + "ltgt" "~2.1.1" + "pull-defer" "^0.2.2" + "pull-level" "^2.0.3" + "pull-stream" "^3.6.8" + "typewiselite" "~1.0.0" + "xtend" "~4.0.0" + +"level-supports@~1.0.0": + "integrity" "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==" + "resolved" "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "xtend" "^4.0.2" + +"level-ws@^1.0.0": + "integrity" "sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q==" + "resolved" "https://registry.npmjs.org/level-ws/-/level-ws-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "inherits" "^2.0.3" + "readable-stream" "^2.2.8" + "xtend" "^4.0.1" + +"level-ws@^2.0.0": + "integrity" "sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==" + "resolved" "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "inherits" "^2.0.3" + "readable-stream" "^3.1.0" + "xtend" "^4.0.1" + +"level-ws@0.0.0": + "integrity" "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=" + "resolved" "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz" + "version" "0.0.0" + dependencies: + "readable-stream" "~1.0.15" + "xtend" "~2.1.1" + +"levelup@^1.2.1": + "integrity" "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==" + "resolved" "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz" + "version" "1.3.9" + dependencies: + "deferred-leveldown" "~1.2.1" + "level-codec" "~7.0.0" + "level-errors" "~1.0.3" + "level-iterator-stream" "~1.3.0" + "prr" "~1.0.1" + "semver" "~5.4.1" + "xtend" "~4.0.0" + +"levelup@^3.0.0", "levelup@3.1.1": + "integrity" "sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg==" + "resolved" "https://registry.npmjs.org/levelup/-/levelup-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "deferred-leveldown" "~4.0.0" + "level-errors" "~2.0.0" + "level-iterator-stream" "~3.0.0" + "xtend" "~4.0.0" + +"levelup@^4.3.2": + "integrity" "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==" + "resolved" "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz" + "version" "4.4.0" + 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" + +"levn@^0.4.1": + "integrity" "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==" + "resolved" "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + "version" "0.4.1" + dependencies: + "prelude-ls" "^1.2.1" + "type-check" "~0.4.0" + +"levn@~0.3.0": + "integrity" "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=" + "resolved" "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "prelude-ls" "~1.1.2" + "type-check" "~0.3.2" + +"limiter@^1.1.5": + "integrity" "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + "resolved" "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz" + "version" "1.1.5" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"load-json-file@^1.0.0": + "integrity" "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" + "resolved" "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz" + "version" "1.1.0" + 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" + +"load-json-file@^4.0.0": + "integrity" "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=" + "resolved" "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "graceful-fs" "^4.1.2" + "parse-json" "^4.0.0" + "pify" "^3.0.0" + "strip-bom" "^3.0.0" + +"locate-path@^2.0.0": + "integrity" "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "p-locate" "^2.0.0" + "path-exists" "^3.0.0" + +"locate-path@^3.0.0": + "integrity" "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "p-locate" "^3.0.0" + "path-exists" "^3.0.0" + +"locate-path@^6.0.0": + "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "p-locate" "^5.0.0" + +"lodash.assign@^4.0.3", "lodash.assign@^4.0.6": + "integrity" "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + "resolved" "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" + "version" "4.2.0" + +"lodash.debounce@^4.0.8": + "integrity" "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.merge@^4.6.2": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.truncate@^4.4.2": + "integrity" "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" + "resolved" "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + "version" "4.4.2" + +"lodash@^4.17.11", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.19", "lodash@^4.17.21", "lodash@^4.17.4": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"lodash@4.17.20": + "integrity" "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" + "version" "4.17.20" + +"log-symbols@3.0.0": + "integrity" "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==" + "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "chalk" "^2.4.2" + +"log-symbols@4.1.0": + "integrity" "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==" + "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "chalk" "^4.1.0" + "is-unicode-supported" "^0.1.0" + +"looper@^2.0.0": + "integrity" "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=" + "resolved" "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz" + "version" "2.0.0" + +"looper@^3.0.0": + "integrity" "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k=" + "resolved" "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz" + "version" "3.0.0" + +"loose-envify@^1.0.0": + "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" + "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"loupe@^2.3.1": + "integrity" "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==" + "resolved" "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" + "version" "2.3.4" + dependencies: + "get-func-name" "^2.0.0" + +"lowercase-keys@^1.0.0", "lowercase-keys@^1.0.1": + "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + "version" "1.0.1" + +"lowercase-keys@^2.0.0": + "integrity" "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + "resolved" "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + "version" "2.0.0" + +"lru_map@^0.3.3": + "integrity" "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" + "resolved" "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" + "version" "0.3.3" + +"lru-cache@^3.2.0": + "integrity" "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "pseudomap" "^1.0.1" + +"lru-cache@^5.1.1", "lru-cache@5.1.1": + "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "yallist" "^3.0.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"ltgt@^2.1.2", "ltgt@~2.2.0": + "integrity" "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" + "resolved" "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz" + "version" "2.2.1" + +"ltgt@~2.1.1": + "integrity" "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=" + "resolved" "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz" + "version" "2.1.3" + +"make-dir@^2.0.0", "make-dir@^2.1.0": + "integrity" "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pify" "^4.0.1" + "semver" "^5.6.0" + +"map-cache@^0.2.2": + "integrity" "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "resolved" "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" + "version" "0.2.2" + +"map-visit@^1.0.0": + "integrity" "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=" + "resolved" "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "object-visit" "^1.0.0" + +"markdown-table@^1.1.3": + "integrity" "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==" + "resolved" "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz" + "version" "1.1.3" + +"mcl-wasm@^0.7.1": + "integrity" "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==" + "resolved" "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz" + "version" "0.7.9" + +"md5.js@^1.3.4": + "integrity" "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==" + "resolved" "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + "version" "1.3.5" + dependencies: + "hash-base" "^3.0.0" + "inherits" "^2.0.1" + "safe-buffer" "^5.1.2" + +"media-typer@0.3.0": + "integrity" "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "version" "0.3.0" + +"memdown@^1.0.0": + "integrity" "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=" + "resolved" "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz" + "version" "1.4.1" + 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" + +"memdown@^5.0.0": + "integrity" "sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==" + "resolved" "https://registry.npmjs.org/memdown/-/memdown-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "abstract-leveldown" "~6.2.1" + "functional-red-black-tree" "~1.0.1" + "immediate" "~3.2.3" + "inherits" "~2.0.1" + "ltgt" "~2.2.0" + "safe-buffer" "~5.2.0" + +"memdown@~3.0.0": + "integrity" "sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA==" + "resolved" "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "abstract-leveldown" "~5.0.0" + "functional-red-black-tree" "~1.0.1" + "immediate" "~3.2.3" + "inherits" "~2.0.1" + "ltgt" "~2.2.0" + "safe-buffer" "~5.1.1" + +"memorystream@^0.3.1": + "integrity" "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + "resolved" "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" + "version" "0.3.1" + +"merge-descriptors@1.0.1": + "integrity" "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "version" "1.0.1" + +"merge2@^1.2.3", "merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"merkle-patricia-tree@^2.1.2", "merkle-patricia-tree@^2.3.2": + "integrity" "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==" + "resolved" "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz" + "version" "2.3.2" + dependencies: + "async" "^1.4.2" + "ethereumjs-util" "^5.0.0" + "level-ws" "0.0.0" + "levelup" "^1.2.1" + "memdown" "^1.0.0" + "readable-stream" "^2.0.0" + "rlp" "^2.0.0" + "semaphore" ">=1.0.1" + +"merkle-patricia-tree@^4.2.2": + "integrity" "sha512-S4xevdXl5KvdBGgUxhQcxoep0onqXiIhzfwZp4M78kIuJH3Pu9o9IUgqhzSFOR2ykLO6t265026Xb6PY0q2UFQ==" + "resolved" "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "@types/levelup" "^4.3.0" + "ethereumjs-util" "^7.1.4" + "level-mem" "^5.0.1" + "level-ws" "^2.0.0" + "readable-stream" "^3.6.0" + "semaphore-async-await" "^1.5.1" + +"merkle-patricia-tree@^4.2.3": + "integrity" "sha512-S4xevdXl5KvdBGgUxhQcxoep0onqXiIhzfwZp4M78kIuJH3Pu9o9IUgqhzSFOR2ykLO6t265026Xb6PY0q2UFQ==" + "resolved" "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "@types/levelup" "^4.3.0" + "ethereumjs-util" "^7.1.4" + "level-mem" "^5.0.1" + "level-ws" "^2.0.0" + "readable-stream" "^3.6.0" + "semaphore-async-await" "^1.5.1" + +"merkle-patricia-tree@3.0.0": + "integrity" "sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ==" + "resolved" "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "async" "^2.6.1" + "ethereumjs-util" "^5.2.0" + "level-mem" "^3.0.1" + "level-ws" "^1.0.0" + "readable-stream" "^3.0.6" + "rlp" "^2.0.0" + "semaphore" ">=1.0.1" + +"methods@~1.1.2": + "integrity" "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "version" "1.1.2" + +"micromatch@^3.1.4": + "integrity" "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + "version" "3.1.10" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "braces" "^2.3.1" + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "extglob" "^2.0.4" + "fragment-cache" "^0.2.1" + "kind-of" "^6.0.2" + "nanomatch" "^1.2.9" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.2" + +"micromatch@^4.0.2", "micromatch@^4.0.4": + "integrity" "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" + "version" "4.0.4" + dependencies: + "braces" "^3.0.1" + "picomatch" "^2.2.3" + +"miller-rabin@^4.0.0": + "integrity" "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==" + "resolved" "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "bn.js" "^4.0.0" + "brorand" "^1.0.1" + +"mime-db@1.51.0": + "integrity" "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" + "version" "1.51.0" + +"mime-types@^2.1.12", "mime-types@^2.1.16", "mime-types@~2.1.19", "mime-types@~2.1.24", "mime-types@~2.1.34": + "integrity" "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" + "version" "2.1.34" + dependencies: + "mime-db" "1.51.0" + +"mime@1.6.0": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-response@^1.0.0", "mimic-response@^1.0.1": + "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + "version" "1.0.1" + +"min-document@^2.19.0": + "integrity" "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=" + "resolved" "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz" + "version" "2.19.0" + dependencies: + "dom-walk" "^0.1.0" + +"minimalistic-assert@^1.0.0", "minimalistic-assert@^1.0.1": + "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + "version" "1.0.1" + +"minimalistic-crypto-utils@^1.0.1": + "integrity" "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "resolved" "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4", "minimatch@2 || 3": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@3.0.4": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@4.2.1": + "integrity" "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "brace-expansion" "^1.1.7" + +"minimist@^1.2.0", "minimist@^1.2.5", "minimist@~1.2.5": + "integrity" "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" + "version" "1.2.5" + +"minipass@^2.6.0", "minipass@^2.9.0": + "integrity" "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==" + "resolved" "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz" + "version" "2.9.0" + dependencies: + "safe-buffer" "^5.1.2" + "yallist" "^3.0.0" + +"minizlib@^1.3.3": + "integrity" "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==" + "resolved" "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz" + "version" "1.3.3" + dependencies: + "minipass" "^2.9.0" + +"mixin-deep@^1.2.0": + "integrity" "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==" + "resolved" "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "for-in" "^1.0.2" + "is-extendable" "^1.0.1" + +"mkdirp-promise@^5.0.1": + "integrity" "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=" + "resolved" "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "mkdirp" "*" + +"mkdirp@*": + "integrity" "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + "version" "1.0.4" + +"mkdirp@^0.5.1", "mkdirp@^0.5.5", "mkdirp@0.5.5", "mkdirp@0.5.x": + "integrity" "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==" + "resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" + "version" "0.5.5" + dependencies: + "minimist" "^1.2.5" + +"mnemonist@^0.38.0": + "integrity" "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==" + "resolved" "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz" + "version" "0.38.5" + dependencies: + "obliterator" "^2.0.0" + +"mocha@^7.1.1": + "integrity" "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==" + "resolved" "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "ansi-colors" "3.2.3" + "browser-stdout" "1.3.1" + "chokidar" "3.3.0" + "debug" "3.2.6" + "diff" "3.5.0" + "escape-string-regexp" "1.0.5" + "find-up" "3.0.0" + "glob" "7.1.3" + "growl" "1.10.5" + "he" "1.2.0" + "js-yaml" "3.13.1" + "log-symbols" "3.0.0" + "minimatch" "3.0.4" + "mkdirp" "0.5.5" + "ms" "2.1.1" + "node-environment-flags" "1.0.6" + "object.assign" "4.1.0" + "strip-json-comments" "2.0.1" + "supports-color" "6.0.0" + "which" "1.3.1" + "wide-align" "1.1.3" + "yargs" "13.3.2" + "yargs-parser" "13.1.2" + "yargs-unparser" "1.6.0" + +"mocha@^9.2.0": + "integrity" "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==" + "resolved" "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz" + "version" "9.2.2" + dependencies: + "@ungap/promise-all-settled" "1.1.2" + "ansi-colors" "4.1.1" + "browser-stdout" "1.3.1" + "chokidar" "3.5.3" + "debug" "4.3.3" + "diff" "5.0.0" + "escape-string-regexp" "4.0.0" + "find-up" "5.0.0" + "glob" "7.2.0" + "growl" "1.10.5" + "he" "1.2.0" + "js-yaml" "4.1.0" + "log-symbols" "4.1.0" + "minimatch" "4.2.1" + "ms" "2.1.3" + "nanoid" "3.3.1" + "serialize-javascript" "6.0.0" + "strip-json-comments" "3.1.1" + "supports-color" "8.1.1" + "which" "2.0.2" + "workerpool" "6.2.0" + "yargs" "16.2.0" + "yargs-parser" "20.2.4" + "yargs-unparser" "2.0.0" + +"mock-fs@^4.1.0": + "integrity" "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==" + "resolved" "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz" + "version" "4.14.0" + +"ms@^2.1.1", "ms@2.1.3": + "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + "version" "2.1.3" + +"ms@2.0.0": + "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"ms@2.1.1": + "integrity" "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" + "version" "2.1.1" + +"ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"multibase@^0.7.0": + "integrity" "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==" + "resolved" "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "base-x" "^3.0.8" + "buffer" "^5.5.0" + +"multibase@~0.6.0": + "integrity" "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==" + "resolved" "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz" + "version" "0.6.1" + dependencies: + "base-x" "^3.0.8" + "buffer" "^5.5.0" + +"multicodec@^0.5.5": + "integrity" "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==" + "resolved" "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz" + "version" "0.5.7" + dependencies: + "varint" "^5.0.0" + +"multicodec@^1.0.0": + "integrity" "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==" + "resolved" "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "buffer" "^5.6.0" + "varint" "^5.0.0" + +"multihashes@^0.4.15", "multihashes@~0.4.15": + "integrity" "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==" + "resolved" "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz" + "version" "0.4.21" + dependencies: + "buffer" "^5.5.0" + "multibase" "^0.7.0" + "varint" "^5.0.0" + +"nan@^2.14.0": + "integrity" "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + "resolved" "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz" + "version" "2.15.0" + +"nano-json-stream-parser@^0.1.2": + "integrity" "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" + "resolved" "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz" + "version" "0.1.2" + +"nanoid@3.3.1": + "integrity" "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz" + "version" "3.3.1" + +"nanomatch@^1.2.9": + "integrity" "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==" + "resolved" "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" + "version" "1.2.13" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "fragment-cache" "^0.2.1" + "is-windows" "^1.0.2" + "kind-of" "^6.0.2" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"natural-compare@^1.4.0": + "integrity" "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "resolved" "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + "version" "1.4.0" + +"negotiator@0.6.3": + "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + "version" "0.6.3" + +"neo-async@^2.6.0": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"next-tick@~1.0.0": + "integrity" "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "resolved" "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" + "version" "1.0.0" + +"nice-try@^1.0.4": + "integrity" "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "resolved" "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" + "version" "1.0.5" + +"node-addon-api@^2.0.0": + "integrity" "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + "resolved" "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" + "version" "2.0.2" + +"node-emoji@^1.10.0": + "integrity" "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==" + "resolved" "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz" + "version" "1.11.0" + dependencies: + "lodash" "^4.17.21" + +"node-environment-flags@1.0.6": + "integrity" "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==" + "resolved" "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "object.getownpropertydescriptors" "^2.0.3" + "semver" "^5.7.0" + +"node-fetch@^2.6.0", "node-fetch@^2.6.1": + "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" + "version" "2.6.7" + dependencies: + "whatwg-url" "^5.0.0" + +"node-fetch@~1.7.1": + "integrity" "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz" + "version" "1.7.3" + dependencies: + "encoding" "^0.1.11" + "is-stream" "^1.0.1" + +"node-fetch@2.6.1": + "integrity" "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" + "version" "2.6.1" + +"node-gyp-build@^4.2.0", "node-gyp-build@^4.3.0": + "integrity" "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==" + "resolved" "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz" + "version" "4.3.0" + +"node-releases@^2.0.2": + "integrity" "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" + "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz" + "version" "2.0.2" + +"nofilter@^1.0.4": + "integrity" "sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==" + "resolved" "https://registry.npmjs.org/nofilter/-/nofilter-1.0.4.tgz" + "version" "1.0.4" + +"nopt@3.x": + "integrity" "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=" + "resolved" "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + "version" "3.0.6" + dependencies: + "abbrev" "1" + +"normalize-package-data@^2.3.2": + "integrity" "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==" + "resolved" "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "hosted-git-info" "^2.1.4" + "resolve" "^1.10.0" + "semver" "2 || 3 || 4 || 5" + "validate-npm-package-license" "^3.0.1" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"normalize-url@^4.1.0": + "integrity" "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + "resolved" "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + "version" "4.5.1" + +"npm-run-all@^4.1.5": + "integrity" "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==" + "resolved" "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz" + "version" "4.1.5" + dependencies: + "ansi-styles" "^3.2.1" + "chalk" "^2.4.1" + "cross-spawn" "^6.0.5" + "memorystream" "^0.3.1" + "minimatch" "^3.0.4" + "pidtree" "^0.3.0" + "read-pkg" "^3.0.0" + "shell-quote" "^1.6.1" + "string.prototype.padend" "^3.0.0" + +"number-is-nan@^1.0.0": + "integrity" "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "resolved" "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + "version" "1.0.1" + +"number-to-bn@1.7.0": + "integrity" "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=" + "resolved" "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "bn.js" "4.11.6" + "strip-hex-prefix" "1.0.0" + +"oauth-sign@~0.9.0": + "integrity" "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "resolved" "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" + "version" "0.9.0" + +"object-assign@^4", "object-assign@^4.0.0", "object-assign@^4.1.0", "object-assign@^4.1.1": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-copy@^0.1.0": + "integrity" "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=" + "resolved" "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "copy-descriptor" "^0.1.0" + "define-property" "^0.2.5" + "kind-of" "^3.0.3" + +"object-inspect@^1.11.0", "object-inspect@^1.9.0", "object-inspect@~1.12.0": + "integrity" "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "resolved" "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" + "version" "1.12.0" + +"object-is@^1.0.1": + "integrity" "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==" + "resolved" "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"object-keys@^1.0.11", "object-keys@^1.0.12", "object-keys@^1.1.1": + "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + "version" "1.1.1" + +"object-keys@~0.4.0": + "integrity" "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + "resolved" "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" + "version" "0.4.0" + +"object-visit@^1.0.0": + "integrity" "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=" + "resolved" "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "isobject" "^3.0.0" + +"object.assign@^4.1.0", "object.assign@^4.1.2": + "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" + "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "call-bind" "^1.0.0" + "define-properties" "^1.1.3" + "has-symbols" "^1.0.1" + "object-keys" "^1.1.1" + +"object.assign@4.1.0": + "integrity" "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==" + "resolved" "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "define-properties" "^1.1.2" + "function-bind" "^1.1.1" + "has-symbols" "^1.0.0" + "object-keys" "^1.0.11" + +"object.getownpropertydescriptors@^2.0.3", "object.getownpropertydescriptors@^2.1.1": + "integrity" "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==" + "resolved" "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz" + "version" "2.1.3" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + +"object.pick@^1.3.0": + "integrity" "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=" + "resolved" "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "isobject" "^3.0.1" + +"object.values@^1.1.5": + "integrity" "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==" + "resolved" "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + +"obliterator@^2.0.0": + "integrity" "sha512-g0TrA7SbUggROhDPK8cEu/qpItwH2LSKcNl4tlfBNT54XY+nOsqrs0Q68h1V9b3HOSpIWv15jb1lax2hAggdIg==" + "resolved" "https://registry.npmjs.org/obliterator/-/obliterator-2.0.2.tgz" + "version" "2.0.2" + +"oboe@2.1.4": + "integrity" "sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY=" + "resolved" "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "http-https" "^1.0.0" + +"oboe@2.1.5": + "integrity" "sha1-VVQoTFQ6ImbXo48X4HOCH73jk80=" + "resolved" "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz" + "version" "2.1.5" + dependencies: + "http-https" "^1.0.0" + +"on-finished@~2.3.0": + "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" + +"once@^1.3.0", "once@^1.3.1", "once@^1.4.0", "once@1.x": + "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" + +"open@^7.4.2": + "integrity" "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==" + "resolved" "https://registry.npmjs.org/open/-/open-7.4.2.tgz" + "version" "7.4.2" + dependencies: + "is-docker" "^2.0.0" + "is-wsl" "^2.1.1" + +"opencollective-postinstall@^2.0.2": + "integrity" "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==" + "resolved" "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz" + "version" "2.0.3" + +"optionator@^0.8.1": + "integrity" "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==" + "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" + "version" "0.8.3" + 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" + +"optionator@^0.9.1": + "integrity" "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==" + "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + "version" "0.9.1" + dependencies: + "deep-is" "^0.1.3" + "fast-levenshtein" "^2.0.6" + "levn" "^0.4.1" + "prelude-ls" "^1.2.1" + "type-check" "^0.4.0" + "word-wrap" "^1.2.3" + +"os-homedir@^1.0.0": + "integrity" "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "resolved" "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + "version" "1.0.2" + +"os-locale@^1.4.0": + "integrity" "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=" + "resolved" "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "lcid" "^1.0.0" + +"os-tmpdir@^1.0.1", "os-tmpdir@~1.0.2": + "integrity" "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "resolved" "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + "version" "1.0.2" + +"p-cancelable@^0.3.0": + "integrity" "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz" + "version" "0.3.0" + +"p-cancelable@^1.0.0": + "integrity" "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + "version" "1.1.0" + +"p-finally@^1.0.0": + "integrity" "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "resolved" "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + "version" "1.0.0" + +"p-limit@^1.1.0": + "integrity" "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "p-try" "^1.0.0" + +"p-limit@^2.0.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "p-try" "^2.0.0" + +"p-limit@^3.0.2": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "yocto-queue" "^0.1.0" + +"p-locate@^2.0.0": + "integrity" "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "p-limit" "^1.1.0" + +"p-locate@^3.0.0": + "integrity" "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "p-limit" "^2.0.0" + +"p-locate@^5.0.0": + "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-limit" "^3.0.2" + +"p-map@^4.0.0": + "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" + "resolved" "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "aggregate-error" "^3.0.0" + +"p-timeout@^1.1.1": + "integrity" "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=" + "resolved" "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "p-finally" "^1.0.0" + +"p-try@^1.0.0": + "integrity" "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" + "version" "1.0.0" + +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" + +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + +"parse-asn1@^5.0.0", "parse-asn1@^5.1.5": + "integrity" "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==" + "resolved" "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" + "version" "5.1.6" + 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" + +"parse-cache-control@^1.0.1": + "integrity" "sha1-juqz5U+laSD+Fro493+iGqzC104=" + "resolved" "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz" + "version" "1.0.1" + +"parse-headers@^2.0.0": + "integrity" "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw==" + "resolved" "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.4.tgz" + "version" "2.0.4" + +"parse-json@^2.2.0": + "integrity" "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "error-ex" "^1.2.0" + +"parse-json@^4.0.0": + "integrity" "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "error-ex" "^1.3.1" + "json-parse-better-errors" "^1.0.1" + +"parse-json@^5.0.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "@babel/code-frame" "^7.0.0" + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascalcase@^0.1.1": + "integrity" "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "resolved" "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" + "version" "0.1.1" + +"patch-package@^6.2.2": + "integrity" "sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ==" + "resolved" "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz" + "version" "6.4.7" + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + "chalk" "^2.4.2" + "cross-spawn" "^6.0.5" + "find-yarn-workspace-root" "^2.0.0" + "fs-extra" "^7.0.1" + "is-ci" "^2.0.0" + "klaw-sync" "^6.0.0" + "minimist" "^1.2.0" + "open" "^7.4.2" + "rimraf" "^2.6.3" + "semver" "^5.6.0" + "slash" "^2.0.0" + "tmp" "^0.0.33" + +"patch-package@6.2.2": + "integrity" "sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg==" + "resolved" "https://registry.npmjs.org/patch-package/-/patch-package-6.2.2.tgz" + "version" "6.2.2" + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + "chalk" "^2.4.2" + "cross-spawn" "^6.0.5" + "find-yarn-workspace-root" "^1.2.1" + "fs-extra" "^7.0.1" + "is-ci" "^2.0.0" + "klaw-sync" "^6.0.0" + "minimist" "^1.2.0" + "rimraf" "^2.6.3" + "semver" "^5.6.0" + "slash" "^2.0.0" + "tmp" "^0.0.33" + +"path-browserify@^1.0.0": + "integrity" "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + "resolved" "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" + "version" "1.0.1" + +"path-exists@^2.0.0": + "integrity" "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pinkie-promise" "^2.0.0" + +"path-exists@^3.0.0": + "integrity" "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + "version" "3.0.0" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-is-absolute@^1.0.0", "path-is-absolute@^1.0.1": + "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-key@^2.0.1": + "integrity" "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + "version" "2.0.1" + +"path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.6", "path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@0.1.7": + "integrity" "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "version" "0.1.7" + +"path-type@^1.0.0": + "integrity" "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "graceful-fs" "^4.1.2" + "pify" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"path-type@^3.0.0": + "integrity" "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "pify" "^3.0.0" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"pathval@^1.1.1": + "integrity" "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" + "resolved" "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + "version" "1.1.1" + +"pbkdf2@^3.0.17", "pbkdf2@^3.0.3", "pbkdf2@^3.0.9": + "integrity" "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==" + "resolved" "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" + "version" "3.1.2" + 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" + +"performance-now@^2.1.0": + "integrity" "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "resolved" "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" + "version" "2.1.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pidtree@^0.3.0": + "integrity" "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==" + "resolved" "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz" + "version" "0.3.1" + +"pify@^2.0.0", "pify@^2.3.0": + "integrity" "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "resolved" "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + "version" "2.3.0" + +"pify@^3.0.0": + "integrity" "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "resolved" "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" + "version" "3.0.0" + +"pify@^4.0.1": + "integrity" "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "resolved" "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + "version" "4.0.1" + +"pinkie-promise@^2.0.0": + "integrity" "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" + "resolved" "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "pinkie" "^2.0.0" + +"pinkie@^2.0.0": + "integrity" "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "resolved" "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + "version" "2.0.4" + +"pirates@^4.0.5": + "integrity" "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" + "resolved" "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz" + "version" "4.0.5" + +"pkg-dir@^3.0.0": + "integrity" "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "find-up" "^3.0.0" + +"pkg-dir@^5.0.0": + "integrity" "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "find-up" "^5.0.0" + +"please-upgrade-node@^3.2.0": + "integrity" "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==" + "resolved" "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "semver-compare" "^1.0.0" + +"posix-character-classes@^0.1.0": + "integrity" "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "resolved" "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" + "version" "0.1.1" + +"postinstall-postinstall@^2.1.0": + "integrity" "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==" + "resolved" "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz" + "version" "2.1.0" + +"precond@0.2": + "integrity" "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + "resolved" "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz" + "version" "0.2.3" + +"prelude-ls@^1.2.1": + "integrity" "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "resolved" "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + "version" "1.2.1" + +"prelude-ls@~1.1.2": + "integrity" "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "resolved" "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" + "version" "1.1.2" + +"prepend-http@^1.0.1": + "integrity" "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz" + "version" "1.0.4" + +"prepend-http@^2.0.0": + "integrity" "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + "version" "2.0.0" + +"prettier@^2.1.2": + "integrity" "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==" + "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz" + "version" "2.5.1" + +"printj@~1.3.1": + "integrity" "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==" + "resolved" "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz" + "version" "1.3.1" + +"private@^0.1.6", "private@^0.1.8": + "integrity" "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "resolved" "https://registry.npmjs.org/private/-/private-0.1.8.tgz" + "version" "0.1.8" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"process@^0.11.10": + "integrity" "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz" + "version" "0.11.10" + +"progress@^2.0.0": + "integrity" "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "resolved" "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + "version" "2.0.3" + +"promise-to-callback@^1.0.0": + "integrity" "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=" + "resolved" "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-fn" "^1.0.0" + "set-immediate-shim" "^1.0.1" + +"promise@^8.0.0": + "integrity" "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==" + "resolved" "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz" + "version" "8.1.0" + dependencies: + "asap" "~2.0.6" + +"proxy-addr@~2.0.7": + "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "forwarded" "0.2.0" + "ipaddr.js" "1.9.1" + +"prr@~1.0.1": + "integrity" "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "resolved" "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" + "version" "1.0.1" + +"pseudomap@^1.0.1": + "integrity" "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "resolved" "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" + "version" "1.0.2" + +"psl@^1.1.28": + "integrity" "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "resolved" "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" + "version" "1.8.0" + +"public-encrypt@^4.0.0": + "integrity" "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==" + "resolved" "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" + "version" "4.0.3" + 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" + +"pull-cat@^1.1.9": + "integrity" "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=" + "resolved" "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz" + "version" "1.1.11" + +"pull-defer@^0.2.2": + "integrity" "sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA==" + "resolved" "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.3.tgz" + "version" "0.2.3" + +"pull-level@^2.0.3": + "integrity" "sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg==" + "resolved" "https://registry.npmjs.org/pull-level/-/pull-level-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "level-post" "^1.0.7" + "pull-cat" "^1.1.9" + "pull-live" "^1.0.1" + "pull-pushable" "^2.0.0" + "pull-stream" "^3.4.0" + "pull-window" "^2.1.4" + "stream-to-pull-stream" "^1.7.1" + +"pull-live@^1.0.1": + "integrity" "sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU=" + "resolved" "https://registry.npmjs.org/pull-live/-/pull-live-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "pull-cat" "^1.1.9" + "pull-stream" "^3.4.0" + +"pull-pushable@^2.0.0": + "integrity" "sha1-Xy867UethpGfAbEqLpnW8b13ZYE=" + "resolved" "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz" + "version" "2.2.0" + +"pull-stream@^3.2.3", "pull-stream@^3.4.0", "pull-stream@^3.6.8": + "integrity" "sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew==" + "resolved" "https://registry.npmjs.org/pull-stream/-/pull-stream-3.6.14.tgz" + "version" "3.6.14" + +"pull-window@^2.1.4": + "integrity" "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=" + "resolved" "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "looper" "^2.0.0" + +"pump@^3.0.0": + "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" + "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "end-of-stream" "^1.1.0" + "once" "^1.3.1" + +"punycode@^2.1.0", "punycode@^2.1.1": + "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + "version" "2.1.1" + +"punycode@1.3.2": + "integrity" "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + "version" "1.3.2" + +"punycode@2.1.0": + "integrity" "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz" + "version" "2.1.0" + +"qs@^6.4.0", "qs@^6.7.0": + "integrity" "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz" + "version" "6.10.3" + dependencies: + "side-channel" "^1.0.4" + +"qs@~6.5.2": + "integrity" "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz" + "version" "6.5.3" + +"qs@6.9.7": + "integrity" "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"query-string@^5.0.1": + "integrity" "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==" + "resolved" "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "decode-uri-component" "^0.2.0" + "object-assign" "^4.1.0" + "strict-uri-encode" "^1.0.0" + +"querystring@0.2.0": + "integrity" "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "resolved" "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + "version" "0.2.0" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"randombytes@^2.0.0", "randombytes@^2.0.1", "randombytes@^2.0.5", "randombytes@^2.0.6", "randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"randomfill@^1.0.3": + "integrity" "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==" + "resolved" "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "randombytes" "^2.0.5" + "safe-buffer" "^5.1.0" + +"range-parser@~1.2.1": + "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + "version" "1.2.1" + +"raw-body@^2.4.1": + "integrity" "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" + "version" "2.5.1" + dependencies: + "bytes" "3.1.2" + "http-errors" "2.0.0" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"raw-body@2.4.3": + "integrity" "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz" + "version" "2.4.3" + dependencies: + "bytes" "3.1.2" + "http-errors" "1.8.1" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"read-pkg-up@^1.0.1": + "integrity" "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" + "resolved" "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "find-up" "^1.0.0" + "read-pkg" "^1.0.0" + +"read-pkg@^1.0.0": + "integrity" "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" + "resolved" "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "load-json-file" "^1.0.0" + "normalize-package-data" "^2.3.2" + "path-type" "^1.0.0" + +"read-pkg@^3.0.0": + "integrity" "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=" + "resolved" "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "load-json-file" "^4.0.0" + "normalize-package-data" "^2.3.2" + "path-type" "^3.0.0" + +"readable-stream@^1.0.33": + "integrity" "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "version" "1.1.14" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.1" + "isarray" "0.0.1" + "string_decoder" "~0.10.x" + +"readable-stream@^2.0.0", "readable-stream@^2.0.5", "readable-stream@^2.2.2", "readable-stream@^2.2.9", "readable-stream@^2.3.6", "readable-stream@~2.3.6": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + 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" + +"readable-stream@^2.2.8": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + 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" + +"readable-stream@^3.0.6": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readable-stream@^3.1.0", "readable-stream@^3.4.0", "readable-stream@^3.6.0": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readable-stream@~1.0.15": + "integrity" "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" + "version" "1.0.34" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.1" + "isarray" "0.0.1" + "string_decoder" "~0.10.x" + +"readdirp@~3.2.0": + "integrity" "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "picomatch" "^2.0.4" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"rechoir@^0.6.2": + "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + "version" "0.6.2" + dependencies: + "resolve" "^1.1.6" + +"recursive-readdir@^2.2.2": + "integrity" "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==" + "resolved" "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "minimatch" "3.0.4" + +"regenerate-unicode-properties@^10.0.1": + "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.2.1", "regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.11.0": + "integrity" "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" + "version" "0.11.1" + +"regenerator-runtime@^0.13.4": + "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + "version" "0.13.9" + +"regenerator-transform@^0.10.0": + "integrity" "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz" + "version" "0.10.1" + dependencies: + "babel-runtime" "^6.18.0" + "babel-types" "^6.19.0" + "private" "^0.1.6" + +"regenerator-transform@^0.14.2": + "integrity" "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" + "version" "0.14.5" + dependencies: + "@babel/runtime" "^7.8.4" + +"regex-not@^1.0.0", "regex-not@^1.0.2": + "integrity" "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==" + "resolved" "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "extend-shallow" "^3.0.2" + "safe-regex" "^1.1.0" + +"regexp.prototype.flags@^1.2.0": + "integrity" "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==" + "resolved" "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"regexpp@^3.0.0", "regexpp@^3.1.0": + "integrity" "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + "resolved" "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + "version" "3.2.0" + +"regexpu-core@^2.0.0": + "integrity" "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "regenerate" "^1.2.1" + "regjsgen" "^0.2.0" + "regjsparser" "^0.1.4" + +"regexpu-core@^5.0.1": + "integrity" "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.0.1" + "regjsgen" "^0.6.0" + "regjsparser" "^0.8.2" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"regjsgen@^0.2.0": + "integrity" "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz" + "version" "0.2.0" + +"regjsgen@^0.6.0": + "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + "resolved" "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + "version" "0.6.0" + +"regjsparser@^0.1.4": + "integrity" "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz" + "version" "0.1.5" + dependencies: + "jsesc" "~0.5.0" + +"regjsparser@^0.8.2": + "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + "version" "0.8.4" + dependencies: + "jsesc" "~0.5.0" + +"repeat-element@^1.1.2": + "integrity" "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + "resolved" "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz" + "version" "1.1.4" + +"repeat-string@^1.6.1": + "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "resolved" "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"repeating@^2.0.0": + "integrity" "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=" + "resolved" "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-finite" "^1.0.0" + +"req-cwd@^2.0.0": + "integrity" "sha1-1AgrTURZgDZkD7c93qAe1T20nrw=" + "resolved" "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "req-from" "^2.0.0" + +"req-from@^2.0.0": + "integrity" "sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA=" + "resolved" "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "resolve-from" "^3.0.0" + +"request-promise-core@1.1.4": + "integrity" "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==" + "resolved" "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "lodash" "^4.17.19" + +"request-promise-native@^1.0.5": + "integrity" "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==" + "resolved" "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz" + "version" "1.0.9" + dependencies: + "request-promise-core" "1.1.4" + "stealthy-require" "^1.1.1" + "tough-cookie" "^2.3.3" + +"request@^2.34", "request@^2.79.0", "request@^2.85.0", "request@^2.88.0": + "integrity" "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==" + "resolved" "https://registry.npmjs.org/request/-/request-2.88.2.tgz" + "version" "2.88.2" + 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" + +"require-directory@^2.1.1": + "integrity" "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "resolved" "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + "version" "2.1.1" + +"require-from-string@^1.1.0": + "integrity" "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz" + "version" "1.2.1" + +"require-from-string@^2.0.0", "require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" + +"require-main-filename@^1.0.1": + "integrity" "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "resolved" "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + "version" "1.0.1" + +"require-main-filename@^2.0.0": + "integrity" "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "resolved" "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" + "version" "2.0.0" + +"resolve-from@^3.0.0": + "integrity" "sha1-six699nWiBvItuZTM17rywoYh0g=" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" + "version" "3.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-url@^0.2.1": + "integrity" "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolved" "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" + "version" "0.2.1" + +"resolve@^1.1.6", "resolve@^1.10.0", "resolve@^1.10.1", "resolve@^1.14.2", "resolve@^1.20.0", "resolve@^1.8.1", "resolve@~1.22.0": + "integrity" "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + "version" "1.22.0" + dependencies: + "is-core-module" "^2.8.1" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"resolve@1.1.x": + "integrity" "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" + "version" "1.1.7" + +"resolve@1.17.0": + "integrity" "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz" + "version" "1.17.0" + dependencies: + "path-parse" "^1.0.6" + +"responselike@^1.0.2": + "integrity" "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=" + "resolved" "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "lowercase-keys" "^1.0.0" + +"resumer@~0.0.0": + "integrity" "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=" + "resolved" "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz" + "version" "0.0.0" + dependencies: + "through" "~2.3.4" + +"ret@~0.1.10": + "integrity" "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "resolved" "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" + "version" "0.1.15" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rimraf@^2.2.8", "rimraf@^2.6.3": + "integrity" "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + "version" "2.7.1" + dependencies: + "glob" "^7.1.3" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"ripemd160@^2.0.0", "ripemd160@^2.0.1": + "integrity" "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==" + "resolved" "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "hash-base" "^3.0.0" + "inherits" "^2.0.1" + +"rlp@^2.0.0", "rlp@^2.2.1", "rlp@^2.2.2", "rlp@^2.2.3", "rlp@^2.2.4": + "integrity" "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==" + "resolved" "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz" + "version" "2.2.7" + dependencies: + "bn.js" "^5.2.0" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"rustbn.js@~0.2.0": + "integrity" "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" + "resolved" "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" + "version" "0.2.0" + +"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@^5.1.1", "safe-buffer@^5.1.2", "safe-buffer@^5.2.0", "safe-buffer@^5.2.1", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-event-emitter@^1.0.1": + "integrity" "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==" + "resolved" "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "events" "^3.0.0" + +"safe-regex@^1.1.0": + "integrity" "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=" + "resolved" "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "ret" "~0.1.10" + +"safer-buffer@^2.0.2", "safer-buffer@^2.1.0", "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", "safer-buffer@~2.1.0": + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" + +"sc-istanbul@^0.4.5": + "integrity" "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==" + "resolved" "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz" + "version" "0.4.6" + 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" + +"scrypt-js@^3.0.0", "scrypt-js@^3.0.1", "scrypt-js@3.0.1": + "integrity" "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + "resolved" "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" + "version" "3.0.1" + +"scrypt-js@2.0.4": + "integrity" "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" + "resolved" "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz" + "version" "2.0.4" + +"scryptsy@^1.2.1": + "integrity" "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=" + "resolved" "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "pbkdf2" "^3.0.3" + +"secp256k1@^3.0.1": + "integrity" "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==" + "resolved" "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz" + "version" "3.8.0" + dependencies: + "bindings" "^1.5.0" + "bip66" "^1.1.5" + "bn.js" "^4.11.8" + "create-hash" "^1.2.0" + "drbg.js" "^1.0.1" + "elliptic" "^6.5.2" + "nan" "^2.14.0" + "safe-buffer" "^5.1.2" + +"secp256k1@^4.0.1": + "integrity" "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==" + "resolved" "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "elliptic" "^6.5.4" + "node-addon-api" "^2.0.0" + "node-gyp-build" "^4.2.0" + +"seedrandom@3.0.1": + "integrity" "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==" + "resolved" "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz" + "version" "3.0.1" + +"semaphore-async-await@^1.5.1": + "integrity" "sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo=" + "resolved" "https://registry.npmjs.org/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz" + "version" "1.5.1" + +"semaphore@^1.0.3", "semaphore@^1.1.0", "semaphore@>=1.0.1": + "integrity" "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + "resolved" "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz" + "version" "1.1.0" + +"semver-compare@^1.0.0": + "integrity" "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + "resolved" "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz" + "version" "1.0.0" + +"semver-regex@^3.1.2": + "integrity" "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==" + "resolved" "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz" + "version" "3.1.3" + +"semver@^5.3.0", "semver@^5.5.0", "semver@^5.6.0", "semver@^5.7.0", "semver@2 || 3 || 4 || 5": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^6.1.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.1.1": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.1.2": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.3.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^7.2.1": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.2": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.4": + "integrity" "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" + "version" "7.3.5" + dependencies: + "lru-cache" "^6.0.0" + +"semver@~5.4.1": + "integrity" "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz" + "version" "5.4.1" + +"semver@7.0.0": + "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + "version" "7.0.0" + +"send@0.17.2": + "integrity" "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==" + "resolved" "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + "version" "0.17.2" + 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.8.1" + "mime" "1.6.0" + "ms" "2.1.3" + "on-finished" "~2.3.0" + "range-parser" "~1.2.1" + "statuses" "~1.5.0" + +"serialize-javascript@6.0.0": + "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" + "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "randombytes" "^2.1.0" + +"serve-static@1.14.2": + "integrity" "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==" + "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" + "version" "1.14.2" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.3" + "send" "0.17.2" + +"servify@^0.1.12": + "integrity" "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==" + "resolved" "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz" + "version" "0.1.12" + dependencies: + "body-parser" "^1.16.0" + "cors" "^2.8.1" + "express" "^4.14.0" + "request" "^2.79.0" + "xhr" "^2.3.3" + +"set-blocking@^2.0.0": + "integrity" "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "resolved" "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + "version" "2.0.0" + +"set-immediate-shim@^1.0.1": + "integrity" "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + "resolved" "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + "version" "1.0.1" + +"set-value@^2.0.0", "set-value@^2.0.1": + "integrity" "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==" + "resolved" "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "extend-shallow" "^2.0.1" + "is-extendable" "^0.1.1" + "is-plain-object" "^2.0.3" + "split-string" "^3.0.1" + +"setimmediate@^1.0.5": + "integrity" "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" + "version" "1.0.5" + +"setimmediate@1.0.4": + "integrity" "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + "resolved" "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz" + "version" "1.0.4" + +"setprototypeof@1.2.0": + "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + "version" "1.2.0" + +"sha.js@^2.4.0", "sha.js@^2.4.8": + "integrity" "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==" + "resolved" "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + "version" "2.4.11" + dependencies: + "inherits" "^2.0.1" + "safe-buffer" "^5.0.1" + +"sha1@^1.1.1": + "integrity" "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=" + "resolved" "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "charenc" ">= 0.0.1" + "crypt" ">= 0.0.1" + +"shallow-clone@^3.0.0": + "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" + "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^6.0.2" + +"shebang-command@^1.2.0": + "integrity" "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "shebang-regex" "^1.0.0" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^1.0.0": + "integrity" "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + "version" "1.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.6.1": + "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz" + "version" "1.7.3" + +"shelljs@^0.8.3": + "integrity" "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==" + "resolved" "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" + "version" "0.8.5" + dependencies: + "glob" "^7.0.0" + "interpret" "^1.0.0" + "rechoir" "^0.6.2" + +"side-channel@^1.0.4": + "integrity" "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==" + "resolved" "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "call-bind" "^1.0.0" + "get-intrinsic" "^1.0.2" + "object-inspect" "^1.9.0" + +"simple-concat@^1.0.0": + "integrity" "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + "resolved" "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + "version" "1.0.1" + +"simple-get@^2.7.0": + "integrity" "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==" + "resolved" "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz" + "version" "2.8.2" + dependencies: + "decompress-response" "^3.3.0" + "once" "^1.3.1" + "simple-concat" "^1.0.0" + +"slash@^1.0.0": + "integrity" "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "resolved" "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + "version" "1.0.0" + +"slash@^2.0.0": + "integrity" "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + "resolved" "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" + "version" "2.0.0" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slice-ansi@^4.0.0": + "integrity" "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==" + "resolved" "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "astral-regex" "^2.0.0" + "is-fullwidth-code-point" "^3.0.0" + +"snapdragon-node@^2.0.1": + "integrity" "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==" + "resolved" "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "define-property" "^1.0.0" + "isobject" "^3.0.0" + "snapdragon-util" "^3.0.1" + +"snapdragon-util@^3.0.1": + "integrity" "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==" + "resolved" "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^3.2.0" + +"snapdragon@^0.8.1": + "integrity" "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==" + "resolved" "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" + "version" "0.8.2" + dependencies: + "base" "^0.11.1" + "debug" "^2.2.0" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "map-cache" "^0.2.2" + "source-map" "^0.5.6" + "source-map-resolve" "^0.5.0" + "use" "^3.1.0" + +"solc-0.6.12@npm:solc@^0.6.12": + "integrity" "sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g==" + "resolved" "https://registry.npmjs.org/solc/-/solc-0.6.12.tgz" + "version" "0.6.12" + dependencies: + "command-exists" "^1.2.8" + "commander" "3.0.2" + "fs-extra" "^0.30.0" + "js-sha3" "0.8.0" + "memorystream" "^0.3.1" + "require-from-string" "^2.0.0" + "semver" "^5.5.0" + "tmp" "0.0.33" + +"solc@^0.4.20": + "integrity" "sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==" + "resolved" "https://registry.npmjs.org/solc/-/solc-0.4.26.tgz" + "version" "0.4.26" + dependencies: + "fs-extra" "^0.30.0" + "memorystream" "^0.3.1" + "require-from-string" "^1.1.0" + "semver" "^5.3.0" + "yargs" "^4.7.1" + +"solc@^0.6.3", "solc@^0.6.7": + "integrity" "sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g==" + "resolved" "https://registry.npmjs.org/solc/-/solc-0.6.12.tgz" + "version" "0.6.12" + dependencies: + "command-exists" "^1.2.8" + "commander" "3.0.2" + "fs-extra" "^0.30.0" + "js-sha3" "0.8.0" + "memorystream" "^0.3.1" + "require-from-string" "^2.0.0" + "semver" "^5.5.0" + "tmp" "0.0.33" + +"solc@0.7.3": + "integrity" "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==" + "resolved" "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz" + "version" "0.7.3" + dependencies: + "command-exists" "^1.2.8" + "commander" "3.0.2" + "follow-redirects" "^1.12.1" + "fs-extra" "^0.30.0" + "js-sha3" "0.8.0" + "memorystream" "^0.3.1" + "require-from-string" "^2.0.0" + "semver" "^5.5.0" + "tmp" "0.0.33" + +"solidity-coverage@^0.7.20": + "integrity" "sha512-edOXTugUYdqxrtEnIn4vgrGjLPxdexcL0WD8LzAvVA3d1dwgcfRO3k8xQR02ZQnOnWMBi8Cqs0F+kAQQp3JW8g==" + "resolved" "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.20.tgz" + "version" "0.7.20" + 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" + +"solidity-docgen@^0.5.11": + "integrity" "sha512-rFVpqSNnDGKvL68mPf4J9mEQIl+Ixy6bIz/YE6AgjBCPtrlm4KjWQhcBMQWc/LarSCenOpzhbG1tHqP9gf9kcg==" + "resolved" "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.5.16.tgz" + "version" "0.5.16" + dependencies: + "@oclif/command" "^1.8.0" + "@oclif/config" "^1.17.0" + "@oclif/errors" "^1.3.3" + "@oclif/plugin-help" "^3.2.0" + "globby" "^11.0.0" + "handlebars" "^4.7.6" + "json5" "^2.1.3" + "lodash" "^4.17.15" + "micromatch" "^4.0.2" + "minimatch" "^3.0.4" + "semver" "^7.3.2" + "solc" "^0.6.7" + +"source-map-resolve@^0.5.0": + "integrity" "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==" + "resolved" "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + "version" "0.5.3" + 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" + +"source-map-support@^0.4.15": + "integrity" "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz" + "version" "0.4.18" + dependencies: + "source-map" "^0.5.6" + +"source-map-support@^0.5.13", "source-map-support@^0.5.16": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map-support@0.5.12": + "integrity" "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz" + "version" "0.5.12" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map-url@^0.4.0": + "integrity" "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + "resolved" "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" + "version" "0.4.1" + +"source-map@^0.5.0", "source-map@^0.5.6", "source-map@^0.5.7": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.0": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"source-map@^0.6.1": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"source-map@~0.2.0": + "integrity" "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "amdefine" ">=0.0.4" + +"spdx-correct@^3.0.0": + "integrity" "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==" + "resolved" "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "spdx-expression-parse" "^3.0.0" + "spdx-license-ids" "^3.0.0" + +"spdx-exceptions@^2.1.0": + "integrity" "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "resolved" "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + "version" "2.3.0" + +"spdx-expression-parse@^3.0.0": + "integrity" "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==" + "resolved" "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "spdx-exceptions" "^2.1.0" + "spdx-license-ids" "^3.0.0" + +"spdx-license-ids@^3.0.0": + "integrity" "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + "resolved" "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz" + "version" "3.0.11" + +"split-string@^3.0.1", "split-string@^3.0.2": + "integrity" "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==" + "resolved" "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "extend-shallow" "^3.0.0" + +"sprintf-js@~1.0.2": + "integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "version" "1.0.3" + +"sshpk@^1.7.0": + "integrity" "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==" + "resolved" "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz" + "version" "1.17.0" + 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" + +"stacktrace-parser@^0.1.10": + "integrity" "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==" + "resolved" "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz" + "version" "0.1.10" + dependencies: + "type-fest" "^0.7.1" + +"static-extend@^0.1.1": + "integrity" "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=" + "resolved" "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "define-property" "^0.2.5" + "object-copy" "^0.1.0" + +"statuses@>= 1.5.0 < 2", "statuses@~1.5.0": + "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"statuses@2.0.1": + "integrity" "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + "version" "2.0.1" + +"stealthy-require@^1.1.1": + "integrity" "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + "resolved" "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz" + "version" "1.1.1" + +"stream-to-pull-stream@^1.7.1": + "integrity" "sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg==" + "resolved" "https://registry.npmjs.org/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz" + "version" "1.7.3" + dependencies: + "looper" "^3.0.0" + "pull-stream" "^3.2.3" + +"strict-uri-encode@^1.0.0": + "integrity" "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + "resolved" "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" + "version" "1.1.0" + +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "safe-buffer" "~5.2.0" + +"string_decoder@~0.10.x": + "integrity" "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "version" "0.10.31" + +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-width@^1.0.1": + "integrity" "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "code-point-at" "^1.0.0" + "is-fullwidth-code-point" "^1.0.0" + "strip-ansi" "^3.0.0" + +"string-width@^1.0.2 || 2": + "integrity" "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "is-fullwidth-code-point" "^2.0.0" + "strip-ansi" "^4.0.0" + +"string-width@^2.1.1": + "integrity" "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "is-fullwidth-code-point" "^2.0.0" + "strip-ansi" "^4.0.0" + +"string-width@^3.0.0", "string-width@^3.1.0": + "integrity" "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "emoji-regex" "^7.0.1" + "is-fullwidth-code-point" "^2.0.0" + "strip-ansi" "^5.1.0" + +"string-width@^4.0.0", "string-width@^4.1.0", "string-width@^4.2.0", "string-width@^4.2.3": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + +"string.prototype.padend@^3.0.0": + "integrity" "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==" + "resolved" "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz" + "version" "3.1.3" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + +"string.prototype.trim@~1.2.5": + "integrity" "sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg==" + "resolved" "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz" + "version" "1.2.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + +"string.prototype.trimend@^1.0.4": + "integrity" "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==" + "resolved" "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"string.prototype.trimstart@^1.0.4": + "integrity" "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==" + "resolved" "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + +"strip-ansi@^3.0.0", "strip-ansi@^3.0.1": + "integrity" "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "ansi-regex" "^2.0.0" + +"strip-ansi@^4.0.0": + "integrity" "sha1-qEeQIusaw2iocTibY1JixQXuNo8=" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ansi-regex" "^3.0.0" + +"strip-ansi@^5.0.0", "strip-ansi@^5.1.0", "strip-ansi@^5.2.0": + "integrity" "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "ansi-regex" "^4.1.0" + +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + +"strip-bom@^2.0.0": + "integrity" "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" + "resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "is-utf8" "^0.2.0" + +"strip-bom@^3.0.0": + "integrity" "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + "version" "3.0.0" + +"strip-hex-prefix@1.0.0": + "integrity" "sha1-DF8VX+8RUTczd96du1iNoFUA428=" + "resolved" "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-hex-prefixed" "1.0.0" + +"strip-json-comments@^3.1.0", "strip-json-comments@^3.1.1", "strip-json-comments@3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" + +"strip-json-comments@2.0.1": + "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + "version" "2.0.1" + +"supports-color@^2.0.0": + "integrity" "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + "version" "2.0.0" + +"supports-color@^3.1.0": + "integrity" "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" + "version" "3.2.3" + dependencies: + "has-flag" "^1.0.0" + +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" + +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "has-flag" "^4.0.0" + +"supports-color@6.0.0": + "integrity" "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "has-flag" "^3.0.0" + +"supports-color@8.1.1": + "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + "version" "8.1.1" + dependencies: + "has-flag" "^4.0.0" + +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" + +"swarm-js@^0.1.40": + "integrity" "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==" + "resolved" "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz" + "version" "0.1.40" + 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" + +"sync-request@^6.0.0": + "integrity" "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==" + "resolved" "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "http-response-object" "^3.0.1" + "sync-rpc" "^1.2.1" + "then-request" "^6.0.0" + +"sync-rpc@^1.2.1": + "integrity" "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==" + "resolved" "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz" + "version" "1.3.6" + dependencies: + "get-port" "^3.1.0" + +"table@^6.0.9": + "integrity" "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==" + "resolved" "https://registry.npmjs.org/table/-/table-6.8.0.tgz" + "version" "6.8.0" + dependencies: + "ajv" "^8.0.1" + "lodash.truncate" "^4.4.2" + "slice-ansi" "^4.0.0" + "string-width" "^4.2.3" + "strip-ansi" "^6.0.1" + +"tape@^4.6.3": + "integrity" "sha512-SfRmG2I8QGGgJE/MCiLH8c11L5XxyUXxwK9xLRD0uiK5fehRkkSZGmR6Y1pxOt8vJ19m3sY+POTQpiaVv45/LQ==" + "resolved" "https://registry.npmjs.org/tape/-/tape-4.15.0.tgz" + "version" "4.15.0" + dependencies: + "call-bind" "~1.0.2" + "deep-equal" "~1.1.1" + "defined" "~1.0.0" + "dotignore" "~0.1.2" + "for-each" "~0.3.3" + "glob" "~7.2.0" + "has" "~1.0.3" + "inherits" "~2.0.4" + "is-regex" "~1.1.4" + "minimist" "~1.2.5" + "object-inspect" "~1.12.0" + "resolve" "~1.22.0" + "resumer" "~0.0.0" + "string.prototype.trim" "~1.2.5" + "through" "~2.3.8" + +"tar@^4.0.2": + "integrity" "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==" + "resolved" "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz" + "version" "4.4.19" + 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" + +"test-value@^2.1.0": + "integrity" "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=" + "resolved" "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "array-back" "^1.0.3" + "typical" "^2.6.0" + +"testrpc@0.0.1": + "integrity" "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==" + "resolved" "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz" + "version" "0.0.1" + +"text-table@^0.2.0": + "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"then-request@^6.0.0": + "integrity" "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==" + "resolved" "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/form-data" "0.0.33" + "@types/node" "^8.0.0" + "@types/qs" "^6.2.31" + "caseless" "~0.12.0" + "concat-stream" "^1.6.0" + "form-data" "^2.2.0" + "http-basic" "^8.1.1" + "http-response-object" "^3.0.1" + "promise" "^8.0.0" + "qs" "^6.4.0" + +"through@~2.3.4", "through@~2.3.8": + "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "version" "2.3.8" + +"through2@^2.0.3": + "integrity" "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==" + "resolved" "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + "version" "2.0.5" + dependencies: + "readable-stream" "~2.3.6" + "xtend" "~4.0.1" + +"timed-out@^4.0.0", "timed-out@^4.0.1": + "integrity" "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + "resolved" "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz" + "version" "4.0.1" + +"tmp@^0.0.33", "tmp@0.0.33": + "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" + "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + "version" "0.0.33" + dependencies: + "os-tmpdir" "~1.0.2" + +"tmp@0.1.0": + "integrity" "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==" + "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "rimraf" "^2.6.3" + +"to-fast-properties@^1.0.3": + "integrity" "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" + "version" "1.0.3" + +"to-fast-properties@^2.0.0": + "integrity" "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-object-path@^0.3.0": + "integrity" "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=" + "resolved" "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "kind-of" "^3.0.2" + +"to-readable-stream@^1.0.0": + "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + "version" "1.0.0" + +"to-regex-range@^2.1.0": + "integrity" "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"to-regex@^3.0.1", "to-regex@^3.0.2": + "integrity" "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==" + "resolved" "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "regex-not" "^1.0.2" + "safe-regex" "^1.1.0" + +"toidentifier@1.0.1": + "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + "version" "1.0.1" + +"tough-cookie@^2.3.3", "tough-cookie@~2.5.0": + "integrity" "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==" + "resolved" "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "psl" "^1.1.28" + "punycode" "^2.1.1" + +"tr46@~0.0.3": + "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"trim-right@^1.0.1": + "integrity" "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + "resolved" "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" + "version" "1.0.1" + +"true-case-path@^2.2.1": + "integrity" "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==" + "resolved" "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz" + "version" "2.2.1" + +"ts-essentials@^1.0.0": + "integrity" "sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==" + "resolved" "https://registry.npmjs.org/ts-essentials/-/ts-essentials-1.0.4.tgz" + "version" "1.0.4" + +"ts-essentials@^6.0.3": + "integrity" "sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw==" + "resolved" "https://registry.npmjs.org/ts-essentials/-/ts-essentials-6.0.7.tgz" + "version" "6.0.7" + +"ts-generator@^0.1.1": + "integrity" "sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==" + "resolved" "https://registry.npmjs.org/ts-generator/-/ts-generator-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + "chalk" "^2.4.1" + "glob" "^7.1.2" + "mkdirp" "^0.5.1" + "prettier" "^2.1.2" + "resolve" "^1.8.1" + "ts-essentials" "^1.0.0" + +"ts-interface-checker@^0.1.9": + "integrity" "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "resolved" "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" + "version" "0.1.13" + +"tsconfig-paths@^3.12.0": + "integrity" "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==" + "resolved" "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz" + "version" "3.12.0" + dependencies: + "@types/json5" "^0.0.29" + "json5" "^1.0.1" + "minimist" "^1.2.0" + "strip-bom" "^3.0.0" + +"tslib@^1.9.3": + "integrity" "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + "version" "1.14.1" + +"tslib@^2.0.0": + "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + "version" "2.3.1" + +"tslib@^2.3.1": + "integrity" "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" + "version" "2.3.1" + +"tsort@0.0.1": + "integrity" "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=" + "resolved" "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz" + "version" "0.0.1" + +"tunnel-agent@^0.6.0": + "integrity" "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=" + "resolved" "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "safe-buffer" "^5.0.1" + +"tweetnacl-util@^0.15.0", "tweetnacl-util@^0.15.1": + "integrity" "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + "resolved" "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" + "version" "0.15.1" + +"tweetnacl@^0.14.3", "tweetnacl@~0.14.0": + "integrity" "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "resolved" "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + "version" "0.14.5" + +"tweetnacl@^1.0.0": + "integrity" "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "resolved" "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" + "version" "1.0.3" + +"tweetnacl@^1.0.3": + "integrity" "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "resolved" "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" + "version" "1.0.3" + +"type-check@^0.4.0": + "integrity" "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==" + "resolved" "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "prelude-ls" "^1.2.1" + +"type-check@~0.3.2": + "integrity" "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=" + "resolved" "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" + "version" "0.3.2" + dependencies: + "prelude-ls" "~1.1.2" + +"type-check@~0.4.0": + "integrity" "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==" + "resolved" "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "prelude-ls" "^1.2.1" + +"type-detect@^4.0.0", "type-detect@^4.0.5": + "integrity" "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "resolved" "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + "version" "4.0.8" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-fest@^0.21.3": + "integrity" "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + "version" "0.21.3" + +"type-fest@^0.7.1": + "integrity" "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz" + "version" "0.7.1" + +"type-is@~1.6.18": + "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" + "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + "version" "1.6.18" + dependencies: + "media-typer" "0.3.0" + "mime-types" "~2.1.24" + +"type@^1.0.1": + "integrity" "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "resolved" "https://registry.npmjs.org/type/-/type-1.2.0.tgz" + "version" "1.2.0" + +"type@^2.5.0": + "integrity" "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + "resolved" "https://registry.npmjs.org/type/-/type-2.6.0.tgz" + "version" "2.6.0" + +"typechain@^3.0.0": + "integrity" "sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg==" + "resolved" "https://registry.npmjs.org/typechain/-/typechain-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "command-line-args" "^4.0.7" + "debug" "^4.1.1" + "fs-extra" "^7.0.0" + "js-sha3" "^0.8.0" + "lodash" "^4.17.15" + "ts-essentials" "^6.0.3" + "ts-generator" "^0.1.1" + +"typedarray-to-buffer@^3.1.5": + "integrity" "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==" + "resolved" "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "is-typedarray" "^1.0.0" + +"typedarray@^0.0.6": + "integrity" "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "resolved" "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + "version" "0.0.6" + +"typewise-core@^1.2", "typewise-core@^1.2.0": + "integrity" "sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU=" + "resolved" "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz" + "version" "1.2.0" + +"typewise@^1.0.3": + "integrity" "sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE=" + "resolved" "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "typewise-core" "^1.2.0" + +"typewiselite@~1.0.0": + "integrity" "sha1-yIgvobsQksBgBal/NO9chQjjZk4=" + "resolved" "https://registry.npmjs.org/typewiselite/-/typewiselite-1.0.0.tgz" + "version" "1.0.0" + +"typical@^2.6.0", "typical@^2.6.1": + "integrity" "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" + "resolved" "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz" + "version" "2.6.1" + +"uglify-js@^3.1.4": + "integrity" "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==" + "resolved" "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz" + "version" "3.15.2" + +"ultron@~1.1.0": + "integrity" "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + "resolved" "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz" + "version" "1.1.1" + +"unbox-primitive@^1.0.1": + "integrity" "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==" + "resolved" "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "function-bind" "^1.1.1" + "has-bigints" "^1.0.1" + "has-symbols" "^1.0.2" + "which-boxed-primitive" "^1.0.2" + +"underscore@1.9.1": + "integrity" "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + "resolved" "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz" + "version" "1.9.1" + +"undici@^4.14.1": + "integrity" "sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw==" + "resolved" "https://registry.npmjs.org/undici/-/undici-4.16.0.tgz" + "version" "4.16.0" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.0.0": + "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"union-value@^1.0.0": + "integrity" "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==" + "resolved" "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "arr-union" "^3.1.0" + "get-value" "^2.0.6" + "is-extendable" "^0.1.1" + "set-value" "^2.0.1" + +"universalify@^0.1.0": + "integrity" "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "resolved" "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + "version" "0.1.2" + +"unorm@^1.3.3": + "integrity" "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==" + "resolved" "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz" + "version" "1.6.0" + +"unpipe@~1.0.0", "unpipe@1.0.0": + "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"unset-value@^1.0.0": + "integrity" "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=" + "resolved" "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-value" "^0.3.1" + "isobject" "^3.0.0" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"urix@^0.1.0": + "integrity" "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "resolved" "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" + "version" "0.1.0" + +"url-parse-lax@^1.0.0": + "integrity" "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "prepend-http" "^1.0.1" + +"url-parse-lax@^3.0.0": + "integrity" "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "prepend-http" "^2.0.0" + +"url-set-query@^1.0.0": + "integrity" "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" + "resolved" "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz" + "version" "1.0.0" + +"url-to-options@^1.0.1": + "integrity" "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + "resolved" "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz" + "version" "1.0.1" + +"url@^0.11.0": + "integrity" "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=" + "resolved" "https://registry.npmjs.org/url/-/url-0.11.0.tgz" + "version" "0.11.0" + dependencies: + "punycode" "1.3.2" + "querystring" "0.2.0" + +"use@^3.1.0": + "integrity" "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "resolved" "https://registry.npmjs.org/use/-/use-3.1.1.tgz" + "version" "3.1.1" + +"utf-8-validate@^5.0.2": + "integrity" "sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA==" + "resolved" "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.8.tgz" + "version" "5.0.8" + dependencies: + "node-gyp-build" "^4.3.0" + +"utf8@^3.0.0", "utf8@3.0.0": + "integrity" "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + "resolved" "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz" + "version" "3.0.0" + +"util-deprecate@^1.0.1", "util-deprecate@~1.0.1": + "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"util.promisify@^1.0.0": + "integrity" "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==" + "resolved" "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz" + "version" "1.1.1" + 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" + +"util@^0.12.0": + "integrity" "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==" + "resolved" "https://registry.npmjs.org/util/-/util-0.12.4.tgz" + "version" "0.12.4" + 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" + +"utils-merge@1.0.1": + "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^3.3.2": + "integrity" "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" + "version" "3.4.0" + +"uuid@^8.3.2": + "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + "version" "8.3.2" + +"uuid@2.0.1": + "integrity" "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz" + "version" "2.0.1" + +"uuid@3.3.2": + "integrity" "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz" + "version" "3.3.2" + +"v8-compile-cache@^2.0.3": + "integrity" "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "resolved" "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + "version" "2.3.0" + +"validate-npm-package-license@^3.0.1": + "integrity" "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==" + "resolved" "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "spdx-correct" "^3.0.0" + "spdx-expression-parse" "^3.0.0" + +"varint@^5.0.0": + "integrity" "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" + "resolved" "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz" + "version" "5.0.2" + +"vary@^1", "vary@~1.1.2": + "integrity" "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" + +"verror@1.10.0": + "integrity" "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=" + "resolved" "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" + "version" "1.10.0" + dependencies: + "assert-plus" "^1.0.0" + "core-util-is" "1.0.2" + "extsprintf" "^1.2.0" + +"web3-bzz@1.2.11": + "integrity" "sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg==" + "resolved" "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@types/node" "^12.12.6" + "got" "9.6.0" + "swarm-js" "^0.1.40" + "underscore" "1.9.1" + +"web3-bzz@1.5.3": + "integrity" "sha512-SlIkAqG0eS6cBS9Q2eBOTI1XFzqh83RqGJWnyrNZMDxUwsTVHL+zNnaPShVPvrWQA1Ub5b0bx1Kc5+qJVxsTJg==" + "resolved" "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "@types/node" "^12.12.6" + "got" "9.6.0" + "swarm-js" "^0.1.40" + +"web3-core-helpers@1.2.11": + "integrity" "sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A==" + "resolved" "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "underscore" "1.9.1" + "web3-eth-iban" "1.2.11" + "web3-utils" "1.2.11" + +"web3-core-helpers@1.5.3": + "integrity" "sha512-Ip1IjB3S8vN7Kf1PPjK41U5gskmMk6IJQlxIVuS8/1U7n/o0jC8krqtpRwiMfAgYyw3TXwBFtxSRTvJtnLyXZw==" + "resolved" "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "web3-eth-iban" "1.5.3" + "web3-utils" "1.5.3" + +"web3-core-method@1.2.11": + "integrity" "sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw==" + "resolved" "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + "underscore" "1.9.1" + "web3-core-helpers" "1.2.11" + "web3-core-promievent" "1.2.11" + "web3-core-subscriptions" "1.2.11" + "web3-utils" "1.2.11" + +"web3-core-method@1.5.3": + "integrity" "sha512-8wJrwQ2qD9ibWieF9oHXwrJsUGrv3XAtEkNeyvyNMpktNTIjxJ2jaFGQUuLiyUrMubD18XXgLk4JS6PJU4Loeg==" + "resolved" "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-core-promievent@1.2.11": + "integrity" "sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA==" + "resolved" "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "eventemitter3" "4.0.4" + +"web3-core-promievent@1.5.3": + "integrity" "sha512-CFfgqvk3Vk6PIAxtLLuX+pOMozxkKCY+/GdGr7weMh033mDXEPvwyVjoSRO1PqIKj668/hMGQsVoIgbyxkJ9Mg==" + "resolved" "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "eventemitter3" "4.0.4" + +"web3-core-requestmanager@1.2.11": + "integrity" "sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA==" + "resolved" "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "underscore" "1.9.1" + "web3-core-helpers" "1.2.11" + "web3-providers-http" "1.2.11" + "web3-providers-ipc" "1.2.11" + "web3-providers-ws" "1.2.11" + +"web3-core-requestmanager@1.5.3": + "integrity" "sha512-9k/Bze2rs8ONix5IZR+hYdMNQv+ark2Ek2kVcrFgWO+LdLgZui/rn8FikPunjE+ub7x7pJaKCgVRbYFXjo3ZWg==" + "resolved" "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-core-subscriptions@1.2.11": + "integrity" "sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg==" + "resolved" "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "eventemitter3" "4.0.4" + "underscore" "1.9.1" + "web3-core-helpers" "1.2.11" + +"web3-core-subscriptions@1.5.3": + "integrity" "sha512-L2m9vG1iRN6thvmv/HQwO2YLhOQlmZU8dpLG6GSo9FBN14Uch868Swk0dYVr3rFSYjZ/GETevSXU+O+vhCummA==" + "resolved" "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "eventemitter3" "4.0.4" + "web3-core-helpers" "1.5.3" + +"web3-core@1.2.11": + "integrity" "sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ==" + "resolved" "https://registry.npmjs.org/web3-core/-/web3-core-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + "bignumber.js" "^9.0.0" + "web3-core-helpers" "1.2.11" + "web3-core-method" "1.2.11" + "web3-core-requestmanager" "1.2.11" + "web3-utils" "1.2.11" + +"web3-core@1.5.3": + "integrity" "sha512-ACTbu8COCu+0eUNmd9pG7Q9EVsNkAg2w3Y7SqhDr+zjTgbSHZV01jXKlapm9z+G3AN/BziV3zGwudClJ4u4xXQ==" + "resolved" "https://registry.npmjs.org/web3-core/-/web3-core-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-eth-abi@1.2.11": + "integrity" "sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg==" + "resolved" "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + "underscore" "1.9.1" + "web3-utils" "1.2.11" + +"web3-eth-abi@1.5.3": + "integrity" "sha512-i/qhuFsoNrnV130CSRYX/z4SlCfSQ4mHntti5yTmmQpt70xZKYZ57BsU0R29ueSQ9/P+aQrL2t2rqkQkAloUxg==" + "resolved" "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "@ethersproject/abi" "5.0.7" + "web3-utils" "1.5.3" + +"web3-eth-accounts@1.2.11": + "integrity" "sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw==" + "resolved" "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "crypto-browserify" "3.12.0" + "eth-lib" "0.2.8" + "ethereumjs-common" "^1.3.2" + "ethereumjs-tx" "^2.1.1" + "scrypt-js" "^3.0.1" + "underscore" "1.9.1" + "uuid" "3.3.2" + "web3-core" "1.2.11" + "web3-core-helpers" "1.2.11" + "web3-core-method" "1.2.11" + "web3-utils" "1.2.11" + +"web3-eth-accounts@1.5.3": + "integrity" "sha512-pdGhXgeBaEJENMvRT6W9cmji3Zz/46ugFSvmnLLw79qi5EH7XJhKISNVb41eWCrs4am5GhI67GLx5d2s2a72iw==" + "resolved" "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-eth-contract@1.2.11": + "integrity" "sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow==" + "resolved" "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@types/bn.js" "^4.11.5" + "underscore" "1.9.1" + "web3-core" "1.2.11" + "web3-core-helpers" "1.2.11" + "web3-core-method" "1.2.11" + "web3-core-promievent" "1.2.11" + "web3-core-subscriptions" "1.2.11" + "web3-eth-abi" "1.2.11" + "web3-utils" "1.2.11" + +"web3-eth-contract@1.5.3": + "integrity" "sha512-Gdlt1L6cdHe83k7SdV6xhqCytVtOZkjD0kY/15x441AuuJ4JLubCHuqu69k2Dr3tWifHYVys/vG8QE/W16syGg==" + "resolved" "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-eth-ens@1.2.11": + "integrity" "sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA==" + "resolved" "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "content-hash" "^2.5.2" + "eth-ens-namehash" "2.0.8" + "underscore" "1.9.1" + "web3-core" "1.2.11" + "web3-core-helpers" "1.2.11" + "web3-core-promievent" "1.2.11" + "web3-eth-abi" "1.2.11" + "web3-eth-contract" "1.2.11" + "web3-utils" "1.2.11" + +"web3-eth-ens@1.5.3": + "integrity" "sha512-QmGFFtTGElg0E+3xfCIFhiUF+1imFi9eg/cdsRMUZU4F1+MZCC/ee+IAelYLfNTGsEslCqfAusliKOT9DdGGnw==" + "resolved" "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-eth-iban@1.2.11": + "integrity" "sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ==" + "resolved" "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "bn.js" "^4.11.9" + "web3-utils" "1.2.11" + +"web3-eth-iban@1.5.3": + "integrity" "sha512-vMzmGqolYZvRHwP9P4Nf6G8uYM5aTLlQu2a34vz78p0KlDC+eV1th3+90Qeaupa28EG7OO0IT1F0BejiIauOPw==" + "resolved" "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "bn.js" "^4.11.9" + "web3-utils" "1.5.3" + +"web3-eth-personal@1.2.11": + "integrity" "sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw==" + "resolved" "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "@types/node" "^12.12.6" + "web3-core" "1.2.11" + "web3-core-helpers" "1.2.11" + "web3-core-method" "1.2.11" + "web3-net" "1.2.11" + "web3-utils" "1.2.11" + +"web3-eth-personal@1.5.3": + "integrity" "sha512-JzibJafR7ak/Icas8uvos3BmUNrZw1vShuNR5Cxjo+vteOC8XMqz1Vr7RH65B4bmlfb3bm9xLxetUHO894+Sew==" + "resolved" "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-eth@1.2.11": + "integrity" "sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ==" + "resolved" "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "underscore" "1.9.1" + "web3-core" "1.2.11" + "web3-core-helpers" "1.2.11" + "web3-core-method" "1.2.11" + "web3-core-subscriptions" "1.2.11" + "web3-eth-abi" "1.2.11" + "web3-eth-accounts" "1.2.11" + "web3-eth-contract" "1.2.11" + "web3-eth-ens" "1.2.11" + "web3-eth-iban" "1.2.11" + "web3-eth-personal" "1.2.11" + "web3-net" "1.2.11" + "web3-utils" "1.2.11" + +"web3-eth@1.5.3": + "integrity" "sha512-saFurA1L23Bd7MEf7cBli6/jRdMhD4X/NaMiO2mdMMCXlPujoudlIJf+VWpRWJpsbDFdu7XJ2WHkmBYT5R3p1Q==" + "resolved" "https://registry.npmjs.org/web3-eth/-/web3-eth-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3-net@1.2.11": + "integrity" "sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg==" + "resolved" "https://registry.npmjs.org/web3-net/-/web3-net-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "web3-core" "1.2.11" + "web3-core-method" "1.2.11" + "web3-utils" "1.2.11" + +"web3-net@1.5.3": + "integrity" "sha512-0W/xHIPvgVXPSdLu0iZYnpcrgNnhzHMC888uMlGP5+qMCt8VuflUZHy7tYXae9Mzsg1kxaJAS5lHVNyeNw4CoQ==" + "resolved" "https://registry.npmjs.org/web3-net/-/web3-net-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "web3-core" "1.5.3" + "web3-core-method" "1.5.3" + "web3-utils" "1.5.3" + +"web3-provider-engine@14.2.1": + "integrity" "sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==" + "resolved" "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz" + "version" "14.2.1" + dependencies: + "async" "^2.5.0" + "backoff" "^2.5.0" + "clone" "^2.0.0" + "cross-fetch" "^2.1.0" + "eth-block-tracker" "^3.0.0" + "eth-json-rpc-infura" "^3.1.0" + "eth-sig-util" "^1.4.2" + "ethereumjs-block" "^1.2.2" + "ethereumjs-tx" "^1.2.0" + "ethereumjs-util" "^5.1.5" + "ethereumjs-vm" "^2.3.4" + "json-rpc-error" "^2.0.0" + "json-stable-stringify" "^1.0.1" + "promise-to-callback" "^1.0.0" + "readable-stream" "^2.2.9" + "request" "^2.85.0" + "semaphore" "^1.0.3" + "ws" "^5.1.1" + "xhr" "^2.2.0" + "xtend" "^4.0.1" + +"web3-providers-http@1.2.11": + "integrity" "sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA==" + "resolved" "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "web3-core-helpers" "1.2.11" + "xhr2-cookies" "1.1.0" + +"web3-providers-http@1.5.3": + "integrity" "sha512-5DpUyWGHtDAr2RYmBu34Fu+4gJuBAuNx2POeiJIooUtJ+Mu6pIx4XkONWH6V+Ez87tZAVAsFOkJRTYuzMr3rPw==" + "resolved" "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "web3-core-helpers" "1.5.3" + "xhr2-cookies" "1.1.0" + +"web3-providers-ipc@1.2.11": + "integrity" "sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ==" + "resolved" "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "oboe" "2.1.4" + "underscore" "1.9.1" + "web3-core-helpers" "1.2.11" + +"web3-providers-ipc@1.5.3": + "integrity" "sha512-JmeAptugVpmXI39LGxUSAymx0NOFdgpuI1hGQfIhbEAcd4sv7fhfd5D+ZU4oLHbRI8IFr4qfGU0uhR8BXhDzlg==" + "resolved" "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "oboe" "2.1.5" + "web3-core-helpers" "1.5.3" + +"web3-providers-ws@1.2.11": + "integrity" "sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg==" + "resolved" "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "eventemitter3" "4.0.4" + "underscore" "1.9.1" + "web3-core-helpers" "1.2.11" + "websocket" "^1.0.31" + +"web3-providers-ws@1.5.3": + "integrity" "sha512-6DhTw4Q7nm5CFYEUHOJM0gAb3xFx+9gWpVveg3YxJ/ybR1BUvEWo3bLgIJJtX56cYX0WyY6DS35a7f0LOI1kVg==" + "resolved" "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "eventemitter3" "4.0.4" + "web3-core-helpers" "1.5.3" + "websocket" "^1.0.32" + +"web3-shh@1.2.11": + "integrity" "sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg==" + "resolved" "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "web3-core" "1.2.11" + "web3-core-method" "1.2.11" + "web3-core-subscriptions" "1.2.11" + "web3-net" "1.2.11" + +"web3-shh@1.5.3": + "integrity" "sha512-COfEXfsqoV/BkcsNLRxQqnWc1Teb8/9GxdGag5GtPC5gQC/vsN+7hYVJUwNxY9LtJPKYTij2DHHnx6UkITng+Q==" + "resolved" "https://registry.npmjs.org/web3-shh/-/web3-shh-1.5.3.tgz" + "version" "1.5.3" + dependencies: + "web3-core" "1.5.3" + "web3-core-method" "1.5.3" + "web3-core-subscriptions" "1.5.3" + "web3-net" "1.5.3" + +"web3-utils@^1.0.0-beta.31": + "integrity" "sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w==" + "resolved" "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "bn.js" "^4.11.9" + "ethereum-bloom-filters" "^1.0.6" + "ethereumjs-util" "^7.1.0" + "ethjs-unit" "0.1.6" + "number-to-bn" "1.7.0" + "randombytes" "^2.1.0" + "utf8" "3.0.0" + +"web3-utils@^1.3.0": + "integrity" "sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w==" + "resolved" "https://registry.npmjs.org/web3-utils/-/web3-utils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "bn.js" "^4.11.9" + "ethereum-bloom-filters" "^1.0.6" + "ethereumjs-util" "^7.1.0" + "ethjs-unit" "0.1.6" + "number-to-bn" "1.7.0" + "randombytes" "^2.1.0" + "utf8" "3.0.0" + +"web3-utils@1.2.11": + "integrity" "sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ==" + "resolved" "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.11.tgz" + "version" "1.2.11" + 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" + "underscore" "1.9.1" + "utf8" "3.0.0" + +"web3-utils@1.5.3": + "integrity" "sha512-56nRgA+Ad9SEyCv39g36rTcr5fpsd4L9LgV3FK0aB66nAMazLAA6Qz4lH5XrUKPDyBIPGJIR+kJsyRtwcu2q1Q==" + "resolved" "https://registry.npmjs.org/web3-utils/-/web3-utils-1.5.3.tgz" + "version" "1.5.3" + 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" + +"web3@1.2.11": + "integrity" "sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ==" + "resolved" "https://registry.npmjs.org/web3/-/web3-1.2.11.tgz" + "version" "1.2.11" + dependencies: + "web3-bzz" "1.2.11" + "web3-core" "1.2.11" + "web3-eth" "1.2.11" + "web3-eth-personal" "1.2.11" + "web3-net" "1.2.11" + "web3-shh" "1.2.11" + "web3-utils" "1.2.11" + +"web3@1.5.3": + "integrity" "sha512-eyBg/1K44flfv0hPjXfKvNwcUfIVDI4NX48qHQe6wd7C8nPSdbWqo9vLy6ksZIt9NLa90HjI8HsGYgnMSUxn6w==" + "resolved" "https://registry.npmjs.org/web3/-/web3-1.5.3.tgz" + "version" "1.5.3" + 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" + +"webidl-conversions@^3.0.0": + "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"websocket@^1.0.31", "websocket@^1.0.32": + "integrity" "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==" + "resolved" "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz" + "version" "1.0.34" + 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" + +"websocket@1.0.32": + "integrity" "sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q==" + "resolved" "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz" + "version" "1.0.32" + 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" + +"whatwg-fetch@2.0.4": + "integrity" "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + "resolved" "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz" + "version" "2.0.4" + +"whatwg-url@^5.0.0": + "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" + "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" + +"which-boxed-primitive@^1.0.2": + "integrity" "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==" + "resolved" "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + "version" "1.0.2" + 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" + +"which-module@^1.0.0": + "integrity" "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + "resolved" "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz" + "version" "1.0.0" + +"which-module@^2.0.0": + "integrity" "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "resolved" "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" + "version" "2.0.0" + +"which-pm-runs@^1.0.0": + "integrity" "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==" + "resolved" "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz" + "version" "1.1.0" + +"which-typed-array@^1.1.2": + "integrity" "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==" + "resolved" "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz" + "version" "1.1.7" + 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" + +"which@^1.1.1", "which@^1.2.9", "which@^1.3.1", "which@1.3.1": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"which@2.0.2": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"wide-align@1.1.3": + "integrity" "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==" + "resolved" "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "string-width" "^1.0.2 || 2" + +"widest-line@^3.1.0": + "integrity" "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==" + "resolved" "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "string-width" "^4.0.0" + +"window-size@^0.2.0": + "integrity" "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" + "resolved" "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" + "version" "0.2.0" + +"word-wrap@^1.2.3", "word-wrap@~1.2.3": + "integrity" "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "resolved" "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + "version" "1.2.3" + +"wordwrap@^1.0.0": + "integrity" "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "resolved" "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + "version" "1.0.0" + +"workerpool@6.2.0": + "integrity" "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==" + "resolved" "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz" + "version" "6.2.0" + +"wrap-ansi@^2.0.0": + "integrity" "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "string-width" "^1.0.1" + "strip-ansi" "^3.0.1" + +"wrap-ansi@^5.1.0": + "integrity" "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "ansi-styles" "^3.2.0" + "string-width" "^3.0.0" + "strip-ansi" "^5.0.0" + +"wrap-ansi@^6.2.0": + "integrity" "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"ws@^3.0.0": + "integrity" "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==" + "resolved" "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" + "version" "3.3.3" + dependencies: + "async-limiter" "~1.0.0" + "safe-buffer" "~5.1.0" + "ultron" "~1.1.0" + +"ws@^5.1.1": + "integrity" "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==" + "resolved" "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz" + "version" "5.2.3" + dependencies: + "async-limiter" "~1.0.0" + +"ws@^7.4.6": + "integrity" "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "resolved" "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz" + "version" "7.5.7" + +"ws@7.4.6": + "integrity" "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" + "resolved" "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" + "version" "7.4.6" + +"xhr-request-promise@^0.1.2": + "integrity" "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==" + "resolved" "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz" + "version" "0.1.3" + dependencies: + "xhr-request" "^1.1.0" + +"xhr-request@^1.0.1", "xhr-request@^1.1.0": + "integrity" "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==" + "resolved" "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz" + "version" "1.1.0" + 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" + +"xhr@^2.0.4", "xhr@^2.2.0", "xhr@^2.3.3": + "integrity" "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==" + "resolved" "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz" + "version" "2.6.0" + dependencies: + "global" "~4.4.0" + "is-function" "^1.0.1" + "parse-headers" "^2.0.0" + "xtend" "^4.0.0" + +"xhr2-cookies@1.1.0": + "integrity" "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=" + "resolved" "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "cookiejar" "^2.1.1" + +"xmlhttprequest@1.8.0": + "integrity" "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + "resolved" "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz" + "version" "1.8.0" + +"xtend@^4.0.0", "xtend@^4.0.1", "xtend@^4.0.2", "xtend@~4.0.0", "xtend@~4.0.1": + "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + "version" "4.0.2" + +"xtend@~2.1.1": + "integrity" "sha1-bv7MKk2tjmlixJAbM3znuoe10os=" + "resolved" "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "object-keys" "~0.4.0" + +"y18n@^3.2.1": + "integrity" "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "resolved" "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz" + "version" "3.2.2" + +"y18n@^4.0.0": + "integrity" "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "resolved" "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" + "version" "4.0.3" + +"y18n@^5.0.5": + "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "resolved" "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + "version" "5.0.8" + +"yaeti@^0.0.6": + "integrity" "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" + "resolved" "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz" + "version" "0.0.6" + +"yallist@^3.0.0", "yallist@^3.0.2", "yallist@^3.1.1": + "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + "version" "3.1.1" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yaml@^1.10.0": + "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "resolved" "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" + "version" "1.10.2" + +"yargs-parser@^13.1.2", "yargs-parser@13.1.2": + "integrity" "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==" + "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz" + "version" "13.1.2" + dependencies: + "camelcase" "^5.0.0" + "decamelize" "^1.2.0" + +"yargs-parser@^2.4.1": + "integrity" "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=" + "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "camelcase" "^3.0.0" + "lodash.assign" "^4.0.6" + +"yargs-parser@^20.2.2", "yargs-parser@20.2.4": + "integrity" "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" + "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + "version" "20.2.4" + +"yargs-unparser@1.6.0": + "integrity" "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==" + "resolved" "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "flat" "^4.1.0" + "lodash" "^4.17.15" + "yargs" "^13.3.0" + +"yargs-unparser@2.0.0": + "integrity" "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==" + "resolved" "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "camelcase" "^6.0.0" + "decamelize" "^4.0.0" + "flat" "^5.0.2" + "is-plain-obj" "^2.1.0" + +"yargs@^13.3.0", "yargs@13.3.2": + "integrity" "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==" + "resolved" "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz" + "version" "13.3.2" + 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" + +"yargs@^4.7.1": + "integrity" "sha1-wMQpJMpKqmsObaFznfshZDn53cA=" + "resolved" "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz" + "version" "4.8.1" + dependencies: + "cliui" "^3.2.0" + "decamelize" "^1.1.1" + "get-caller-file" "^1.0.1" + "lodash.assign" "^4.0.3" + "os-locale" "^1.4.0" + "read-pkg-up" "^1.0.1" + "require-directory" "^2.1.1" + "require-main-filename" "^1.0.1" + "set-blocking" "^2.0.0" + "string-width" "^1.0.1" + "which-module" "^1.0.0" + "window-size" "^0.2.0" + "y18n" "^3.2.1" + "yargs-parser" "^2.4.1" + +"yargs@16.2.0": + "integrity" "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==" + "resolved" "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + "version" "16.2.0" + dependencies: + "cliui" "^7.0.2" + "escalade" "^3.1.1" + "get-caller-file" "^2.0.5" + "require-directory" "^2.1.1" + "string-width" "^4.2.0" + "y18n" "^5.0.5" + "yargs-parser" "^20.2.2" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0"