From cd1a85e133dd6ebce5694c7445eb08a460dcf97b Mon Sep 17 00:00:00 2001 From: Mikers Date: Wed, 20 Dec 2023 10:29:45 -1000 Subject: [PATCH] precompile diamond function selectors at compile time (#407) --- Makefile | 7 +- scripts/python/build_selector_library.py | 116 ++++++++++++++ scripts/python/get_selectors.py | 47 ------ test/IntegrationTestBase.sol | 33 ++-- ...tract.sol => NumberContractFacetEight.sol} | 6 - test/helpers/NumberContractFacetSeven.sol | 8 + test/helpers/SelectorLibrary.sol | 141 ++++++++++++++++++ test/helpers/TestUtils.sol | 10 -- test/integration/GatewayDiamond.t.sol | 9 +- test/integration/GatewayDiamondToken.t.sol | 3 +- test/integration/SubnetActorDiamond.t.sol | 8 +- test/invariants/SubnetActorInvariants.t.sol | 2 +- .../handlers/SubnetActorHandler.sol | 2 +- ...or.sol => SubnetActorManagerFacetMock.sol} | 0 14 files changed, 303 insertions(+), 89 deletions(-) create mode 100644 scripts/python/build_selector_library.py delete mode 100644 scripts/python/get_selectors.py rename test/helpers/{NumberContract.sol => NumberContractFacetEight.sol} (61%) create mode 100644 test/helpers/NumberContractFacetSeven.sol create mode 100644 test/helpers/SelectorLibrary.sol rename test/mocks/{SubnetActor.sol => SubnetActorManagerFacetMock.sol} (100%) diff --git a/Makefile b/Makefile index 18256cbcb..551529993 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,12 @@ make coverage-for-mac: | forge genhtml -o coverage_report lcov.info --branch-coverage --ignore-errors category ./tools/check_coverage.sh -prepare: fmt lint test slither +prepare: build-selector-library fmt lint test slither + + +build-selector-library: | forge + python scripts/python/build_selector_library.py + npx prettier -w test/helpers/SelectorLibrary.sol # Forge is used by the ipc-solidity-actors compilation steps. .PHONY: forge diff --git a/scripts/python/build_selector_library.py b/scripts/python/build_selector_library.py new file mode 100644 index 000000000..50f793677 --- /dev/null +++ b/scripts/python/build_selector_library.py @@ -0,0 +1,116 @@ +import argparse +import glob +import json +import os +import subprocess +import sys +from eth_abi import encode +from json.decoder import JSONDecodeError + +def writeToFile(selector_storage_content): + # Define the file path + file_path = 'test/helpers/SelectorLibrary.sol' + + # Write the content to the file + with open(file_path, 'w') as file: + file.write(selector_storage_content) + + +def generate_solidity_function(contract_selectors): + solidity_code = "// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity ^0.8.19;\n" + solidity_code += "library SelectorLibrary {\n" + solidity_code += " function resolveSelectors(string memory facetName) public pure returns (bytes4[] memory facetSelectors) {\n" + + for contract_name, selectors in contract_selectors.items(): + solidity_code += f' if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("{contract_name}"))) {{\n' + solidity_code += f' return abi.decode(hex"{selectors}", (bytes4[]));\n' + solidity_code += " }\n" + + solidity_code += " revert(\"Selector not found\");\n" + solidity_code += " }\n" + solidity_code += "}\n" + return solidity_code + +def format_selector(selector_bytes): + hex_str = selector_bytes.hex() + if len(hex_str) % 2 != 0: + hex_str = '0' + hex_str # Add a leading zero if the length is odd + return hex_str + +def parse_selectors(encoded_selectors): + # Assuming the encoded selectors are in the format provided in your example + decoded = bytes.fromhex(encoded_selectors[2:]) # Skip the "0x" prefix + return [format_selector(decoded[i:i+4]) for i in range(0, len(decoded), 4)] # Return in chunks of 4 bytes + +def get_selectors(contract): + """This function gets the selectors of the functions of the target contract.""" + + res = subprocess.run( + ["forge", "inspect", contract, "methodIdentifiers"], capture_output=True) + res = res.stdout.decode() + try: + res = json.loads(res) + except JSONDecodeError as e: + print("failed to load JSON:", e) + print("forge output:", res) + print("contract:", contract) + sys.exit(1) + + selectors = [] + for signature in res: + selector = res[signature] + selectors.append(bytes.fromhex(selector)) + + enc = encode(["bytes4[]"], [selectors]) + return "" + enc.hex() + +def main(): + contract_selectors = {} + filepaths_to_target = [ + 'src/GatewayDiamond.sol', + 'src/SubnetActorDiamond.sol', + 'src/SubnetRegistryDiamond.sol', + 'src/diamond/DiamondCutFacet.sol', + 'src/diamond/DiamondLoupeFacet.sol', + 'src/gateway/GatewayGetterFacet.sol', + 'src/gateway/GatewayManagerFacet.sol', + 'src/gateway/GatewayMessengerFacet.sol', + 'src/gateway/GatewayRouterFacet.sol', + 'src/subnet/SubnetActorGetterFacet.sol', + 'src/subnet/SubnetActorManagerFacet.sol', + 'src/subnetregistry/RegisterSubnetFacet.sol', + 'src/subnetregistry/SubnetGetterFacet.sol', + 'test/helpers/ERC20PresetFixedSupply.sol', + 'test/helpers/NumberContractFacetEight.sol', + 'test/helpers/NumberContractFacetSeven.sol', + 'test/helpers/SelectorLibrary.sol', + 'test/helpers/TestUtils.sol', + 'test/mocks/SubnetActorManagerFacetMock.sol', + ] + + for filepath in filepaths_to_target: + + # Extract just the contract name (without path and .sol extension) + contract_name = os.path.splitext(os.path.basename(filepath))[0] + + #skip lib or interfaces + if contract_name.startswith("Lib") or contract_name.startswith("I") or contract_name.endswith("Helper"): + continue + + # Format full path + # Call get_selectors for each contract + try: + selectors = get_selectors(filepath + ':' + contract_name) + if selectors: + contract_selectors[contract_name] = selectors + except Exception as oops: + print(f"Error processing {filepath}: {oops}") + + + # Print the final JSON + solidity_library_code = generate_solidity_function(contract_selectors) + writeToFile(solidity_library_code) + +if __name__ == "__main__": + main() + diff --git a/scripts/python/get_selectors.py b/scripts/python/get_selectors.py deleted file mode 100644 index 4a66bfc21..000000000 --- a/scripts/python/get_selectors.py +++ /dev/null @@ -1,47 +0,0 @@ -import subprocess -import argparse -import json - -from eth_abi import encode -from json.decoder import JSONDecodeError - -def get_selectors(args): - """This function gets the selectors of the functions of the target contract. - We have to have selectors to be able to initialize a Diamond contract - and create its facets having the functions with corresponding selectors. - Later, this function may be replaced by a Foundry utility - https://github.com/foundry-rs/foundry/issues/5012. - """ - - contract = args.contract - - res = subprocess.run( - ["forge", "inspect", contract, "methodIdentifiers"], capture_output=True) - res = res.stdout.decode() - try: - res = json.loads(res) - except JSONDecodeError as e: - print("failed to load JSON:", e) - print("forge output:", res); - - selectors = [] - for signature in res: - selector = res[signature] - selectors.append(bytes.fromhex(selector)) - - enc = encode(["bytes4[]"], [selectors]) - print("0x" + enc.hex()) - - -def parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument("contract", type=str) - return parser.parse_args() - - -def main(): - args = parse_args() - get_selectors(args) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/test/IntegrationTestBase.sol b/test/IntegrationTestBase.sol index 3727955f6..5fa68fafd 100644 --- a/test/IntegrationTestBase.sol +++ b/test/IntegrationTestBase.sol @@ -23,7 +23,7 @@ import {GatewayGetterFacet} from "../src/gateway/GatewayGetterFacet.sol"; import {GatewayMessengerFacet} from "../src/gateway/GatewayMessengerFacet.sol"; import {GatewayManagerFacet} from "../src/gateway/GatewayManagerFacet.sol"; import {GatewayRouterFacet} from "../src/gateway/GatewayRouterFacet.sol"; -import {SubnetActorManagerFacetMock} from "./mocks/SubnetActor.sol"; +import {SubnetActorManagerFacetMock} from "./mocks/SubnetActorManagerFacetMock.sol"; import {SubnetActorManagerFacet} from "../src/subnet/SubnetActorManagerFacet.sol"; import {SubnetActorGetterFacet} from "../src/subnet/SubnetActorGetterFacet.sol"; import {SubnetRegistryDiamond} from "../src/SubnetRegistryDiamond.sol"; @@ -33,6 +33,7 @@ import {DiamondLoupeFacet} from "../src/diamond/DiamondLoupeFacet.sol"; import {DiamondCutFacet} from "../src/diamond/DiamondCutFacet.sol"; import {SupplySourceHelper} from "../src/lib/SupplySourceHelper.sol"; import {TestUtils} from "./helpers/TestUtils.sol"; +import {SelectorLibrary} from "./helpers/SelectorLibrary.sol"; contract TestParams { uint64 constant MAX_NONCE = type(uint64).max; @@ -71,10 +72,10 @@ contract TestRegistry is Test, TestParams { SubnetGetterFacet registrySubnetGetterFacet; constructor() { - registerSubnetFacetSelectors = TestUtils.generateSelectors(vm, "RegisterSubnetFacet"); - registerSubnetGetterFacetSelectors = TestUtils.generateSelectors(vm, "SubnetGetterFacet"); - registerCutterSelectors = TestUtils.generateSelectors(vm, "DiamondCutFacet"); - registerLouperSelectors = TestUtils.generateSelectors(vm, "DiamondLoupeFacet"); + registerSubnetFacetSelectors = SelectorLibrary.resolveSelectors("RegisterSubnetFacet"); + registerSubnetGetterFacetSelectors = SelectorLibrary.resolveSelectors("SubnetGetterFacet"); + registerCutterSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); + registerLouperSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); } } @@ -95,12 +96,12 @@ contract TestGatewayActor is Test, TestParams { DiamondLoupeFacet gwLouper; constructor() { - gwRouterSelectors = TestUtils.generateSelectors(vm, "GatewayRouterFacet"); - gwGetterSelectors = TestUtils.generateSelectors(vm, "GatewayGetterFacet"); - gwManagerSelectors = TestUtils.generateSelectors(vm, "GatewayManagerFacet"); - gwMessengerSelectors = TestUtils.generateSelectors(vm, "GatewayMessengerFacet"); - gwCutterSelectors = TestUtils.generateSelectors(vm, "DiamondCutFacet"); - gwLoupeSelectors = TestUtils.generateSelectors(vm, "DiamondLoupeFacet"); + gwRouterSelectors = SelectorLibrary.resolveSelectors("GatewayRouterFacet"); + gwGetterSelectors = SelectorLibrary.resolveSelectors("GatewayGetterFacet"); + gwManagerSelectors = SelectorLibrary.resolveSelectors("GatewayManagerFacet"); + gwMessengerSelectors = SelectorLibrary.resolveSelectors("GatewayMessengerFacet"); + gwCutterSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); + gwLoupeSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); } function defaultGatewayParams() internal pure virtual returns (GatewayDiamond.ConstructorParams memory) { @@ -133,11 +134,11 @@ contract TestSubnetActor is Test, TestParams { DiamondLoupeFacet saLouper; constructor() { - saGetterSelectors = TestUtils.generateSelectors(vm, "SubnetActorGetterFacet"); - saManagerSelectors = TestUtils.generateSelectors(vm, "SubnetActorManagerFacet"); - saManagerMockedSelectors = TestUtils.generateSelectors(vm, "SubnetActorManagerFacetMock"); - saCutterSelectors = TestUtils.generateSelectors(vm, "DiamondCutFacet"); - saLouperSelectors = TestUtils.generateSelectors(vm, "DiamondLoupeFacet"); + saGetterSelectors = SelectorLibrary.resolveSelectors("SubnetActorGetterFacet"); + saManagerSelectors = SelectorLibrary.resolveSelectors("SubnetActorManagerFacet"); + saManagerMockedSelectors = SelectorLibrary.resolveSelectors("SubnetActorManagerFacetMock"); + saCutterSelectors = SelectorLibrary.resolveSelectors("DiamondCutFacet"); + saLouperSelectors = SelectorLibrary.resolveSelectors("DiamondLoupeFacet"); } function defaultSubnetActorParamsWithGateway( diff --git a/test/helpers/NumberContract.sol b/test/helpers/NumberContractFacetEight.sol similarity index 61% rename from test/helpers/NumberContract.sol rename to test/helpers/NumberContractFacetEight.sol index ac493b148..4d69efb1a 100644 --- a/test/helpers/NumberContract.sol +++ b/test/helpers/NumberContractFacetEight.sol @@ -1,12 +1,6 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.19; -contract NumberContractFacetSeven { - function getNum() external pure returns (uint8) { - return 7; - } -} - contract NumberContractFacetEight { function getNum() external pure returns (uint8) { return 8; diff --git a/test/helpers/NumberContractFacetSeven.sol b/test/helpers/NumberContractFacetSeven.sol new file mode 100644 index 000000000..391813fc1 --- /dev/null +++ b/test/helpers/NumberContractFacetSeven.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.19; + +contract NumberContractFacetSeven { + function getNum() external pure returns (uint8) { + return 7; + } +} diff --git a/test/helpers/SelectorLibrary.sol b/test/helpers/SelectorLibrary.sol new file mode 100644 index 000000000..96dd69f7b --- /dev/null +++ b/test/helpers/SelectorLibrary.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.19; + +library SelectorLibrary { + function resolveSelectors(string memory facetName) public pure returns (bytes4[] memory facetSelectors) { + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayDiamond"))) { + return + abi.decode( + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorDiamond"))) { + return + abi.decode( + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetRegistryDiamond"))) { + return + abi.decode( + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("DiamondCutFacet"))) { + return + abi.decode( + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("DiamondLoupeFacet"))) { + return + abi.decode( + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a700000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayGetterFacet"))) { + return + abi.decode( + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000268789f83b0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000002da5794a00000000000000000000000000000000000000000000000000000000dd81b5cf0000000000000000000000000000000000000000000000000000000069e737fd0000000000000000000000000000000000000000000000000000000041b6a2e80000000000000000000000000000000000000000000000000000000024729425000000000000000000000000000000000000000000000000000000009e530b57000000000000000000000000000000000000000000000000000000006547cd6400000000000000000000000000000000000000000000000000000000b9ee584200000000000000000000000000000000000000000000000000000000a9294bdd000000000000000000000000000000000000000000000000000000002218059400000000000000000000000000000000000000000000000000000000b3ab3f7400000000000000000000000000000000000000000000000000000000ac12d763000000000000000000000000000000000000000000000000000000004aa8f8a500000000000000000000000000000000000000000000000000000000ca41d5ce00000000000000000000000000000000000000000000000000000000d6c5c39700000000000000000000000000000000000000000000000000000000544dddff000000000000000000000000000000000000000000000000000000006ad21bb000000000000000000000000000000000000000000000000000000000a517218f000000000000000000000000000000000000000000000000000000009704276600000000000000000000000000000000000000000000000000000000767ee5f400000000000000000000000000000000000000000000000000000000335eb62a00000000000000000000000000000000000000000000000000000000b1ba49b000000000000000000000000000000000000000000000000000000000f3229131000000000000000000000000000000000000000000000000000000000338150f0000000000000000000000000000000000000000000000000000000094074b03000000000000000000000000000000000000000000000000000000007edeac920000000000000000000000000000000000000000000000000000000006572c1a00000000000000000000000000000000000000000000000000000000c66c66a1000000000000000000000000000000000000000000000000000000009d3070b5000000000000000000000000000000000000000000000000000000005d02968500000000000000000000000000000000000000000000000000000000599c7bd10000000000000000000000000000000000000000000000000000000005aff0b300000000000000000000000000000000000000000000000000000000375b3c0a000000000000000000000000000000000000000000000000000000008cfd78e70000000000000000000000000000000000000000000000000000000002e30f9a00000000000000000000000000000000000000000000000000000000a2b6715800000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayManagerFacet"))) { + return + abi.decode( + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000085a627dbc0000000000000000000000000000000000000000000000000000000018f44b70000000000000000000000000000000000000000000000000000000000517e1aa0000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000f207564e000000000000000000000000000000000000000000000000000000006b2c1eef00000000000000000000000000000000000000000000000000000000d8e255720000000000000000000000000000000000000000000000000000000045f5448500000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayMessengerFacet"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000225bf0db600000000000000000000000000000000000000000000000000000000210b944e00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayRouterFacet"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c0db0f77c0000000000000000000000000000000000000000000000000000000053b4e7bf00000000000000000000000000000000000000000000000000000000c62eb4d5000000000000000000000000000000000000000000000000000000000df144610000000000000000000000000000000000000000000000000000000047dc9b4f000000000000000000000000000000000000000000000000000000001119697400000000000000000000000000000000000000000000000000000000743037710000000000000000000000000000000000000000000000000000000032e7661f000000000000000000000000000000000000000000000000000000000bed761500000000000000000000000000000000000000000000000000000000ac81837900000000000000000000000000000000000000000000000000000000bacc656d00000000000000000000000000000000000000000000000000000000e49a547d00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorGetterFacet"))) { + return + abi.decode( + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000253354c3e10000000000000000000000000000000000000000000000000000000035142c8c0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000004b27aa72000000000000000000000000000000000000000000000000000000004b0694e20000000000000000000000000000000000000000000000000000000069e737fd000000000000000000000000000000000000000000000000000000008ef3f761000000000000000000000000000000000000000000000000000000003da3324100000000000000000000000000000000000000000000000000000000903e693000000000000000000000000000000000000000000000000000000000948628a900000000000000000000000000000000000000000000000000000000d92e8f1200000000000000000000000000000000000000000000000000000000c7cda762000000000000000000000000000000000000000000000000000000009754b29e0000000000000000000000000000000000000000000000000000000038a210b30000000000000000000000000000000000000000000000000000000080f76021000000000000000000000000000000000000000000000000000000005dd9147c00000000000000000000000000000000000000000000000000000000b2bd295e00000000000000000000000000000000000000000000000000000000d6eb591000000000000000000000000000000000000000000000000000000000332a5ac9000000000000000000000000000000000000000000000000000000001597bf7e0000000000000000000000000000000000000000000000000000000052d182d1000000000000000000000000000000000000000000000000000000001904bb2e000000000000000000000000000000000000000000000000000000002bc31eb300000000000000000000000000000000000000000000000000000000f75499dc00000000000000000000000000000000000000000000000000000000cfca28240000000000000000000000000000000000000000000000000000000040550a1c00000000000000000000000000000000000000000000000000000000d081be03000000000000000000000000000000000000000000000000000000001f3a0e410000000000000000000000000000000000000000000000000000000072d0a0e00000000000000000000000000000000000000000000000000000000028d5551d00000000000000000000000000000000000000000000000000000000599c7bd1000000000000000000000000000000000000000000000000000000009e33bd02000000000000000000000000000000000000000000000000000000006704287c00000000000000000000000000000000000000000000000000000000c5ab224100000000000000000000000000000000000000000000000000000000f0cf6c9600000000000000000000000000000000000000000000000000000000ad81e4d60000000000000000000000000000000000000000000000000000000080875df700000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorManagerFacet"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001210fd4261000000000000000000000000000000000000000000000000000000004e71d92d00000000000000000000000000000000000000000000000000000000ed7c4da1000000000000000000000000000000000000000000000000000000004c860af6000000000000000000000000000000000000000000000000000000006170b1620000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000d66d9e19000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000000b7fbe600000000000000000000000000000000000000000000000000000000066783c9b00000000000000000000000000000000000000000000000000000000da5d09ee000000000000000000000000000000000000000000000000000000003a4b66f1000000000000000000000000000000000000000000000000000000002681193600000000000000000000000000000000000000000000000000000000b9ee2bb9000000000000000000000000000000000000000000000000000000003f4ba83a000000000000000000000000000000000000000000000000000000002e17de7800000000000000000000000000000000000000000000000000000000cc2dc2b900000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("RegisterSubnetFacet"))) { + return + abi.decode( + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000017be005d500000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetGetterFacet"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000942bf3cc1000000000000000000000000000000000000000000000000000000000be06111000000000000000000000000000000000000000000000000000000001b0766c300000000000000000000000000000000000000000000000000000000a372bf30000000000000000000000000000000000000000000000000000000000f5849d1000000000000000000000000000000000000000000000000000000009836b75f00000000000000000000000000000000000000000000000000000000030f6051000000000000000000000000000000000000000000000000000000001163dca500000000000000000000000000000000000000000000000000000000a46d044d00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("ERC20PresetFixedSupply"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000ddd62ed3e00000000000000000000000000000000000000000000000000000000095ea7b30000000000000000000000000000000000000000000000000000000070a082310000000000000000000000000000000000000000000000000000000042966c680000000000000000000000000000000000000000000000000000000079cc679000000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000a457c2d700000000000000000000000000000000000000000000000000000000395093510000000000000000000000000000000000000000000000000000000006fdde030000000000000000000000000000000000000000000000000000000095d89b410000000000000000000000000000000000000000000000000000000018160ddd00000000000000000000000000000000000000000000000000000000a9059cbb0000000000000000000000000000000000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("NumberContractFacetEight"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000167e0badb00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("NumberContractFacetSeven"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000167e0badb00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SelectorLibrary"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000166e2898c00000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("TestUtils"))) { + return + abi.decode( + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000008997da8d4000000000000000000000000000000000000000000000000000000005727dc5c0000000000000000000000000000000000000000000000000000000003a507be000000000000000000000000000000000000000000000000000000007a308a4c00000000000000000000000000000000000000000000000000000000eeeac01e00000000000000000000000000000000000000000000000000000000bc9e2bcf00000000000000000000000000000000000000000000000000000000f6caf0ac00000000000000000000000000000000000000000000000000000000573081a200000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorManagerFacetMock"))) { + return + abi.decode( + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001410fd4261000000000000000000000000000000000000000000000000000000004e71d92d00000000000000000000000000000000000000000000000000000000ed7c4da100000000000000000000000000000000000000000000000000000000350a14bf00000000000000000000000000000000000000000000000000000000c7ebdaef000000000000000000000000000000000000000000000000000000004c860af6000000000000000000000000000000000000000000000000000000006170b1620000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000d66d9e19000000000000000000000000000000000000000000000000000000008456cb59000000000000000000000000000000000000000000000000000000005c975abb000000000000000000000000000000000000000000000000000000000b7fbe600000000000000000000000000000000000000000000000000000000066783c9b00000000000000000000000000000000000000000000000000000000da5d09ee000000000000000000000000000000000000000000000000000000003a4b66f1000000000000000000000000000000000000000000000000000000002681193600000000000000000000000000000000000000000000000000000000b9ee2bb9000000000000000000000000000000000000000000000000000000003f4ba83a000000000000000000000000000000000000000000000000000000002e17de7800000000000000000000000000000000000000000000000000000000cc2dc2b900000000000000000000000000000000000000000000000000000000", + (bytes4[]) + ); + } + revert("Selector not found"); + } +} diff --git a/test/helpers/TestUtils.sol b/test/helpers/TestUtils.sol index e25bd5741..22af3a351 100644 --- a/test/helpers/TestUtils.sol +++ b/test/helpers/TestUtils.sol @@ -28,16 +28,6 @@ library TestUtils { return abi.encodePacked(uint8(0x4), pubKeyX, pubKeyY); } - function generateSelectors(Vm vm, string memory facetName) internal returns (bytes4[] memory facetSelectors) { - string[] memory inputs = new string[](3); - inputs[0] = "python3"; - inputs[1] = "scripts/python/get_selectors.py"; - inputs[2] = facetName; - - bytes memory res = vm.ffi(inputs); - facetSelectors = abi.decode(res, (bytes4[])); - } - function getFourValidators( Vm vm ) internal returns (uint256[] memory validatorKeys, address[] memory addresses, uint256[] memory weights) { diff --git a/test/integration/GatewayDiamond.t.sol b/test/integration/GatewayDiamond.t.sol index 196bf6f36..dd3600368 100644 --- a/test/integration/GatewayDiamond.t.sol +++ b/test/integration/GatewayDiamond.t.sol @@ -4,7 +4,8 @@ pragma solidity 0.8.19; import "forge-std/Test.sol"; import "../../src/errors/IPCErrors.sol"; -import {NumberContractFacetSeven, NumberContractFacetEight} from "../helpers/NumberContract.sol"; +import {NumberContractFacetSeven} from "../helpers/NumberContractFacetSeven.sol"; +import {NumberContractFacetEight} from "../helpers/NumberContractFacetEight.sol"; import {EMPTY_BYTES, METHOD_SEND} from "../../src/constants/Constants.sol"; import {Status} from "../../src/enums/Status.sol"; import {IERC165} from "../../src/interfaces/IERC165.sol"; @@ -30,6 +31,7 @@ import {LibDiamond} from "../../src/lib/LibDiamond.sol"; import {MerkleTreeHelper} from "../helpers/MerkleTreeHelper.sol"; import {TestUtils} from "../helpers/TestUtils.sol"; import {IntegrationTestBase} from "../IntegrationTestBase.sol"; +import {SelectorLibrary} from "../helpers/SelectorLibrary.sol"; contract GatewayActorDiamondTest is Test, IntegrationTestBase { using SubnetIDHelper for SubnetID; @@ -86,7 +88,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { DiamondCutFacet gwDiamondCutter = DiamondCutFacet(address(gatewayDiamond)); IDiamond.FacetCut[] memory gwDiamondCut = new IDiamond.FacetCut[](1); - bytes4[] memory ncGetterSelectors = TestUtils.generateSelectors(vm, "NumberContractFacetSeven"); + bytes4[] memory ncGetterSelectors = SelectorLibrary.resolveSelectors("NumberContractFacetSeven"); gwDiamondCut[0] = ( IDiamond.FacetCut({ @@ -105,7 +107,8 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { NumberContractFacetSeven gwNumberContract = NumberContractFacetSeven(address(gatewayDiamond)); assert(gwNumberContract.getNum() == 7); - ncGetterSelectors = TestUtils.generateSelectors(vm, "NumberContractFacetEight"); + ncGetterSelectors = SelectorLibrary.resolveSelectors("NumberContractFacetEight"); + gwDiamondCut[0] = ( IDiamond.FacetCut({ facetAddress: address(ncFacetB), diff --git a/test/integration/GatewayDiamondToken.t.sol b/test/integration/GatewayDiamondToken.t.sol index d4d867d3b..3d5623deb 100644 --- a/test/integration/GatewayDiamondToken.t.sol +++ b/test/integration/GatewayDiamondToken.t.sol @@ -4,7 +4,8 @@ pragma solidity 0.8.19; import "forge-std/Test.sol"; import "../../src/errors/IPCErrors.sol"; -import {NumberContractFacetSeven, NumberContractFacetEight} from "../helpers/NumberContract.sol"; +import {NumberContractFacetSeven} from "../helpers/NumberContractFacetSeven.sol"; +import {NumberContractFacetEight} from "../helpers/NumberContractFacetEight.sol"; import {EMPTY_BYTES, METHOD_SEND, EMPTY_HASH} from "../../src/constants/Constants.sol"; import {Status} from "../../src/enums/Status.sol"; import {IERC165} from "../../src/interfaces/IERC165.sol"; diff --git a/test/integration/SubnetActorDiamond.t.sol b/test/integration/SubnetActorDiamond.t.sol index 3bfdcef9a..b178144a8 100644 --- a/test/integration/SubnetActorDiamond.t.sol +++ b/test/integration/SubnetActorDiamond.t.sol @@ -5,7 +5,9 @@ import "../../src/errors/IPCErrors.sol"; import {Test} from "forge-std/Test.sol"; import "forge-std/console.sol"; import {TestUtils} from "../helpers/TestUtils.sol"; -import {NumberContractFacetSeven, NumberContractFacetEight} from "../helpers/NumberContract.sol"; +import {SelectorLibrary} from "../helpers/SelectorLibrary.sol"; +import {NumberContractFacetSeven} from "../helpers/NumberContractFacetSeven.sol"; +import {NumberContractFacetEight} from "../helpers/NumberContractFacetEight.sol"; import {METHOD_SEND} from "../../src/constants/Constants.sol"; import {ConsensusType} from "../../src/enums/ConsensusType.sol"; import {BottomUpMsgBatch, CrossMsg, BottomUpCheckpoint, StorableMsg} from "../../src/structs/CrossNet.sol"; @@ -915,7 +917,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { DiamondCutFacet saDiamondCutter = DiamondCutFacet(address(saDiamond)); IDiamond.FacetCut[] memory saDiamondCut = new IDiamond.FacetCut[](1); - bytes4[] memory ncGetterSelectors = TestUtils.generateSelectors(vm, "NumberContractFacetSeven"); + bytes4[] memory ncGetterSelectors = SelectorLibrary.resolveSelectors("NumberContractFacetSeven"); saDiamondCut[0] = ( IDiamond.FacetCut({ @@ -934,7 +936,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { NumberContractFacetSeven saNumberContract = NumberContractFacetSeven(address(saDiamond)); assert(saNumberContract.getNum() == 7); - ncGetterSelectors = TestUtils.generateSelectors(vm, "NumberContractFacetEight"); + ncGetterSelectors = SelectorLibrary.resolveSelectors("NumberContractFacetEight"); saDiamondCut[0] = ( IDiamond.FacetCut({ facetAddress: address(ncFacetB), diff --git a/test/invariants/SubnetActorInvariants.t.sol b/test/invariants/SubnetActorInvariants.t.sol index 7e63239ae..c88bb4e74 100644 --- a/test/invariants/SubnetActorInvariants.t.sol +++ b/test/invariants/SubnetActorInvariants.t.sol @@ -11,7 +11,7 @@ import {GatewayMessengerFacet} from "../../src/gateway/GatewayMessengerFacet.sol import {GatewayManagerFacet} from "../../src/gateway/GatewayManagerFacet.sol"; import {GatewayRouterFacet} from "../../src/gateway/GatewayRouterFacet.sol"; import {SubnetActorHandler, ETH_SUPPLY} from "./handlers/SubnetActorHandler.sol"; -import {SubnetActorManagerFacetMock} from "../mocks/SubnetActor.sol"; +import {SubnetActorManagerFacetMock} from "../mocks/SubnetActorManagerFacetMock.sol"; import {SubnetActorGetterFacet} from "../../src/subnet/SubnetActorGetterFacet.sol"; import {IntegrationTestBase} from "../IntegrationTestBase.sol"; import {SupplySourceHelper} from "../../src/lib/SupplySourceHelper.sol"; diff --git a/test/invariants/handlers/SubnetActorHandler.sol b/test/invariants/handlers/SubnetActorHandler.sol index fe7cf7384..a860b8beb 100644 --- a/test/invariants/handlers/SubnetActorHandler.sol +++ b/test/invariants/handlers/SubnetActorHandler.sol @@ -6,7 +6,7 @@ import "forge-std/StdCheats.sol"; import {CommonBase} from "forge-std/Base.sol"; import {SubnetActorDiamond} from "../../../src/SubnetActorDiamond.sol"; import {SubnetActorGetterFacet} from "../../../src/subnet/SubnetActorGetterFacet.sol"; -import {SubnetActorManagerFacetMock} from "../../mocks/SubnetActor.sol"; +import {SubnetActorManagerFacetMock} from "../../mocks/SubnetActorManagerFacetMock.sol"; import {TestUtils} from "../../helpers/TestUtils.sol"; import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol"; diff --git a/test/mocks/SubnetActor.sol b/test/mocks/SubnetActorManagerFacetMock.sol similarity index 100% rename from test/mocks/SubnetActor.sol rename to test/mocks/SubnetActorManagerFacetMock.sol