diff --git a/script/salts/salts.json b/script/salts/salts.json
index a776f567..0f7c1e1e 100644
--- a/script/salts/salts.json
+++ b/script/salts/salts.json
@@ -50,12 +50,12 @@
"0xed4ba02077e70f78db70ce191509333d2dcccfff136d30dcb011f567305e88ad": "0x2b8bc588174d409692f1bd993942e3806c9a11344dbe674f46aed32a030aacf1"
},
"Test_AllocatedMerkleAllowlist": {
- "0xb17794250569bcd64aae2ec1312399120db92167bf0a2602821e0ee953dd3d31": "0xa8a4fc4fb8d721bdce27342cdd381eb510362146f49e56698a8bcb6c639306ff",
- "0xecbee26b3d0e662be84e4cef678b23166957f507ca68f32eaa49e60ceb567981": "0x1598e58155ab6f6f2d8b2813c5c763f04ab980c3e65dffe2b3a312e8ccba4ae7"
+ "0x8de6e7b0b1f6974167a896ad8d377c8c29ad0132dd3f7b26f3aae7d4bb348d2f": "0xbafe0e1369edea3d992723bf3ff6a352dafbbb9f4dd6b81d52da4b538c123bb5",
+ "0xce7f9e37dca3a16d5c26ba67c9eba2e889ff76c1d27a05ed9ebd75083d46e241": "0x9c9a73570423fffe4c11df49d5434528af493273cd7424ec18e474b7940627ed"
},
"Test_CappedMerkleAllowlist": {
- "0xa0ed568f98efa2efd4e93f21a5445970919a333349a8f5369a28ae93271d9cca": "0x6fb3e2a45254801d17269019f8afcadbd132d417f4dde1bfc65dd8f440256a56",
- "0xfd2c28cb6c38931a1f784078c41d21d7bf8fc3653231edca225a5fbbc50529dc": "0x88a482ab0eacd2d6c1fc7b3858bfba29aa92b8abfc6239e02e6952640c3ebdf7"
+ "0x5abd4cf6f12f56a1077d607918110659db02bbb5f419e4f4643c926e7c78d701": "0x7e5435b4313ad9ef6d831b39306df989156afac6ebeb1c4644cd7bd63088bfb7",
+ "0xe577ed57cc6c3ce09f0d1f66fbf3fcb30b35fde4c350c8d515d0f930603c41df": "0x97167e0f92b3e91d6e0fb8637c5ddfa224a3ec191528f46208663258c0cb95c3"
},
"Test_GUniFactory": {
"0xa8ee5069b769099da4dbc8c5d4c95cb74d416554203119678be4d0eba33f5962": "0x767e6faad4f8e62d6ab897930a0eb497cb71ebc75f90856dc13996fb00b907d3"
@@ -85,13 +85,13 @@
"0x78a7c23f669f5df656575693f45f928b7af2ed4bc981cf6dec77bef2c03bb081": "0xf0bc4482fcf2593df36fb9fb83ee5d273e7ee6a3caa9414d9c24eeee96567b6f"
},
"Test_UniswapV2DirectToLiquidity": {
- "0x9c33aa54294ebd7a8909181ebd6aed2b967b0eb4b0fb95467495624e6c211a67": "0xba73f6582c497ae5c4d38c53ba8bfb98266aa3566aaafef6d00f65d327effd66"
+ "0xf108beb959acb1e7e41cab1e1a3039f077c572167a9dadf5c31b642d80bc8c3c": "0x776bb071737d0bd3c0c1096a8a9d83574280b883b2681dadffaf6fa94fc669fc"
},
"Test_UniswapV2Router": {
"0xe6204aa211921628df345ff0b909c863298684cd8ca65de5479af6b70662e622": "0xf5700f795856223d45b9e1b76fa0f23db9d770b25c44cae8f556ae6d1e7bee5e"
},
"Test_UniswapV3DirectToLiquidity": {
- "0xca7cd77c52253f2e1eec58c25dbb3b89ccaa938974767ed31217819f71d2db06": "0xdb4b3fa1df0a6205daaeb852a4b456a86df10140fd1d479072f7c62ea9ba7a79"
+ "0x5aec331792b9b995051d0efd683176c0800e527130eb7514f415c4f1a9f09f43": "0x37c69f7eea77a282f753c9ae1505d0272745cd870612e78e4e962285eb0de2d3"
},
"Test_UniswapV3Factory": {
"0xbcd657c3390ecd2e1782b6473400c51fa124922eb98b69f1b5192eb0f8e3d3df": "0xfad08a6eaa7974f06cec79e15064de7f6fa17b22ecdb3764988b2c4b1571c613"
diff --git a/src/interfaces/modules/IDerivative.sol b/src/interfaces/modules/IDerivative.sol
index a4ea48b7..c9a1c487 100644
--- a/src/interfaces/modules/IDerivative.sol
+++ b/src/interfaces/modules/IDerivative.sol
@@ -14,13 +14,15 @@ interface IDerivative {
/// @notice Metadata for a derivative token
///
/// @param exists True if the token has been deployed
- /// @param wrapped True if an ERC20-wrapped derivative has been deployed
+ /// @param wrapped Non-zero if an ERC20-wrapped derivative has been deployed
/// @param underlyingToken The address of the underlying token
+ /// @param supply The total supply of the derivative token
/// @param data Implementation-specific data
struct Token {
bool exists;
address wrapped;
address underlyingToken;
+ uint256 supply;
bytes data;
}
@@ -30,13 +32,20 @@ interface IDerivative {
///
/// @param tokenId The ID of the derivative token
/// @return exists True if the token has been deployed
- /// @return wrapped True if an ERC20-wrapped derivative has been deployed
+ /// @return wrapped Non-zero if an ERC20-wrapped derivative has been deployed
/// @return underlyingToken The address of the underlying token
+ /// @return supply The total supply of the derivative token
/// @return data Implementation-specific data
function tokenMetadata(uint256 tokenId)
external
view
- returns (bool exists, address wrapped, address underlyingToken, bytes memory data);
+ returns (
+ bool exists,
+ address wrapped,
+ address underlyingToken,
+ uint256 supply,
+ bytes memory data
+ );
// ========== DERIVATIVE MANAGEMENT ========== //
diff --git a/src/lib/ERC6909Metadata.sol b/src/lib/ERC6909Metadata.sol
index eea62145..3d83cd01 100644
--- a/src/lib/ERC6909Metadata.sol
+++ b/src/lib/ERC6909Metadata.sol
@@ -19,4 +19,16 @@ abstract contract ERC6909Metadata {
/// @param tokenId_ The ID of the token
/// @return uint8 The number of decimals used by the token
function decimals(uint256 tokenId_) public view virtual returns (uint8);
+
+ /// @notice Returns the URI of the token
+ ///
+ /// @param tokenId_ The ID of the token
+ /// @return string The URI of the token
+ function tokenURI(uint256 tokenId_) public view virtual returns (string memory);
+
+ /// @notice Returns the total supply of the token
+ ///
+ /// @param tokenId_ The ID of the token
+ /// @return uint256 The total supply of the token
+ function totalSupply(uint256 tokenId_) public view virtual returns (uint256);
}
diff --git a/src/lib/SVG.sol b/src/lib/SVG.sol
new file mode 100644
index 00000000..9b693cca
--- /dev/null
+++ b/src/lib/SVG.sol
@@ -0,0 +1,251 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.8.12;
+
+// hot-chain-svg: https://github.com/w1nt3r-eth/hot-chain-svg
+
+// Core utils used extensively to format CSS and numbers.
+library utils {
+ // used to simulate empty strings
+ string internal constant NULL = "";
+
+ // formats a CSS variable line. includes a semicolon for formatting.
+ function setCssVar(
+ string memory _key,
+ string memory _val
+ ) internal pure returns (string memory) {
+ return string.concat("--", _key, ":", _val, ";");
+ }
+
+ // formats getting a css variable
+ function getCssVar(string memory _key) internal pure returns (string memory) {
+ return string.concat("var(--", _key, ")");
+ }
+
+ // formats getting a def URL
+ function getDefURL(string memory _id) internal pure returns (string memory) {
+ return string.concat("url(#", _id, ")");
+ }
+
+ // formats rgba white with a specified opacity / alpha
+ function white_a(uint256 _a) internal pure returns (string memory) {
+ return rgba(255, 255, 255, _a);
+ }
+
+ // formats rgba black with a specified opacity / alpha
+ function black_a(uint256 _a) internal pure returns (string memory) {
+ return rgba(0, 0, 0, _a);
+ }
+
+ // formats generic rgba color in css
+ function rgba(
+ uint256 _r,
+ uint256 _g,
+ uint256 _b,
+ uint256 _a
+ ) internal pure returns (string memory) {
+ string memory formattedA = _a < 100 ? string.concat("0.", utils.uint2str(_a)) : "1";
+ return string.concat(
+ "rgba(",
+ utils.uint2str(_r),
+ ",",
+ utils.uint2str(_g),
+ ",",
+ utils.uint2str(_b),
+ ",",
+ formattedA,
+ ")"
+ );
+ }
+
+ // checks if two strings are equal
+ function stringsEqual(string memory _a, string memory _b) internal pure returns (bool) {
+ return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b));
+ }
+
+ // returns the length of a string in characters
+ function utfStringLength(string memory _str) internal pure returns (uint256 length) {
+ uint256 i = 0;
+ bytes memory string_rep = bytes(_str);
+
+ while (i < string_rep.length) {
+ if (string_rep[i] >> 7 == 0) {
+ i += 1;
+ } else if (string_rep[i] >> 5 == bytes1(uint8(0x6))) {
+ i += 2;
+ } else if (string_rep[i] >> 4 == bytes1(uint8(0xE))) {
+ i += 3;
+ } else if (string_rep[i] >> 3 == bytes1(uint8(0x1E))) {
+ i += 4;
+ }
+ //For safety
+ else {
+ i += 1;
+ }
+
+ length++;
+ }
+ }
+
+ // converts an unsigned integer to a string
+ function uint2str(uint256 _i) internal pure returns (string memory _uintAsString) {
+ if (_i == 0) {
+ return "0";
+ }
+ uint256 j = _i;
+ uint256 len;
+ while (j != 0) {
+ len++;
+ j /= 10;
+ }
+ bytes memory bstr = new bytes(len);
+ uint256 k = len;
+ while (_i != 0) {
+ k = k - 1;
+ uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
+ bytes1 b1 = bytes1(temp);
+ bstr[k] = b1;
+ _i /= 10;
+ }
+ return string(bstr);
+ }
+}
+
+// Core SVG utilitiy library which helps us construct
+// onchain SVG's with a simple, web-like API.
+library svg {
+ /* MAIN ELEMENTS */
+ function g(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("g", _props, _children);
+ }
+
+ function path(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("path", _props, _children);
+ }
+
+ function text(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("text", _props, _children);
+ }
+
+ function line(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("line", _props, _children);
+ }
+
+ function circle(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("circle", _props, _children);
+ }
+
+ function circle(string memory _props) internal pure returns (string memory) {
+ return el("circle", _props);
+ }
+
+ function ellipse(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("ellipse", _props, _children);
+ }
+
+ function ellipse(string memory _props) internal pure returns (string memory) {
+ return el("ellipse", _props);
+ }
+
+ function rect(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("rect", _props, _children);
+ }
+
+ function rect(string memory _props) internal pure returns (string memory) {
+ return el("rect", _props);
+ }
+
+ function filter(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("filter", _props, _children);
+ }
+
+ function cdata(string memory _content) internal pure returns (string memory) {
+ return string.concat("");
+ }
+
+ /* GRADIENTS */
+ function radialGradient(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("radialGradient", _props, _children);
+ }
+
+ function linearGradient(
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return el("linearGradient", _props, _children);
+ }
+
+ function gradientStop(
+ uint256 offset,
+ string memory stopColor,
+ string memory _props
+ ) internal pure returns (string memory) {
+ return el(
+ "stop",
+ string.concat(
+ prop("stop-color", stopColor),
+ " ",
+ prop("offset", string.concat(utils.uint2str(offset), "%")),
+ " ",
+ _props
+ )
+ );
+ }
+
+ function animateTransform(string memory _props) internal pure returns (string memory) {
+ return el("animateTransform", _props);
+ }
+
+ function image(
+ string memory _href,
+ string memory _props
+ ) internal pure returns (string memory) {
+ return el("image", string.concat(prop("href", _href), " ", _props));
+ }
+
+ /* COMMON */
+ // A generic element, can be used to construct any SVG (or HTML) element
+ function el(
+ string memory _tag,
+ string memory _props,
+ string memory _children
+ ) internal pure returns (string memory) {
+ return string.concat("<", _tag, " ", _props, ">", _children, "", _tag, ">");
+ }
+
+ // A generic element, can be used to construct any SVG (or HTML) element without children
+ function el(string memory _tag, string memory _props) internal pure returns (string memory) {
+ return string.concat("<", _tag, " ", _props, "/>");
+ }
+
+ // an SVG attribute
+ function prop(string memory _key, string memory _val) internal pure returns (string memory) {
+ return string.concat(_key, "=", '"', _val, '" ');
+ }
+}
diff --git a/src/modules/Derivative.sol b/src/modules/Derivative.sol
index 6aa0bf7f..702185ba 100644
--- a/src/modules/Derivative.sol
+++ b/src/modules/Derivative.sol
@@ -21,4 +21,11 @@ abstract contract DerivativeModule is IDerivative, ERC6909, ERC6909Metadata, Mod
function getTokenMetadata(uint256 tokenId) external view virtual returns (Token memory) {
return tokenMetadata[tokenId];
}
+
+ // ========== ERC6909 TOKEN SUPPLY EXTENSION ========== //
+
+ /// @inheritdoc ERC6909Metadata
+ function totalSupply(uint256 tokenId) public view virtual override returns (uint256) {
+ return tokenMetadata[tokenId].supply;
+ }
}
diff --git a/src/modules/derivatives/LinearVesting.sol b/src/modules/derivatives/LinearVesting.sol
index a8747b77..1fe7961b 100644
--- a/src/modules/derivatives/LinearVesting.sol
+++ b/src/modules/derivatives/LinearVesting.sol
@@ -8,12 +8,14 @@ import {ClonesWithImmutableArgs} from "src/lib/clones/ClonesWithImmutableArgs.so
import {Timestamp} from "src/lib/Timestamp.sol";
import {ERC6909Metadata} from "src/lib/ERC6909Metadata.sol";
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
+import {Base64} from "lib/openzeppelin-contracts/contracts/utils/Base64.sol";
import {IDerivative} from "src/interfaces/modules/IDerivative.sol";
import {ILinearVesting} from "src/interfaces/modules/derivatives/ILinearVesting.sol";
import {DerivativeModule} from "src/modules/Derivative.sol";
import {Module, Veecode, toKeycode, wrapVeecode} from "src/modules/Modules.sol";
import {SoulboundCloneERC20} from "src/modules/derivatives/SoulboundCloneERC20.sol";
+import {LinearVestingCard} from "src/modules/derivatives/LinearVestingCard.sol";
/// @title LinearVesting
/// @notice A derivative module that allows for the creation of linearly vesting tokens
@@ -23,7 +25,7 @@ import {SoulboundCloneERC20} from "src/modules/derivatives/SoulboundCloneERC20.s
///
/// The start timestamp enables vesting tokens to have a cliff, after which vesting commences.
/// @author Axis Finance
-contract LinearVesting is DerivativeModule, ILinearVesting {
+contract LinearVesting is DerivativeModule, ILinearVesting, LinearVestingCard {
using SafeTransferLib for ERC20;
using ClonesWithImmutableArgs for address;
using Timestamp for uint48;
@@ -41,7 +43,7 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
// ========== MODULE SETUP ========== //
- constructor(address parent_) Module(parent_) {
+ constructor(address parent_) Module(parent_) LinearVestingCard() {
// Deploy the clone implementation
_IMPLEMENTATION = address(new SoulboundCloneERC20());
}
@@ -163,7 +165,12 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
SoulboundCloneERC20 wrappedToken = SoulboundCloneERC20(token_.wrapped);
wrappedToken.mint(to_, amount_);
} else {
- // Otherwise mint the normal derivative token
+ // Increment the supply
+ unchecked {
+ token_.supply += amount_;
+ }
+
+ // Mint the normal derivative token
_mint(to_, tokenId_, amount_);
}
}
@@ -265,6 +272,9 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
// Burn the unwrapped tokens
if (derivativeToBurn > 0) {
+ unchecked {
+ tokenData.supply -= derivativeToBurn;
+ }
_burn(user_, tokenId_, derivativeToBurn);
}
// Burn the wrapped tokens - will be 0 if not wrapped
@@ -394,6 +404,11 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
if (balanceOf[msg.sender][tokenId_] < amount_) revert InsufficientBalance();
+ // Decrement supply on this contract, since it's tracked on the ERC20
+ unchecked {
+ tokenMetadata[tokenId_].supply -= amount_;
+ }
+
// Burn the derivative token
_burn(msg.sender, tokenId_, amount_);
@@ -423,6 +438,11 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
if (wrappedToken.balanceOf(msg.sender) < amount_) revert InsufficientBalance();
+ // Increment supply on this contract
+ unchecked {
+ token.supply += amount_;
+ }
+
// Burn the wrapped derivative token
wrappedToken.burn(msg.sender, amount_);
@@ -682,4 +702,55 @@ contract LinearVesting is DerivativeModule, ILinearVesting {
return ERC20(token.underlyingToken).decimals();
}
+
+ // ========== ERC6909 CONTENT EXTENSION ========== //
+
+ /// @inheritdoc ERC6909Metadata
+ /// @dev This function reverts if:
+ /// - The token ID does not exist
+ function tokenURI(uint256 tokenId_)
+ public
+ view
+ override
+ onlyValidTokenId(tokenId_)
+ returns (string memory)
+ {
+ Token storage token = tokenMetadata[tokenId_];
+ VestingParams memory data = abi.decode(token.data, (VestingParams));
+
+ // Get the underlying token symbol
+ string memory _symbol = ERC20(token.underlyingToken).symbol();
+
+ // Create token info for rendering token card
+ Info memory info = Info({
+ tokenId: tokenId_,
+ baseToken: token.underlyingToken,
+ baseTokenSymbol: _symbol,
+ start: data.start,
+ expiry: data.expiry,
+ supply: totalSupply(tokenId_)
+ });
+
+ // Return the token URI
+ // solhint-disable quotes
+ return string.concat(
+ "data:application/json;base64,",
+ Base64.encode(
+ bytes(
+ string.concat(
+ '{"name": "',
+ name(tokenId_),
+ '", "description": "',
+ _symbol,
+ ' Soulbound Linear Vesting Derivative Token. Powered by Axis.", "attributes": ',
+ _attributes(info),
+ ', "image": "data:image/svg+xml;base64,',
+ Base64.encode(bytes(_render(info))),
+ '"}'
+ )
+ )
+ )
+ );
+ // solhint-enable quotes
+ }
}
diff --git a/src/modules/derivatives/LinearVestingCard.sol b/src/modules/derivatives/LinearVestingCard.sol
new file mode 100644
index 00000000..02027805
--- /dev/null
+++ b/src/modules/derivatives/LinearVestingCard.sol
@@ -0,0 +1,319 @@
+/// SPDX-License-Identifier: BSL-1.1
+pragma solidity 0.8.19;
+
+import {svg} from "src/lib/SVG.sol";
+import {Timestamp} from "src/lib/Timestamp.sol";
+import {Strings} from "lib/openzeppelin-contracts/contracts/utils/Strings.sol";
+
+contract LinearVestingCard {
+ // solhint-disable quotes
+
+ // ========== DATA STRUCTURES ========== //
+
+ struct Info {
+ uint256 tokenId;
+ address baseToken;
+ string baseTokenSymbol;
+ uint48 start;
+ uint48 expiry;
+ uint256 supply;
+ }
+
+ // ========== STATE VARIABLES ========== //
+
+ string internal constant _TEXT_STYLE =
+ 'font-family="\'Menlo\', monospace" fill="white" text-anchor="middle"';
+ string internal constant _NULL = "";
+ string internal _addrString;
+
+ string internal constant _COLOR_BLUE = "rgb(110, 148, 240)";
+ string internal constant _COLOR_LIGHT_BLUE = "rgb(118, 189, 242)";
+ string internal constant _COLOR_GREEN = "rgb(206, 244, 117)";
+ string internal constant _COLOR_YELLOW_GREEN = "rgb(243, 244, 189)";
+ string internal constant _COLOR_YELLOW = "rgb(243, 244, 189)";
+ string internal constant _COLOR_ORANGE = "rgb(246, 172, 84)";
+ string internal constant _COLOR_RED = "rgb(242, 103, 64)";
+
+ // ========== CONSTRUCTOR ========== //
+
+ constructor() {
+ _addrString = Strings.toHexString(address(this));
+ }
+
+ // ========== ATTRIBUTES ========== //
+
+ function _attributes(Info memory tokenInfo) internal pure returns (string memory) {
+ return string.concat(
+ '[{"trait_type":"Token ID","value":"',
+ Strings.toString(tokenInfo.tokenId),
+ '"},',
+ '{"trait_type":"Base Token","value":"',
+ Strings.toHexString(tokenInfo.baseToken),
+ '"},',
+ '{"trait_type":"Base Token Symbol", "value":"',
+ tokenInfo.baseTokenSymbol,
+ '"},',
+ '{"trait_type":"Vesting Start","display_type":"date","value":"',
+ Strings.toString(tokenInfo.start),
+ '"},',
+ '{"trait_type":"Vesting End","display_type":"date","value":"',
+ Strings.toString(tokenInfo.expiry),
+ '"},',
+ '{"trait_type":"Total Supply","value":"',
+ Strings.toString(tokenInfo.supply),
+ '"}]'
+ );
+ }
+
+ // ========== RENDERER ========== //
+ function _render(Info memory tokenInfo) internal view returns (string memory) {
+ return string.concat(
+ '"
+ );
+ }
+
+ // ========== COMPONENTS ========== //
+
+ function _title(string memory symbol) internal pure returns (string memory) {
+ return string.concat(
+ svg.text(string.concat('x="145" y="40" font-size="20" ', _TEXT_STYLE), "Linear Vesting"),
+ svg.text(string.concat('x="145" y="100" font-size="56" ', _TEXT_STYLE), symbol)
+ );
+ }
+
+ function _logo() internal pure returns (string memory) {
+ return string.concat(
+ svg.rect(
+ 'x="143" y="240" width="6" height="125" fill="url(#fullGradientReverse90)"', _NULL
+ ),
+ svg.rect(
+ 'x="79" y="246" width="6" height="125" fill="url(#fullGradient90)" transform="rotate(-60 145 250)"',
+ _NULL
+ ),
+ svg.rect(
+ 'x="206" y="244" width="6" height="125" fill="url(#fullGradient90)" transform="rotate(60 145 250)"',
+ _NULL
+ )
+ );
+ }
+
+ function _identifier(uint256 tokenId) internal view returns (string memory) {
+ return string.concat(
+ svg.text(string.concat('x="145" y="460" font-size="10" ', _TEXT_STYLE), _addrString),
+ svg.text(
+ string.concat('x="145" y="480" font-size="6" ', _TEXT_STYLE),
+ string.concat("ID: ", Strings.toHexString(tokenId))
+ )
+ );
+ }
+
+ function _progressBar(uint256 start, uint256 end) internal view returns (string memory) {
+ uint256 currentTime = block.timestamp; // 1717200000 + 70 * 86400;
+
+ string memory startBar;
+ string memory endBar;
+ uint256 progress;
+ {
+ bool started = start <= currentTime;
+
+ progress = started ? ((currentTime - start) * 100) / (end - start) : 0;
+ // progress can be at most 100
+ progress = progress > 100 ? 100 : progress;
+
+ startBar = svg.line(
+ string.concat(
+ 'x1="60" y1="155" x2="60" y2="175" stroke="',
+ started ? _COLOR_BLUE : "grey",
+ '" stroke-width="6"'
+ ),
+ _NULL
+ );
+
+ endBar = svg.line(
+ string.concat(
+ 'x1="230" y1="155" x2="230" y2="175" stroke="',
+ progress == 100 ? _COLOR_GREEN : "grey",
+ '" stroke-width="6"'
+ ),
+ _NULL
+ );
+ }
+
+ uint256 len = (168 * progress) / 100;
+ string memory current = Strings.toString(62 + len);
+
+ string memory progressLine = svg.line(
+ string.concat(
+ 'x1="62" y1="165" x2="',
+ current,
+ '" y2="165" stroke="url(#blueGreenGradient)" stroke-width="6"'
+ ),
+ _NULL
+ );
+
+ string memory progressCircle = svg.circle(
+ string.concat('cx="', current, '" cy="165" r="6" fill="url(#blueGreenGradient)"'), _NULL
+ );
+
+ string memory shadowLine = svg.line(
+ string.concat('x1="63" y1="165" x2="230" y2="165" stroke="grey" stroke-width="4"'),
+ _NULL
+ );
+
+ return svg.g(
+ _NULL,
+ string.concat(
+ startBar,
+ shadowLine,
+ progressLine,
+ progress < 15 ? "" : _animateLine(len),
+ endBar,
+ progress < 5 || progress > 95 ? "" : progressCircle
+ )
+ );
+ }
+
+ function _animateLine(uint256 len) internal pure returns (string memory) {
+ return svg.rect(
+ string.concat(
+ 'x="62" y="161" width="12" height="8" fill="url(#blueGreenGradient)" rx="4" ry="4"'
+ ),
+ svg.el(
+ "animate",
+ string.concat(
+ 'attributeName="x" values="62;',
+ Strings.toString(62 + len - 16),
+ ';" dur="',
+ Strings.toString(((5 * len) / 168) + 1),
+ 's" repeatCount="indefinite"'
+ ),
+ _NULL
+ )
+ );
+ }
+
+ function _progressLabels(uint48 start_, uint48 expiry_) internal pure returns (string memory) {
+ (string memory start, string memory expiry) = _getTimeStrings(start_, expiry_);
+
+ return string.concat(
+ svg.text(string.concat('x="60" y="200" font-size="12" ', _TEXT_STYLE), start),
+ svg.text(string.concat('x="230" y="200" font-size="12" ', _TEXT_STYLE), expiry)
+ );
+ }
+
+ // ========== COLOR GRADIENTS ========== //
+
+ function _fullGradientStops() internal pure returns (string memory) {
+ return string.concat(
+ svg.gradientStop(2, _COLOR_BLUE, _NULL),
+ svg.gradientStop(10, _COLOR_LIGHT_BLUE, _NULL),
+ svg.gradientStop(32, _COLOR_GREEN, _NULL),
+ svg.gradientStop(49, _COLOR_YELLOW_GREEN, _NULL),
+ svg.gradientStop(52, _COLOR_YELLOW, _NULL),
+ svg.gradientStop(79, _COLOR_ORANGE, _NULL),
+ svg.gradientStop(100, _COLOR_RED, _NULL)
+ );
+ }
+
+ function _fullGradientReverseStops() internal pure returns (string memory) {
+ return string.concat(
+ svg.gradientStop(2, _COLOR_RED, _NULL),
+ svg.gradientStop(21, _COLOR_ORANGE, _NULL),
+ svg.gradientStop(48, _COLOR_YELLOW, _NULL),
+ svg.gradientStop(51, _COLOR_YELLOW_GREEN, _NULL),
+ svg.gradientStop(68, _COLOR_GREEN, _NULL),
+ svg.gradientStop(90, _COLOR_LIGHT_BLUE, _NULL),
+ svg.gradientStop(100, _COLOR_BLUE, _NULL)
+ );
+ }
+
+ function _fullGradient() internal pure returns (string memory) {
+ return
+ svg.linearGradient(string.concat(svg.prop("id", "fullGradient")), _fullGradientStops());
+ }
+
+ function _fullGradient90() internal pure returns (string memory) {
+ return svg.linearGradient(
+ string.concat(
+ svg.prop("id", "fullGradient90"), svg.prop("gradientTransform", "rotate(90)")
+ ),
+ _fullGradientStops()
+ );
+ }
+
+ function _fullGradientReverse90() internal pure returns (string memory) {
+ return svg.linearGradient(
+ string.concat(
+ svg.prop("id", "fullGradientReverse90"), svg.prop("gradientTransform", "rotate(90)")
+ ),
+ _fullGradientReverseStops()
+ );
+ }
+
+ function _blueGreenGradient() internal pure returns (string memory) {
+ return svg.linearGradient(
+ string.concat(
+ svg.prop("id", "blueGreenGradient"), svg.prop("gradientUnits", "userSpaceOnUse")
+ ),
+ string.concat(
+ svg.gradientStop(20, _COLOR_BLUE, _NULL),
+ svg.gradientStop(40, _COLOR_LIGHT_BLUE, _NULL),
+ svg.gradientStop(60, _COLOR_GREEN, _NULL)
+ )
+ );
+ }
+
+ // ========== UTILITIES ========== //
+
+ function _getTimeStrings(
+ uint48 start,
+ uint48 end
+ ) internal pure returns (string memory, string memory) {
+ (string memory startYear, string memory startMonth, string memory startDay) =
+ Timestamp.toPaddedString(start);
+ (string memory endYear, string memory endMonth, string memory endDay) =
+ Timestamp.toPaddedString(end);
+
+ return (
+ string.concat(startYear, "-", startMonth, "-", startDay),
+ string.concat(endYear, "-", endMonth, "-", endDay)
+ );
+ }
+
+ // ========== EXAMPLE ========== //
+ // Used by hot-chain-svg during development.
+ //
+ // function example() external view returns (string memory) {
+ // Info memory info = Info({
+ // baseToken: address(0x1234567890123456789012345678901234567890),
+ // baseTokenSymbol: "XYZ",
+ // tokenId: 123_456,
+ // start: 1_717_200_000, // 2024-06-01
+ // expiry: 1_725_148_800 // 2024-09-01
+ // });
+ // return _render(info);
+ // }
+}
diff --git a/test/modules/derivatives/LinearVesting.t.sol b/test/modules/derivatives/LinearVesting.t.sol
index 7fcbbbc1..ae8f2361 100644
--- a/test/modules/derivatives/LinearVesting.t.sol
+++ b/test/modules/derivatives/LinearVesting.t.sol
@@ -3,6 +3,7 @@ pragma solidity 0.8.19;
// Libraries
import {Test} from "forge-std/Test.sol";
+import {console2} from "forge-std/console2.sol";
import {Permit2User} from "test/lib/permit2/Permit2User.sol";
import {StringHelper} from "test/lib/String.sol";
@@ -53,7 +54,7 @@ contract LinearVestingTest is Test, Permit2User {
vm.warp(_VESTING_START - 1);
_underlyingToken =
- new MockFeeOnTransferERC20("Underlying", "UNDERLYING", _underlyingTokenDecimals);
+ new MockFeeOnTransferERC20("Underlying", "UNDY", _underlyingTokenDecimals);
_underlyingTokenAddress = address(_underlyingToken);
_auctionHouse = new AtomicAuctionHouse(address(this), _PROTOCOL, _permit2Address);
@@ -65,7 +66,7 @@ contract LinearVestingTest is Test, Permit2User {
_vestingParamsBytes = abi.encode(_vestingParams);
_wrappedDerivativeTokenName = "Underlying 2024-01-12";
- _wrappedDerivativeTokenSymbol = "UNDERLYING 2024-01-12";
+ _wrappedDerivativeTokenSymbol = "UNDY 2024-01-12";
_wrappedDerivativeTokenNameLength = bytes(_wrappedDerivativeTokenName).length;
_wrappedDerivativeTokenSymbolLength = bytes(_wrappedDerivativeTokenSymbol).length;
}
@@ -124,7 +125,7 @@ contract LinearVestingTest is Test, Permit2User {
_vestingParamsBytes = abi.encode(_vestingParams);
_wrappedDerivativeTokenName = "Underlying 2024-01-14";
- _wrappedDerivativeTokenSymbol = "UNDERLYING 2024-01-14";
+ _wrappedDerivativeTokenSymbol = "UNDY 2024-01-14";
_wrappedDerivativeTokenNameLength = bytes(_wrappedDerivativeTokenName).length;
_wrappedDerivativeTokenSymbolLength = bytes(_wrappedDerivativeTokenSymbol).length;
_;
@@ -841,6 +842,7 @@ contract LinearVestingTest is Test, Permit2User {
assertTrue(wrappedAddress == address(0), "wrappedAddress mismatch");
assertEq(amountCreated, _AMOUNT, "amountCreated mismatch");
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_expiryTimestampIsBeforeCurrentTimestamp()
@@ -859,6 +861,7 @@ contract LinearVestingTest is Test, Permit2User {
assertTrue(wrappedAddress == address(0), "wrappedAddress mismatch");
assertEq(amountCreated, _AMOUNT, "amountCreated mismatch");
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_afterExpiry()
@@ -880,6 +883,7 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
assertEq(_underlyingToken.balanceOf(_ALICE), 0, "underlying: balanceOf mismatch");
assertEq(_linearVesting.redeemable(_ALICE, tokenId), _AMOUNT, "redeemable mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_mintAmountIsZero_reverts() public {
@@ -905,6 +909,7 @@ contract LinearVestingTest is Test, Permit2User {
// Check values
assertTrue(tokenId > 0, "tokenId mismatch");
assertEq(_linearVesting.balanceOf(address(0), tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_insufficentBalance_reverts() public {
@@ -953,6 +958,7 @@ contract LinearVestingTest is Test, Permit2User {
);
assertEq(_underlyingToken.balanceOf(_ALICE), 0, "underlying: balanceOf mismatch");
assertEq(_linearVesting.redeemable(_ALICE, tokenId), 0, "redeemable mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_afterVestingStart(uint48 elapsed_)
@@ -984,6 +990,7 @@ contract LinearVestingTest is Test, Permit2User {
expectedRedeemableAmount,
"redeemable mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_givenExistingDerivativeTokens_afterVestingStart(uint48 elapsed_)
@@ -1028,6 +1035,7 @@ contract LinearVestingTest is Test, Permit2User {
expectedRedeemableAmount,
"redeemable mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT + _AMOUNT_TWO, "totalSupply mismatch");
}
function test_mint_params_notWrapped_tokenNotDeployed()
@@ -1045,6 +1053,7 @@ contract LinearVestingTest is Test, Permit2User {
assertTrue(wrappedAddress == address(0), "wrappedAddress mismatch");
assertEq(amountCreated, _AMOUNT, "amountCreated mismatch");
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_notWrapped_tokenDeployed()
@@ -1063,6 +1072,7 @@ contract LinearVestingTest is Test, Permit2User {
assertTrue(wrappedAddress == address(0), "wrappedAddress mismatch");
assertEq(amountCreated, _AMOUNT, "amountCreated mismatch");
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_params_wrapped_wrappedTokenIsNotDeployed()
@@ -1083,6 +1093,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
function test_mint_params_wrapped_wrappedTokenIsDeployed()
@@ -1103,6 +1115,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
function test_mint_params_notParent()
@@ -1123,6 +1137,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
function test_mint_params_notParent_insufficientBalance_reverts()
@@ -1196,6 +1212,7 @@ contract LinearVestingTest is Test, Permit2User {
// Check values
assertEq(_linearVesting.balanceOf(address(0), tokenId), _AMOUNT);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_tokenId_insufficentBalance_reverts() public givenDerivativeIsDeployed {
@@ -1244,6 +1261,7 @@ contract LinearVestingTest is Test, Permit2User {
);
assertEq(_underlyingToken.balanceOf(_ALICE), 0, "underlying: balanceOf mismatch");
assertEq(_linearVesting.redeemable(_ALICE, tokenId), 0, "redeemable mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_tokenId_afterVestingStart(uint48 elapsed_)
@@ -1275,6 +1293,7 @@ contract LinearVestingTest is Test, Permit2User {
expectedRedeemableAmount,
"redeemable mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_tokenId_afterVestingExpiry()
@@ -1297,6 +1316,7 @@ contract LinearVestingTest is Test, Permit2User {
);
assertEq(_underlyingToken.balanceOf(_ALICE), 0, "underlying: balanceOf mismatch");
assertEq(_linearVesting.redeemable(_ALICE, tokenId), _AMOUNT, "redeemable mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_tokenId_givenExistingDerivativeTokens_afterVestingStart(uint48 elapsed_)
@@ -1340,6 +1360,7 @@ contract LinearVestingTest is Test, Permit2User {
expectedRedeemableAmount,
"redeemable mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT + _AMOUNT_TWO, "totalSupply mismatch");
}
function test_mint_tokenId_givenExistingDerivativeTokens_afterVestingExpiry()
@@ -1377,6 +1398,7 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
_linearVesting.redeemable(_ALICE, tokenId), _AMOUNT + _AMOUNT_TWO, "redeemable mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT + _AMOUNT_TWO, "totalSupply mismatch");
}
function test_mint_tokenId_notWrapped()
@@ -1394,6 +1416,7 @@ contract LinearVestingTest is Test, Permit2User {
assertTrue(wrappedAddress == address(0));
assertEq(amountCreated, _AMOUNT);
assertEq(_linearVesting.balanceOf(_ALICE, tokenId), _AMOUNT, "balanceOf mismatch");
+ assertEq(_linearVesting.totalSupply(tokenId), _AMOUNT, "totalSupply mismatch");
}
function test_mint_tokenId_wrapped_wrappedTokenIsNotDeployed()
@@ -1414,6 +1437,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
function test_mint_tokenId_wrapped_wrappedTokenIsDeployed()
@@ -1434,6 +1459,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
function test_mint_tokenId_notParent()
@@ -1454,6 +1481,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(
SoulboundCloneERC20(wrappedAddress).balanceOf(_ALICE), _AMOUNT, "balanceOf mismatch"
);
+ assertEq(_linearVesting.totalSupply(tokenId), 0, "totalSupply mismatch");
+ assertEq(SoulboundCloneERC20(wrappedAddress).totalSupply(), _AMOUNT, "balanceOf mismatch");
}
// redeem
@@ -1538,6 +1567,7 @@ contract LinearVestingTest is Test, Permit2User {
// Check values
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), _AMOUNT - amount);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), amount);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), _AMOUNT - amount);
}
function test_redeem_givenWrappedBalance(uint256 amount_)
@@ -1556,6 +1586,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), 0);
assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).balanceOf(_ALICE), _AMOUNT - amount);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), amount);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), 0);
+ assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(), _AMOUNT - amount);
}
function test_redeem_givenUnwrappedBalance(uint256 amount_)
@@ -1574,6 +1606,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), _AMOUNT - amount);
assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).balanceOf(_ALICE), 0);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), amount);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), _AMOUNT - amount);
+ assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(), 0);
}
function test_redeem_givenMixedBalance()
@@ -1593,6 +1627,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), 0); // Redeems unwrapped first
assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).balanceOf(_ALICE), _AMOUNT - 1);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), amountToRedeem);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), 0);
+ assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(), _AMOUNT - 1);
}
// redeem max
@@ -1643,6 +1679,7 @@ contract LinearVestingTest is Test, Permit2User {
// Check values
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), 0);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), _AMOUNT);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), 0);
}
function test_redeemMax_givenWrappedBalance_givenVestingExpiry()
@@ -1659,6 +1696,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), 0);
assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).balanceOf(_ALICE), 0);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), _AMOUNT);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), 0);
+ assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(), 0);
}
function test_redeemMax_givenUnwrappedBalance_givenVestingExpiry()
@@ -1675,6 +1714,8 @@ contract LinearVestingTest is Test, Permit2User {
assertEq(_linearVesting.balanceOf(_ALICE, _derivativeTokenId), 0);
assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).balanceOf(_ALICE), 0);
assertEq(SoulboundCloneERC20(_underlyingTokenAddress).balanceOf(_ALICE), _AMOUNT);
+ assertEq(_linearVesting.totalSupply(_derivativeTokenId), 0);
+ assertEq(SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(), 0);
}
function test_redeemMax(uint48 elapsed_) public givenWrappedDerivativeIsDeployed {
@@ -1717,6 +1758,16 @@ contract LinearVestingTest is Test, Permit2User {
redeemable,
"underlying token: balanceOf mismatch"
);
+ assertEq(
+ _linearVesting.totalSupply(_derivativeTokenId),
+ expectedBalanceUnwrapped,
+ "derivative token: totalSupply mismatch"
+ );
+ assertEq(
+ SoulboundCloneERC20(_derivativeWrappedAddress).totalSupply(),
+ expectedBalanceWrapped,
+ "wrapped derivative token: totalSupply mismatch"
+ );
}
// redeemable
@@ -2493,4 +2544,77 @@ contract LinearVestingTest is Test, Permit2User {
// Call
_linearVesting.exercise(_derivativeTokenId, _AMOUNT);
}
+
+ // tokenURI
+ // [X] given the vesting period hasn't started
+ // [X] the progress bar is grey (verified externally)
+ // [X] given the vesting period has just started
+ // [X] the progress bar has blue green gradient at the left bar (verified externally)
+ // [X] given the vesting period is halfway through
+ // [X] the progress bar has blue green gradient in the middle and a circle showing current point (verified externally)
+ // [X] given the vesting period has ended
+ // [X] the progress bar is fully blue green gradient (verified externally)
+
+ function test_tokenURI_beforeStart()
+ public
+ givenDerivativeIsDeployed
+ givenAliceHasDerivativeTokens(_AMOUNT)
+ {
+ // Call
+ string memory tokenURI = _linearVesting.tokenURI(_derivativeTokenId);
+
+ console2.log("beforeStart: ", tokenURI);
+ }
+
+ function test_tokenURI_atStart()
+ public
+ givenDerivativeIsDeployed
+ givenAliceHasDerivativeTokens(_AMOUNT)
+ {
+ vm.warp(_VESTING_START);
+
+ // Call
+ string memory tokenURI = _linearVesting.tokenURI(_derivativeTokenId);
+
+ console2.log("atStart: ", tokenURI);
+ }
+
+ function test_tokenURI_halfway()
+ public
+ givenDerivativeIsDeployed
+ givenAliceHasDerivativeTokens(_AMOUNT)
+ {
+ vm.warp(_VESTING_START + _VESTING_DURATION / 2);
+
+ // Call
+ string memory tokenURI = _linearVesting.tokenURI(_derivativeTokenId);
+
+ console2.log("halfway: ", tokenURI);
+ }
+
+ function test_tokenURI_atEnd()
+ public
+ givenDerivativeIsDeployed
+ givenAliceHasDerivativeTokens(_AMOUNT)
+ {
+ vm.warp(_VESTING_START + _VESTING_DURATION);
+
+ // Call
+ string memory tokenURI = _linearVesting.tokenURI(_derivativeTokenId);
+
+ console2.log("atEnd: ", tokenURI);
+ }
+
+ function test_tokenURI_afterEnd()
+ public
+ givenDerivativeIsDeployed
+ givenAliceHasDerivativeTokens(_AMOUNT)
+ {
+ vm.warp(_VESTING_START + _VESTING_DURATION * 2);
+
+ // Call
+ string memory tokenURI = _linearVesting.tokenURI(_derivativeTokenId);
+
+ console2.log("afterEnd: ", tokenURI);
+ }
}
diff --git a/test/modules/derivatives/mocks/MockDerivativeModule.sol b/test/modules/derivatives/mocks/MockDerivativeModule.sol
index 5bc36d96..dfb1922f 100644
--- a/test/modules/derivatives/mocks/MockDerivativeModule.sol
+++ b/test/modules/derivatives/mocks/MockDerivativeModule.sol
@@ -93,6 +93,8 @@ contract MockDerivativeModule is DerivativeModule {
}
// Otherwise mint as normal
else {
+ // Increment the supply
+ tokenMetadata[tokenId].supply += amount_;
derivativeToken.mint(to_, tokenId, outputAmount);
}
@@ -209,4 +211,8 @@ contract MockDerivativeModule is DerivativeModule {
function symbol(uint256 tokenId_) public view virtual override returns (string memory) {}
function decimals(uint256 tokenId_) public view virtual override returns (uint8) {}
+
+ function tokenURI(uint256 tokenId_) public view virtual override returns (string memory) {}
+
+ function totalSupply(uint256 tokenId_) public view virtual override returns (uint256) {}
}
diff --git a/utils/hot-chain-svg/package.json b/utils/hot-chain-svg/package.json
new file mode 100644
index 00000000..63697bb4
--- /dev/null
+++ b/utils/hot-chain-svg/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "hot-chain-svg",
+ "version": "0.0.1",
+ "main": "src/index.js",
+ "author": "w1nt3r.eth",
+ "license": "MIT",
+ "scripts": {
+ "start": "node .",
+ "qa": "node src/qa.js",
+ "sync-nfts": "node src/sync-nfts.js"
+ },
+ "prettier": {
+ "singleQuote": true
+ },
+ "dependencies": {
+ "@ethereumjs/vm": "^5.8.0",
+ "@ethersproject/abi": "^5.6.0",
+ "ethers": "^5.6.8",
+ "solc": "0.8.19",
+ "xmldom": "^0.6.0"
+ },
+ "devDependencies": {
+ "prettier": "^2.6.2"
+ }
+}
diff --git a/utils/hot-chain-svg/src/boot.js b/utils/hot-chain-svg/src/boot.js
new file mode 100644
index 00000000..1eeb4fff
--- /dev/null
+++ b/utils/hot-chain-svg/src/boot.js
@@ -0,0 +1,22 @@
+const { Account, Address, BN } = require('ethereumjs-util');
+const VM = require('@ethereumjs/vm').default;
+
+async function boot() {
+ const pk = Buffer.from(
+ '1122334455667788112233445566778811223344556677881122334455667788',
+ 'hex'
+ );
+
+ const accountAddress = Address.fromPrivateKey(pk);
+ const account = Account.fromAccountData({
+ nonce: 0,
+ balance: new BN(10).pow(new BN(18 + 2)), // 100 eth
+ });
+
+ const vm = new VM();
+ await vm.stateManager.putAccount(accountAddress, account);
+
+ return { vm, pk };
+}
+
+module.exports = boot;
diff --git a/utils/hot-chain-svg/src/call.js b/utils/hot-chain-svg/src/call.js
new file mode 100644
index 00000000..2a8e46cd
--- /dev/null
+++ b/utils/hot-chain-svg/src/call.js
@@ -0,0 +1,34 @@
+const { defaultAbiCoder, Interface } = require('@ethersproject/abi');
+
+async function call(vm, address, abi, name, args = []) {
+ const iface = new Interface(abi);
+ const data = iface.encodeFunctionData(name, args);
+
+ const renderResult = await vm.runCall({
+ to: address,
+ caller: address,
+ origin: address,
+ data: Buffer.from(data.slice(2), 'hex'),
+ });
+
+ if (renderResult.execResult.exceptionError) {
+ throw renderResult.execResult.exceptionError;
+ }
+
+ const logs = renderResult.execResult.logs?.map(([address, topic, data]) =>
+ data.toString().replace(/\x00/g, '')
+ );
+
+ if (logs?.length) {
+ console.log(logs);
+ }
+
+ const results = defaultAbiCoder.decode(
+ ['string'],
+ renderResult.execResult.returnValue
+ );
+
+ return results[0];
+}
+
+module.exports = call;
diff --git a/utils/hot-chain-svg/src/compile.js b/utils/hot-chain-svg/src/compile.js
new file mode 100644
index 00000000..93665495
--- /dev/null
+++ b/utils/hot-chain-svg/src/compile.js
@@ -0,0 +1,69 @@
+const fs = require('fs');
+const path = require('path');
+const solc = require('solc');
+
+function getSolcInput(source) {
+ return {
+ language: 'Solidity',
+ sources: {
+ [path.basename(source)]: {
+ content: fs.readFileSync(source, 'utf8'),
+ },
+ },
+ settings: {
+ optimizer: {
+ enabled: true,
+ runs: 200,
+ },
+ evmVersion: 'paris',
+ outputSelection: {
+ '*': {
+ '*': ['abi', 'evm.bytecode'],
+ },
+ },
+ },
+ };
+}
+
+function findImports(path) {
+ try {
+ const file = fs.existsSync(path)
+ ? fs.readFileSync(path, 'utf8')
+ : fs.readFileSync(require.resolve(path), 'utf8');
+ return { contents: file };
+ } catch (error) {
+ console.error(error);
+ return { error };
+ }
+}
+
+function compile(source, project_dir) {
+ const input = getSolcInput(source);
+ process.chdir(project_dir);
+ const output = JSON.parse(
+ solc.compile(JSON.stringify(input), { import: findImports })
+ );
+
+ let errors = [];
+
+ if (output.errors) {
+ for (const error of output.errors) {
+ if (error.severity === 'error') {
+ errors.push(error.formattedMessage);
+ }
+ }
+ }
+
+ if (errors.length > 0) {
+ throw new Error(errors.join('\n\n'));
+ }
+
+ const result = output.contracts[path.basename(source)];
+ const contractName = Object.keys(result)[0];
+ return {
+ abi: result[contractName].abi,
+ bytecode: result[contractName].evm.bytecode.object,
+ };
+}
+
+module.exports = compile;
diff --git a/utils/hot-chain-svg/src/deploy.js b/utils/hot-chain-svg/src/deploy.js
new file mode 100644
index 00000000..b2d317b9
--- /dev/null
+++ b/utils/hot-chain-svg/src/deploy.js
@@ -0,0 +1,27 @@
+const { Address } = require('ethereumjs-util');
+const { Transaction } = require('@ethereumjs/tx');
+
+async function deploy(vm, pk, bytecode) {
+ const address = Address.fromPrivateKey(pk);
+ const account = await vm.stateManager.getAccount(address);
+
+ const txData = {
+ value: 0,
+ gasLimit: 200_000_000_000,
+ gasPrice: 1,
+ data: '0x' + bytecode.toString('hex'),
+ nonce: account.nonce,
+ };
+
+ const tx = Transaction.fromTxData(txData).sign(pk);
+
+ const deploymentResult = await vm.runTx({ tx });
+
+ if (deploymentResult.execResult.exceptionError) {
+ throw deploymentResult.execResult.exceptionError;
+ }
+
+ return deploymentResult.createdAddress;
+}
+
+module.exports = deploy;
diff --git a/utils/hot-chain-svg/src/index.js b/utils/hot-chain-svg/src/index.js
new file mode 100644
index 00000000..bba813c7
--- /dev/null
+++ b/utils/hot-chain-svg/src/index.js
@@ -0,0 +1,29 @@
+const fs = require('fs');
+const path = require('path');
+const serve = require('./serve');
+const boot = require('./boot');
+const call = require('./call');
+const compile = require('./compile');
+const deploy = require('./deploy');
+
+const SOURCE = path.join(__dirname, '..', '..', '..', 'src', 'modules', 'derivatives', 'LinearVestingCard.sol');
+const PROJECT_DIR = path.join(__dirname, '..', '..', '..');
+
+async function main() {
+ const { vm, pk } = await boot();
+
+ async function handler() {
+ const { abi, bytecode } = compile(SOURCE, PROJECT_DIR);
+ const address = await deploy(vm, pk, bytecode);
+ const result = await call(vm, address, abi, 'example');
+ return result;
+ }
+
+ const { notify } = await serve(handler);
+
+ fs.watch(path.dirname(SOURCE), notify);
+ console.log('Watching', path.dirname(SOURCE));
+ console.log('Serving http://localhost:9901/');
+}
+
+main();
diff --git a/utils/hot-chain-svg/src/qa.js b/utils/hot-chain-svg/src/qa.js
new file mode 100644
index 00000000..a967a4ee
--- /dev/null
+++ b/utils/hot-chain-svg/src/qa.js
@@ -0,0 +1,35 @@
+const fs = require('fs');
+const os = require('os');
+const path = require('path');
+const boot = require('./boot');
+const call = require('./call');
+const compile = require('./compile');
+const deploy = require('./deploy');
+const { DOMParser } = require('xmldom');
+
+const SOURCE = path.join(__dirname, '..', 'contracts', 'Renderer.sol');
+const DESTINATION = path.join(os.tmpdir(), 'hot-chain-svg-');
+
+async function main() {
+ const { vm, pk } = await boot();
+ const { abi, bytecode } = compile(SOURCE);
+ const address = await deploy(vm, pk, bytecode);
+
+ const tempFolder = fs.mkdtempSync(DESTINATION);
+ console.log('Saving to', tempFolder);
+
+ for (let i = 1; i < 256; i++) {
+ const fileName = path.join(tempFolder, i + '.svg');
+ console.log('Rendering', fileName);
+ const svg = await call(vm, address, abi, 'render', [i]);
+ fs.writeFileSync(fileName, svg);
+
+ // Throws on invalid XML
+ new DOMParser().parseFromString(svg);
+ }
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
diff --git a/utils/hot-chain-svg/src/serve.js b/utils/hot-chain-svg/src/serve.js
new file mode 100644
index 00000000..a370b377
--- /dev/null
+++ b/utils/hot-chain-svg/src/serve.js
@@ -0,0 +1,48 @@
+const http = require('http');
+const EventEmitter = require('events');
+
+async function serve(handler) {
+ const events = new EventEmitter();
+
+ function requestListener(req, res) {
+ if (req.url === '/changes') {
+ res.setHeader('Content-Type', 'text/event-stream');
+ res.writeHead(200);
+ const sendEvent = () => res.write('event: change\ndata:\n\n');
+ events.on('change', sendEvent);
+ req.on('close', () => events.off('change', sendEvent));
+ return;
+ }
+
+ if (req.url === '/') {
+ res.writeHead(200);
+ handler().then(
+ (content) => res.end(webpage(content)),
+ (error) => res.end(webpage(`
${error.message}
`))
+ );
+ return;
+ }
+
+ res.writeHead(404);
+ res.end('Not found: ' + req.url);
+ }
+ const server = http.createServer(requestListener);
+ await new Promise((resolve) => server.listen(9901, resolve));
+
+ return {
+ notify: () => events.emit('change'),
+ };
+}
+
+const webpage = (content) => `
+
+Hot Chain SVG
+${content}
+
+
+`;
+
+module.exports = serve;
diff --git a/utils/hot-chain-svg/src/sync-nfts.js b/utils/hot-chain-svg/src/sync-nfts.js
new file mode 100644
index 00000000..52c4aff4
--- /dev/null
+++ b/utils/hot-chain-svg/src/sync-nfts.js
@@ -0,0 +1,66 @@
+const { formatEther } = require('@ethersproject/units');
+const ethers = require('ethers');
+const fs = require('fs');
+const path = require('path');
+
+const address = '0xa7988c8abb7706e024a8f2a1328e376227aaad18';
+const url = process.env.PROVIDER_URL;
+
+async function main() {
+ const provider = new ethers.providers.JsonRpcProvider({ url });
+ const abi = [
+ 'event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount)',
+ 'event CollectionNameUpdated(address indexed collection, string name)',
+ ];
+ const contract = new ethers.Contract(address, abi, provider);
+
+ const [mints, names] = await Promise.all([
+ contract.queryFilter(
+ contract.filters.TransferSingle(null, ethers.constants.AddressZero)
+ ),
+ contract.queryFilter(contract.filters.CollectionNameUpdated()),
+ ]);
+
+ const collectionNames = Object.fromEntries(
+ names.map((e) => [e.args.collection.toLowerCase(), e.args.name])
+ );
+
+ const owners = [...new Set(mints.map((e) => e.args.to.toLowerCase()))];
+ const ensNames = await Promise.all(
+ owners.map((address) => provider.lookupAddress(address))
+ );
+
+ const ownerNames = Object.fromEntries(
+ owners.map((address, index) => [address, ensNames[index] || address])
+ );
+
+ const log = mints.map((e) => {
+ const { id, to } = e.args;
+ const collection = ethers.utils.hexZeroPad(
+ id.and(
+ ethers.BigNumber.from('0xffffffffffffffffffffffffffffffffffffffff')
+ ),
+ 20
+ );
+
+ const name = collectionNames[collection] || collection;
+ const owner = ownerNames[to.toLowerCase()];
+
+ return `- [${name}](https://etherscan.io/address/${collection}) by ${owner}`;
+ });
+
+ console.log(log);
+
+ const readme = path.resolve(__dirname, '..', 'README.md');
+ const content = fs.readFileSync(readme, 'utf8');
+ const updated = content.replaceAll(
+ /[\s\S]+/gim,
+ ['', ...log, ''].join('\n')
+ );
+ fs.writeFileSync(readme, updated);
+}
+
+main().catch((error) => {
+ console.error(error);
+ process.exit(1);
+});
diff --git a/utils/hot-chain-svg/yarn.lock b/utils/hot-chain-svg/yarn.lock
new file mode 100644
index 00000000..0fe67215
--- /dev/null
+++ b/utils/hot-chain-svg/yarn.lock
@@ -0,0 +1,1167 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.2", "@ethereumjs/block@^3.6.3":
+ version "3.6.3"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.3.tgz#d96cbd7af38b92ebb3424223dbf773f5ccd27f84"
+ integrity sha512-CegDeryc2DVKnDkg5COQrE0bJfw/p0v3GBk2W5/Dj5dOVfEmb50Ux0GLnSPypooLnfqjwFaorGuT9FokWB3GRg==
+ dependencies:
+ "@ethereumjs/common" "^2.6.5"
+ "@ethereumjs/tx" "^3.5.2"
+ ethereumjs-util "^7.1.5"
+ merkle-patricia-tree "^4.2.4"
+
+"@ethereumjs/blockchain@^5.5.3":
+ version "5.5.3"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.3.tgz#aa49a6a04789da6b66b5bcbb0d0b98efc369f640"
+ integrity sha512-bi0wuNJ1gw4ByNCV56H0Z4Q7D+SxUbwyG12Wxzbvqc89PXLRNR20LBcSUZRKpN0+YCPo6m0XZL/JLio3B52LTw==
+ dependencies:
+ "@ethereumjs/block" "^3.6.2"
+ "@ethereumjs/common" "^2.6.4"
+ "@ethereumjs/ethash" "^1.1.0"
+ debug "^4.3.3"
+ ethereumjs-util "^7.1.5"
+ level-mem "^5.0.1"
+ lru-cache "^5.1.1"
+ semaphore-async-await "^1.5.1"
+
+"@ethereumjs/common@^2.6.4", "@ethereumjs/common@^2.6.5":
+ version "2.6.5"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30"
+ integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==
+ dependencies:
+ crc-32 "^1.2.0"
+ ethereumjs-util "^7.1.5"
+
+"@ethereumjs/ethash@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb"
+ integrity sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA==
+ 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.5.2":
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c"
+ integrity sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==
+ dependencies:
+ "@ethereumjs/common" "^2.6.4"
+ ethereumjs-util "^7.1.5"
+
+"@ethereumjs/vm@^5.8.0":
+ version "5.9.3"
+ resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.3.tgz#6d69202e4c132a4a1e1628ac246e92062e230823"
+ integrity sha512-Ha04TeF8goEglr8eL7hkkYyjhzdZS0PsoRURzYlTF6I0VVId5KjKb0N7MrA8GMgheN+UeTncfTgYx52D/WhEmg==
+ dependencies:
+ "@ethereumjs/block" "^3.6.3"
+ "@ethereumjs/blockchain" "^5.5.3"
+ "@ethereumjs/common" "^2.6.5"
+ "@ethereumjs/tx" "^3.5.2"
+ async-eventemitter "^0.2.4"
+ core-js-pure "^3.0.1"
+ debug "^4.3.3"
+ ethereumjs-util "^7.1.5"
+ functional-red-black-tree "^1.0.1"
+ mcl-wasm "^0.7.1"
+ merkle-patricia-tree "^4.2.4"
+ rustbn.js "~0.2.0"
+
+"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.6.0", "@ethersproject/abi@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449"
+ integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==
+ dependencies:
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef"
+ integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/networks" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
+
+"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2"
+ integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+
+"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
+ integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+
+"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c"
+ integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+
+"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b"
+ integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+
+"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
+ integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ bn.js "^5.2.1"
+
+"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d"
+ integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e"
+ integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+
+"@ethersproject/contracts@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e"
+ integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==
+ dependencies:
+ "@ethersproject/abi" "^5.7.0"
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+
+"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7"
+ integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf"
+ integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/basex" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/pbkdf2" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/wordlists" "^5.7.0"
+
+"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360"
+ integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==
+ dependencies:
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hdnode" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/pbkdf2" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ aes-js "3.0.0"
+ scrypt-js "3.0.1"
+
+"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a"
+ integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ js-sha3 "0.8.0"
+
+"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
+ integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
+
+"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6"
+ integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102"
+ integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+
+"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
+ integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==
+ dependencies:
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/providers@5.7.2":
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb"
+ integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/basex" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/networks" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
+ bech32 "1.1.4"
+ ws "7.4.6"
+
+"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c"
+ integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
+ integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb"
+ integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ hash.js "1.1.7"
+
+"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3"
+ integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ bn.js "^5.2.1"
+ elliptic "6.5.4"
+ hash.js "1.1.7"
+
+"@ethersproject/solidity@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8"
+ integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/sha2" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2"
+ integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b"
+ integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==
+ dependencies:
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+
+"@ethersproject/units@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1"
+ integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==
+ dependencies:
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+
+"@ethersproject/wallet@5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d"
+ integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==
+ dependencies:
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/hdnode" "^5.7.0"
+ "@ethersproject/json-wallets" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/random" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/wordlists" "^5.7.0"
+
+"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0":
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae"
+ integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==
+ dependencies:
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5"
+ integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==
+ dependencies:
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
+
+"@types/abstract-leveldown@*":
+ version "7.2.5"
+ resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.5.tgz#db2cf364c159fb1f12be6cd3549f56387eaf8d73"
+ integrity sha512-/2B0nQF4UdupuxeKTJA2+Rj1D+uDemo6P4kMwKCpbfpnzeVaWSELTsAw4Lxn3VJD6APtRrZOCuYo+4nHUQfTfg==
+
+"@types/bn.js@^5.1.0":
+ version "5.1.5"
+ resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0"
+ integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==
+ dependencies:
+ "@types/node" "*"
+
+"@types/level-errors@*":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@types/level-errors/-/level-errors-3.0.2.tgz#f33ec813c50780b547463da9ad8acac89ee457d9"
+ integrity sha512-gyZHbcQ2X5hNXf/9KS2qGEmgDe9EN2WDM3rJ5Ele467C0nA1sLhtmv1bZiPMDYfAYCfPWft0uQIaTvXbASSTRA==
+
+"@types/levelup@^4.3.0":
+ version "4.3.3"
+ resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-4.3.3.tgz#4dc2b77db079b1cf855562ad52321aa4241b8ef4"
+ integrity sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA==
+ dependencies:
+ "@types/abstract-leveldown" "*"
+ "@types/level-errors" "*"
+ "@types/node" "*"
+
+"@types/node@*":
+ version "20.14.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.2.tgz#a5f4d2bcb4b6a87bffcaa717718c5a0f208f4a18"
+ integrity sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==
+ dependencies:
+ undici-types "~5.26.4"
+
+"@types/pbkdf2@^3.0.0":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc"
+ integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==
+ dependencies:
+ "@types/node" "*"
+
+"@types/secp256k1@^4.0.1":
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf"
+ integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==
+ dependencies:
+ "@types/node" "*"
+
+abstract-leveldown@^6.2.1:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a"
+ integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==
+ 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@~6.2.1:
+ version "6.2.3"
+ resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb"
+ integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==
+ dependencies:
+ buffer "^5.5.0"
+ immediate "^3.2.3"
+ level-concat-iterator "~2.0.0"
+ level-supports "~1.0.0"
+ xtend "~4.0.0"
+
+aes-js@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
+ integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==
+
+async-eventemitter@^0.2.4:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca"
+ integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==
+ dependencies:
+ async "^2.4.0"
+
+async@^2.4.0:
+ version "2.6.4"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
+ integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
+ dependencies:
+ lodash "^4.17.14"
+
+base-x@^3.0.2:
+ version "3.0.9"
+ resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320"
+ integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+base64-js@^1.3.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+bech32@1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
+ integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
+
+blakejs@^1.1.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814"
+ integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==
+
+bn.js@^4.0.0, bn.js@^4.11.9:
+ version "4.12.0"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
+ integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
+
+bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70"
+ integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
+
+brorand@^1.0.1, brorand@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+ integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
+
+browserify-aes@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+ integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+ dependencies:
+ buffer-xor "^1.0.3"
+ cipher-base "^1.0.0"
+ create-hash "^1.1.0"
+ evp_bytestokey "^1.0.3"
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+bs58@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
+ integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==
+ dependencies:
+ base-x "^3.0.2"
+
+bs58check@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc"
+ integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==
+ dependencies:
+ bs58 "^4.0.0"
+ create-hash "^1.1.0"
+ safe-buffer "^5.1.2"
+
+buffer-xor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+ integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
+
+buffer-xor@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289"
+ integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==
+ dependencies:
+ safe-buffer "^5.1.1"
+
+buffer@^5.5.0, buffer@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+ integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.1.13"
+
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+ integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+command-exists@^1.2.8:
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
+ integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
+
+commander@^8.1.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
+ integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
+
+core-js-pure@^3.0.1:
+ version "3.37.1"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd"
+ integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==
+
+crc-32@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
+ integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
+
+create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+ integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+ dependencies:
+ 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.4, create-hmac@^1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+ integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+ dependencies:
+ cipher-base "^1.0.3"
+ create-hash "^1.1.0"
+ inherits "^2.0.1"
+ ripemd160 "^2.0.0"
+ safe-buffer "^5.0.1"
+ sha.js "^2.4.8"
+
+debug@^4.3.3:
+ version "4.3.5"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
+ integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
+ dependencies:
+ ms "2.1.2"
+
+deferred-leveldown@~5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058"
+ integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==
+ dependencies:
+ abstract-leveldown "~6.2.1"
+ inherits "^2.0.3"
+
+elliptic@6.5.4:
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+ integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
+ dependencies:
+ bn.js "^4.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"
+
+elliptic@^6.5.4:
+ version "6.5.5"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded"
+ integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==
+ 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"
+
+encoding-down@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b"
+ integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==
+ dependencies:
+ abstract-leveldown "^6.2.1"
+ inherits "^2.0.3"
+ level-codec "^9.0.0"
+ level-errors "^2.0.0"
+
+errno@~0.1.1:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
+ integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
+ dependencies:
+ prr "~1.0.1"
+
+ethereum-cryptography@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191"
+ integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==
+ dependencies:
+ "@types/pbkdf2" "^3.0.0"
+ "@types/secp256k1" "^4.0.1"
+ blakejs "^1.1.0"
+ browserify-aes "^1.2.0"
+ bs58check "^2.1.2"
+ create-hash "^1.2.0"
+ create-hmac "^1.1.7"
+ hash.js "^1.1.7"
+ keccak "^3.0.0"
+ pbkdf2 "^3.0.17"
+ randombytes "^2.1.0"
+ safe-buffer "^5.1.2"
+ scrypt-js "^3.0.0"
+ secp256k1 "^4.0.1"
+ setimmediate "^1.0.5"
+
+ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5:
+ version "7.1.5"
+ resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181"
+ integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==
+ dependencies:
+ "@types/bn.js" "^5.1.0"
+ bn.js "^5.1.2"
+ create-hash "^1.1.2"
+ ethereum-cryptography "^0.1.3"
+ rlp "^2.2.4"
+
+ethers@^5.6.8:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
+ integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
+ dependencies:
+ "@ethersproject/abi" "5.7.0"
+ "@ethersproject/abstract-provider" "5.7.0"
+ "@ethersproject/abstract-signer" "5.7.0"
+ "@ethersproject/address" "5.7.0"
+ "@ethersproject/base64" "5.7.0"
+ "@ethersproject/basex" "5.7.0"
+ "@ethersproject/bignumber" "5.7.0"
+ "@ethersproject/bytes" "5.7.0"
+ "@ethersproject/constants" "5.7.0"
+ "@ethersproject/contracts" "5.7.0"
+ "@ethersproject/hash" "5.7.0"
+ "@ethersproject/hdnode" "5.7.0"
+ "@ethersproject/json-wallets" "5.7.0"
+ "@ethersproject/keccak256" "5.7.0"
+ "@ethersproject/logger" "5.7.0"
+ "@ethersproject/networks" "5.7.1"
+ "@ethersproject/pbkdf2" "5.7.0"
+ "@ethersproject/properties" "5.7.0"
+ "@ethersproject/providers" "5.7.2"
+ "@ethersproject/random" "5.7.0"
+ "@ethersproject/rlp" "5.7.0"
+ "@ethersproject/sha2" "5.7.0"
+ "@ethersproject/signing-key" "5.7.0"
+ "@ethersproject/solidity" "5.7.0"
+ "@ethersproject/strings" "5.7.0"
+ "@ethersproject/transactions" "5.7.0"
+ "@ethersproject/units" "5.7.0"
+ "@ethersproject/wallet" "5.7.0"
+ "@ethersproject/web" "5.7.1"
+ "@ethersproject/wordlists" "5.7.0"
+
+evp_bytestokey@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+ integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
+ dependencies:
+ md5.js "^1.3.4"
+ safe-buffer "^5.1.1"
+
+follow-redirects@^1.12.1:
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
+ integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
+
+functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+ integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
+
+hash-base@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
+ integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==
+ dependencies:
+ inherits "^2.0.4"
+ readable-stream "^3.6.0"
+ safe-buffer "^5.2.0"
+
+hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+ integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+ dependencies:
+ inherits "^2.0.3"
+ minimalistic-assert "^1.0.1"
+
+hmac-drbg@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+ integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==
+ dependencies:
+ hash.js "^1.0.3"
+ minimalistic-assert "^1.0.0"
+ minimalistic-crypto-utils "^1.0.1"
+
+ieee754@^1.1.13:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+immediate@^3.2.3:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266"
+ integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==
+
+immediate@~3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
+ integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg==
+
+inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+js-sha3@0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+ integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
+keccak@^3.0.0:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d"
+ integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==
+ dependencies:
+ node-addon-api "^2.0.0"
+ node-gyp-build "^4.2.0"
+ readable-stream "^3.6.0"
+
+level-codec@^9.0.0:
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc"
+ integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==
+ dependencies:
+ buffer "^5.6.0"
+
+level-concat-iterator@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263"
+ integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==
+
+level-errors@^2.0.0, level-errors@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8"
+ integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==
+ dependencies:
+ errno "~0.1.1"
+
+level-iterator-stream@~4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c"
+ integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==
+ dependencies:
+ inherits "^2.0.4"
+ readable-stream "^3.4.0"
+ xtend "^4.0.2"
+
+level-mem@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d"
+ integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg==
+ dependencies:
+ level-packager "^5.0.3"
+ memdown "^5.0.0"
+
+level-packager@^5.0.3:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939"
+ integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==
+ dependencies:
+ encoding-down "^6.3.0"
+ levelup "^4.3.2"
+
+level-supports@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d"
+ integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==
+ dependencies:
+ xtend "^4.0.2"
+
+level-ws@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339"
+ integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^3.1.0"
+ xtend "^4.0.1"
+
+levelup@^4.3.2:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6"
+ integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==
+ 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"
+
+lodash@^4.17.14:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+ltgt@~2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5"
+ integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==
+
+mcl-wasm@^0.7.1:
+ version "0.7.9"
+ resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f"
+ integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==
+
+md5.js@^1.3.4:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+ integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+ dependencies:
+ hash-base "^3.0.0"
+ inherits "^2.0.1"
+ safe-buffer "^5.1.2"
+
+memdown@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb"
+ integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw==
+ 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"
+
+memorystream@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+ integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==
+
+merkle-patricia-tree@^4.2.4:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.4.tgz#ff988d045e2bf3dfa2239f7fabe2d59618d57413"
+ integrity sha512-eHbf/BG6eGNsqqfbLED9rIqbsF4+sykEaBn6OLNs71tjclbMcMOk1tEPmJKcNcNCLkvbpY/lwyOlizWsqPNo8w==
+ 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"
+
+miller-rabin@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+ integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
+ dependencies:
+ bn.js "^4.0.0"
+ brorand "^1.0.1"
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+ integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+node-addon-api@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
+ integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
+
+node-gyp-build@^4.2.0:
+ version "4.8.1"
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5"
+ integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==
+
+os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
+
+pbkdf2@^3.0.17:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
+ integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==
+ dependencies:
+ create-hash "^1.1.2"
+ create-hmac "^1.1.4"
+ ripemd160 "^2.0.1"
+ safe-buffer "^5.0.1"
+ sha.js "^2.4.8"
+
+prettier@^2.6.2:
+ version "2.8.8"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
+ integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
+
+prr@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+ integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+ integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+ dependencies:
+ hash-base "^3.0.0"
+ inherits "^2.0.1"
+
+rlp@^2.2.4:
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf"
+ integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==
+ dependencies:
+ bn.js "^5.2.0"
+
+rustbn.js@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca"
+ integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==
+
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+scrypt-js@3.0.1, scrypt-js@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312"
+ integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==
+
+secp256k1@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303"
+ integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==
+ dependencies:
+ elliptic "^6.5.4"
+ node-addon-api "^2.0.0"
+ node-gyp-build "^4.2.0"
+
+semaphore-async-await@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa"
+ integrity sha512-b/ptP11hETwYWpeilHXXQiV5UJNJl7ZWWooKRE5eBIYWoom6dZ0SluCIdCtKycsMtZgKWE01/qAw6jblw1YVhg==
+
+semver@^5.5.0:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+ integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
+setimmediate@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+ integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
+
+sha.js@^2.4.0, sha.js@^2.4.8:
+ version "2.4.11"
+ resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+ integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+solc@0.8.19:
+ version "0.8.19"
+ resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.19.tgz#cac6541106ae3cff101c740042c7742aa56a2ed3"
+ integrity sha512-yqurS3wzC4LdEvmMobODXqprV4MYJcVtinuxgrp61ac8K2zz40vXA0eSAskSHPgv8dQo7Nux39i3QBsHx4pqyA==
+ dependencies:
+ command-exists "^1.2.8"
+ commander "^8.1.0"
+ follow-redirects "^1.12.1"
+ js-sha3 "0.8.0"
+ memorystream "^0.3.1"
+ semver "^5.5.0"
+ tmp "0.0.33"
+
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+tmp@0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
+util-deprecate@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+ws@7.4.6:
+ version "7.4.6"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
+ integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
+
+xmldom@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.6.0.tgz#43a96ecb8beece991cef382c08397d82d4d0c46f"
+ integrity sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==
+
+xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==