├── .gitignore ├── remappings.txt ├── foundry.toml ├── .prettierrc.json ├── .eslintrc.js ├── test ├── mock │ ├── MockERC20.sol │ └── MockArtGobblers.sol ├── utils │ └── GnosisSafe.t.sol ├── GooSitter.t.sol └── GobblerBuyerModule.t.sol ├── script ├── TotalGoo.s.sol ├── GooSitter.s.sol ├── det-addr.js ├── price-after-buys.js ├── get-inventory.js ├── emissions-analysis.js └── automate-buyer.js ├── .gitmodules ├── package.json ├── src ├── VirtualGoo.sol ├── TotalGoo.sol ├── interfaces │ └── IArtGobblers.sol ├── GobblerBuyerModule.sol ├── GooSitter.sol └── GobblerThrone.sol ├── LICENSE ├── README.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | cache 3 | out 4 | .env 5 | broadcast 6 | -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | @openzeppelin/=lib/openzeppelin-contracts/contracts/ 2 | @solmate/=lib/solmate/src/ 3 | @solady/=lib/solady/src/ 4 | @gnosis-safe/=lib/safe-contracts/contracts/ 5 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | optimizer_runs = 10000 6 | 7 | # See more config options https://github.com/foundry-rs/foundry/tree/master/config 8 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 100, 4 | "semi": false, 5 | "singleQuote": true, 6 | "trailingComma": "none", 7 | "overrides": [ 8 | { 9 | "files": "*.sol", 10 | "options": { 11 | "tabWidth": 4, 12 | "printWidth": 120, 13 | "singleQuote": false 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | commonjs: true, 4 | es2021: true, 5 | node: true 6 | }, 7 | extends: 'eslint:recommended', 8 | parserOptions: { 9 | ecmaVersion: 'latest' 10 | }, 11 | rules: { 12 | indent: ['error', 2], 13 | 'linebreak-style': ['error', 'unix'], 14 | quotes: ['error', 'single'], 15 | semi: ['error', 'never'], 16 | 'comma-dangle': ['error', 'never'] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/mock/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {ERC20} from "@solmate/tokens/ERC20.sol"; 5 | 6 | /// @author Philippe Dumonet 7 | contract MockERC20 is ERC20 { 8 | constructor() ERC20("Mock Token", "MCK", 18) {} 9 | 10 | function mint(address _recipient, uint256 _amount) external { 11 | _mint(_recipient, _amount); 12 | } 13 | 14 | function burn(address _recipient, uint256 _amount) external { 15 | _burn(_recipient, _amount); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /script/TotalGoo.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {Script} from "forge-std/Script.sol"; 6 | import {TotalGoo} from "../src/TotalGoo.sol"; 7 | 8 | /// @author Philippe Dumonet 9 | contract DeployTotalGoo is Script, Test { 10 | function run() external { 11 | uint256 deployKey = vm.envUint("VANITY_PRIV_KEY"); 12 | vm.startBroadcast(deployKey); 13 | TotalGoo totalGoo = new TotalGoo(); 14 | vm.stopBroadcast(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | [submodule "lib/solmate"] 5 | path = lib/solmate 6 | url = https://github.com/transmissions11/solmate 7 | [submodule "lib/openzeppelin-contracts"] 8 | path = lib/openzeppelin-contracts 9 | url = https://github.com/openzeppelin/openzeppelin-contracts 10 | [submodule "lib/solady"] 11 | path = lib/solady 12 | url = https://github.com/Vectorized/solady 13 | [submodule "lib/safe-contracts"] 14 | path = lib/safe-contracts 15 | url = https://github.com/safe-global/safe-contracts 16 | branch = v1.3.0 17 | -------------------------------------------------------------------------------- /script/GooSitter.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {Script} from "forge-std/Script.sol"; 6 | import {GooSitter} from "../src/GooSitter.sol"; 7 | 8 | /// @author Philippe Dumonet 9 | contract DeployGooSitter is Script, Test { 10 | function run() external { 11 | uint256 deployKey = vm.envUint("MANAGER_PRIV_KEY"); 12 | vm.startBroadcast(deployKey); 13 | new GooSitter(vm.addr(deployKey), vm.envAddress("COLD_WALLET")); 14 | vm.stopBroadcast(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wrapped-gobblers", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Philippe Dumonet ", 6 | "license": "MIT", 7 | "devDependencies": { 8 | "prettier": "^2.7.1", 9 | "prettier-plugin-solidity": "^1.0.0-beta.24" 10 | }, 11 | "dependencies": { 12 | "@flashbots/ethers-provider-bundle": "^0.5.0", 13 | "dotenv": "^16.0.3", 14 | "easy-multicall": "^1.2.0", 15 | "eslint": "^8.26.0", 16 | "eslint-plugin-prettier": "^4.2.1", 17 | "ethers": "^5.7.2", 18 | "keccak256": "^1.0.6", 19 | "lodash": "^4.17.21", 20 | "rlp": "^3.0.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/VirtualGoo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; 5 | import {IArtGobblers} from "./interfaces/IArtGobblers.sol"; 6 | 7 | /// @author Philogy 8 | contract VirtualGoo { 9 | string public constant name = "Virtual GOO"; 10 | string public constant symbol = "vGOO"; 11 | 12 | IArtGobblers public immutable artGobblers; 13 | 14 | constructor(address _artGobblers) { 15 | artGobblers = IArtGobblers(_artGobblers); 16 | } 17 | 18 | function balanceOf(address _addr) external view returns (uint256) { 19 | return artGobblers.gooBalance(_addr); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /script/det-addr.js: -------------------------------------------------------------------------------- 1 | const rlp = require('rlp') 2 | const keccak = require('keccak') 3 | 4 | async function main() { 5 | const getDetAddr = (addr, nonce) => { 6 | const rlpEncoded = rlp.encode([addr, nonce]) 7 | console.log('rlpEncoded: ', Buffer.from(rlpEncoded).toString('hex')) 8 | const resHash = keccak('keccak256') 9 | .update(Buffer.from(rlpEncoded)) 10 | .digest('hex') 11 | 12 | const emptyhash = keccak('keccak256').digest('hex') 13 | console.log('emptyhash: ', emptyhash) 14 | 15 | const contractAddr = `0x${resHash.substring(24)}` 16 | return contractAddr 17 | } 18 | 19 | const addr = '0x77f4780189d87f3ec7af925ada7d0d7828867adc' 20 | console.log('getDetAddr(addr, 0): ', getDetAddr(addr, 0)) 21 | } 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch((err) => { 26 | console.error('err:', err) 27 | process.exit(1) 28 | }) 29 | -------------------------------------------------------------------------------- /src/TotalGoo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; 5 | import {IArtGobblers} from "./interfaces/IArtGobblers.sol"; 6 | 7 | /// @author philogy 8 | contract TotalGoo { 9 | string public constant name = "Total GOO (virtual + token)"; 10 | string public constant symbol = "tGOO"; 11 | 12 | uint8 public constant decimals = 18; 13 | 14 | IArtGobblers public constant artGobblers = IArtGobblers(0x60bb1e2AA1c9ACAfB4d34F71585D7e959f387769); 15 | 16 | IERC20 public immutable goo = IERC20(0x600000000a36F3cD48407e35eB7C5c910dc1f7a8); 17 | 18 | event Transfer(address indexed from, address indexed to, uint256 value); 19 | 20 | constructor() { 21 | // Ensure Etherscan recognizes contract as ERC20. 22 | emit Transfer(address(0), address(uint160(0xdead)), 1); 23 | emit Transfer(address(uint160(0xdead)), address(0), 1); 24 | } 25 | 26 | function balanceOf(address _addr) external view returns (uint256) { 27 | return artGobblers.gooBalance(_addr) + goo.balanceOf(_addr); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Dumonet Distributed Technologies UG (limited liability) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/interfaces/IArtGobblers.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {IERC721} from "@openzeppelin/token/ERC721/IERC721.sol"; 5 | 6 | /// @author Philogy 7 | /// @notice Not full interface, certain methods missing 8 | interface IArtGobblers is IERC721 { 9 | function goo() external view returns (address); 10 | 11 | function tokenURI(uint256 gobblerId) external view returns (string memory); 12 | 13 | function gooBalance(address user) external view returns (uint256); 14 | 15 | function removeGoo(uint256 gooAmount) external; 16 | 17 | function addGoo(uint256 gooAmount) external; 18 | 19 | function getUserEmissionMultiple(address user) 20 | external 21 | view 22 | returns (uint256); 23 | 24 | function getGobblerEmissionMultiple(uint256 gobblerId) 25 | external 26 | view 27 | returns (uint256); 28 | 29 | function mintLegendaryGobbler(uint256[] calldata gobblerIds) 30 | external 31 | returns (uint256 gobblerId); 32 | 33 | function mintFromGoo(uint256 maxPrice, bool useVirtualBalance) 34 | external 35 | returns (uint256 gobblerId); 36 | 37 | function legendaryGobblerPrice() external view returns (uint256); 38 | } 39 | -------------------------------------------------------------------------------- /test/utils/GnosisSafe.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {GnosisSafe} from "@gnosis-safe/GnosisSafe.sol"; 6 | import {GnosisSafeProxyFactory} from "@gnosis-safe/proxies/GnosisSafeProxyFactory.sol"; 7 | 8 | /// @author philogy 9 | contract GnosisSafeTest is Test { 10 | address private _singleton = address(new GnosisSafe()); 11 | GnosisSafeProxyFactory private _safeFactory = new GnosisSafeProxyFactory(); 12 | 13 | function deploySafe( 14 | address[] memory _owners, 15 | uint256 _threshhold, 16 | address _to, 17 | bytes memory _data, 18 | uint256 _salt 19 | ) internal returns (address) { 20 | return 21 | address( 22 | _safeFactory.createProxyWithNonce( 23 | address(_singleton), 24 | abi.encodeCall( 25 | GnosisSafe.setup, 26 | (_owners, _threshhold, _to, _data, address(0), address(0), 0, payable(0)) 27 | ), 28 | _salt 29 | ) 30 | ); 31 | } 32 | 33 | function getCallerSignature(address _caller) internal pure returns (bytes memory) { 34 | return abi.encodePacked(uint256(uint160(_caller)), uint256(0), uint8(1)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/mock/MockArtGobblers.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {ERC721} from "@solmate/tokens/ERC721.sol"; 5 | import {MockERC20} from "./MockERC20.sol"; 6 | 7 | /// @author Philippe Dumonet 8 | contract MockArtGobblers is ERC721 { 9 | uint256 __someState; 10 | 11 | MockERC20 internal immutable goo; 12 | 13 | mapping(address => uint256) public gooBalance; 14 | uint256 public totalSupply; 15 | uint256 public maxPrice; 16 | address public lastCaller; 17 | 18 | error PriceExceededMax(); 19 | 20 | constructor(MockERC20 _goo) ERC721("Mock ArtGobblers", "MAGOO") { 21 | goo = _goo; 22 | } 23 | 24 | function setMaxPrice(uint256 _newMaxPrice) external { 25 | maxPrice = _newMaxPrice; 26 | } 27 | 28 | function addGoo(uint256 _amount) external { 29 | goo.burn(msg.sender, _amount); 30 | gooBalance[msg.sender] += _amount; 31 | } 32 | 33 | function removeGoo(uint256 _amount) external { 34 | goo.mint(msg.sender, _amount); 35 | gooBalance[msg.sender] -= _amount; 36 | } 37 | 38 | function tokenURI(uint256) public pure override returns (string memory) { 39 | return "lmao, no uri"; 40 | } 41 | 42 | function mint(address _recipient) external returns (uint256 newId) { 43 | unchecked { 44 | _mint(_recipient, (newId = ++totalSupply)); 45 | } 46 | } 47 | 48 | function mintFromGoo(uint256 _maxPrice, bool _useVirtualBalance) external returns (uint256 gobblerId) { 49 | if (_maxPrice > maxPrice) revert PriceExceededMax(); 50 | lastCaller = msg.sender; 51 | __someState++; 52 | gobblerId = uint256(keccak256(abi.encode(_maxPrice, _useVirtualBalance))); 53 | _mint(msg.sender, gobblerId); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /script/price-after-buys.js: -------------------------------------------------------------------------------- 1 | const ethers = require('ethers') 2 | const { BigNumber } = require('ethers/lib') 3 | require('dotenv').config() 4 | 5 | const getTimestamp = () => ethers.BigNumber.from(Math.floor(Date.now() / 1000)) 6 | const timeToDaysWad = (time) => 7 | time.mul(BigNumber.from('1000000000000000000')).div(BigNumber.from('86400')) 8 | 9 | const dec18ToFloat = (x) => parseFloat(ethers.utils.formatUnits(x)) 10 | 11 | async function main() { 12 | const formatter = Intl.NumberFormat('en', { 13 | notation: 'compact', 14 | maximumSignificantDigits: 3 15 | }) 16 | const x = 120_398.09 17 | 18 | const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL) 19 | const gobbler = new ethers.Contract( 20 | '0x60bb1e2aa1c9acafb4d34f71585d7e959f387769', 21 | [ 22 | 'function gobblerPrice() view returns (uint256)', 23 | 'function numMintedFromGoo() view returns (uint256)', 24 | 'function mintStart() view returns (uint256)', 25 | 'function getVRGDAPrice(int256 timeSinceStart, uint256 sold) public view returns (uint256)' 26 | ], 27 | provider 28 | ) 29 | const args = process.argv.slice(2) 30 | const buys = parseInt(args[0]) 31 | const [mintStart, numMinted, currentPrice] = await Promise.all([ 32 | gobbler.mintStart(), 33 | gobbler.numMintedFromGoo(), 34 | gobbler.gobblerPrice() 35 | ]) 36 | const priceAfterBuys = await gobbler.getVRGDAPrice( 37 | timeToDaysWad(getTimestamp().sub(mintStart)), 38 | BigNumber.from(buys).add(numMinted) 39 | ) 40 | console.log(`current price: ${formatter.format(dec18ToFloat(currentPrice))}`) 41 | console.log( 42 | `price after buy (${buys}): ${formatter.format( 43 | dec18ToFloat(priceAfterBuys) 44 | )}` 45 | ) 46 | } 47 | 48 | main() 49 | .then(() => process.exit(0)) 50 | .catch((err) => { 51 | console.error('err:', err) 52 | process.exit(1) 53 | }) 54 | -------------------------------------------------------------------------------- /script/get-inventory.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const ethers = require('ethers') 3 | const { getMulticaller, createCallEncoder } = require('easy-multicall') 4 | const _ = require('lodash') 5 | 6 | const gobblerCall = createCallEncoder( 7 | [ 8 | 'function ownerOf(uint256) view returns (address)', 9 | 'function getUserEmissionMultiple(address) view returns (uint32)', 10 | 'function gooBalance(address) view returns (uint256)', 11 | 'function gobblerPrice() public view returns (uint256)', 12 | 'function getVRGDAPrice(int256, uint256) public view returns (uint256)', 13 | 'function currentNonLegendaryId() public view returns (uint128)', 14 | 'function getGobblerEmissionMultiple(uint256) returns (uint256)', 15 | 'function getGobblerData(uint256) returns (address owner, uint64 idx, uint32 emissionMultiple)' 16 | ], 17 | '0x60bb1e2aa1c9acafb4d34f71585d7e959f387769' 18 | ) 19 | 20 | async function main() { 21 | const [, , inpAddr] = process.argv 22 | const targetAddr = ethers.utils.getAddress(inpAddr) 23 | const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL) 24 | const multicall = getMulticaller('0xeefba1e63905ef1d7acba5a8513c70307c1ce441', provider) 25 | const [totalMinted] = await multicall([gobblerCall('currentNonLegendaryId')], {}) 26 | const tokenIds = _.range(1, totalMinted.toNumber() + 1) 27 | 28 | console.log('getting all owners') 29 | const gobblerData = await multicall( 30 | tokenIds.map((tokenId) => gobblerCall('getGobblerData', tokenId)), 31 | {} 32 | ) 33 | const sortedOwners = _.map(gobblerData, 'owner') 34 | 35 | console.log('filtering for target owner') 36 | const targetGobblers = _.zip(tokenIds, sortedOwners) 37 | .filter(([, owner]) => owner === targetAddr) 38 | .map(([gobbler]) => gobbler) 39 | 40 | console.log('getting multiples') 41 | const multiples = await multicall( 42 | targetGobblers.map((gobbler) => gobblerCall('getGobblerEmissionMultiple', gobbler)), 43 | {} 44 | ) 45 | for (const [gobbler, multiple] of _.zip(targetGobblers, multiples)) { 46 | console.log(`${gobbler}: x${multiple}`) 47 | } 48 | if (multiples.length >= 1) { 49 | const totalMultiple = multiples.reduce((total, x) => total.add(x)) 50 | console.log(`Total Multiple (${multiples.length}): ${totalMultiple}`) 51 | } else { 52 | console.log('No gobblers') 53 | } 54 | } 55 | 56 | main() 57 | .then(() => process.exit(0)) 58 | .catch((err) => { 59 | // console.error('err:', err) 60 | const fs = require('fs') 61 | fs.writeFileSync('./error.json', JSON.stringify(err, null, 2)) 62 | console.log('saved error') 63 | process.exit(1) 64 | }) 65 | -------------------------------------------------------------------------------- /script/emissions-analysis.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const ethers = require('ethers') 3 | const { getMulticaller, createCallEncoder } = require('easy-multicall') 4 | const _ = require('lodash') 5 | 6 | const gobblerCall = createCallEncoder( 7 | [ 8 | 'function ownerOf(uint256) view returns (address)', 9 | 'function getUserEmissionMultiple(address) view returns (uint32)', 10 | 'function gooBalance(address) view returns (uint256)', 11 | 'function gobblerPrice() public view returns (uint256)', 12 | 'function getVRGDAPrice(int256, uint256) public view returns (uint256)', 13 | 'function currentNonLegendaryId() public view returns (uint128)' 14 | ], 15 | '0x60bb1e2aa1c9acafb4d34f71585d7e959f387769' 16 | ) 17 | 18 | async function main() { 19 | const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL) 20 | const multicall = getMulticaller( 21 | '0xeefba1e63905ef1d7acba5a8513c70307c1ce441', 22 | provider 23 | ) 24 | const currentBlock = await provider.getBlockNumber() 25 | const [totalMinted] = await multicall( 26 | [gobblerCall('currentNonLegendaryId')], 27 | { blockTag: currentBlock } 28 | ) 29 | const tokenIds = _.range(1, totalMinted.toNumber() + 1) 30 | const sortedOwners = await multicall( 31 | tokenIds.map((tokenId) => gobblerCall('ownerOf', tokenId)), 32 | { blockTag: currentBlock } 33 | ) 34 | const ownerOf = Object.fromEntries(_.zip(tokenIds, sortedOwners)) 35 | const ownedTokens = {} 36 | for (const [tokenId, owner] of Object.entries(ownerOf)) { 37 | const ownedTokenSet = ownedTokens[owner] ?? new Set() 38 | ownedTokenSet.add(tokenId) 39 | ownedTokens[owner] = ownedTokenSet 40 | } 41 | const owners = Array.from(Object.keys(ownedTokens)) 42 | const emissionMultiples = Object.fromEntries( 43 | _.zip( 44 | owners, 45 | await multicall( 46 | owners.map((owner) => gobblerCall('getUserEmissionMultiple', owner)), 47 | { blockTag: currentBlock } 48 | ) 49 | ) 50 | ) 51 | const totalEmissions = _.sum(Object.values(emissionMultiples)) 52 | const users = owners.map((owner) => ({ 53 | addr: owner, 54 | balanceOf: ownedTokens[owner].size, 55 | emissionMultiple: emissionMultiples[owner] 56 | })) 57 | const sortedUsers = _.reverse(_.sortBy(users, ['emissionMultiple'])) 58 | const Formatter = new Intl.NumberFormat('en', { 59 | style: 'percent', 60 | minimumFractionDigits: 3, 61 | maximumFractionDigits: 3 62 | }) 63 | console.log('totalEmissions: ', totalEmissions) 64 | sortedUsers.forEach(({ addr, balanceOf, emissionMultiple }, i) => { 65 | console.log( 66 | `#${i + 1} ${addr} ${Formatter.format( 67 | emissionMultiple / totalEmissions 68 | )} (${balanceOf} - ${emissionMultiple})` 69 | ) 70 | }) 71 | } 72 | 73 | main() 74 | .then(() => process.exit(0)) 75 | .catch((err) => { 76 | console.error('err:', err) 77 | process.exit(1) 78 | }) 79 | -------------------------------------------------------------------------------- /src/GobblerBuyerModule.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import {ModuleManager} from "@gnosis-safe/base/ModuleManager.sol"; 5 | import {Enum} from "@gnosis-safe/common/Enum.sol"; 6 | import {IArtGobblers} from "./interfaces/IArtGobblers.sol"; 7 | import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; 8 | 9 | /// @author philogy 10 | contract GobblerBuyerModule { 11 | address internal immutable THIS; 12 | address internal constant GOBBLERS = 0x60bb1e2AA1c9ACAfB4d34F71585D7e959f387769; 13 | address internal constant GOO = 0x600000000a36F3cD48407e35eB7C5c910dc1f7a8; 14 | 15 | mapping(address => address) public buyerOf; 16 | 17 | event BuyerSet(address indexed safe, address indexed buyer); 18 | 19 | error NotBuyer(); 20 | error BuyFailed(); 21 | error AttemptedDelegate(); 22 | error NotDelegateCall(); 23 | error RemoveFailed(); 24 | 25 | constructor() { 26 | THIS = address(this); 27 | } 28 | 29 | /// @dev Prevent safe from accidentally calling this module via `DelegateCall` operation. 30 | modifier preventDelegateCall() { 31 | if (address(this) != THIS) revert AttemptedDelegate(); 32 | _; 33 | } 34 | 35 | /// @dev Allows safes to setup this method in their `setup` method 36 | function setupGobblerBuyer(address _buyer) external { 37 | if (address(this) == THIS) revert NotDelegateCall(); 38 | ModuleManager(address(this)).enableModule(THIS); 39 | GobblerBuyerModule(THIS).setBuyer(_buyer); 40 | } 41 | 42 | /// @notice Permits `_buyer` to mint new Gobblers with GOO on behalf of safe. 43 | /// @param _buyer Account allowed to trigger `mintFromGoo` method. 44 | function setBuyer(address _buyer) external preventDelegateCall { 45 | buyerOf[msg.sender] = _buyer; 46 | emit BuyerSet(msg.sender, _buyer); 47 | } 48 | 49 | /// @dev Always uses virtual balances, GOO tokens are not spendable by the buyer 50 | function buyFor(address _safe, uint256 _maxPrice) external preventDelegateCall { 51 | if (buyerOf[_safe] != msg.sender) revert NotBuyer(); 52 | bool success = ModuleManager(_safe).execTransactionFromModule( 53 | GOBBLERS, 54 | 0, 55 | abi.encodeCall(IArtGobblers.mintFromGoo, (_maxPrice, true)), 56 | Enum.Operation.Call 57 | ); 58 | if (!success) revert BuyFailed(); 59 | } 60 | 61 | function removeAllGoo() external preventDelegateCall { 62 | uint256 totalVirtualGoo = IArtGobblers(GOBBLERS).gooBalance(msg.sender); 63 | bool success = ModuleManager(msg.sender).execTransactionFromModule( 64 | GOBBLERS, 65 | 0, 66 | abi.encodeCall(IArtGobblers.removeGoo, (totalVirtualGoo)), 67 | Enum.Operation.Call 68 | ); 69 | if (!success) revert RemoveFailed(); 70 | } 71 | 72 | function removeAllGooAndTransferTo(address _recipient) external preventDelegateCall { 73 | uint256 totalVirtualGoo = IArtGobblers(GOBBLERS).gooBalance(msg.sender); 74 | bool successRemove = ModuleManager(msg.sender).execTransactionFromModule( 75 | GOBBLERS, 76 | 0, 77 | abi.encodeCall(IArtGobblers.removeGoo, (totalVirtualGoo)), 78 | Enum.Operation.Call 79 | ); 80 | bool successTransfer = ModuleManager(msg.sender).execTransactionFromModule( 81 | GOO, 82 | 0, 83 | abi.encodeCall(IERC20.transfer, (_recipient, totalVirtualGoo)), 84 | Enum.Operation.Call 85 | ); 86 | if (!(successRemove && successTransfer)) revert RemoveFailed(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/GooSitter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {Owned} from "@solmate/auth/Owned.sol"; 5 | import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; 6 | import {IArtGobblers} from "./interfaces/IArtGobblers.sol"; 7 | 8 | /// @author Philippe Dumonet 9 | contract GooSitter is Owned { 10 | IArtGobblers internal constant gobblers = IArtGobblers(0x60bb1e2AA1c9ACAfB4d34F71585D7e959f387769); 11 | IERC20 internal constant goo = IERC20(0x600000000a36F3cD48407e35eB7C5c910dc1f7a8); 12 | address internal immutable manager; 13 | 14 | bool internal constant BUY_GOBBLER_WITH_VIRTUAL = true; 15 | 16 | error NotManager(); 17 | error FailedCustomCall(bytes errorData); 18 | 19 | constructor(address _manager, address _initialOwner) Owned(_initialOwner) { 20 | manager = _manager; 21 | } 22 | 23 | /// @dev Transfers gobblers and virtual GOO to `_recipient`. 24 | /// @notice Does **not** use `safeTransferFrom` so be sure double-check `_recipient` before calling. 25 | function withdraw( 26 | address _recipient, 27 | uint256[] calldata _gobblerIds, 28 | uint256 _gooAmount 29 | ) external onlyOwner { 30 | uint256 gobblerCount = _gobblerIds.length; 31 | for (uint256 i; i < gobblerCount; ) { 32 | gobblers.transferFrom(address(this), _recipient, _gobblerIds[i]); 33 | // prettier-ignore 34 | unchecked { ++i; } 35 | } 36 | if (_gooAmount == type(uint256).max) _gooAmount = gobblers.gooBalance(address(this)); 37 | gobblers.removeGoo(_gooAmount); 38 | goo.transfer(_recipient, _gooAmount); 39 | } 40 | 41 | /// @dev Allow `owner` to call any contract, necessary to claim certain airdrops. 42 | function doCustomCall(address _target, bytes calldata _calldata) external payable onlyOwner { 43 | (bool success, bytes memory errorData) = _target.call{value: msg.value}(_calldata); 44 | if (!success) revert FailedCustomCall(errorData); 45 | } 46 | 47 | /// @dev Allows the `manager` to buy a gobbler on your behalf. 48 | /// @dev Not actually payable, but callvalue check is done more cheaply in assembly. 49 | function buyGobbler(uint256 _maxPrice) external payable { 50 | // Copy immutables locally since they're not supported in assembly. 51 | address manager_ = manager; 52 | address gobblers_ = address(gobblers); 53 | assembly { 54 | // Store `mintFromGoo(uint256,bool)` selector. 55 | mstore(0x00, 0xc9bddac6) 56 | // Prepare `mintFromGoo` parameters. 57 | mstore(0x20, _maxPrice) 58 | mstore(0x40, BUY_GOBBLER_WITH_VIRTUAL) 59 | 60 | // Call optimistically and do `msg.sender` auth require after. 61 | let success := call(gas(), gobblers_, 0, 0x1c, 0x44, 0x00, 0x00) 62 | 63 | // If `msg.sender != manager` sub result will be non-zero. 64 | let authDiff := sub(caller(), manager_) 65 | if or(or(authDiff, callvalue()), iszero(success)) { 66 | if authDiff { 67 | // Revert `NotManager()`. 68 | mstore(0x00, 0xc0fc8a8a) 69 | revert(0x1c, 0x04) 70 | } 71 | let revSize := mul(iszero(callvalue()), returndatasize()) 72 | returndatacopy(0x00, 0x00, revSize) 73 | revert(0x00, revSize) 74 | } 75 | 76 | // End here to ensure we can safely leave the free memory pointer. 77 | stop() 78 | } 79 | } 80 | 81 | /// @dev Doesn't send GOO anywhere so it's safe for anyone to be able to call. 82 | function consolidateGoo() external { 83 | gobblers.addGoo(goo.balanceOf(address(this))); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Just Gobbler Things 2 | While this repo initially only housed my "Gobbler Thrones" project over time I've added a small 3 | range of Art Gobbler related utility contracts. 4 | 5 | ## [GOO-Sitter](./src/GooSitter.sol) 6 | A custody contract that holds Gobblers & GOO on your behalf, allowing you to designate a separate 7 | "manager" address that can buy Gobblers on your behalf. Intended for people who want to ensure that 8 | Gobblers are protected in cold storage while still allowing a hot wallet to mint Gobblers on their 9 | behalf, via a script like [automate-buyer](./script/automate-buyer.js). 10 | 11 | ## [Gnosis Safe "Buyer Module"](./src/GobblerBuyerModule.sol) 12 | 13 | Deployed on mainnet at: [0xbBd44120c0FbC55583Df1e08dC11D386C02eDf7A](https://etherscan.io/address/0xbbd44120c0fbc55583df1e08dc11d386c02edf7a) 14 | 15 | Similar to GOO Sitter except aimed at making the above setup more seamless for [Gnosis 16 | Safe](https://gnosis-safe.io) users. 17 | 18 | **How to use:** 19 | 1. Enable the module deployed at `(deployment pending)` in your safe 20 | 2. Configure the buying hot wallet via `setBuyer(address)` 21 | 3. The buying hot wallet can now buy on behalf of your safe by calling `buyFor(address safe, uint maxPrice)` on the module 22 | 23 | The contract also has `removeAllGoo` and `removeAllGooAndTransferTo` methods to allow a safe to 24 | easily remove and/or transfer out GOO without leaving behind dust. 25 | 26 | **Note:** The designated can only spend accruing virtual GOO, if you want to set aside GOO you can 27 | convert some virtual GOO to token GOO via the ArtGobbler's `removeGoo` method. 28 | 29 | 30 | ## Gobbler Thrones 31 | > No one person can bear the might of a legendary gobbler, we shall bear it together! 32 | 33 | `GobblerThrone` is a relatively simple pooling contract that can be deployed by 34 | anybody. The deployed pools can be joined by anybody by depositing their revealed Gobblers. 35 | The core goal is to make exposure to Legendary Gobblers more accessible to average holders. 36 | 37 | If the legendary mint is successful the almighty, freshly minted legendary Gobbler 38 | is placed upon the throne, out of all the participants' reach, accruing GOO, locked 39 | in place until the throne is set to be dissolved. In exchange for their 40 | sacrifice participants receive Gobbler Throne shares (or GOTTEM's). 41 | 42 | Once the throne is set to dissolve, the Legendary Gobbler is auctioned off for 43 | even more GOO. Once the auction is complete 44 | and the throne is fully dissolved shares can be redeemed for a proportional 45 | share of all the GOO that was accumulated in the throne contract. 46 | 47 | ### Specifics 48 | #### Share Receival 49 | Due to the decreasing price of legendary Gobblers the contract is first-come 50 | first-served meaning if there's 60 Gobblers in the contract but the legendary 51 | only costs 57, only the first 57 participants will be able to receive shares, 52 | the last 3 will however be able to retrieve their unused Gobblers from the 53 | throne contract (not including any accrued GOO). Shares are minted 54 | proportionally to the emissions multiple of the deposited Gobbler(s). 55 | 56 | #### Failure To Form 57 | If the throne contract doesn't accrue sufficient Gobblers by a certain time it 58 | can enter failure mode, allowing all participants to withdraw their Gobblers. 59 | The time until the failure mode can be activated is set upon deployment. 60 | 61 | #### Auction 62 | The final auction is also set to begin at a certain time after throne creation 63 | depending on the configured delay. The auction must go for at least 30 minutes 64 | without bids before finalizing, this is to protect against last minute sniping 65 | whereby people wait until the last moment to submit bids. Each bid must be at 66 | least 5% higher than the previous. 67 | 68 | #### GOO Withdrawal 69 | To simplify the system and ensure the maximum amount of GOO is issued GOO can 70 | only be withdrawn once the throne is dissolved. TODO: Have legendary Gobbler be 71 | deposited in [Goo Stew](https://github.com/MrToph/goostew/) for even better GOO 72 | production. 73 | -------------------------------------------------------------------------------- /test/GooSitter.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {MockArtGobblers} from "./mock/MockArtGobblers.sol"; 6 | import {MockERC20} from "./mock/MockERC20.sol"; 7 | import {IArtGobblers} from "../src/interfaces/IArtGobblers.sol"; 8 | import {GooSitter} from "../src/GooSitter.sol"; 9 | 10 | /// @author Philippe Dumonet 11 | contract GooSitterTest is Test { 12 | MockERC20 goo = MockERC20(0x600000000a36F3cD48407e35eB7C5c910dc1f7a8); 13 | MockArtGobblers gobblers = MockArtGobblers(0x60bb1e2AA1c9ACAfB4d34F71585D7e959f387769); 14 | GooSitter sitter; 15 | 16 | address manager = vm.addr(1); 17 | address owner = vm.addr(2); 18 | 19 | function setUp() public { 20 | MockERC20 fakeGoo = new MockERC20(); 21 | vm.etch(address(goo), address(fakeGoo).code); 22 | MockArtGobblers fakeGobblers = new MockArtGobblers(goo); 23 | vm.etch(address(gobblers), address(fakeGobblers).code); 24 | sitter = new GooSitter(manager, owner); 25 | } 26 | 27 | function testInitialOwner() public { 28 | assertEq(sitter.owner(), owner); 29 | } 30 | 31 | function testNotManagerBuy(address _caller) public { 32 | vm.assume(_caller != manager); 33 | vm.prank(_caller); 34 | vm.expectRevert(GooSitter.NotManager.selector); 35 | sitter.buyGobbler(100e18); 36 | } 37 | 38 | function testFailCallValueBuy(uint256 _amount) public { 39 | vm.assume(_amount > 0); 40 | vm.deal(manager, _amount); 41 | vm.prank(manager); 42 | sitter.buyGobbler{value: _amount}(100e18); 43 | } 44 | 45 | function testManagerCanBuy() public { 46 | uint256 maxPrice = 3000e18; 47 | gobblers.setMaxPrice(maxPrice); 48 | vm.prank(manager); 49 | vm.expectCall(address(gobblers), abi.encodeCall(IArtGobblers.mintFromGoo, (maxPrice, true))); 50 | sitter.buyGobbler(maxPrice); 51 | } 52 | 53 | function testRevertingManagerBuy() public { 54 | uint256 maxPrice = 269e18; 55 | gobblers.setMaxPrice(maxPrice - 1); 56 | vm.prank(manager); 57 | vm.expectCall(address(gobblers), abi.encodeCall(IArtGobblers.mintFromGoo, (maxPrice, true))); 58 | vm.expectRevert(MockArtGobblers.PriceExceededMax.selector); 59 | sitter.buyGobbler(maxPrice); 60 | } 61 | 62 | function testGooConsolidation(uint256 _mintAmount) public { 63 | goo.mint(address(sitter), _mintAmount); 64 | sitter.consolidateGoo(); 65 | assertEq(gobblers.gooBalance(address(sitter)), _mintAmount); 66 | assertEq(goo.balanceOf(address(sitter)), 0); 67 | } 68 | 69 | function testFailNotOwnerWithdraw(address _withdrawer) public { 70 | vm.assume(_withdrawer != owner); 71 | vm.prank(_withdrawer); 72 | sitter.withdraw(_withdrawer, new uint256[](0), type(uint256).max); 73 | } 74 | 75 | function testOwnerWithdraw(address _recipient, uint256 _gooAmount) public { 76 | vm.assume(_recipient != address(0)); 77 | 78 | // setup Gobblers 79 | uint256[] memory tokens = new uint256[](5); 80 | for (uint256 i; i < 5; ) { 81 | tokens[i] = gobblers.mint(address(sitter)); 82 | assertEq(gobblers.ownerOf(tokens[i]), address(sitter)); 83 | // prettier-ignore 84 | unchecked { ++i; } 85 | } 86 | 87 | // setup GOO 88 | goo.mint(address(sitter), _gooAmount); 89 | sitter.consolidateGoo(); 90 | assertEq(gobblers.gooBalance(address(sitter)), _gooAmount); 91 | assertEq(goo.balanceOf(address(sitter)), 0); 92 | 93 | vm.prank(owner); 94 | sitter.withdraw(_recipient, tokens, type(uint256).max); 95 | 96 | for (uint256 i; i < 5; ) { 97 | assertEq(gobblers.ownerOf(tokens[i]), _recipient); 98 | // prettier-ignore 99 | unchecked { ++i; } 100 | } 101 | assertEq(goo.balanceOf(_recipient), _gooAmount); 102 | } 103 | 104 | function testWithdrawPartial( 105 | address _recipient, 106 | uint256 _a, 107 | uint256 _b 108 | ) public { 109 | vm.assume(_recipient != address(0)); 110 | (uint256 deposit, uint256 withdraw) = _a > _b ? (_a, _b) : (_b, _a); 111 | // prepare test 112 | goo.mint(address(sitter), deposit); 113 | sitter.consolidateGoo(); 114 | // withdraw 115 | vm.prank(owner); 116 | sitter.withdraw(_recipient, new uint256[](0), withdraw); 117 | // check end state 118 | assertEq(gobblers.gooBalance(address(sitter)), deposit - withdraw); 119 | assertEq(goo.balanceOf(_recipient), withdraw); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /script/automate-buyer.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const ethers = require('ethers') 3 | const { 4 | FlashbotsBundleProvider, 5 | FlashbotsTransactionResolution 6 | } = require('@flashbots/ethers-provider-bundle') 7 | const { getMulticaller, createCallEncoder } = require('easy-multicall') 8 | 9 | const gobblerCall = createCallEncoder( 10 | [ 11 | 'function gooBalance(address) view returns (uint256)', 12 | 'function gobblerPrice() public view returns (uint256)', 13 | 'function getVRGDAPrice(int256, uint256) public view returns (uint256)', 14 | 'function gobblerRevealsData() view returns (uint64 randomSeed,uint64 nextRevealTimestamp,uint56 lastRevealid,uint56 toBeRevealed,bool waitingForSeed)' 15 | ], 16 | '0x60bb1e2aa1c9acafb4d34f71585d7e959f387769' 17 | ) 18 | 19 | const sleep = (delay) => new Promise((resolve) => setTimeout(() => resolve(), delay)) 20 | 21 | const wadToFloat = (wad) => parseFloat(ethers.utils.formatUnits(wad, 18)) 22 | const bnToFloat = (bn, unit) => parseFloat(ethers.utils.formatUnits(bn, unit)) 23 | 24 | const BAL_TO_PRICE_THRESHOLD = 1.25 25 | const TIME_TO_REVEAL_THRESHOLD = 1.0 // hours 26 | const GAS_PRICE_CAP = ethers.utils.parseUnits('100', 'gwei') 27 | 28 | const divmod = (x, y) => [Math.floor(x / y), x % y] 29 | const rounder2 = new Intl.NumberFormat('en', { maximumFractionDigits: 2 }) 30 | const formatTimeDelta = (td) => { 31 | const [totalMinutes, seconds] = divmod(td, 60) 32 | const [totalHours, minutes] = divmod(totalMinutes, 60) 33 | const [totalDays, hours] = divmod(totalHours, 24) 34 | const [weeks, days] = divmod(totalDays, 7) 35 | const components = [ 36 | [weeks, 'w'], 37 | [days, 'd'], 38 | [hours, 'h'], 39 | [minutes, 'm'], 40 | [seconds, 's'] 41 | ].filter(([units]) => units > 0) 42 | 43 | return components.map(([unit, char]) => `${rounder2.format(unit)}${char}`).join(' ') 44 | } 45 | 46 | const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL) 47 | const multicall = getMulticaller('0xeefba1e63905ef1d7acba5a8513c70307c1ce441', provider) 48 | const managerSigner = new ethers.Wallet(process.env.MANAGER_PRIV_KEY) 49 | console.log('managerSigner.address: ', managerSigner.address) 50 | const gooSitter = new ethers.Contract( 51 | process.env.SITTER_ADDR, 52 | ['function buyGobbler(uint256) external', 'function owner() view returns (address)'], 53 | provider 54 | ) 55 | 56 | async function sendBuy(flashbotsProvider) { 57 | const { baseFeePerGas } = await provider.getBlock('latest') 58 | const [bnPrice] = await multicall([gobblerCall('gobblerPrice')], {}) 59 | const [estGas, nonce] = await Promise.all([ 60 | gooSitter.estimateGas.buyGobbler(bnPrice, { 61 | from: managerSigner.address 62 | }), 63 | provider.getTransactionCount(managerSigner.address) 64 | ]) 65 | try { 66 | const buyTx = await gooSitter.populateTransaction.buyGobbler(bnPrice, { 67 | type: 2, 68 | from: managerSigner.address, 69 | maxFeePerGas: baseFeePerGas.mul('143').div('100'), 70 | maxPriorityFeePerGas: ethers.utils.parseUnits('2', 'gwei'), 71 | gasLimit: Math.round(estGas * 1.2), 72 | nonce 73 | }) 74 | buyTx.chainId = 1 75 | const res = await flashbotsProvider.sendPrivateTransaction({ 76 | transaction: buyTx, 77 | signer: managerSigner 78 | }) 79 | const { hash } = res.transaction 80 | console.log('hash:', hash) 81 | 82 | const waitRes = await res.wait() 83 | if (waitRes === FlashbotsTransactionResolution.TransactionIncluded) { 84 | console.log('Private transaction successfully included on-chain.') 85 | } else if (waitRes === FlashbotsTransactionResolution.TransactionDropped) { 86 | console.log( 87 | 'Private transaction was not included in a block and has been removed from the system.' 88 | ) 89 | } 90 | } catch (err) { 91 | console.log('err: ', err) 92 | } 93 | } 94 | async function main() { 95 | const flashbotsProvider = await FlashbotsBundleProvider.create(provider, managerSigner) 96 | 97 | while (true) { 98 | try { 99 | const [bnPrice, bnGooBal, { nextRevealTimestamp: bnNextReveal }] = await multicall( 100 | [ 101 | gobblerCall('gobblerPrice'), 102 | gobblerCall('gooBalance', gooSitter.address), 103 | gobblerCall('gobblerRevealsData') 104 | ], 105 | {} 106 | ) 107 | const { baseFeePerGas } = await provider.getBlock('latest') 108 | 109 | const [price, gooBal] = [bnPrice, bnGooBal].map(wadToFloat) 110 | const nextReveal = bnNextReveal.toNumber() 111 | 112 | const timeToReveal = nextReveal - Date.now() / 1000 113 | const PerecentFormatter = new Intl.NumberFormat('en', { 114 | style: 'percent', 115 | minimumFractionDigits: 3, 116 | maximumFractionDigits: 3 117 | }) 118 | const BalFormatter = new Intl.NumberFormat('en', { 119 | maximumFractionDigits: 2, 120 | minimumFractionDigits: 1 121 | }) 122 | 123 | console.log( 124 | `Goo to price: ${PerecentFormatter.format(gooBal / price)} (bal: ${BalFormatter.format( 125 | gooBal 126 | )} GOO, target: ${PerecentFormatter.format( 127 | BAL_TO_PRICE_THRESHOLD 128 | )}, next reveal in ${formatTimeDelta(timeToReveal)}, gas price: ${rounder2.format( 129 | bnToFloat(baseFeePerGas, 'gwei') 130 | )} gwei)` 131 | ) 132 | 133 | if ( 134 | gooBal / price >= BAL_TO_PRICE_THRESHOLD && 135 | 0 <= timeToReveal && 136 | timeToReveal <= TIME_TO_REVEAL_THRESHOLD * 60 * 60 && 137 | baseFeePerGas.lte(GAS_PRICE_CAP) 138 | ) { 139 | await sendBuy(flashbotsProvider) 140 | } else { 141 | await sleep(4000) 142 | } 143 | } catch (err) { 144 | console.log(`${err} occured, sleeping...`) 145 | 146 | await sleep(20000) 147 | } 148 | } 149 | } 150 | 151 | main() 152 | .then(() => process.exit(0)) 153 | .catch((err) => { 154 | console.error('err:', err) 155 | process.exit(1) 156 | }) 157 | -------------------------------------------------------------------------------- /test/GobblerBuyerModule.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {GnosisSafeTest} from "./utils/GnosisSafe.t.sol"; 6 | import {MockArtGobblers} from "./mock/MockArtGobblers.sol"; 7 | import {MockERC20} from "./mock/MockERC20.sol"; 8 | import {IArtGobblers} from "../src/interfaces/IArtGobblers.sol"; 9 | 10 | import {GnosisSafe} from "@gnosis-safe/GnosisSafe.sol"; 11 | import {Enum} from "@gnosis-safe/common/Enum.sol"; 12 | import {GobblerBuyerModule} from "../src/GobblerBuyerModule.sol"; 13 | 14 | /// @author philogy 15 | contract GobblerBuyerModuleTest is Test, GnosisSafeTest { 16 | address internal defaultUser = vm.addr(1); 17 | address[] internal defaultOwners; 18 | GobblerBuyerModule internal buyerModule; 19 | MockERC20 goo = MockERC20(0x600000000a36F3cD48407e35eB7C5c910dc1f7a8); 20 | MockArtGobblers gobblers = MockArtGobblers(0x60bb1e2AA1c9ACAfB4d34F71585D7e959f387769); 21 | 22 | uint256 internal constant DEFAULT_NONCE = 0; 23 | 24 | event BuyerSet(address indexed safe, address indexed buyer); 25 | event EnabledModule(address module); 26 | 27 | function setUp() public { 28 | MockERC20 fakeGoo = new MockERC20(); 29 | vm.etch(address(goo), address(fakeGoo).code); 30 | MockArtGobblers fakeGobblers = new MockArtGobblers(goo); 31 | vm.etch(address(gobblers), address(fakeGobblers).code); 32 | gobblers.setMaxPrice(type(uint256).max); 33 | 34 | defaultOwners = new address[](1); 35 | defaultOwners[0] = defaultUser; 36 | buyerModule = new GobblerBuyerModule(); 37 | } 38 | 39 | function testSetupBuyerAtDeploy(address _buyer) public { 40 | GnosisSafe multisig = GnosisSafe( 41 | payable( 42 | deploySafe( 43 | defaultOwners, 44 | 1, 45 | address(buyerModule), 46 | abi.encodeCall(buyerModule.setupGobblerBuyer, (_buyer)), 47 | DEFAULT_NONCE 48 | ) 49 | ) 50 | ); 51 | assertEq(buyerModule.buyerOf(address(multisig)), _buyer); 52 | assertTrue(multisig.isModuleEnabled(address(buyerModule))); 53 | } 54 | 55 | function testAfterDeployEnable() public { 56 | GnosisSafe multisig = createDefaultMultisig(); 57 | vm.expectEmit(true, true, true, true, address(multisig)); 58 | emit EnabledModule(address(buyerModule)); 59 | callMultisig(multisig, address(multisig), abi.encodeCall(multisig.enableModule, (address(buyerModule)))); 60 | assertTrue(multisig.isModuleEnabled(address(buyerModule))); 61 | } 62 | 63 | function testSetBuyer(address _buyer) public { 64 | GnosisSafe multisig = createEnabledMultisig(); 65 | vm.expectEmit(true, true, true, true, address(buyerModule)); 66 | emit BuyerSet(address(multisig), _buyer); 67 | callMultisig(multisig, address(buyerModule), abi.encodeCall(buyerModule.setBuyer, (_buyer))); 68 | assertEq(buyerModule.buyerOf(address(multisig)), _buyer); 69 | } 70 | 71 | function testBuyerCanMint(address _buyer, uint256 _price) public { 72 | vm.assume(_buyer != address(0)); 73 | GnosisSafe multisig = createEnabledMultisig(); 74 | callMultisig(multisig, address(buyerModule), abi.encodeCall(buyerModule.setBuyer, (_buyer))); 75 | vm.prank(_buyer); 76 | vm.expectCall(address(gobblers), abi.encodeCall(IArtGobblers.mintFromGoo, (_price, true))); 77 | buyerModule.buyFor(address(multisig), _price); 78 | assertEq(gobblers.lastCaller(), address(multisig)); 79 | assertEq(gobblers.balanceOf(address(multisig)), 1); 80 | } 81 | 82 | function testNonBuyerCannotMint( 83 | address _buyer, 84 | address _notBuyer, 85 | uint256 _price 86 | ) public { 87 | vm.assume(_buyer != _notBuyer); 88 | vm.assume(_notBuyer != address(0)); 89 | GnosisSafe multisig = createEnabledMultisig(); 90 | callMultisig(multisig, address(buyerModule), abi.encodeCall(buyerModule.setBuyer, (_buyer))); 91 | vm.prank(_notBuyer); 92 | vm.expectRevert(GobblerBuyerModule.NotBuyer.selector); 93 | buyerModule.buyFor(address(multisig), _price); 94 | } 95 | 96 | function testRemoveAll(uint256 _totalGoo) public { 97 | GnosisSafe multisig = createEnabledMultisig(); 98 | goo.mint(address(multisig), _totalGoo); 99 | vm.prank(address(multisig)); 100 | gobblers.addGoo(_totalGoo); 101 | assertEq(gobblers.gooBalance(address(multisig)), _totalGoo); 102 | 103 | callMultisig(multisig, address(buyerModule), abi.encodeCall(buyerModule.removeAllGoo, ())); 104 | assertEq(gobblers.gooBalance(address(multisig)), 0); 105 | assertEq(goo.balanceOf(address(multisig)), _totalGoo); 106 | } 107 | 108 | function testTransferAll(address _recipient, uint256 _totalGoo) public { 109 | vm.assume(_recipient != address(0)); 110 | 111 | GnosisSafe multisig = createEnabledMultisig(); 112 | goo.mint(address(multisig), _totalGoo); 113 | vm.prank(address(multisig)); 114 | gobblers.addGoo(_totalGoo); 115 | assertEq(gobblers.gooBalance(address(multisig)), _totalGoo); 116 | 117 | callMultisig( 118 | multisig, 119 | address(buyerModule), 120 | abi.encodeCall(buyerModule.removeAllGooAndTransferTo, (_recipient)) 121 | ); 122 | assertEq(gobblers.gooBalance(address(multisig)), 0); 123 | assertEq(goo.balanceOf(address(multisig)), 0); 124 | assertEq(goo.balanceOf(_recipient), _totalGoo); 125 | } 126 | 127 | function createEnabledMultisig() internal returns (GnosisSafe multisig) { 128 | multisig = createDefaultMultisig(); 129 | callMultisig(multisig, address(multisig), abi.encodeCall(multisig.enableModule, (address(buyerModule)))); 130 | } 131 | 132 | function callMultisig( 133 | GnosisSafe _multisig, 134 | address _target, 135 | bytes memory _calldata 136 | ) internal { 137 | vm.prank(defaultUser); 138 | _multisig.execTransaction( 139 | _target, 140 | 0, 141 | _calldata, 142 | Enum.Operation.Call, 143 | 0, 144 | 0, 145 | 0, 146 | address(0), 147 | payable(0), 148 | getCallerSignature(defaultUser) 149 | ); 150 | } 151 | 152 | function createDefaultMultisig() internal returns (GnosisSafe multisig) { 153 | multisig = GnosisSafe(payable(deploySafe(defaultOwners, 1, address(0), "", DEFAULT_NONCE))); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/GobblerThrone.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; 5 | import {Multicall} from "@openzeppelin/utils/Multicall.sol"; 6 | import {ERC20} from "@solmate/tokens/ERC20.sol"; 7 | import {IArtGobblers} from "./interfaces/IArtGobblers.sol"; 8 | 9 | /// @author Philogy 10 | /// @dev WARNING: basic af, not optimized just yet 11 | contract GobblerThrone is ERC20, Multicall { 12 | struct Participant { 13 | address account; 14 | uint16 gobblerId; 15 | uint8 multiple; 16 | } 17 | mapping(uint256 => Participant) internal participants; 18 | 19 | uint256 internal constant FIRST_LEGENDARY_GOBBLER_ID = 9991; 20 | // 1000 shares / 1x gobbler multiple 21 | uint256 internal constant MULTIPLE_TO_SHARES_FACTOR = 1e21; 22 | 23 | uint256 internal constant ONE_IN_BPS = 10000; // 5% 24 | uint256 internal constant BID_MIN_INCREASE_BPS = 500; // 5% 25 | uint256 internal constant BID_MIN_INCREASE_FACTOR_BPS = ONE_IN_BPS + BID_MIN_INCREASE_BPS; // x1.05 26 | uint256 internal constant AUCTION_GRACE_PERIOD = 30 minutes; 27 | uint256 internal constant AUCTION_START_DURATION = 7 days; 28 | 29 | // Model contract as finite state machine for the sake of simplicity and 30 | // security 31 | enum ThroneState { 32 | Forming, 33 | FormationFailed, 34 | Formed, 35 | AuctionInProgress, 36 | Dissolved 37 | } 38 | 39 | uint16 public totalJoined; 40 | uint16 public totalParticipants; 41 | uint16 public legendaryGobblerId; 42 | 43 | // auction data 44 | uint64 public auctionEnd; 45 | uint128 public bestBid; 46 | address public topBidder; 47 | 48 | uint256 public immutable auctionStartsAt; 49 | uint256 public immutable formationFailsAt; 50 | IArtGobblers public immutable artGobblers; 51 | IERC20 public immutable goo; 52 | 53 | error WrongState(); 54 | error UnacceptableGobbler(); 55 | error SharesAlreadyIssued(); 56 | error NotParticipant(); 57 | error ParticipantCannotExit(); 58 | error InsufficientGobblers(); 59 | error BidTooLow(); 60 | 61 | constructor( 62 | address _artGobblers, 63 | uint256 _maxFormationTime, 64 | uint256 _totalLifeTime 65 | ) ERC20("Gobbler Throne Shares", "GOTTEM", 18) { 66 | assert(_maxFormationTime < _totalLifeTime); 67 | auctionStartsAt = block.timestamp + _totalLifeTime; 68 | formationFailsAt = block.timestamp + _maxFormationTime; 69 | artGobblers = IArtGobblers(_artGobblers); 70 | goo = IERC20(IArtGobblers(_artGobblers).goo()); 71 | } 72 | 73 | modifier onlyState(ThroneState _expectedState) { 74 | if (state() != _expectedState) revert WrongState(); 75 | _; 76 | } 77 | 78 | function state() public view returns (ThroneState) { 79 | if (legendaryGobblerId == 0) { 80 | return block.timestamp >= formationFailsAt ? ThroneState.FormationFailed : ThroneState.Forming; 81 | } else { 82 | if (block.timestamp < auctionStartsAt) return ThroneState.Formed; 83 | if (topBidder == address(0) || block.timestamp < auctionEnd) return ThroneState.AuctionInProgress; 84 | return ThroneState.Dissolved; 85 | } 86 | } 87 | 88 | /// @dev deposit a Gobbler, adding a potential piece to the throne 89 | function join(uint256 _gobblerId) external onlyState(ThroneState.Forming) { 90 | artGobblers.transferFrom(msg.sender, address(this), _gobblerId); 91 | unchecked { 92 | uint256 emissionsMultiple = artGobblers.getGobblerEmissionMultiple(_gobblerId); 93 | // abuse underflow for cheaper range check 94 | if ((emissionsMultiple - 6) >= 4 || _gobblerId >= FIRST_LEGENDARY_GOBBLER_ID) revert UnacceptableGobbler(); 95 | 96 | participants[totalJoined++] = Participant({ 97 | account: msg.sender, 98 | gobblerId: uint16(_gobblerId), 99 | multiple: uint8(emissionsMultiple) 100 | }); 101 | } 102 | } 103 | 104 | /// @dev attempts to mint the legendary Gobbler 105 | function form() external onlyState(ThroneState.Forming) { 106 | uint256 gobblersToBeSacrificed = artGobblers.legendaryGobblerPrice(); 107 | if (totalJoined < gobblersToBeSacrificed) revert InsufficientGobblers(); 108 | uint256[] memory gobblerIds = new uint256[](gobblersToBeSacrificed); 109 | for (uint256 i; i < gobblersToBeSacrificed; ) { 110 | gobblerIds[i] = participants[i].gobblerId; 111 | // prettier-ignore 112 | unchecked { i++; } 113 | } 114 | legendaryGobblerId = uint16(artGobblers.mintLegendaryGobbler(gobblerIds)); 115 | totalParticipants = uint16(gobblersToBeSacrificed); 116 | } 117 | 118 | /// @dev retrieve Gobbler if throne formation failed 119 | function failExit(uint256 _participantId) external onlyState(ThroneState.FormationFailed) { 120 | address account = participants[_participantId].account; 121 | uint256 gobblerId = participants[_participantId].gobblerId; 122 | delete participants[_participantId]; 123 | artGobblers.transferFrom(address(this), account, gobblerId); 124 | } 125 | 126 | /// @dev if legendary Gobbler was minted get shares 127 | function issueShares(uint256 _participantId) external onlyState(ThroneState.Formed) { 128 | if (_participantId >= totalParticipants) revert NotParticipant(); 129 | address account = participants[_participantId].account; 130 | uint256 multiple = participants[_participantId].multiple; 131 | if (account == address(0)) revert SharesAlreadyIssued(); 132 | delete participants[_participantId]; 133 | _mint(account, MULTIPLE_TO_SHARES_FACTOR * multiple); 134 | } 135 | 136 | /// @dev retrieve Gobbler that couldn't be used to mint legendary 137 | function notParticipantExit(uint256 _participantId) external onlyState(ThroneState.Formed) { 138 | if (_participantId < totalParticipants) revert ParticipantCannotExit(); 139 | address account = participants[_participantId].account; 140 | uint256 gobblerId = participants[_participantId].gobblerId; 141 | delete participants[_participantId]; 142 | artGobblers.transferFrom(address(this), account, gobblerId); 143 | } 144 | 145 | /// @dev bid in auction using GOO tokens 146 | function bid(uint256 _bidAmount) external onlyState(ThroneState.AuctionInProgress) { 147 | goo.transferFrom(msg.sender, address(this), _bidAmount); 148 | address currentTopBidder = topBidder; 149 | if (currentTopBidder == address(0)) { 150 | // first bid can be any non-zero value 151 | if (_bidAmount == 0) revert BidTooLow(); 152 | } else { 153 | uint256 prevBestBid = bestBid; 154 | if (_bidAmount * ONE_IN_BPS < prevBestBid * BID_MIN_INCREASE_FACTOR_BPS) revert BidTooLow(); 155 | goo.transfer(currentTopBidder, prevBestBid); 156 | } 157 | bestBid = uint128(_bidAmount); 158 | topBidder = msg.sender; 159 | uint256 minimumEndTime = block.timestamp + AUCTION_GRACE_PERIOD; 160 | uint256 currentAuctionEnd = auctionEnd; 161 | auctionEnd = uint64(minimumEndTime > currentAuctionEnd ? minimumEndTime : currentAuctionEnd); 162 | } 163 | 164 | /// @dev claim share of GOO produced by the legendary + auction proceeds 165 | function claimShare(address _recipient) external onlyState(ThroneState.Dissolved) { 166 | // Convert virtual GOO into transferable ERC20 GOO. 167 | uint256 vGoo = artGobblers.gooBalance(address(this)); 168 | if (vGoo != 0) artGobblers.removeGoo(vGoo); 169 | 170 | uint256 shares = balanceOf[msg.sender]; 171 | uint256 totalShares = totalSupply; 172 | uint256 gooShare = (goo.balanceOf(address(this)) * shares) / totalShares; 173 | _burn(msg.sender, shares); 174 | goo.transfer(_recipient, gooShare); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@eslint/eslintrc@^1.3.3": 6 | version "1.3.3" 7 | resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz" 8 | integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg== 9 | dependencies: 10 | ajv "^6.12.4" 11 | debug "^4.3.2" 12 | espree "^9.4.0" 13 | globals "^13.15.0" 14 | ignore "^5.2.0" 15 | import-fresh "^3.2.1" 16 | js-yaml "^4.1.0" 17 | minimatch "^3.1.2" 18 | strip-json-comments "^3.1.1" 19 | 20 | "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": 21 | version "5.7.0" 22 | resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" 23 | integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== 24 | dependencies: 25 | "@ethersproject/address" "^5.7.0" 26 | "@ethersproject/bignumber" "^5.7.0" 27 | "@ethersproject/bytes" "^5.7.0" 28 | "@ethersproject/constants" "^5.7.0" 29 | "@ethersproject/hash" "^5.7.0" 30 | "@ethersproject/keccak256" "^5.7.0" 31 | "@ethersproject/logger" "^5.7.0" 32 | "@ethersproject/properties" "^5.7.0" 33 | "@ethersproject/strings" "^5.7.0" 34 | 35 | "@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": 36 | version "5.7.0" 37 | resolved "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" 38 | integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== 39 | dependencies: 40 | "@ethersproject/bignumber" "^5.7.0" 41 | "@ethersproject/bytes" "^5.7.0" 42 | "@ethersproject/logger" "^5.7.0" 43 | "@ethersproject/networks" "^5.7.0" 44 | "@ethersproject/properties" "^5.7.0" 45 | "@ethersproject/transactions" "^5.7.0" 46 | "@ethersproject/web" "^5.7.0" 47 | 48 | "@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": 49 | version "5.7.0" 50 | resolved "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" 51 | integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== 52 | dependencies: 53 | "@ethersproject/abstract-provider" "^5.7.0" 54 | "@ethersproject/bignumber" "^5.7.0" 55 | "@ethersproject/bytes" "^5.7.0" 56 | "@ethersproject/logger" "^5.7.0" 57 | "@ethersproject/properties" "^5.7.0" 58 | 59 | "@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": 60 | version "5.7.0" 61 | resolved "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" 62 | integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== 63 | dependencies: 64 | "@ethersproject/bignumber" "^5.7.0" 65 | "@ethersproject/bytes" "^5.7.0" 66 | "@ethersproject/keccak256" "^5.7.0" 67 | "@ethersproject/logger" "^5.7.0" 68 | "@ethersproject/rlp" "^5.7.0" 69 | 70 | "@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": 71 | version "5.7.0" 72 | resolved "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" 73 | integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== 74 | dependencies: 75 | "@ethersproject/bytes" "^5.7.0" 76 | 77 | "@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": 78 | version "5.7.0" 79 | resolved "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz" 80 | integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== 81 | dependencies: 82 | "@ethersproject/bytes" "^5.7.0" 83 | "@ethersproject/properties" "^5.7.0" 84 | 85 | "@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": 86 | version "5.7.0" 87 | resolved "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" 88 | integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== 89 | dependencies: 90 | "@ethersproject/bytes" "^5.7.0" 91 | "@ethersproject/logger" "^5.7.0" 92 | bn.js "^5.2.1" 93 | 94 | "@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": 95 | version "5.7.0" 96 | resolved "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" 97 | integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== 98 | dependencies: 99 | "@ethersproject/logger" "^5.7.0" 100 | 101 | "@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": 102 | version "5.7.0" 103 | resolved "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" 104 | integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== 105 | dependencies: 106 | "@ethersproject/bignumber" "^5.7.0" 107 | 108 | "@ethersproject/contracts@5.7.0": 109 | version "5.7.0" 110 | resolved "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz" 111 | integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== 112 | dependencies: 113 | "@ethersproject/abi" "^5.7.0" 114 | "@ethersproject/abstract-provider" "^5.7.0" 115 | "@ethersproject/abstract-signer" "^5.7.0" 116 | "@ethersproject/address" "^5.7.0" 117 | "@ethersproject/bignumber" "^5.7.0" 118 | "@ethersproject/bytes" "^5.7.0" 119 | "@ethersproject/constants" "^5.7.0" 120 | "@ethersproject/logger" "^5.7.0" 121 | "@ethersproject/properties" "^5.7.0" 122 | "@ethersproject/transactions" "^5.7.0" 123 | 124 | "@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": 125 | version "5.7.0" 126 | resolved "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" 127 | integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== 128 | dependencies: 129 | "@ethersproject/abstract-signer" "^5.7.0" 130 | "@ethersproject/address" "^5.7.0" 131 | "@ethersproject/base64" "^5.7.0" 132 | "@ethersproject/bignumber" "^5.7.0" 133 | "@ethersproject/bytes" "^5.7.0" 134 | "@ethersproject/keccak256" "^5.7.0" 135 | "@ethersproject/logger" "^5.7.0" 136 | "@ethersproject/properties" "^5.7.0" 137 | "@ethersproject/strings" "^5.7.0" 138 | 139 | "@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": 140 | version "5.7.0" 141 | resolved "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz" 142 | integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== 143 | dependencies: 144 | "@ethersproject/abstract-signer" "^5.7.0" 145 | "@ethersproject/basex" "^5.7.0" 146 | "@ethersproject/bignumber" "^5.7.0" 147 | "@ethersproject/bytes" "^5.7.0" 148 | "@ethersproject/logger" "^5.7.0" 149 | "@ethersproject/pbkdf2" "^5.7.0" 150 | "@ethersproject/properties" "^5.7.0" 151 | "@ethersproject/sha2" "^5.7.0" 152 | "@ethersproject/signing-key" "^5.7.0" 153 | "@ethersproject/strings" "^5.7.0" 154 | "@ethersproject/transactions" "^5.7.0" 155 | "@ethersproject/wordlists" "^5.7.0" 156 | 157 | "@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": 158 | version "5.7.0" 159 | resolved "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz" 160 | integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== 161 | dependencies: 162 | "@ethersproject/abstract-signer" "^5.7.0" 163 | "@ethersproject/address" "^5.7.0" 164 | "@ethersproject/bytes" "^5.7.0" 165 | "@ethersproject/hdnode" "^5.7.0" 166 | "@ethersproject/keccak256" "^5.7.0" 167 | "@ethersproject/logger" "^5.7.0" 168 | "@ethersproject/pbkdf2" "^5.7.0" 169 | "@ethersproject/properties" "^5.7.0" 170 | "@ethersproject/random" "^5.7.0" 171 | "@ethersproject/strings" "^5.7.0" 172 | "@ethersproject/transactions" "^5.7.0" 173 | aes-js "3.0.0" 174 | scrypt-js "3.0.1" 175 | 176 | "@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": 177 | version "5.7.0" 178 | resolved "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" 179 | integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== 180 | dependencies: 181 | "@ethersproject/bytes" "^5.7.0" 182 | js-sha3 "0.8.0" 183 | 184 | "@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": 185 | version "5.7.0" 186 | resolved "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" 187 | integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== 188 | 189 | "@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": 190 | version "5.7.1" 191 | resolved "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" 192 | integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== 193 | dependencies: 194 | "@ethersproject/logger" "^5.7.0" 195 | 196 | "@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": 197 | version "5.7.0" 198 | resolved "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz" 199 | integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== 200 | dependencies: 201 | "@ethersproject/bytes" "^5.7.0" 202 | "@ethersproject/sha2" "^5.7.0" 203 | 204 | "@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": 205 | version "5.7.0" 206 | resolved "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" 207 | integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== 208 | dependencies: 209 | "@ethersproject/logger" "^5.7.0" 210 | 211 | "@ethersproject/providers@5.7.2": 212 | version "5.7.2" 213 | resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz" 214 | integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== 215 | dependencies: 216 | "@ethersproject/abstract-provider" "^5.7.0" 217 | "@ethersproject/abstract-signer" "^5.7.0" 218 | "@ethersproject/address" "^5.7.0" 219 | "@ethersproject/base64" "^5.7.0" 220 | "@ethersproject/basex" "^5.7.0" 221 | "@ethersproject/bignumber" "^5.7.0" 222 | "@ethersproject/bytes" "^5.7.0" 223 | "@ethersproject/constants" "^5.7.0" 224 | "@ethersproject/hash" "^5.7.0" 225 | "@ethersproject/logger" "^5.7.0" 226 | "@ethersproject/networks" "^5.7.0" 227 | "@ethersproject/properties" "^5.7.0" 228 | "@ethersproject/random" "^5.7.0" 229 | "@ethersproject/rlp" "^5.7.0" 230 | "@ethersproject/sha2" "^5.7.0" 231 | "@ethersproject/strings" "^5.7.0" 232 | "@ethersproject/transactions" "^5.7.0" 233 | "@ethersproject/web" "^5.7.0" 234 | bech32 "1.1.4" 235 | ws "7.4.6" 236 | 237 | "@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": 238 | version "5.7.0" 239 | resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz" 240 | integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== 241 | dependencies: 242 | "@ethersproject/bytes" "^5.7.0" 243 | "@ethersproject/logger" "^5.7.0" 244 | 245 | "@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": 246 | version "5.7.0" 247 | resolved "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" 248 | integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== 249 | dependencies: 250 | "@ethersproject/bytes" "^5.7.0" 251 | "@ethersproject/logger" "^5.7.0" 252 | 253 | "@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": 254 | version "5.7.0" 255 | resolved "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz" 256 | integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== 257 | dependencies: 258 | "@ethersproject/bytes" "^5.7.0" 259 | "@ethersproject/logger" "^5.7.0" 260 | hash.js "1.1.7" 261 | 262 | "@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": 263 | version "5.7.0" 264 | resolved "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" 265 | integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== 266 | dependencies: 267 | "@ethersproject/bytes" "^5.7.0" 268 | "@ethersproject/logger" "^5.7.0" 269 | "@ethersproject/properties" "^5.7.0" 270 | bn.js "^5.2.1" 271 | elliptic "6.5.4" 272 | hash.js "1.1.7" 273 | 274 | "@ethersproject/solidity@5.7.0": 275 | version "5.7.0" 276 | resolved "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz" 277 | integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== 278 | dependencies: 279 | "@ethersproject/bignumber" "^5.7.0" 280 | "@ethersproject/bytes" "^5.7.0" 281 | "@ethersproject/keccak256" "^5.7.0" 282 | "@ethersproject/logger" "^5.7.0" 283 | "@ethersproject/sha2" "^5.7.0" 284 | "@ethersproject/strings" "^5.7.0" 285 | 286 | "@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": 287 | version "5.7.0" 288 | resolved "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" 289 | integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== 290 | dependencies: 291 | "@ethersproject/bytes" "^5.7.0" 292 | "@ethersproject/constants" "^5.7.0" 293 | "@ethersproject/logger" "^5.7.0" 294 | 295 | "@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": 296 | version "5.7.0" 297 | resolved "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" 298 | integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== 299 | dependencies: 300 | "@ethersproject/address" "^5.7.0" 301 | "@ethersproject/bignumber" "^5.7.0" 302 | "@ethersproject/bytes" "^5.7.0" 303 | "@ethersproject/constants" "^5.7.0" 304 | "@ethersproject/keccak256" "^5.7.0" 305 | "@ethersproject/logger" "^5.7.0" 306 | "@ethersproject/properties" "^5.7.0" 307 | "@ethersproject/rlp" "^5.7.0" 308 | "@ethersproject/signing-key" "^5.7.0" 309 | 310 | "@ethersproject/units@5.7.0": 311 | version "5.7.0" 312 | resolved "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz" 313 | integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== 314 | dependencies: 315 | "@ethersproject/bignumber" "^5.7.0" 316 | "@ethersproject/constants" "^5.7.0" 317 | "@ethersproject/logger" "^5.7.0" 318 | 319 | "@ethersproject/wallet@5.7.0": 320 | version "5.7.0" 321 | resolved "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz" 322 | integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== 323 | dependencies: 324 | "@ethersproject/abstract-provider" "^5.7.0" 325 | "@ethersproject/abstract-signer" "^5.7.0" 326 | "@ethersproject/address" "^5.7.0" 327 | "@ethersproject/bignumber" "^5.7.0" 328 | "@ethersproject/bytes" "^5.7.0" 329 | "@ethersproject/hash" "^5.7.0" 330 | "@ethersproject/hdnode" "^5.7.0" 331 | "@ethersproject/json-wallets" "^5.7.0" 332 | "@ethersproject/keccak256" "^5.7.0" 333 | "@ethersproject/logger" "^5.7.0" 334 | "@ethersproject/properties" "^5.7.0" 335 | "@ethersproject/random" "^5.7.0" 336 | "@ethersproject/signing-key" "^5.7.0" 337 | "@ethersproject/transactions" "^5.7.0" 338 | "@ethersproject/wordlists" "^5.7.0" 339 | 340 | "@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": 341 | version "5.7.1" 342 | resolved "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" 343 | integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== 344 | dependencies: 345 | "@ethersproject/base64" "^5.7.0" 346 | "@ethersproject/bytes" "^5.7.0" 347 | "@ethersproject/logger" "^5.7.0" 348 | "@ethersproject/properties" "^5.7.0" 349 | "@ethersproject/strings" "^5.7.0" 350 | 351 | "@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": 352 | version "5.7.0" 353 | resolved "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz" 354 | integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== 355 | dependencies: 356 | "@ethersproject/bytes" "^5.7.0" 357 | "@ethersproject/hash" "^5.7.0" 358 | "@ethersproject/logger" "^5.7.0" 359 | "@ethersproject/properties" "^5.7.0" 360 | "@ethersproject/strings" "^5.7.0" 361 | 362 | "@flashbots/ethers-provider-bundle@^0.5.0": 363 | version "0.5.0" 364 | resolved "https://registry.npmjs.org/@flashbots/ethers-provider-bundle/-/ethers-provider-bundle-0.5.0.tgz" 365 | integrity sha512-w7vc6aWDtgaHkDSgACjda0NoKYjOJ4mkr2av+u0NctvsoeNTg5dji65zeyU+98Fx3s6IbK0mfUTSGHAUtyt21A== 366 | dependencies: 367 | ts-node "^9.1.0" 368 | typescript "^4.1.2" 369 | 370 | "@humanwhocodes/config-array@^0.11.6": 371 | version "0.11.7" 372 | resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz" 373 | integrity sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw== 374 | dependencies: 375 | "@humanwhocodes/object-schema" "^1.2.1" 376 | debug "^4.1.1" 377 | minimatch "^3.0.5" 378 | 379 | "@humanwhocodes/module-importer@^1.0.1": 380 | version "1.0.1" 381 | resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" 382 | integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 383 | 384 | "@humanwhocodes/object-schema@^1.2.1": 385 | version "1.2.1" 386 | resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" 387 | integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== 388 | 389 | "@nodelib/fs.scandir@2.1.5": 390 | version "2.1.5" 391 | resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" 392 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 393 | dependencies: 394 | "@nodelib/fs.stat" "2.0.5" 395 | run-parallel "^1.1.9" 396 | 397 | "@nodelib/fs.stat@2.0.5": 398 | version "2.0.5" 399 | resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" 400 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 401 | 402 | "@nodelib/fs.walk@^1.2.8": 403 | version "1.2.8" 404 | resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" 405 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 406 | dependencies: 407 | "@nodelib/fs.scandir" "2.1.5" 408 | fastq "^1.6.0" 409 | 410 | "@solidity-parser/parser@^0.14.3": 411 | version "0.14.3" 412 | resolved "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.3.tgz" 413 | integrity sha512-29g2SZ29HtsqA58pLCtopI1P/cPy5/UAzlcAXO6T/CNJimG6yA8kx4NaseMyJULiC+TEs02Y9/yeHzClqoA0hw== 414 | dependencies: 415 | antlr4ts "^0.5.0-alpha.4" 416 | 417 | acorn-jsx@^5.3.2: 418 | version "5.3.2" 419 | resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" 420 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 421 | 422 | acorn@^8.8.0: 423 | version "8.8.1" 424 | resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz" 425 | integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== 426 | 427 | aes-js@3.0.0: 428 | version "3.0.0" 429 | resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" 430 | integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== 431 | 432 | ajv@^6.10.0, ajv@^6.12.4: 433 | version "6.12.6" 434 | resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" 435 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 436 | dependencies: 437 | fast-deep-equal "^3.1.1" 438 | fast-json-stable-stringify "^2.0.0" 439 | json-schema-traverse "^0.4.1" 440 | uri-js "^4.2.2" 441 | 442 | ansi-regex@^5.0.1: 443 | version "5.0.1" 444 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" 445 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 446 | 447 | ansi-styles@^4.1.0: 448 | version "4.3.0" 449 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" 450 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 451 | dependencies: 452 | color-convert "^2.0.1" 453 | 454 | antlr4ts@^0.5.0-alpha.4: 455 | version "0.5.0-alpha.4" 456 | resolved "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz" 457 | integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== 458 | 459 | arg@^4.1.0: 460 | version "4.1.3" 461 | resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" 462 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 463 | 464 | argparse@^2.0.1: 465 | version "2.0.1" 466 | resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 467 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 468 | 469 | balanced-match@^1.0.0: 470 | version "1.0.2" 471 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" 472 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 473 | 474 | base64-js@^1.3.1: 475 | version "1.5.1" 476 | resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" 477 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 478 | 479 | bech32@1.1.4: 480 | version "1.1.4" 481 | resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" 482 | integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== 483 | 484 | bn.js@^4.11.9: 485 | version "4.12.0" 486 | resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" 487 | integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== 488 | 489 | bn.js@^5.2.0, bn.js@^5.2.1: 490 | version "5.2.1" 491 | resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" 492 | integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== 493 | 494 | brace-expansion@^1.1.7: 495 | version "1.1.11" 496 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" 497 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 498 | dependencies: 499 | balanced-match "^1.0.0" 500 | concat-map "0.0.1" 501 | 502 | brorand@^1.1.0: 503 | version "1.1.0" 504 | resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" 505 | integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== 506 | 507 | buffer-from@^1.0.0: 508 | version "1.1.2" 509 | resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" 510 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 511 | 512 | buffer@^6.0.3: 513 | version "6.0.3" 514 | resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" 515 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 516 | dependencies: 517 | base64-js "^1.3.1" 518 | ieee754 "^1.2.1" 519 | 520 | callsites@^3.0.0: 521 | version "3.1.0" 522 | resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" 523 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 524 | 525 | chalk@^4.0.0: 526 | version "4.1.2" 527 | resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" 528 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 529 | dependencies: 530 | ansi-styles "^4.1.0" 531 | supports-color "^7.1.0" 532 | 533 | color-convert@^2.0.1: 534 | version "2.0.1" 535 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" 536 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 537 | dependencies: 538 | color-name "~1.1.4" 539 | 540 | color-name@~1.1.4: 541 | version "1.1.4" 542 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" 543 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 544 | 545 | concat-map@0.0.1: 546 | version "0.0.1" 547 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 548 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 549 | 550 | create-require@^1.1.0: 551 | version "1.1.1" 552 | resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" 553 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 554 | 555 | cross-spawn@^7.0.2: 556 | version "7.0.3" 557 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" 558 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 559 | dependencies: 560 | path-key "^3.1.0" 561 | shebang-command "^2.0.0" 562 | which "^2.0.1" 563 | 564 | debug@^4.1.1, debug@^4.3.2: 565 | version "4.3.4" 566 | resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" 567 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 568 | dependencies: 569 | ms "2.1.2" 570 | 571 | deep-is@^0.1.3: 572 | version "0.1.4" 573 | resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" 574 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 575 | 576 | diff@^4.0.1: 577 | version "4.0.2" 578 | resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" 579 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 580 | 581 | doctrine@^3.0.0: 582 | version "3.0.0" 583 | resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" 584 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 585 | dependencies: 586 | esutils "^2.0.2" 587 | 588 | dotenv@^16.0.3: 589 | version "16.0.3" 590 | resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz" 591 | integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== 592 | 593 | easy-multicall@^1.2.0: 594 | version "1.2.0" 595 | resolved "https://registry.npmjs.org/easy-multicall/-/easy-multicall-1.2.0.tgz" 596 | integrity sha512-0lgLo11PdTHoXqfAbTE7bVsDqKuLZTYsQJtkYKmTenBW/cqbaoiUJUSleDFqlxYOsaV25sxUfAH1uyohNNrsUw== 597 | dependencies: 598 | ethers "^5.4.7" 599 | 600 | elliptic@6.5.4: 601 | version "6.5.4" 602 | resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" 603 | integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== 604 | dependencies: 605 | bn.js "^4.11.9" 606 | brorand "^1.1.0" 607 | hash.js "^1.0.0" 608 | hmac-drbg "^1.0.1" 609 | inherits "^2.0.4" 610 | minimalistic-assert "^1.0.1" 611 | minimalistic-crypto-utils "^1.0.1" 612 | 613 | emoji-regex@^10.1.0: 614 | version "10.1.0" 615 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.1.0.tgz" 616 | integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== 617 | 618 | emoji-regex@^8.0.0: 619 | version "8.0.0" 620 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" 621 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 622 | 623 | escape-string-regexp@^4.0.0: 624 | version "4.0.0" 625 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" 626 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 627 | 628 | eslint-plugin-prettier@^4.2.1: 629 | version "4.2.1" 630 | resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz" 631 | integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== 632 | dependencies: 633 | prettier-linter-helpers "^1.0.0" 634 | 635 | eslint-scope@^7.1.1: 636 | version "7.1.1" 637 | resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz" 638 | integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== 639 | dependencies: 640 | esrecurse "^4.3.0" 641 | estraverse "^5.2.0" 642 | 643 | eslint-utils@^3.0.0: 644 | version "3.0.0" 645 | resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" 646 | integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== 647 | dependencies: 648 | eslint-visitor-keys "^2.0.0" 649 | 650 | eslint-visitor-keys@^2.0.0: 651 | version "2.1.0" 652 | resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" 653 | integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== 654 | 655 | eslint-visitor-keys@^3.3.0: 656 | version "3.3.0" 657 | resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz" 658 | integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== 659 | 660 | eslint@^8.26.0: 661 | version "8.26.0" 662 | resolved "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz" 663 | integrity sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg== 664 | dependencies: 665 | "@eslint/eslintrc" "^1.3.3" 666 | "@humanwhocodes/config-array" "^0.11.6" 667 | "@humanwhocodes/module-importer" "^1.0.1" 668 | "@nodelib/fs.walk" "^1.2.8" 669 | ajv "^6.10.0" 670 | chalk "^4.0.0" 671 | cross-spawn "^7.0.2" 672 | debug "^4.3.2" 673 | doctrine "^3.0.0" 674 | escape-string-regexp "^4.0.0" 675 | eslint-scope "^7.1.1" 676 | eslint-utils "^3.0.0" 677 | eslint-visitor-keys "^3.3.0" 678 | espree "^9.4.0" 679 | esquery "^1.4.0" 680 | esutils "^2.0.2" 681 | fast-deep-equal "^3.1.3" 682 | file-entry-cache "^6.0.1" 683 | find-up "^5.0.0" 684 | glob-parent "^6.0.2" 685 | globals "^13.15.0" 686 | grapheme-splitter "^1.0.4" 687 | ignore "^5.2.0" 688 | import-fresh "^3.0.0" 689 | imurmurhash "^0.1.4" 690 | is-glob "^4.0.0" 691 | is-path-inside "^3.0.3" 692 | js-sdsl "^4.1.4" 693 | js-yaml "^4.1.0" 694 | json-stable-stringify-without-jsonify "^1.0.1" 695 | levn "^0.4.1" 696 | lodash.merge "^4.6.2" 697 | minimatch "^3.1.2" 698 | natural-compare "^1.4.0" 699 | optionator "^0.9.1" 700 | regexpp "^3.2.0" 701 | strip-ansi "^6.0.1" 702 | strip-json-comments "^3.1.0" 703 | text-table "^0.2.0" 704 | 705 | espree@^9.4.0: 706 | version "9.4.0" 707 | resolved "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz" 708 | integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== 709 | dependencies: 710 | acorn "^8.8.0" 711 | acorn-jsx "^5.3.2" 712 | eslint-visitor-keys "^3.3.0" 713 | 714 | esquery@^1.4.0: 715 | version "1.4.0" 716 | resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" 717 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 718 | dependencies: 719 | estraverse "^5.1.0" 720 | 721 | esrecurse@^4.3.0: 722 | version "4.3.0" 723 | resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" 724 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 725 | dependencies: 726 | estraverse "^5.2.0" 727 | 728 | estraverse@^5.1.0, estraverse@^5.2.0: 729 | version "5.3.0" 730 | resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" 731 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 732 | 733 | esutils@^2.0.2: 734 | version "2.0.3" 735 | resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" 736 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 737 | 738 | ethers@^5.4.7, ethers@^5.7.2: 739 | version "5.7.2" 740 | resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz" 741 | integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== 742 | dependencies: 743 | "@ethersproject/abi" "5.7.0" 744 | "@ethersproject/abstract-provider" "5.7.0" 745 | "@ethersproject/abstract-signer" "5.7.0" 746 | "@ethersproject/address" "5.7.0" 747 | "@ethersproject/base64" "5.7.0" 748 | "@ethersproject/basex" "5.7.0" 749 | "@ethersproject/bignumber" "5.7.0" 750 | "@ethersproject/bytes" "5.7.0" 751 | "@ethersproject/constants" "5.7.0" 752 | "@ethersproject/contracts" "5.7.0" 753 | "@ethersproject/hash" "5.7.0" 754 | "@ethersproject/hdnode" "5.7.0" 755 | "@ethersproject/json-wallets" "5.7.0" 756 | "@ethersproject/keccak256" "5.7.0" 757 | "@ethersproject/logger" "5.7.0" 758 | "@ethersproject/networks" "5.7.1" 759 | "@ethersproject/pbkdf2" "5.7.0" 760 | "@ethersproject/properties" "5.7.0" 761 | "@ethersproject/providers" "5.7.2" 762 | "@ethersproject/random" "5.7.0" 763 | "@ethersproject/rlp" "5.7.0" 764 | "@ethersproject/sha2" "5.7.0" 765 | "@ethersproject/signing-key" "5.7.0" 766 | "@ethersproject/solidity" "5.7.0" 767 | "@ethersproject/strings" "5.7.0" 768 | "@ethersproject/transactions" "5.7.0" 769 | "@ethersproject/units" "5.7.0" 770 | "@ethersproject/wallet" "5.7.0" 771 | "@ethersproject/web" "5.7.1" 772 | "@ethersproject/wordlists" "5.7.0" 773 | 774 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 775 | version "3.1.3" 776 | resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" 777 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 778 | 779 | fast-diff@^1.1.2: 780 | version "1.2.0" 781 | resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" 782 | integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== 783 | 784 | fast-json-stable-stringify@^2.0.0: 785 | version "2.1.0" 786 | resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" 787 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 788 | 789 | fast-levenshtein@^2.0.6: 790 | version "2.0.6" 791 | resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" 792 | integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 793 | 794 | fastq@^1.6.0: 795 | version "1.13.0" 796 | resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" 797 | integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== 798 | dependencies: 799 | reusify "^1.0.4" 800 | 801 | file-entry-cache@^6.0.1: 802 | version "6.0.1" 803 | resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" 804 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 805 | dependencies: 806 | flat-cache "^3.0.4" 807 | 808 | find-up@^5.0.0: 809 | version "5.0.0" 810 | resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" 811 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 812 | dependencies: 813 | locate-path "^6.0.0" 814 | path-exists "^4.0.0" 815 | 816 | flat-cache@^3.0.4: 817 | version "3.0.4" 818 | resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" 819 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== 820 | dependencies: 821 | flatted "^3.1.0" 822 | rimraf "^3.0.2" 823 | 824 | flatted@^3.1.0: 825 | version "3.2.7" 826 | resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" 827 | integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== 828 | 829 | fs.realpath@^1.0.0: 830 | version "1.0.0" 831 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" 832 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 833 | 834 | glob-parent@^6.0.2: 835 | version "6.0.2" 836 | resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" 837 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 838 | dependencies: 839 | is-glob "^4.0.3" 840 | 841 | glob@^7.1.3: 842 | version "7.2.3" 843 | resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" 844 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 845 | dependencies: 846 | fs.realpath "^1.0.0" 847 | inflight "^1.0.4" 848 | inherits "2" 849 | minimatch "^3.1.1" 850 | once "^1.3.0" 851 | path-is-absolute "^1.0.0" 852 | 853 | globals@^13.15.0: 854 | version "13.17.0" 855 | resolved "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz" 856 | integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== 857 | dependencies: 858 | type-fest "^0.20.2" 859 | 860 | grapheme-splitter@^1.0.4: 861 | version "1.0.4" 862 | resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz" 863 | integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== 864 | 865 | has-flag@^4.0.0: 866 | version "4.0.0" 867 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" 868 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 869 | 870 | hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: 871 | version "1.1.7" 872 | resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" 873 | integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== 874 | dependencies: 875 | inherits "^2.0.3" 876 | minimalistic-assert "^1.0.1" 877 | 878 | hmac-drbg@^1.0.1: 879 | version "1.0.1" 880 | resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" 881 | integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== 882 | dependencies: 883 | hash.js "^1.0.3" 884 | minimalistic-assert "^1.0.0" 885 | minimalistic-crypto-utils "^1.0.1" 886 | 887 | ieee754@^1.2.1: 888 | version "1.2.1" 889 | resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" 890 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 891 | 892 | ignore@^5.2.0: 893 | version "5.2.0" 894 | resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" 895 | integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== 896 | 897 | import-fresh@^3.0.0, import-fresh@^3.2.1: 898 | version "3.3.0" 899 | resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" 900 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 901 | dependencies: 902 | parent-module "^1.0.0" 903 | resolve-from "^4.0.0" 904 | 905 | imurmurhash@^0.1.4: 906 | version "0.1.4" 907 | resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" 908 | integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 909 | 910 | inflight@^1.0.4: 911 | version "1.0.6" 912 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" 913 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 914 | dependencies: 915 | once "^1.3.0" 916 | wrappy "1" 917 | 918 | inherits@2, inherits@^2.0.3, inherits@^2.0.4: 919 | version "2.0.4" 920 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 921 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 922 | 923 | is-extglob@^2.1.1: 924 | version "2.1.1" 925 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" 926 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 927 | 928 | is-fullwidth-code-point@^3.0.0: 929 | version "3.0.0" 930 | resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" 931 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 932 | 933 | is-glob@^4.0.0, is-glob@^4.0.3: 934 | version "4.0.3" 935 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" 936 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 937 | dependencies: 938 | is-extglob "^2.1.1" 939 | 940 | is-path-inside@^3.0.3: 941 | version "3.0.3" 942 | resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" 943 | integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== 944 | 945 | isexe@^2.0.0: 946 | version "2.0.0" 947 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" 948 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 949 | 950 | js-sdsl@^4.1.4: 951 | version "4.1.5" 952 | resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz" 953 | integrity sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q== 954 | 955 | js-sha3@0.8.0: 956 | version "0.8.0" 957 | resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" 958 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== 959 | 960 | js-yaml@^4.1.0: 961 | version "4.1.0" 962 | resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" 963 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 964 | dependencies: 965 | argparse "^2.0.1" 966 | 967 | json-schema-traverse@^0.4.1: 968 | version "0.4.1" 969 | resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" 970 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 971 | 972 | json-stable-stringify-without-jsonify@^1.0.1: 973 | version "1.0.1" 974 | resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" 975 | integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 976 | 977 | keccak256@^1.0.6: 978 | version "1.0.6" 979 | resolved "https://registry.npmjs.org/keccak256/-/keccak256-1.0.6.tgz" 980 | integrity sha512-8GLiM01PkdJVGUhR1e6M/AvWnSqYS0HaERI+K/QtStGDGlSTx2B1zTqZk4Zlqu5TxHJNTxWAdP9Y+WI50OApUw== 981 | dependencies: 982 | bn.js "^5.2.0" 983 | buffer "^6.0.3" 984 | keccak "^3.0.2" 985 | 986 | keccak@^3.0.2: 987 | version "3.0.2" 988 | resolved "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz" 989 | integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== 990 | dependencies: 991 | node-addon-api "^2.0.0" 992 | node-gyp-build "^4.2.0" 993 | readable-stream "^3.6.0" 994 | 995 | levn@^0.4.1: 996 | version "0.4.1" 997 | resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" 998 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 999 | dependencies: 1000 | prelude-ls "^1.2.1" 1001 | type-check "~0.4.0" 1002 | 1003 | locate-path@^6.0.0: 1004 | version "6.0.0" 1005 | resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" 1006 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1007 | dependencies: 1008 | p-locate "^5.0.0" 1009 | 1010 | lodash.merge@^4.6.2: 1011 | version "4.6.2" 1012 | resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" 1013 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 1014 | 1015 | lodash@^4.17.21: 1016 | version "4.17.21" 1017 | resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 1018 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1019 | 1020 | lru-cache@^6.0.0: 1021 | version "6.0.0" 1022 | resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" 1023 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 1024 | dependencies: 1025 | yallist "^4.0.0" 1026 | 1027 | make-error@^1.1.1: 1028 | version "1.3.6" 1029 | resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" 1030 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 1031 | 1032 | minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: 1033 | version "1.0.1" 1034 | resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" 1035 | integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== 1036 | 1037 | minimalistic-crypto-utils@^1.0.1: 1038 | version "1.0.1" 1039 | resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" 1040 | integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== 1041 | 1042 | minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: 1043 | version "3.1.2" 1044 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" 1045 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1046 | dependencies: 1047 | brace-expansion "^1.1.7" 1048 | 1049 | ms@2.1.2: 1050 | version "2.1.2" 1051 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" 1052 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1053 | 1054 | natural-compare@^1.4.0: 1055 | version "1.4.0" 1056 | resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" 1057 | integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 1058 | 1059 | node-addon-api@^2.0.0: 1060 | version "2.0.2" 1061 | resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" 1062 | integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== 1063 | 1064 | node-gyp-build@^4.2.0: 1065 | version "4.5.0" 1066 | resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz" 1067 | integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== 1068 | 1069 | once@^1.3.0: 1070 | version "1.4.0" 1071 | resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" 1072 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1073 | dependencies: 1074 | wrappy "1" 1075 | 1076 | optionator@^0.9.1: 1077 | version "0.9.1" 1078 | resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" 1079 | integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== 1080 | dependencies: 1081 | deep-is "^0.1.3" 1082 | fast-levenshtein "^2.0.6" 1083 | levn "^0.4.1" 1084 | prelude-ls "^1.2.1" 1085 | type-check "^0.4.0" 1086 | word-wrap "^1.2.3" 1087 | 1088 | p-limit@^3.0.2: 1089 | version "3.1.0" 1090 | resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" 1091 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1092 | dependencies: 1093 | yocto-queue "^0.1.0" 1094 | 1095 | p-locate@^5.0.0: 1096 | version "5.0.0" 1097 | resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" 1098 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1099 | dependencies: 1100 | p-limit "^3.0.2" 1101 | 1102 | parent-module@^1.0.0: 1103 | version "1.0.1" 1104 | resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" 1105 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1106 | dependencies: 1107 | callsites "^3.0.0" 1108 | 1109 | path-exists@^4.0.0: 1110 | version "4.0.0" 1111 | resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" 1112 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1113 | 1114 | path-is-absolute@^1.0.0: 1115 | version "1.0.1" 1116 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 1117 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1118 | 1119 | path-key@^3.1.0: 1120 | version "3.1.1" 1121 | resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" 1122 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1123 | 1124 | prelude-ls@^1.2.1: 1125 | version "1.2.1" 1126 | resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" 1127 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1128 | 1129 | prettier-linter-helpers@^1.0.0: 1130 | version "1.0.0" 1131 | resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" 1132 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 1133 | dependencies: 1134 | fast-diff "^1.1.2" 1135 | 1136 | prettier-plugin-solidity@^1.0.0-beta.24: 1137 | version "1.0.0-beta.24" 1138 | resolved "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.24.tgz" 1139 | integrity sha512-6JlV5BBTWzmDSq4kZ9PTXc3eLOX7DF5HpbqmmaF+kloyUwOZbJ12hIYsUaZh2fVgZdV2t0vWcvY6qhILhlzgqg== 1140 | dependencies: 1141 | "@solidity-parser/parser" "^0.14.3" 1142 | emoji-regex "^10.1.0" 1143 | escape-string-regexp "^4.0.0" 1144 | semver "^7.3.7" 1145 | solidity-comments-extractor "^0.0.7" 1146 | string-width "^4.2.3" 1147 | 1148 | prettier@^2.7.1: 1149 | version "2.7.1" 1150 | resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz" 1151 | integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== 1152 | 1153 | punycode@^2.1.0: 1154 | version "2.1.1" 1155 | resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" 1156 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1157 | 1158 | queue-microtask@^1.2.2: 1159 | version "1.2.3" 1160 | resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" 1161 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 1162 | 1163 | readable-stream@^3.6.0: 1164 | version "3.6.0" 1165 | resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" 1166 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 1167 | dependencies: 1168 | inherits "^2.0.3" 1169 | string_decoder "^1.1.1" 1170 | util-deprecate "^1.0.1" 1171 | 1172 | regexpp@^3.2.0: 1173 | version "3.2.0" 1174 | resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" 1175 | integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== 1176 | 1177 | resolve-from@^4.0.0: 1178 | version "4.0.0" 1179 | resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" 1180 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1181 | 1182 | reusify@^1.0.4: 1183 | version "1.0.4" 1184 | resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" 1185 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1186 | 1187 | rimraf@^3.0.2: 1188 | version "3.0.2" 1189 | resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" 1190 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1191 | dependencies: 1192 | glob "^7.1.3" 1193 | 1194 | rlp@^3.0.0: 1195 | version "3.0.0" 1196 | resolved "https://registry.npmjs.org/rlp/-/rlp-3.0.0.tgz" 1197 | integrity sha512-PD6U2PGk6Vq2spfgiWZdomLvRGDreBLxi5jv5M8EpRo3pU6VEm31KO+HFxE18Q3vgqfDrQ9pZA3FP95rkijNKw== 1198 | 1199 | run-parallel@^1.1.9: 1200 | version "1.2.0" 1201 | resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" 1202 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1203 | dependencies: 1204 | queue-microtask "^1.2.2" 1205 | 1206 | safe-buffer@~5.2.0: 1207 | version "5.2.1" 1208 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" 1209 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1210 | 1211 | scrypt-js@3.0.1: 1212 | version "3.0.1" 1213 | resolved "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" 1214 | integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== 1215 | 1216 | semver@^7.3.7: 1217 | version "7.3.7" 1218 | resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" 1219 | integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== 1220 | dependencies: 1221 | lru-cache "^6.0.0" 1222 | 1223 | shebang-command@^2.0.0: 1224 | version "2.0.0" 1225 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" 1226 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1227 | dependencies: 1228 | shebang-regex "^3.0.0" 1229 | 1230 | shebang-regex@^3.0.0: 1231 | version "3.0.0" 1232 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" 1233 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1234 | 1235 | solidity-comments-extractor@^0.0.7: 1236 | version "0.0.7" 1237 | resolved "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz" 1238 | integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== 1239 | 1240 | source-map-support@^0.5.17: 1241 | version "0.5.21" 1242 | resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" 1243 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1244 | dependencies: 1245 | buffer-from "^1.0.0" 1246 | source-map "^0.6.0" 1247 | 1248 | source-map@^0.6.0: 1249 | version "0.6.1" 1250 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" 1251 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1252 | 1253 | string-width@^4.2.3: 1254 | version "4.2.3" 1255 | resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" 1256 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1257 | dependencies: 1258 | emoji-regex "^8.0.0" 1259 | is-fullwidth-code-point "^3.0.0" 1260 | strip-ansi "^6.0.1" 1261 | 1262 | string_decoder@^1.1.1: 1263 | version "1.3.0" 1264 | resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" 1265 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 1266 | dependencies: 1267 | safe-buffer "~5.2.0" 1268 | 1269 | strip-ansi@^6.0.1: 1270 | version "6.0.1" 1271 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" 1272 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1273 | dependencies: 1274 | ansi-regex "^5.0.1" 1275 | 1276 | strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: 1277 | version "3.1.1" 1278 | resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" 1279 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1280 | 1281 | supports-color@^7.1.0: 1282 | version "7.2.0" 1283 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" 1284 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1285 | dependencies: 1286 | has-flag "^4.0.0" 1287 | 1288 | text-table@^0.2.0: 1289 | version "0.2.0" 1290 | resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" 1291 | integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== 1292 | 1293 | ts-node@^9.1.0: 1294 | version "9.1.1" 1295 | resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz" 1296 | integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== 1297 | dependencies: 1298 | arg "^4.1.0" 1299 | create-require "^1.1.0" 1300 | diff "^4.0.1" 1301 | make-error "^1.1.1" 1302 | source-map-support "^0.5.17" 1303 | yn "3.1.1" 1304 | 1305 | type-check@^0.4.0, type-check@~0.4.0: 1306 | version "0.4.0" 1307 | resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" 1308 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1309 | dependencies: 1310 | prelude-ls "^1.2.1" 1311 | 1312 | type-fest@^0.20.2: 1313 | version "0.20.2" 1314 | resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" 1315 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 1316 | 1317 | typescript@^4.1.2: 1318 | version "4.8.4" 1319 | resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz" 1320 | integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== 1321 | 1322 | uri-js@^4.2.2: 1323 | version "4.4.1" 1324 | resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" 1325 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1326 | dependencies: 1327 | punycode "^2.1.0" 1328 | 1329 | util-deprecate@^1.0.1: 1330 | version "1.0.2" 1331 | resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" 1332 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1333 | 1334 | which@^2.0.1: 1335 | version "2.0.2" 1336 | resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" 1337 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1338 | dependencies: 1339 | isexe "^2.0.0" 1340 | 1341 | word-wrap@^1.2.3: 1342 | version "1.2.3" 1343 | resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" 1344 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1345 | 1346 | wrappy@1: 1347 | version "1.0.2" 1348 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 1349 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1350 | 1351 | ws@7.4.6: 1352 | version "7.4.6" 1353 | resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" 1354 | integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== 1355 | 1356 | yallist@^4.0.0: 1357 | version "4.0.0" 1358 | resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" 1359 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1360 | 1361 | yn@3.1.1: 1362 | version "3.1.1" 1363 | resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" 1364 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1365 | 1366 | yocto-queue@^0.1.0: 1367 | version "0.1.0" 1368 | resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" 1369 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1370 | --------------------------------------------------------------------------------