From fd88b1f4ce27c82ea66e5e904ee68ce209dd6ebd Mon Sep 17 00:00:00 2001 From: nigiri <168690269+0xnigir1@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:06:06 -0300 Subject: [PATCH] refactor: l1 tvl multicall fetch (#40) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # 🤖 Linear Closes ZKS-146 ## Description Replace current impl. of fetching token balances using virtual batching contract with `Multicall` contract Delete contracts and files related to old implementation. Delete foundry related deps and configuration since it's no longer required --- .github/actions/setup/action.yml | 3 - .github/workflows/lint.yml | 3 - .solhint.json | 17 -- .solhint.tests.json | 21 --- contracts/foundry.toml | 19 --- contracts/remappings.txt | 4 - contracts/src/contracts/TokenBalances.sol | 50 ------ contracts/src/interfaces/IERC20.sol | 9 -- contracts/test/TokenBalances.t.sol | 100 ------------ libs/metrics/src/l1/abis/tokenBalances.abi.ts | 14 -- libs/metrics/src/l1/bytecode/index.ts | 2 - libs/metrics/src/l1/l1MetricsService.ts | 35 ++-- .../test/unit/l1/l1MetricsService.spec.ts | 48 +++--- package.json | 14 +- pnpm-lock.yaml | 149 ------------------ 15 files changed, 47 insertions(+), 441 deletions(-) delete mode 100644 .solhint.json delete mode 100644 .solhint.tests.json delete mode 100644 contracts/foundry.toml delete mode 100644 contracts/remappings.txt delete mode 100644 contracts/src/contracts/TokenBalances.sol delete mode 100644 contracts/src/interfaces/IERC20.sol delete mode 100644 contracts/test/TokenBalances.t.sol delete mode 100644 libs/metrics/src/l1/abis/tokenBalances.abi.ts delete mode 100644 libs/metrics/src/l1/bytecode/index.ts diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 4b8573f..7409e3f 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -14,6 +14,3 @@ runs: with: node-version: 20 cache: "pnpm" - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0506b79..8f3c752 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -33,6 +33,3 @@ jobs: - name: Run Linter run: pnpm lint - - - name: Run Contracts Linter - run: pnpm lint:contracts:check diff --git a/.solhint.json b/.solhint.json deleted file mode 100644 index f53704f..0000000 --- a/.solhint.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["off"], - "constructor-syntax": "warn", - "quotes": ["error", "single"], - "func-visibility": ["warn", { "ignoreConstructors": true }], - "not-rely-on-time": "off", - "no-inline-assembly": "off", - "no-empty-blocks": "off", - "private-vars-leading-underscore": ["warn", { "strict": false }], - "ordering": "warn", - "avoid-low-level-calls": "off", - "no-console": "off", - "max-line-length": ["warn", 120] - } -} diff --git a/.solhint.tests.json b/.solhint.tests.json deleted file mode 100644 index 669c498..0000000 --- a/.solhint.tests.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["off"], - "constructor-syntax": "warn", - "quotes": ["error", "single"], - "func-visibility": ["warn", { "ignoreConstructors": true }], - "not-rely-on-time": "off", - "style-guide-casing": "off", - "no-inline-assembly": "off", - "no-empty-blocks": "error", - "named-parameters-function": "off", - "no-global-import": "off", - "max-states-count": "off", - "private-vars-leading-underscore": ["warn", { "strict": false }], - "ordering": "off", - "avoid-low-level-calls": "off", - "one-contract-per-file": "off", - "max-line-length": ["warn", 120] - } -} diff --git a/contracts/foundry.toml b/contracts/foundry.toml deleted file mode 100644 index f5ff150..0000000 --- a/contracts/foundry.toml +++ /dev/null @@ -1,19 +0,0 @@ -[fmt] -line_length = 120 -tab_width = 2 -bracket_spacing = false -int_types = 'long' -quote_style = 'single' -number_underscore = 'thousands' -multiline_func_header = 'params_first' -sort_imports = true - -[profile.default] -solc_version = '0.8.0' -optimizer=false -src = "src" -out = "out" -# This translates to `solc --allow-paths ../node_modules` -allow_paths = ["../node_modules"] - -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/contracts/remappings.txt b/contracts/remappings.txt deleted file mode 100644 index bc8690a..0000000 --- a/contracts/remappings.txt +++ /dev/null @@ -1,4 +0,0 @@ -forge-std/=../node_modules/forge-std/src/ - -contracts/=src/contracts -interfaces/=src/interfaces \ No newline at end of file diff --git a/contracts/src/contracts/TokenBalances.sol b/contracts/src/contracts/TokenBalances.sol deleted file mode 100644 index 0c02f61..0000000 --- a/contracts/src/contracts/TokenBalances.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.0; - -import {IERC20} from 'interfaces/IERC20.sol'; - -/** - * @title TokenBalances - * - * @dev This contract is not meant to be deployed. Instead, use a static call with the - * deployment bytecode as payload. - * - * @notice The purpose of this contract is to provide a mechanism for performing batch request - * for fetching the balances of multiple tokens and ether held by an address. - * - */ -contract TokenBalances { - /// @notice Returns the balance of the target contract for the specified tokens and ether - /// @param _targetAddress The target contract address to query balances - /// @param _tokenAddresses The token addresses - constructor(address _targetAddress, address[] memory _tokenAddresses) { - uint256 length = _tokenAddresses.length; - - // one additional element for the ether balance - uint256[] memory returnData = new uint256[](length + 1); - - uint256 i; //saves gas as default is 0 - while (i < length) { - IERC20 token = IERC20(_tokenAddresses[i]); - - uint256 balance = token.balanceOf(_targetAddress); - returnData[i] = balance; - - unchecked { - ++i; - } - } - returnData[i] = _targetAddress.balance; - - // encode return data - bytes memory data = abi.encode(returnData); - - // force constructor return via assembly - assembly { - // Return from the start of the data (discarding the original data address) - // up to the end of the memory used - let dataStart := add(data, 32) // abi.encode adds an additional offset - return(dataStart, sub(msize(), dataStart)) - } - } -} diff --git a/contracts/src/interfaces/IERC20.sol b/contracts/src/interfaces/IERC20.sol deleted file mode 100644 index 1dc54ec..0000000 --- a/contracts/src/interfaces/IERC20.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.0; - -interface IERC20 { - /** - * @dev Returns the value of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); -} diff --git a/contracts/test/TokenBalances.t.sol b/contracts/test/TokenBalances.t.sol deleted file mode 100644 index 8a53c29..0000000 --- a/contracts/test/TokenBalances.t.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.0; - -import {TokenBalances} from 'contracts/TokenBalances.sol'; -import {Test} from 'forge-std/Test.sol'; -import {IERC20} from 'interfaces/IERC20.sol'; - -contract TokenBalancesTest is Test { - address internal _target = makeAddr('target'); - IERC20 internal _tokenA = IERC20(makeAddr('tokenA')); - IERC20 internal _tokenB = IERC20(makeAddr('tokenB')); - uint256 internal _initialBalanceA = 100; - uint256 internal _initialBalanceB = 200; - address internal _deploymentAddress; - address[] internal _emptyArray; - - function setUp() public { - //based on the CREATE2 opcode's address derivation formula and Claude-AI chatting - _deploymentAddress = - address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), address(this), bytes1(0x01)))))); - } - - function test_fetchingTokenData() public { - vm.deal(_target, 10 ether); - vm.mockCall(address(_tokenA), abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(_initialBalanceA)); - vm.mockCall(address(_tokenB), abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(_initialBalanceB)); - address[] memory tokenAddresses = new address[](2); - tokenAddresses[0] = address(_tokenA); - tokenAddresses[1] = address(_tokenB); - - bytes memory creationCode = _getBytecode(_target, tokenAddresses); - - // We're using vm.etch to place the creation code at a deterministic address. - vm.etch(_deploymentAddress, creationCode); - - // simulate deployment - (bool success, bytes memory result) = _deploymentAddress.call(''); - - require(success, 'Deployment simulation failed'); - - uint256[] memory balances = abi.decode(result, (uint256[])); - - assertEq(balances.length, 3, 'Incorrect number of balances returned'); - assertEq(balances[0], _initialBalanceA, 'Incorrect balance for tokenA'); - assertEq(balances[1], _initialBalanceB, 'Incorrect balance for tokenB'); - assertEq(balances[2], 10 ether, 'Incorrect ether balance'); - } - - function test_fetchingEmptyTokenArray() public { - vm.deal(_target, 10 ether); - - bytes memory creationCode = _getBytecode(_target, _emptyArray); - - // We're using vm.etch to place the creation code at a deterministic address. - vm.etch(_deploymentAddress, creationCode); - - // simulate deployment - (bool success, bytes memory result) = _deploymentAddress.call(''); - - require(success, 'Deployment simulation failed'); - - uint256[] memory balances = abi.decode(result, (uint256[])); - - assertEq(balances.length, 1, 'Incorrect number of balances returned'); - assertEq(balances[0], 10 ether, 'Incorrect ether balance'); - } - - function test_revertWithNonERC20Token() public { - address nonERC20 = address(0x123); // Some address that's not an ERC20 token - - address[] memory tokenAddresses = new address[](3); - tokenAddresses[0] = address(_tokenA); - tokenAddresses[1] = nonERC20; - tokenAddresses[2] = address(_tokenB); - - // Mock calls for valid ERC20 tokens - vm.mockCall( - address(_tokenA), abi.encodeWithSelector(IERC20.balanceOf.selector, _target), abi.encode(_initialBalanceA) - ); - vm.mockCall( - address(_tokenB), abi.encodeWithSelector(IERC20.balanceOf.selector, _target), abi.encode(_initialBalanceB) - ); - - bytes memory creationCode = _getBytecode(_target, _emptyArray); - - // We're using vm.etch to place the creation code at a deterministic address. - vm.etch(_deploymentAddress, creationCode); - - // Expect the call to revert - vm.expectRevert(); - (bool success,) = _deploymentAddress.call(''); - - require(!success, 'Deployment should have reverted'); - } - - function _getBytecode(address target, address[] memory _tokenAddresses) internal pure returns (bytes memory) { - bytes memory bytecode = abi.encodePacked(type(TokenBalances).creationCode); - return abi.encodePacked(bytecode, abi.encode(target, _tokenAddresses)); - } -} diff --git a/libs/metrics/src/l1/abis/tokenBalances.abi.ts b/libs/metrics/src/l1/abis/tokenBalances.abi.ts deleted file mode 100644 index fc49859..0000000 --- a/libs/metrics/src/l1/abis/tokenBalances.abi.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const tokenBalancesAbi = [ - { - inputs: [ - { internalType: "address", name: "_targetAddress", type: "address" }, - { - internalType: "address[]", - name: "_tokenAddresses", - type: "address[]", - }, - ], - stateMutability: "nonpayable", - type: "constructor", - }, -] as const; diff --git a/libs/metrics/src/l1/bytecode/index.ts b/libs/metrics/src/l1/bytecode/index.ts deleted file mode 100644 index 3ef949c..0000000 --- a/libs/metrics/src/l1/bytecode/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const tokenBalancesBytecode = - "0x608060405234801561001057600080fd5b5060405161063538038061063583398181016040528101906100329190610332565b60008151905060006001826100479190610516565b67ffffffffffffffff811115610086577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156100b45781602001602082028036833780820191505090505b50905060005b828110156101e75760008482815181106100fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231886040518263ffffffff1660e01b81526004016101429190610443565b60206040518083038186803b15801561015a57600080fd5b505afa15801561016e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101929190610386565b9050808484815181106101ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101818152505082600101925050506100ba565b8473ffffffffffffffffffffffffffffffffffffffff1631828281518110610238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001018181525050600082604051602001610257919061045e565b60405160208183030381529060405290506020810180590381f35b6000610285610280846104b1565b610480565b905080838252602082019050828560208602820111156102a457600080fd5b60005b858110156102d457816102ba88826102de565b8452602084019350602083019250506001810190506102a7565b5050509392505050565b6000815190506102ed81610606565b92915050565b600082601f83011261030457600080fd5b8151610314848260208601610272565b91505092915050565b60008151905061032c8161061d565b92915050565b6000806040838503121561034557600080fd5b6000610353858286016102de565b925050602083015167ffffffffffffffff81111561037057600080fd5b61037c858286016102f3565b9150509250929050565b60006020828403121561039857600080fd5b60006103a68482850161031d565b91505092915050565b60006103bb8383610434565b60208301905092915050565b6103d08161056c565b82525050565b60006103e1826104ed565b6103eb8185610505565b93506103f6836104dd565b8060005b8381101561042757815161040e88826103af565b9750610419836104f8565b9250506001810190506103fa565b5085935050505092915050565b61043d8161059e565b82525050565b600060208201905061045860008301846103c7565b92915050565b6000602082019050818103600083015261047881846103d6565b905092915050565b6000604051905081810181811067ffffffffffffffff821117156104a7576104a66105d7565b5b8060405250919050565b600067ffffffffffffffff8211156104cc576104cb6105d7565b5b602082029050602081019050919050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b60006105218261059e565b915061052c8361059e565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610561576105606105a8565b5b828201905092915050565b60006105778261057e565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61060f8161056c565b811461061a57600080fd5b50565b6106268161059e565b811461063157600080fd5b5056fe"; diff --git a/libs/metrics/src/l1/l1MetricsService.ts b/libs/metrics/src/l1/l1MetricsService.ts index cc051d8..4c9f112 100644 --- a/libs/metrics/src/l1/l1MetricsService.ts +++ b/libs/metrics/src/l1/l1MetricsService.ts @@ -4,11 +4,9 @@ import { Inject, Injectable, LoggerService } from "@nestjs/common"; import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston"; import { Address, - ContractConstructorArgs, encodeFunctionData, erc20Abi, formatUnits, - parseAbiParameters, parseEther, parseUnits, zeroAddress, @@ -16,8 +14,6 @@ import { import { L1ProviderException } from "@zkchainhub/metrics/exceptions/provider.exception"; import { bridgeHubAbi, sharedBridgeAbi } from "@zkchainhub/metrics/l1/abis"; -import { tokenBalancesAbi } from "@zkchainhub/metrics/l1/abis/tokenBalances.abi"; -import { tokenBalancesBytecode } from "@zkchainhub/metrics/l1/bytecode"; import { AssetTvl, GasInfo } from "@zkchainhub/metrics/types"; import { IPricingService, PRICING_PROVIDER } from "@zkchainhub/pricing"; import { EvmProviderService } from "@zkchainhub/providers"; @@ -121,29 +117,30 @@ export class L1MetricsService { /** * Fetches the token balances for the given addresses and ETH balance. - * Note: The last balance in the returned array is the ETH balance, so the fetch length should be addresses.length + 1. * @param addresses - An array of addresses for which to fetch the token balances. * @returns A promise that resolves to an object containing the ETH balance and an array of address balances. */ private async fetchTokenBalances( addresses: Address[], ): Promise<{ ethBalance: bigint; addressesBalance: bigint[] }> { - const returnAbiParams = parseAbiParameters("uint256[]"); - const args: ContractConstructorArgs = [ - L1_CONTRACTS.SHARED_BRIDGE, - addresses, - ]; - - const [balances] = await this.evmProviderService.batchRequest( - tokenBalancesAbi, - tokenBalancesBytecode, - args, - returnAbiParams, - ); + const balances = await this.evmProviderService.multicall({ + contracts: [ + ...addresses.map((tokenAddress) => { + return { + address: tokenAddress, + abi: erc20Abi, + functionName: "balanceOf", + args: [this.sharedBridge.address], + } as const; + }), + ], + allowFailure: false, + }); + const ethBalance = await this.evmProviderService.getBalance(this.sharedBridge.address); - assert(balances.length === addresses.length + 1, "Invalid balances length"); + assert(balances.length === addresses.length, "Invalid balances length"); - return { ethBalance: balances[addresses.length]!, addressesBalance: balances.slice(0, -1) }; + return { ethBalance: ethBalance, addressesBalance: balances }; } //TODO: Implement getBatchesInfo. diff --git a/libs/metrics/test/unit/l1/l1MetricsService.spec.ts b/libs/metrics/test/unit/l1/l1MetricsService.spec.ts index 18def4b..9d06c19 100644 --- a/libs/metrics/test/unit/l1/l1MetricsService.spec.ts +++ b/libs/metrics/test/unit/l1/l1MetricsService.spec.ts @@ -7,8 +7,6 @@ import { encodeFunctionData, erc20Abi, parseEther, zeroAddress } from "viem"; import { L1ProviderException } from "@zkchainhub/metrics/exceptions/provider.exception"; import { L1MetricsService } from "@zkchainhub/metrics/l1/"; import { bridgeHubAbi, sharedBridgeAbi } from "@zkchainhub/metrics/l1/abis"; -import { tokenBalancesAbi } from "@zkchainhub/metrics/l1/abis/tokenBalances.abi"; -import { tokenBalancesBytecode } from "@zkchainhub/metrics/l1/bytecode"; import { IPricingService, PRICING_PROVIDER } from "@zkchainhub/pricing"; import { EvmProviderService } from "@zkchainhub/providers"; import { ETH_TOKEN_ADDRESS, L1_CONTRACTS, vitalikAddress } from "@zkchainhub/shared"; @@ -152,10 +150,14 @@ describe("L1MetricsService", () => { describe("l1Tvl", () => { it("return the TVL on L1 Shared Bridge", async () => { - const mockBalances = [60_841_657_140641n, 135_63005559n, 123_803_824374847279970609n]; // Mocked balances + const mockMulticallBalances = [60_841_657_140641n, 135_63005559n]; // Mocked balances + const mockEtherBalance = 123_803_824374847279970609n; const mockPrices = { "wrapped-bitcoin": 66_129, "usd-coin": 0.999, ethereum: 3_181.09 }; // Mocked prices - jest.spyOn(mockEvmProviderService, "batchRequest").mockResolvedValue([mockBalances]); + jest.spyOn(mockEvmProviderService, "multicall").mockResolvedValue( + mockMulticallBalances, + ); + jest.spyOn(mockEvmProviderService, "getBalance").mockResolvedValue(mockEtherBalance); jest.spyOn(mockPricingService, "getTokenPrices").mockResolvedValue(mockPrices); const result = await l1MetricsService.l1Tvl(); @@ -199,21 +201,25 @@ describe("L1MetricsService", () => { decimals: 8, }, ]); - expect(mockEvmProviderService.batchRequest).toHaveBeenCalledWith( - tokenBalancesAbi, - tokenBalancesBytecode, - [ - L1_CONTRACTS.SHARED_BRIDGE, - [ - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", - ], - ], - [ + expect(mockEvmProviderService.multicall).toHaveBeenCalledWith({ + contracts: [ + { + address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + abi: erc20Abi, + functionName: "balanceOf", + args: [L1_CONTRACTS.SHARED_BRIDGE], + }, { - type: "uint256[]", + address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + abi: erc20Abi, + functionName: "balanceOf", + args: [L1_CONTRACTS.SHARED_BRIDGE], }, ], + allowFailure: false, + }); + expect(mockEvmProviderService.getBalance).toHaveBeenCalledWith( + L1_CONTRACTS.SHARED_BRIDGE, ); expect(mockPricingService.getTokenPrices).toHaveBeenCalledWith([ "ethereum", @@ -223,15 +229,19 @@ describe("L1MetricsService", () => { }); it("throws an error if the balances length is invalid", async () => { - jest.spyOn(mockEvmProviderService, "batchRequest").mockResolvedValue([[]]); + jest.spyOn(mockEvmProviderService, "multicall").mockResolvedValue([]); await expect(l1MetricsService.l1Tvl()).rejects.toThrowError("Invalid balances length"); }); it("throws an error if the prices length is invalid", async () => { - jest.spyOn(mockEvmProviderService, "batchRequest").mockResolvedValue([ - [60_841_657_140641n, 135_63005559n, 123_803_824374847279970609n], + jest.spyOn(mockEvmProviderService, "multicall").mockResolvedValue([ + 60_841_657_140641n, + 135_63005559n, ]); + jest.spyOn(mockEvmProviderService, "getBalance").mockResolvedValue( + 123_803_824374847279970609n, + ); jest.spyOn(mockPricingService, "getTokenPrices").mockResolvedValue({ ethereum: 3_181.09, "usd-coin": 0.999, diff --git a/package.json b/package.json index e6b6d92..c582d92 100644 --- a/package.json +++ b/package.json @@ -7,27 +7,20 @@ "license": "UNLICENSED", "scripts": { "build": "nest build", - "build:contracts": "forge build --root contracts", "format": "prettier --write \"{apps,libs}/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/apps/api/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "lint:contracts": "forge fmt --root contracts && pnpm lint:contracts:sol-tests --fix && pnpm lint:contracts:sol-logic --fix", - "lint:contracts:check": "pnpm lint:contracts:sol-tests && pnpm lint:contracts:sol-logic && forge fmt --check --root contracts", - "lint:contracts:sol-logic": "solhint -c .solhint.json 'contracts/src/**/*.sol'", - "lint:contracts:sol-tests": "solhint -c .solhint.tests.json 'contracts/test/**/*.sol'", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:contracts": "forge test -vvv --root contracts", "test:e2e": "jest --config ./apps/api/test/jest-e2e.json", "create-lib": "echo @zkchainhub | pnpm nest g library $1 ", "prepare": "husky", - "preinstall": "npx only-allow pnpm", - "postinstall": "pnpm build:contracts" + "preinstall": "npx only-allow pnpm" }, "dependencies": { "@nestjs/axios": "3.0.2", @@ -43,7 +36,6 @@ "nest-winston": "1.9.7", "reflect-metadata": "0.1.13", "rxjs": "7.8.1", - "solhint-community": "4.0.0", "viem": "2.17.5", "winston": "3.13.1" }, @@ -65,7 +57,6 @@ "eslint": "8.56.0", "eslint-config-prettier": "9.0.0", "eslint-plugin-prettier": "5.0.0", - "forge-std": "github:foundry-rs/forge-std#semver:1.8.2", "husky": "9.0.11", "jest": "29.5.0", "lint-staged": "15.2.7", @@ -116,7 +107,6 @@ "(apps|libs)/**/*.(ts|js)": [ "pnpm lint", "pnpm format" - ], - "contracts/**/*.(sol)": "pnpm lint:contracts" + ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 367aca1..447a081 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,9 +47,6 @@ importers: rxjs: specifier: 7.8.1 version: 7.8.1 - solhint-community: - specifier: 4.0.0 - version: 4.0.0(typescript@5.1.3) viem: specifier: 2.17.5 version: 2.17.5(typescript@5.1.3)(zod@3.23.8) @@ -108,9 +105,6 @@ importers: eslint-plugin-prettier: specifier: 5.0.0 version: 5.0.0(@types/eslint@8.56.10)(eslint-config-prettier@9.0.0(eslint@8.56.0))(eslint@8.56.0)(prettier@3.0.0) - forge-std: - specifier: github:foundry-rs/forge-std#semver:1.8.2 - version: https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801 husky: specifier: 9.0.11 version: 9.0.11 @@ -729,9 +723,6 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - '@solidity-parser/parser@0.16.2': - resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} - '@swc/core-darwin-arm64@1.6.13': resolution: {integrity: sha512-SOF4buAis72K22BGJ3N8y88mLNfxLNprTuJUpzikyMGrvkuBFNcxYtMhmomO0XHsgLDzOJ+hWzcgjRNzjMsUcQ==} engines: {node: '>=10'} @@ -1129,13 +1120,6 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - antlr4@4.13.1: - resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} - engines: {node: '>=16'} - - antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -1168,13 +1152,6 @@ packages: asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -1400,10 +1377,6 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -1493,15 +1466,6 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} - cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -1852,10 +1816,6 @@ packages: debug: optional: true - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801: - resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801} - version: 1.8.2 - fork-ts-checker-webpack-plugin@8.0.0: resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} @@ -1948,11 +1908,6 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - glob@9.3.5: resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} engines: {node: '>=16 || 14 >=14.17'} @@ -2464,9 +2419,6 @@ packages: lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} @@ -2572,10 +2524,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - minimatch@8.0.4: resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} engines: {node: '>=16 || 14 >=14.17'} @@ -2815,11 +2763,6 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - prettier@3.0.0: resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} engines: {node: '>=14'} @@ -3049,10 +2992,6 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -3061,10 +3000,6 @@ packages: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} - solhint-community@4.0.0: - resolution: {integrity: sha512-BERw3qYzkJE64EwvYrp2+iiTN8yAZOJ74FCiL4bTBp7v0JFUvRYCEGZKAqfHcfi/koKkzM6qThsJUceKm9vvfg==} - hasBin: true - source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} @@ -3186,10 +3121,6 @@ packages: resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} engines: {node: ^14.18.0 || >=16.0.0} - table@6.8.2: - resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} - engines: {node: '>=10.0.0'} - tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} @@ -4320,10 +4251,6 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@solidity-parser/parser@0.16.2': - dependencies: - antlr4ts: 0.5.0-alpha.4 - '@swc/core-darwin-arm64@1.6.13': optional: true @@ -4757,10 +4684,6 @@ snapshots: ansi-styles@6.2.1: {} - antlr4@4.13.1: {} - - antlr4ts@0.5.0-alpha.4: {} - anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -4786,10 +4709,6 @@ snapshots: asap@2.0.6: {} - ast-parents@0.0.1: {} - - astral-regex@2.0.0: {} - async@3.2.5: {} asynckit@0.4.0: {} @@ -5085,8 +5004,6 @@ snapshots: dependencies: delayed-stream: 1.0.0 - commander@11.1.0: {} - commander@12.1.0: {} commander@2.20.3: {} @@ -5178,15 +5095,6 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.1.3): - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - optionalDependencies: - typescript: 5.1.3 - cosmiconfig@9.0.0(typescript@5.1.3): dependencies: env-paths: 2.2.1 @@ -5586,8 +5494,6 @@ snapshots: follow-redirects@1.15.6: {} - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/978ac6fadb62f5f0b723c996f64be52eddba6801: {} - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.1.3)(webpack@5.87.0(@swc/core@1.6.13)): dependencies: '@babel/code-frame': 7.24.7 @@ -5685,14 +5591,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - glob@9.3.5: dependencies: fs.realpath: 1.0.0 @@ -6362,8 +6260,6 @@ snapshots: lodash.startcase@4.4.0: {} - lodash.truncate@4.4.2: {} - lodash.uniq@4.5.0: {} lodash.upperfirst@4.3.1: {} @@ -6453,10 +6349,6 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.1 - minimatch@8.0.4: dependencies: brace-expansion: 2.0.1 @@ -6663,9 +6555,6 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@2.8.8: - optional: true - prettier@3.0.0: {} pretty-format@29.7.0: @@ -6902,12 +6791,6 @@ snapshots: slash@3.0.0: {} - slice-ansi@4.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 @@ -6918,30 +6801,6 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - solhint-community@4.0.0(typescript@5.1.3): - dependencies: - '@solidity-parser/parser': 0.16.2 - ajv: 6.12.6 - antlr4: 4.13.1 - ast-parents: 0.0.1 - chalk: 4.1.2 - commander: 11.1.0 - cosmiconfig: 8.3.6(typescript@5.1.3) - fast-diff: 1.3.0 - glob: 8.1.0 - ignore: 5.3.1 - js-yaml: 4.1.0 - lodash: 4.17.21 - pluralize: 8.0.0 - semver: 6.3.1 - strip-ansi: 6.0.1 - table: 6.8.2 - text-table: 0.2.0 - optionalDependencies: - prettier: 2.8.8 - transitivePeerDependencies: - - typescript - source-map-support@0.5.13: dependencies: buffer-from: 1.1.2 @@ -7059,14 +6918,6 @@ snapshots: '@pkgr/core': 0.1.1 tslib: 2.6.3 - table@6.8.2: - dependencies: - ajv: 8.12.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - tapable@2.2.1: {} terser-webpack-plugin@5.3.10(@swc/core@1.6.13)(webpack@5.87.0(@swc/core@1.6.13)):