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, ""); + } + + // 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( + '', + svg.el( + "defs", + _NULL, + string.concat( + _fullGradient(), + _fullGradient90(), + _fullGradientReverse90(), + _blueGreenGradient() + ) + ), + svg.rect( + 'x="0" y="0" width="290" height="500" fill="rgb(30, 30, 30)" rx="25" ry="25"', _NULL + ), + svg.rect( + 'x="8" y="8" width="274" height="484" fill="none" stroke="url(#fullGradient)" stroke-width="2" rx="20" ry="20"', + _NULL + ), + _title(tokenInfo.baseTokenSymbol), + _progressBar(uint256(tokenInfo.start), uint256(tokenInfo.expiry)), + _progressLabels(tokenInfo.start, tokenInfo.expiry), + _logo(), + _identifier(tokenInfo.tokenId), + "" + ); + } + + // ========== 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==