From c7cea8e63f63184b91b1153f0a55a3c27871f4fc Mon Sep 17 00:00:00 2001 From: Satyajeet Kolhapure <77279246+satyajeetkolhapure@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:57:01 +0100 Subject: [PATCH 01/10] feat: As a user i want to convert refUID to relationship attestation (#166) Co-authored-by: Satyajeet Kolhapure --- src/example/EASPortal.sol | 39 +++++++++------ test/example/EASPortal.t.sol | 69 ++++++++++++++++++++++++-- test/mocks/AttestationRegistryMock.sol | 9 ++++ 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/example/EASPortal.sol b/src/example/EASPortal.sol index 0e91042c..6d5ba425 100644 --- a/src/example/EASPortal.sol +++ b/src/example/EASPortal.sol @@ -29,6 +29,10 @@ contract EASPortal is AbstractPortal { AttestationRequestData data; } + bytes32 private relationshipSchemaId = 0x89bd76e17fd84df8e1e448fa1b46dd8d97f7e8e806552b003f8386a5aebcb9f0; + + /// @notice Error thrown when reference attestation with refUID is not registered + error ReferenceAttestationNotRegistered(); /// @notice Error thrown when trying to revoke an attestation error NoRevocation(); /// @notice Error thrown when trying to bulk revoke attestations @@ -47,7 +51,7 @@ contract EASPortal is AbstractPortal { function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} - function attest(AttestationRequest memory attestationRequest) external payable { + function attest(AttestationRequest memory attestationRequest) public payable { bytes[] memory validationPayload = new bytes[](0); AttestationPayload memory attestationPayload = AttestationPayload( @@ -56,26 +60,29 @@ contract EASPortal is AbstractPortal { abi.encodePacked(attestationRequest.data.recipient), attestationRequest.data.data ); - super.attest(attestationPayload, validationPayload); - } - - function bulkAttest(AttestationRequest[] memory attestationsRequests) public payable { - AttestationPayload[] memory attestationsPayloads = new AttestationPayload[](attestationsRequests.length); - bytes[][] memory validationPayloads = new bytes[][](attestationsRequests.length); - - for (uint256 i = 0; i < attestationsRequests.length; i++) { - attestationsPayloads[i] = AttestationPayload( - attestationsRequests[i].schema, - attestationsRequests[i].data.expirationTime, - abi.encodePacked(attestationsRequests[i].data.recipient), - attestationsRequests[i].data.data + // if refUID exists then create relationship attestation + if (attestationRequest.data.refUID != 0) { + if (!attestationRegistry.isRegistered(attestationRequest.data.refUID)) revert ReferenceAttestationNotRegistered(); + + uint32 attestationIdCounter = attestationRegistry.getAttestationIdCounter(); + bytes32 attestationId = bytes32(abi.encode(attestationIdCounter)); + + AttestationPayload memory relationshipAttestationPayload = AttestationPayload( + relationshipSchemaId, + attestationRequest.data.expirationTime, + abi.encodePacked(attestationRequest.data.refUID), + abi.encode(attestationId, "EASrefUID", attestationRequest.data.refUID) ); - validationPayloads[i] = new bytes[](0); + super.attest(relationshipAttestationPayload, validationPayload); } + } - super.bulkAttest(attestationsPayloads, validationPayloads); + function bulkAttest(AttestationRequest[] memory attestationsRequests) external payable { + for (uint256 i = 0; i < attestationsRequests.length; i++) { + attest(attestationsRequests[i]); + } } function revoke(bytes32 /*attestationId*/, bytes32 /*replacedBy*/) public pure override { diff --git a/test/example/EASPortal.t.sol b/test/example/EASPortal.t.sol index 21ec593a..fb18c81c 100644 --- a/test/example/EASPortal.t.sol +++ b/test/example/EASPortal.t.sol @@ -41,7 +41,7 @@ contract EASPortalTest is Test { makeAddr("recipient"), uint64(block.timestamp + 1 days), false, - bytes32("refUID"), + bytes32(0), new bytes(0), uint256(1) ); @@ -55,13 +55,74 @@ contract EASPortalTest is Test { easPortal.attest(attestationRequest); } + function test_attest_WithRelationshipAttestation() public { + // Create first EAS attestation request without RefUID + EASPortal.AttestationRequestData memory attestationRequestDataWithoutRefUID = EASPortal.AttestationRequestData( + makeAddr("recipient"), + uint64(block.timestamp + 1 days), + false, + bytes32(0), + new bytes(0), + uint256(1) + ); + EASPortal.AttestationRequest memory attestationRequestWithoutRefUID = EASPortal.AttestationRequest( + bytes32(uint256(1)), + attestationRequestDataWithoutRefUID + ); + + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + easPortal.attest(attestationRequestWithoutRefUID); + + bytes32 attestationIdWithoutRefUID = bytes32(abi.encode(1)); + + // Create second EAS attestation request with RefUID + EASPortal.AttestationRequestData memory attestationRequestDataWithRefUID = EASPortal.AttestationRequestData( + makeAddr("recipient"), + uint64(block.timestamp + 1 days), + false, + attestationIdWithoutRefUID, + new bytes(0), + uint256(1) + ); + EASPortal.AttestationRequest memory attestationRequestWithRefUID = EASPortal.AttestationRequest( + bytes32(uint256(1)), + attestationRequestDataWithRefUID + ); + + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + easPortal.attest(attestationRequestWithRefUID); + } + + function test_attest_ReferenceAttestationNotRegistered() public { + // Create EAS attestation request + EASPortal.AttestationRequestData memory attestationRequestData = EASPortal.AttestationRequestData( + makeAddr("recipient"), + uint64(block.timestamp + 1 days), + false, + bytes32("NotRegistered"), + new bytes(0), + uint256(1) + ); + EASPortal.AttestationRequest memory attestationRequest = EASPortal.AttestationRequest( + bytes32(uint256(1)), + attestationRequestData + ); + + vm.expectRevert(EASPortal.ReferenceAttestationNotRegistered.selector); + easPortal.attest(attestationRequest); + } + function test_bulkAttest() public { // Create EAS attestation request EASPortal.AttestationRequestData memory attestationRequestData = EASPortal.AttestationRequestData( makeAddr("recipient"), uint64(block.timestamp + 1 days), false, - bytes32("refUID"), + bytes32(0), new bytes(0), uint256(1) ); @@ -71,7 +132,9 @@ contract EASPortalTest is Test { attestationsRequests[1] = EASPortal.AttestationRequest(bytes32(uint256(1)), attestationRequestData); vm.expectEmit(true, true, true, true); - emit BulkAttestationsRegistered(); + emit AttestationRegistered(); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); easPortal.bulkAttest(attestationsRequests); } diff --git a/test/mocks/AttestationRegistryMock.sol b/test/mocks/AttestationRegistryMock.sol index 608ab4da..9f27511e 100644 --- a/test/mocks/AttestationRegistryMock.sol +++ b/test/mocks/AttestationRegistryMock.sol @@ -60,6 +60,15 @@ contract AttestationRegistryMock { return version; } + function isRegistered(bytes32 attestationId) public pure returns (bool) { + if (attestationId == bytes32("NotRegistered")) return false; + return true; + } + + function getAttestationIdCounter() public view returns (uint32) { + return attestationIdCounter; + } + function getAttestation(bytes32 attestationId) public view returns (Attestation memory) { return attestations[attestationId]; } From 2b6d9e60fb1a09496dd25ec3e17f996df0f99673 Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Tue, 12 Sep 2023 09:19:06 +0200 Subject: [PATCH 02/10] feat: Investigate mass import mechanism (#161) --- src/AttestationRegistry.sol | 31 +++++- test/AttestationRegistry.t.sol | 28 +++++ .../integration/AttestationRegistryMass.t.sol | 103 ++++++++++++++++++ 3 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 test/integration/AttestationRegistryMass.t.sol diff --git a/src/AttestationRegistry.sol b/src/AttestationRegistry.sol index 795a4774..3c3772c9 100644 --- a/src/AttestationRegistry.sol +++ b/src/AttestationRegistry.sol @@ -94,9 +94,10 @@ contract AttestationRegistry is OwnableUpgradeable { if (attestationPayload.attestationData.length == 0) revert AttestationDataFieldEmpty(); // Auto increment attestation counter attestationIdCounter++; + bytes32 id = bytes32(abi.encode(attestationIdCounter)); // Create attestation - Attestation memory attestation = Attestation( - bytes32(abi.encode(attestationIdCounter)), + attestations[id] = Attestation( + id, attestationPayload.schemaId, bytes32(0), attester, @@ -109,8 +110,7 @@ contract AttestationRegistry is OwnableUpgradeable { attestationPayload.subject, attestationPayload.attestationData ); - attestations[attestation.attestationId] = attestation; - emit AttestationRegistered(attestation.attestationId); + emit AttestationRegistered(id); } /** @@ -123,6 +123,29 @@ contract AttestationRegistry is OwnableUpgradeable { } } + function massImport(AttestationPayload[] calldata attestationsPayloads, address portal) public onlyOwner { + for (uint256 i = 0; i < attestationsPayloads.length; i++) { + // Auto increment attestation counter + attestationIdCounter++; + bytes32 id = bytes32(abi.encode(attestationIdCounter)); + // Create attestation + attestations[id] = Attestation( + id, + attestationsPayloads[i].schemaId, + bytes32(0), + msg.sender, + portal, + uint64(block.timestamp), + attestationsPayloads[i].expirationDate, + 0, + version, + false, + attestationsPayloads[i].subject, + attestationsPayloads[i].attestationData + ); + } + } + /** * @notice Revokes an attestation for given identifier and can replace it by an other one * @param attestationId the attestation ID to revoke diff --git a/test/AttestationRegistry.t.sol b/test/AttestationRegistry.t.sol index 1dca61eb..382203f8 100644 --- a/test/AttestationRegistry.t.sol +++ b/test/AttestationRegistry.t.sol @@ -150,6 +150,34 @@ contract AttestationRegistryTest is Test { attestationRegistry.bulkAttest(payloadsToAttest, attester); } + function test_massImport(AttestationPayload[2] memory attestationsPayloads) public { + vm.assume(attestationsPayloads[0].subject.length != 0); + vm.assume(attestationsPayloads[0].attestationData.length != 0); + vm.assume(attestationsPayloads[1].subject.length != 0); + vm.assume(attestationsPayloads[1].attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationsPayloads[0].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationsPayloads[1].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationsPayloads[0]; + payloadsToAttest[1] = attestationsPayloads[1]; + + bool isRegistered1 = attestationRegistry.isRegistered(bytes32(abi.encode(1))); + assertFalse(isRegistered1); + bool isRegistered2 = attestationRegistry.isRegistered(bytes32(abi.encode(2))); + assertFalse(isRegistered2); + + vm.prank(address(0)); + attestationRegistry.massImport(payloadsToAttest, portal); + + isRegistered1 = attestationRegistry.isRegistered(bytes32(abi.encode(1))); + assertTrue(isRegistered1); + isRegistered2 = attestationRegistry.isRegistered(bytes32(abi.encode(2))); + assertTrue(isRegistered2); + } + function test_revoke(AttestationPayload memory attestationPayload) public { vm.assume(attestationPayload.subject.length != 0); vm.assume(attestationPayload.attestationData.length != 0); diff --git a/test/integration/AttestationRegistryMass.t.sol b/test/integration/AttestationRegistryMass.t.sol new file mode 100644 index 00000000..5a661fd6 --- /dev/null +++ b/test/integration/AttestationRegistryMass.t.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Test } from "forge-std/Test.sol"; +import { AttestationRegistry } from "../../src/AttestationRegistry.sol"; +import { PortalRegistry } from "../../src/PortalRegistry.sol"; +import { SchemaRegistry } from "../../src/SchemaRegistry.sol"; +import { ModuleRegistry } from "../../src/ModuleRegistry.sol"; +import { DefaultPortal } from "../../src/portal/DefaultPortal.sol"; +import { Attestation, AttestationPayload } from "../../src/types/Structs.sol"; +import { Router } from "../../src/Router.sol"; + +contract AttestationRegistryMassTest is Test { + address public portalOwner = makeAddr("portalOwner"); + Router public router; + AttestationRegistry public attestationRegistry; + PortalRegistry public portalRegistry; + SchemaRegistry public schemaRegistry; + ModuleRegistry public moduleRegistry; + bytes32 public schemaId; + AttestationPayload[] public payloadsToAttest; + bytes[][] public validationPayloads; + DefaultPortal public defaultPortal; + + event Initialized(uint8 version); + event AttestationRegistered(bytes32 indexed attestationId); + event BulkAttestationsRegistered(Attestation[] attestations); + event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + event VersionUpdated(uint16 version); + + function setUp() public { + router = new Router(); + router.initialize(); + + attestationRegistry = new AttestationRegistry(); + router.updateAttestationRegistry(address(attestationRegistry)); + vm.prank(address(0)); + attestationRegistry.updateRouter(address(router)); + + portalRegistry = new PortalRegistry(); + router.updatePortalRegistry(address(portalRegistry)); + vm.prank(address(0)); + portalRegistry.updateRouter(address(router)); + + schemaRegistry = new SchemaRegistry(); + router.updateSchemaRegistry(address(schemaRegistry)); + vm.prank(address(0)); + schemaRegistry.updateRouter(address(router)); + + moduleRegistry = new ModuleRegistry(); + router.updateModuleRegistry(address(moduleRegistry)); + vm.prank(address(0)); + moduleRegistry.updateRouter(address(router)); + + vm.prank(address(0)); + portalRegistry.setIssuer(portalOwner); + vm.prank(portalOwner); + address[] memory modules = new address[](0); + defaultPortal = new DefaultPortal(); + defaultPortal.initialize(modules, address(router)); + + vm.prank(portalOwner); + portalRegistry.register(address(defaultPortal), "Name", "Description", true, "Linea"); + + schemaId = schemaRegistry.getIdFromSchemaString("uint8 tier"); + vm.prank(portalOwner); + schemaRegistry.createSchema("name", "description", "context", "uint8 tier"); + + AttestationPayload memory attestationPayload = AttestationPayload( + schemaId, + 1794160904, + bytes(abi.encode(address(0x809e815596AbEB3764aBf81BE2DC39fBBAcc9949))), + bytes(abi.encode(uint8(4))) + ); + + payloadsToAttest.push(attestationPayload); + payloadsToAttest.push(attestationPayload); + + // Create validation payloads + bytes[] memory validationPayload1 = new bytes[](1); + bytes[] memory validationPayload2 = new bytes[](1); + + validationPayloads = new bytes[][](2); + validationPayloads[0] = validationPayload1; + validationPayloads[1] = validationPayload2; + } + + function test_bulkAttest() public { + vm.prank(address(defaultPortal)); + attestationRegistry.bulkAttest(payloadsToAttest, address(this)); + } + + function test_bulkAttestThroughPortal() public { + vm.prank(address(0)); + defaultPortal.bulkAttest(payloadsToAttest, validationPayloads); + } + + function test_massImport() public { + vm.prank(address(0)); + attestationRegistry.massImport(payloadsToAttest, address(defaultPortal)); + } +} From c0c13442776fcb80ba230e950b960ec2de3970a0 Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Tue, 12 Sep 2023 09:21:38 +0200 Subject: [PATCH 03/10] chore: Improve contracts upgrade tooling (#165) --- .eslintignore | 5 + .eslintrc.json | 21 + .github/workflows/smart-contracts-test.yml | 10 +- .gitignore | 9 - .openzeppelin/unknown-59140.json | 1557 ++++++++++++++++++ .openzeppelin/unknown-59144.json | 1214 ++++++++++++++ .prettierignore | 7 +- README.md | 28 +- package.json | 31 +- pnpm-lock.yaml | 481 ++++++ script/deploy/postDeployment.ts | 66 +- script/recreateNetworkFile.ts | 44 + script/{ => upgrade}/checkUpgradeability.ts | 6 + script/upgrade/checkUpgradeable.ts | 44 + script/upgrade/upgradeAttestationRegistry.ts | 30 - script/upgrade/upgradeEverything.ts | 153 ++ script/upgrade/upgradeModuleRegistry.ts | 27 - script/upgrade/upgradePortalRegistry.ts | 27 - script/upgrade/upgradeRouter.ts | 27 - script/upgrade/upgradeSchemaRegistry.ts | 27 - tsconfig.json | 20 +- 21 files changed, 3620 insertions(+), 214 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .openzeppelin/unknown-59140.json create mode 100644 .openzeppelin/unknown-59144.json create mode 100644 script/recreateNetworkFile.ts rename script/{ => upgrade}/checkUpgradeability.ts (76%) create mode 100644 script/upgrade/checkUpgradeable.ts delete mode 100644 script/upgrade/upgradeAttestationRegistry.ts create mode 100644 script/upgrade/upgradeEverything.ts delete mode 100644 script/upgrade/upgradeModuleRegistry.ts delete mode 100644 script/upgrade/upgradePortalRegistry.ts delete mode 100644 script/upgrade/upgradeRouter.ts delete mode 100644 script/upgrade/upgradeSchemaRegistry.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..b1431ec3 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +# directories +node_modules +coverage +lib +typechain-types diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..2f751e50 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "env": { + "node": true + }, + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "parserOptions": { + "project": ["tsconfig.json"], + "ecmaVersion": "latest", + "sourceType": "module" + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "rules": {}, + "settings": { + "import/resolver": { + "node": { + "extensions": [".ts"] + } + } + } +} diff --git a/.github/workflows/smart-contracts-test.yml b/.github/workflows/smart-contracts-test.yml index 1fa06d7e..964d50d8 100644 --- a/.github/workflows/smart-contracts-test.yml +++ b/.github/workflows/smart-contracts-test.yml @@ -72,7 +72,7 @@ jobs: test-unit: env: FOUNDRY_FUZZ_RUNS: "5000" - needs: [ "lint", "build" ] + needs: ["lint", "build"] runs-on: "ubuntu-latest" steps: - name: "Check out the repo" @@ -84,7 +84,7 @@ jobs: uses: "foundry-rs/foundry-toolchain@v1" - name: "Run the unit tests" - run: "forge test --match-path \"test/*\"" + run: 'forge test --match-path "test/*"' - name: "Add test summary" run: | @@ -92,7 +92,7 @@ jobs: echo "✅ Passed" >> $GITHUB_STEP_SUMMARY coverage: - needs: [ "lint", "build" ] + needs: ["lint", "build"] runs-on: "ubuntu-latest" steps: - name: "Check out the repo" @@ -104,7 +104,7 @@ jobs: uses: "foundry-rs/foundry-toolchain@v1" - name: "Generate the coverage report using the unit tests" - run: "forge coverage --match-path \"test/**/*.sol\" --report lcov" + run: 'forge coverage --match-path "test/**/*.sol" --report lcov' - name: "Upload coverage report to Codecov" uses: "codecov/codecov-action@v3" @@ -126,7 +126,7 @@ jobs: echo "✅ Uploaded to Codecov" >> $GITHUB_STEP_SUMMARY upgradeability: - needs: [ "lint", "build" ] + needs: ["lint", "build"] runs-on: "ubuntu-latest" steps: - name: "Check out the repo" diff --git a/.gitignore b/.gitignore index ed40f473..01253200 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,6 @@ cache/ out/ -# Ignores development broadcast logs -!/broadcast -/broadcast/*/31337/ -/broadcast/**/dry-run/ - -# Docs -docs/ - # Dotenv file .env @@ -28,4 +20,3 @@ coverage cache_hardhat artifacts typechain-types -.openzeppelin diff --git a/.openzeppelin/unknown-59140.json b/.openzeppelin/unknown-59140.json new file mode 100644 index 00000000..c62d79cf --- /dev/null +++ b/.openzeppelin/unknown-59140.json @@ -0,0 +1,1557 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x8D2001F35592d5EC064c8F39025C6CD4F5f29FD3" + }, + "proxies": [ + { + "address": "0xC765F28096F6121C2F2b82D35A4346280164428b", + "kind": "transparent" + }, + { + "address": "0x1a20b2CFA134686306436D2c9f778D7eC6c43A43", + "kind": "transparent" + }, + { + "address": "0x506f88a5Ca8D5F001f2909b029738A40042e42a6", + "kind": "transparent" + }, + { + "address": "0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5", + "kind": "transparent" + }, + { + "address": "0xB2c4Da1f8F08A0CA25862509E5431289BE2b598B", + "kind": "transparent" + } + ], + "impls": { + "b691dd183cf6f473f4ca45c1137ad1eb4864f54ee5022d963c714aff8cf5d54b": { + "address": "0xa1208eCe66C6A646e670Bb544c9D2979f9e21D9d", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3212", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3308_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3212": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3308_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3308_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "0c9cd030e12686ba31b726490fc39fc7d0c02c4f6bdba2a803bc2842b9261c54": { + "address": "0xBcCA16cb798F060e8a7AD347799E6603a09e5F6c", + "txHash": "0x59eb50e0699347e5576ae6ecee5e14aeb6fa0aed4d00bfe706a6d6101a7b4932", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3204", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3298_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3204": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3298_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3298_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "c77665b61bcd61972876c8c704c24310020197885799794579b6e9aa00c78a8a": { + "address": "0xA0067D85002FC7da818bA47dE235638B71eC69c1", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3212", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3340_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3212": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3340_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3340_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "006e27f238452a2f5808f8fb5d6c11cb9676df3258fc26d8485134443eb7f8d3": { + "address": "0x66539A4B90Cca7064634C33164Acb293d5A9Bb33", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3212", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3333_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3212": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3333_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3333_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "4353fbe787c13443291bba3d18e906853909285ba948d10f4d95994940b68c97": { + "address": "0xC88E223D7a11E0b148b14C91411ED47e920f8c97", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "ATTESTATION_REGISTRY", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:13" + }, + { + "label": "MODULE_REGISTRY", + "offset": 0, + "slot": "102", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:14" + }, + { + "label": "PORTAL_REGISTRY", + "offset": 0, + "slot": "103", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:15" + }, + { + "label": "SCHEMA_REGISTRY", + "offset": 0, + "slot": "104", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:16" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "0e565d3af4874384e79b514fc2386c7fa28858f16795fd7f69763b0a84ba7df2": { + "address": "0x5A8726B3EdbCD5554bb5C0508617cB7171495736", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:15" + }, + { + "label": "schemas", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Schema)3228_storage)", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:17" + }, + { + "label": "schemaIds", + "offset": 0, + "slot": "103", + "type": "t_array(t_bytes32)dyn_storage", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:19" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Schema)3228_storage)": { + "label": "mapping(bytes32 => struct Schema)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Schema)3228_storage": { + "label": "struct Schema", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "context", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "schema", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "ff8a575bab2fd43245baebd6bce2e7a2888a6acdf97dfc539c070a79e8173f2e": { + "address": "0x1D20234674D06273cdAf09d027423F311922fC9a", + "txHash": "0x13a63d73b2bdcc8562dd8374fafa75d193c98675da4cb55de93fa0a220e8eb77", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3219_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3219_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3219_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "f4e4150d4d087bd04cd61e521edc4d0f98fef1e6db8e1fce35f8814b72fd9912": { + "address": "0xD2DCbA93FFEF0c1b8E1b08E61F1e57Af24ca3660", + "txHash": "0x71cddfb76a699687ec7bbbdc4c21a4f7e3368f970b2acca9c092e603488b26c7", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3251_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3251_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3251_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "fe9abe8944216c204bb5f7ea53e3426b721b34cea4b43910d9a68a5f197f9601": { + "address": "0x155F661749d5473F6dECfBBC53FB12f262C97127", + "txHash": "0xfd8aaeb612deb671f01b6eab2ed3b64633f1fe9584fdd539edb7ec2d2f6aa324", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3244_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3244_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3244_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + } + } +} diff --git a/.openzeppelin/unknown-59144.json b/.openzeppelin/unknown-59144.json new file mode 100644 index 00000000..6f7d0205 --- /dev/null +++ b/.openzeppelin/unknown-59144.json @@ -0,0 +1,1214 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x31C2b0C23c0B9afEC70229C18efc2C272722c2CF", + "txHash": "0x7122421e79a6e20bb7e76e782e685a083c02586ba23715d8a837a5f1a82323a6" + }, + "proxies": [ + { + "address": "0x4d3a380A03f3a18A5dC44b01119839D8674a552E", + "txHash": "0x7fb25a75962f7193c848bfc3a033521f79719dab96c9322d3ac52faf5fecc9c0", + "kind": "transparent" + }, + { + "address": "0x3de3893aa4Cdea029e84e75223a152FD08315138", + "txHash": "0xff0a1b28e8c51868d25c880df102937878774398fda62b1de2caf59bd0402379", + "kind": "transparent" + }, + { + "address": "0xf851513A732996F22542226341748f3C9978438f", + "txHash": "0xefb44a65ff8aa3671d7a10f7c182a4a5bd6c38f0f419d36eb4e50c52a30bb4b4", + "kind": "transparent" + }, + { + "address": "0xd5d61e4ECDf6d46A63BfdC262af92544DFc19083", + "txHash": "0x2325b2932857308a778ba8bf1ff8494c41f023762c4ca6dfebed1e4fff55a710", + "kind": "transparent" + }, + { + "address": "0x0f95dCec4c7a93F2637eb13b655F2223ea036B59", + "txHash": "0x27aed824935b2b2663a1d5c86d09d87445867b8e408310d159c5cd5cafdfcf9a", + "kind": "transparent" + } + ], + "impls": { + "4353fbe787c13443291bba3d18e906853909285ba948d10f4d95994940b68c97": { + "address": "0xeb205B722d60334Ba8d45A8b4585A6ddfd56Ed83", + "txHash": "0x29d7ef5e5c96a1fd1cfd87b12a86cfdf6a0a1ac5fc1d519ce54d0751c959437a", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "ATTESTATION_REGISTRY", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:13" + }, + { + "label": "MODULE_REGISTRY", + "offset": 0, + "slot": "102", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:14" + }, + { + "label": "PORTAL_REGISTRY", + "offset": 0, + "slot": "103", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:15" + }, + { + "label": "SCHEMA_REGISTRY", + "offset": 0, + "slot": "104", + "type": "t_address", + "contract": "Router", + "src": "src/Router.sol:16" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "0c9cd030e12686ba31b726490fc39fc7d0c02c4f6bdba2a803bc2842b9261c54": { + "address": "0x4F0F6D95CaC2Fa09096987A59eDBc0Ce1DC43b55", + "txHash": "0x36be663d214e9af12a467e7fbe81e8b70d4664374c0621932846325968d0b174", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3204", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3298_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3204": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3298_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3298_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "f4e4150d4d087bd04cd61e521edc4d0f98fef1e6db8e1fce35f8814b72fd9912": { + "address": "0x7121E886F968bd8aE7e8Ff8A0B9918C7d7375aBd", + "txHash": "0xb5ab21a4beee09192a4cb2d806f61ad051844c15995e9c0ab0e98662f872ba6b", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3251_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3251_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3251_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "9083e09e1ae19f3ab4dabddaf4b94ccfd61c0fb4ed51c99b2ccf6170bda98e66": { + "address": "0x7F961B13034F0C798b98Be6db6334254B330191A", + "txHash": "0xe5897bac2ee75a26bfa9c618801b40e6827b0f29330a32b605b0441990344773", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3204", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3323_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3204": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3323_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3323_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "0e565d3af4874384e79b514fc2386c7fa28858f16795fd7f69763b0a84ba7df2": { + "address": "0xC5EB17894CE42c2832c1706D07C2906FB04cc641", + "txHash": "0x50c63069eb28f985f679860dad28022441ddb582976a809d86202a5819d52af8", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:15" + }, + { + "label": "schemas", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Schema)3228_storage)", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:17" + }, + { + "label": "schemaIds", + "offset": 0, + "slot": "103", + "type": "t_array(t_bytes32)dyn_storage", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:19" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Schema)3228_storage)": { + "label": "mapping(bytes32 => struct Schema)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Schema)3228_storage": { + "label": "struct Schema", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "context", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "schema", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "ff8a575bab2fd43245baebd6bce2e7a2888a6acdf97dfc539c070a79e8173f2e": { + "address": "0xc942515d1093b12345a14aDCd6D4c05D7150B9BA", + "txHash": "0xf7da43d02398c5d6397f352d99cc5d47908701f1aa92b8de8b1a4c2e939a934f", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3219_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3219_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3219_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "fe9abe8944216c204bb5f7ea53e3426b721b34cea4b43910d9a68a5f197f9601": { + "address": "0xcEFF2a56FDca7C99506e7fEEeEdfC9F2EE86F62E", + "txHash": "0xf0e925c8f2902ebb71179eaf07f0ffff493db88c1e38e2157f0f530e2d8cce08", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3125", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3244_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3125": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3244_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3244_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + } + } +} diff --git a/.prettierignore b/.prettierignore index 79c2615d..d8bc1655 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,16 +1,13 @@ # directories -.github/workflows broadcast cache coverage -docs lib node_modules out -out-optimized -out-svg artifacts cache_hardhat +typechain-types # files *.env @@ -18,6 +15,4 @@ cache_hardhat .DS_Store .pnp.* lcov.info -package-lock.json pnpm-lock.yaml -yarn.lock diff --git a/README.md b/README.md index c5439d57..6b759bfd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -## Verax (Linea Attestation Registry) +## Verax -**Linea Attestation Registry is a set of contracts that allows anyone to read and write attestations of any type and any -subject.** +**Verax, previously known as "Linea Attestation Registry", is a set of contracts that allows anyone to read and write +attestations of any type and any subject.** ## Foundry Installation @@ -196,7 +196,27 @@ Transaction hash: 0x15b25752da1dfd458b92069248825ce959f5be104f974d62b4ae95050710 11. _Optional_: Deploy some valid modules via the `pnpm run deploy:CorrectModule` command and note down their addresses 12. _Optional_: Deploy an invalid module via the `pnpm run deploy:IncorrectModule` command and note down its address -## Verax contract upgrade +## Verax contracts upgrade + +### Check all registries implementations follow the upgradability rules + +Run `pnpm run check:upgradeability` to check if the local versions of the registries follow the upgradability rules. + +:warning: Note: this is a static check, not run against the already deployed contracts. + +### Check all registries implementations are upgradeable + +Run `pnpm run check:upgradeable:goerli` or `pnpm run check:upgradeable` to check if the already deployed registries are +upgradable to the new local versions. + +:warning: Note: this is a dynamic check, run against the already deployed contracts. + +### Recreate the network files + +Run `pnpm run check:upgradeable:goerli` or `pnpm run check:upgradeable` to re-generate the network files describing the +deployed contracts. This can be useful if the file was lost/modified since the last upgrade or the first deployment. + +:warning: Note: the script will fail if a network file already contains one of the targeted proxy addresses. ### On the Linea Goerli testnet: diff --git a/package.json b/package.json index cb3218b2..af950128 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,11 @@ ], "scripts": { "build": "forge build", - "check:upgradeability": "npx hardhat run script/checkUpgradeability.ts", + "check:upgradeability": "npx hardhat run script/upgrade/checkUpgradeability.ts", "check:upgradeability:ci": "cp .env.example .env && pnpm run check:upgradeability", - "clean": "rm -rf lcov.info coverage .openzeppelin artifacts cache_hardhat cache out typechain-types", + "check:upgradeable": "npx hardhat run --network linea script/upgrade/checkUpgradeable.ts", + "check:upgradeable:goerli": "npx hardhat run --network linea-goerli script/upgrade/checkUpgradeable.ts", + "clean": "rm -rf lcov.info coverage artifacts cache_hardhat cache out typechain-types", "deploy:CorrectModule": "npx hardhat run --network linea script/deploy/deployCorrectModule.ts", "deploy:CorrectModule:goerli": "npx hardhat run --network linea-goerli script/deploy/deployCorrectModule.ts", "deploy:IncorrectModule": "npx hardhat run --network linea script/deploy/deployIncorrectModule.ts", @@ -32,31 +34,26 @@ "deploy:all:goerli": "npx hardhat run --network linea-goerli script/deploy/deployEverything.ts", "deploy:post": "npx hardhat run --network linea script/deploy/postDeployment.ts", "deploy:post:goerli": "npx hardhat run --network linea-goerli script/deploy/postDeployment.ts", - "lint": "pnpm lint:sol && pnpm prettier:check", + "lint": "pnpm lint:sol && eslint . && pnpm prettier:check", "lint:sol": "pnpm solhint \"{script,src,test}/**/*.sol\"", "prepare": "husky install", - "prettier:check": "prettier --check \"**/*.{json,md,svg,yml,sol}\"", - "prettier:write": "prettier --write \"**/*.{json,md,svg,yml,sol}\"", + "prettier:check": "prettier --check \"**/*.{json,md,svg,yml,sol,ts}\"", + "prettier:write": "prettier --write \"**/*.{json,md,svg,yml,sol,ts}\"", + "reimport": "npx hardhat run --network linea script/upgrade/upgradeEverything.ts", + "reimport:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeEverything.ts", "test": "forge test", - "upgrade:all": "pnpm run upgrade:AttestationRegistry && pnpm run upgrade:ModuleRegistry && pnpm run upgrade:PortalRegistry && pnpm run upgrade:Router && pnpm run upgrade:SchemaRegistry", - "upgrade:all:goerli": "pnpm run upgrade:AttestationRegistry:goerli && pnpm run upgrade:ModuleRegistry:goerli && pnpm run upgrade:PortalRegistry:goerli && pnpm run upgrade:Router:goerli && pnpm run upgrade:SchemaRegistry:goerli", - "upgrade:AttestationRegistry": "npx hardhat run --network linea script/upgrade/upgradeAttestationRegistry.ts", - "upgrade:AttestationRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeAttestationRegistry.ts", - "upgrade:ModuleRegistry": "npx hardhat run --network linea script/upgrade/upgradeModuleRegistry.ts", - "upgrade:ModuleRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeModuleRegistry.ts", - "upgrade:PortalRegistry": "npx hardhat run --network linea script/upgrade/upgradePortalRegistry.ts", - "upgrade:PortalRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradePortalRegistry.ts", - "upgrade:Router": "npx hardhat run --network linea script/upgrade/upgradeRouter.ts", - "upgrade:Router:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeRouter.ts", - "upgrade:SchemaRegistry": "npx hardhat run --network linea script/upgrade/upgradeSchemaRegistry.ts", - "upgrade:SchemaRegistry:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeSchemaRegistry.ts" + "upgrade:all": "npx hardhat run --network linea script/upgrade/upgradeEverything.ts", + "upgrade:all:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeEverything.ts" }, "devDependencies": { "@nomicfoundation/hardhat-ethers": "^3.0.4", "@nomicfoundation/hardhat-foundry": "^1.1.1", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/hardhat-upgrades": "^2.2.1", + "@typescript-eslint/eslint-plugin": "^6.6.0", + "@typescript-eslint/parser": "^6.6.0", "dotenv": "^16.3.1", + "eslint": "^8.49.0", "ethers": "^6.7.1", "hardhat": "^2.17.2", "husky": "^8.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59721f27..53c40fc4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,9 +22,18 @@ devDependencies: '@openzeppelin/hardhat-upgrades': specifier: ^2.2.1 version: 2.2.1(@nomicfoundation/hardhat-ethers@3.0.4)(@nomicfoundation/hardhat-verify@1.1.1)(ethers@6.7.1)(hardhat@2.17.2) + '@typescript-eslint/eslint-plugin': + specifier: ^6.6.0 + version: 6.6.0(@typescript-eslint/parser@6.6.0)(eslint@8.49.0)(typescript@5.2.2) + '@typescript-eslint/parser': + specifier: ^6.6.0 + version: 6.6.0(eslint@8.49.0)(typescript@5.2.2) dotenv: specifier: ^16.3.1 version: 16.3.1 + eslint: + specifier: ^8.49.0 + version: 8.49.0 ethers: specifier: ^6.7.1 version: 6.7.1 @@ -49,6 +58,11 @@ devDependencies: packages: + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + /@adraffy/ens-normalize@1.9.2: resolution: {integrity: sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==} dev: true @@ -143,6 +157,43 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.49.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.8.0: + resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.2: + resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@8.1.1) + espree: 9.6.1 + globals: 13.21.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@ethereumjs/rlp@4.0.1: resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} engines: {node: '>=14'} @@ -473,6 +524,26 @@ packages: '@ethersproject/strings': 5.7.0 dev: true + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} @@ -1216,6 +1287,10 @@ packages: '@types/node': 20.5.7 dev: true + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + dev: true + /@types/lru-cache@5.1.1: resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} dev: true @@ -1271,6 +1346,141 @@ packages: '@types/node': 20.5.7 dev: true + /@types/semver@7.5.1: + resolution: {integrity: sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==} + dev: true + + /@typescript-eslint/eslint-plugin@6.6.0(@typescript-eslint/parser@6.6.0)(eslint@8.49.0)(typescript@5.2.2): + resolution: {integrity: sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.8.0 + '@typescript-eslint/parser': 6.6.0(eslint@8.49.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.6.0 + '@typescript-eslint/type-utils': 6.6.0(eslint@8.49.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.6.0(eslint@8.49.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.6.0 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.49.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.6.0(eslint@8.49.0)(typescript@5.2.2): + resolution: {integrity: sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.6.0 + '@typescript-eslint/types': 6.6.0 + '@typescript-eslint/typescript-estree': 6.6.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.6.0 + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.49.0 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.6.0: + resolution: {integrity: sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.6.0 + '@typescript-eslint/visitor-keys': 6.6.0 + dev: true + + /@typescript-eslint/type-utils@6.6.0(eslint@8.49.0)(typescript@5.2.2): + resolution: {integrity: sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.6.0(typescript@5.2.2) + '@typescript-eslint/utils': 6.6.0(eslint@8.49.0)(typescript@5.2.2) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.49.0 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.6.0: + resolution: {integrity: sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.6.0(typescript@5.2.2): + resolution: {integrity: sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.6.0 + '@typescript-eslint/visitor-keys': 6.6.0 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.6.0(eslint@8.49.0)(typescript@5.2.2): + resolution: {integrity: sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.1 + '@typescript-eslint/scope-manager': 6.6.0 + '@typescript-eslint/types': 6.6.0 + '@typescript-eslint/typescript-estree': 6.6.0(typescript@5.2.2) + eslint: 8.49.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.6.0: + resolution: {integrity: sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.6.0 + eslint-visitor-keys: 3.4.3 + dev: true + /abbrev@1.0.9: resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} dev: true @@ -1288,6 +1498,14 @@ packages: queue-microtask: 1.2.3 dev: true + /acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} @@ -2050,6 +2268,15 @@ packages: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + /crypt@0.0.2: resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} dev: true @@ -2173,6 +2400,13 @@ packages: path-type: 4.0.0 dev: true + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + /dotenv@16.3.1: resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} engines: {node: '>=12'} @@ -2325,6 +2559,74 @@ packages: source-map: 0.2.0 dev: true + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) + '@eslint-community/regexpp': 4.8.0 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.49.0 + '@humanwhocodes/config-array': 0.11.11 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4(supports-color@8.1.1) + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.21.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.3 + dev: true + /esprima@2.7.3: resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} engines: {node: '>=0.10.0'} @@ -2337,11 +2639,30 @@ packages: hasBin: true dev: true + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + /estraverse@1.9.3: resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} engines: {node: '>=0.10.0'} dev: true + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2583,6 +2904,13 @@ packages: reusify: 1.0.4 dev: true + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.1.0 + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -2619,11 +2947,24 @@ packages: path-exists: 4.0.0 dev: true + /flat-cache@3.1.0: + resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} + engines: {node: '>=12.0.0'} + dependencies: + flatted: 3.2.7 + keyv: 4.5.3 + rimraf: 3.0.2 + dev: true + /flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true dev: true + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -2814,6 +3155,13 @@ packages: is-glob: 4.0.3 dev: true + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + /glob@5.0.15: resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} dependencies: @@ -2895,6 +3243,13 @@ packages: which: 1.3.1 dev: true + /globals@13.21.0: + resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + /globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -2916,6 +3271,18 @@ packages: slash: 3.0.0 dev: true + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -2926,6 +3293,10 @@ packages: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: true + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + /growl@1.10.5: resolution: {integrity: sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==} engines: {node: '>=4.x'} @@ -3208,6 +3579,11 @@ packages: resolve-from: 4.0.0 dev: true + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + /indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} @@ -3348,6 +3724,11 @@ packages: engines: {node: '>=0.12.0'} dev: true + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + /is-plain-obj@2.1.0: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} @@ -3475,6 +3856,10 @@ packages: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} dev: true + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true @@ -3491,6 +3876,10 @@ packages: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} dev: true + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} dev: true @@ -3539,6 +3928,12 @@ packages: readable-stream: 3.6.2 dev: true + /keyv@4.5.3: + resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} + dependencies: + json-buffer: 3.0.1 + dev: true + /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -3579,6 +3974,14 @@ packages: type-check: 0.3.2 dev: true + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true @@ -3618,6 +4021,10 @@ packages: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} dev: true + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + /lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} dev: true @@ -3903,6 +4310,10 @@ packages: resolution: {integrity: sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==} dev: true + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true @@ -4037,6 +4448,18 @@ packages: word-wrap: 1.2.5 dev: true + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + /ordinal@1.0.3: resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} dev: true @@ -4141,6 +4564,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true @@ -4189,6 +4617,11 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + /prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} @@ -4478,6 +4911,13 @@ packages: glob: 7.2.0 dev: true + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + /ripemd160@2.0.2: resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} dependencies: @@ -4631,6 +5071,18 @@ packages: crypt: 0.0.2 dev: true + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + /shelljs@0.8.5: resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} engines: {node: '>=4'} @@ -5060,6 +5512,15 @@ packages: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true + /ts-api-utils@1.0.3(typescript@5.2.2): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.2.2 + dev: true + /ts-command-line-args@2.5.1: resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} hasBin: true @@ -5150,11 +5611,23 @@ packages: prelude-ls: 1.1.2 dev: true + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + /type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} dev: true + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + /type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -5399,6 +5872,14 @@ packages: isexe: 2.0.0 dev: true + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + /wide-align@1.1.3: resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==} dependencies: diff --git a/script/deploy/postDeployment.ts b/script/deploy/postDeployment.ts index 61d138d6..86a0e918 100644 --- a/script/deploy/postDeployment.ts +++ b/script/deploy/postDeployment.ts @@ -1,48 +1,56 @@ import { ethers } from "hardhat"; import dotenv from "dotenv"; +import { Contract } from "ethers"; dotenv.config({ path: "../.env" }); async function main() { const proxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; console.log("Creating relationship schema using schema registry, with proxy at", proxyAddress); - const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); - const schemaRegistry = SchemaRegistry.attach(proxyAddress); - await createSchema(schemaRegistry, - "Relationship", - "Creates a named relationship between two attestations", - "https://schema.org/Property", - "bytes32 subject, string predicate, bytes32 object"); - await createSchema(schemaRegistry, - "namedGraphRelationship", - "Creates a named relationship between two attestations inside a specific named graph", - "https://schema.org/Property", - "string namedGraph, bytes32 subject, string predicate, bytes32 object"); -} + const schemaRegistry = await ethers.getContractAt("SchemaRegistry", proxyAddress); -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); + await createSchema( + schemaRegistry, + "Relationship", + "Creates a named relationship between two attestations", + "https://schema.org/Property", + "bytes32 subject, string predicate, bytes32 object", + ); + await createSchema( + schemaRegistry, + "namedGraphRelationship", + "Creates a named relationship between two attestations inside a specific named graph", + "https://schema.org/Property", + "string namedGraph, bytes32 subject, string predicate, bytes32 object", + ); +} -async function createSchema(schemaRegistry, schemaName, schemaDescription, schemaContext, schemaString) { +async function createSchema( + schemaRegistry: Contract, + schemaName: string, + schemaDescription: string, + schemaContext: string, + schemaString: string, +) { const schemaId = await schemaRegistry.getIdFromSchemaString(schemaString); const schemaExists = await schemaRegistry.isRegistered(schemaId); if (!schemaExists) { const tx = await schemaRegistry.createSchema(schemaName, schemaDescription, schemaContext, schemaString); await tx.wait(); const schemaCreated = await schemaRegistry.isRegistered(schemaId); - if (schemaCreated) - console.log(`${schemaName} schema creation succeeded, schema id : ${schemaId}`); - - else - console.log(`${schemaName} schema creation failed, schema id : ${schemaId}`); - } - - else { - console.log(`${schemaName} schema already exists, schema id : ${schemaId}`); + if (schemaCreated) { + console.log(`Schema "${schemaName}" successfully created with ID ${schemaId}`); + } else { + throw new Error(`Schema "${schemaName}" creation failed!`); + } + } else { + throw new Error(`Schema "${schemaName}" already exists with ID ${schemaId}`); } } +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/recreateNetworkFile.ts b/script/recreateNetworkFile.ts new file mode 100644 index 00000000..cbcdf765 --- /dev/null +++ b/script/recreateNetworkFile.ts @@ -0,0 +1,44 @@ +import { ethers, upgrades } from "hardhat"; + +/* + * This script aims to rec recreate a lost "network file". + * Forces the import of an existing proxy contract deployment to be used with this plugin. + * OpenZeppelin doc: https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#force-import + * OpenZeppelin doc on network files: https://docs.openzeppelin.com/upgrades-plugins/1.x/network-files + */ +async function main() { + console.log("Re-importing deployed contracts..."); + + console.log("Re-importing AttestationRegistry..."); + const attestationRegistryProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + + await upgrades.forceImport(attestationRegistryProxyAddress, AttestationRegistry, { kind: "transparent" }); + + console.log("Re-importing ModuleRegistry..."); + const moduleRegistryProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + + await upgrades.forceImport(moduleRegistryProxyAddress, ModuleRegistry, { kind: "transparent" }); + + console.log("Re-importing PortalRegistry..."); + const portalRegistryProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + + await upgrades.forceImport(portalRegistryProxyAddress, PortalRegistry, { kind: "transparent" }); + + console.log("Re-importing SchemaRegistry..."); + const schemaRegistryProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + + await upgrades.forceImport(schemaRegistryProxyAddress, SchemaRegistry, { kind: "transparent" }); + + console.log("All contracts are re-imported and the network file is re-created!"); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/checkUpgradeability.ts b/script/upgrade/checkUpgradeability.ts similarity index 76% rename from script/checkUpgradeability.ts rename to script/upgrade/checkUpgradeability.ts index cbe56b14..aa9f2f94 100644 --- a/script/checkUpgradeability.ts +++ b/script/upgrade/checkUpgradeability.ts @@ -1,5 +1,11 @@ import { ethers, upgrades } from "hardhat"; +/* + * This script aims to statically check if the registries contracts follow the rules for upgradability. + * It validates implementation contracts without deploying them. + * OpenZeppelin doc: https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#validate-implementation + * Note: this does not run the check against the already deployed version of the registries. + */ async function main() { console.log("Checking contracts for upgradeability..."); diff --git a/script/upgrade/checkUpgradeable.ts b/script/upgrade/checkUpgradeable.ts new file mode 100644 index 00000000..0d393910 --- /dev/null +++ b/script/upgrade/checkUpgradeable.ts @@ -0,0 +1,44 @@ +import { ethers, upgrades } from "hardhat"; + +/* + * This script aims to dynamically check if the registries contracts are upgradeable. + * Validates a new implementation contract without deploying it and without actually upgrading to it. + * OpenZeppelin doc: https://docs.openzeppelin.com/upgrades-plugins/1.x/api-hardhat-upgrades#validate-upgrade + * Note: this does run the check against the already deployed version of the registries. + */ +async function main() { + console.log("Checking contracts for upgradeability..."); + + console.log("Checking AttestationRegistry..."); + const attestationRegistryProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + + await upgrades.validateUpgrade(attestationRegistryProxyAddress, AttestationRegistry, { kind: "transparent" }); + + console.log("Checking ModuleRegistry..."); + const moduleRegistryProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + + await upgrades.validateUpgrade(moduleRegistryProxyAddress, ModuleRegistry, { kind: "transparent" }); + + console.log("Checking PortalRegistry..."); + const portalRegistryProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + + await upgrades.validateUpgrade(portalRegistryProxyAddress, PortalRegistry, { kind: "transparent" }); + + console.log("Checking SchemaRegistry..."); + const schemaRegistryProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + + await upgrades.validateUpgrade(schemaRegistryProxyAddress, SchemaRegistry, { kind: "transparent" }); + + console.log("All contracts are upgradeable!"); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradeAttestationRegistry.ts b/script/upgrade/upgradeAttestationRegistry.ts deleted file mode 100644 index c21b4001..00000000 --- a/script/upgrade/upgradeAttestationRegistry.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ethers, run, upgrades } from "hardhat"; -import dotenv from "dotenv"; - -dotenv.config({ path: "../.env" }); - -async function main() { - const proxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; - console.log("Upgrading AttestationRegistry, with proxy at", proxyAddress); - const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); - const attestationRegistry = await upgrades.upgradeProxy(proxyAddress, AttestationRegistry); - const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); - - await run("verify:verify", { - address: proxyAddress, - }); - - await attestationRegistry.incrementVersionNumber(); - const newVersion = await attestationRegistry.getVersionNumber(); - - console.log(`AttestationRegistry successfully upgraded to version ${newVersion} and verified!`); - console.log(`Proxy is at ${proxyAddress}`); - console.log(`Implementation is at ${implementationAddress}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/script/upgrade/upgradeEverything.ts b/script/upgrade/upgradeEverything.ts new file mode 100644 index 00000000..1b3f79db --- /dev/null +++ b/script/upgrade/upgradeEverything.ts @@ -0,0 +1,153 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + console.log(`START SCRIPT`); + + const routerProxyAddress = process.env.ROUTER_ADDRESS; + if (!routerProxyAddress) { + throw new Error("Router proxy address not found"); + } + + const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; + if (!attestationProxyAddress) { + throw new Error("Attestation proxy address not found"); + } + + const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; + if (!moduleProxyAddress) { + throw new Error("Module proxy address not found"); + } + + const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; + if (!portalProxyAddress) { + throw new Error("Portal proxy address not found"); + } + + const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + if (!schemaProxyAddress) { + throw new Error("Schema proxy address not found"); + } + + console.log("Upgrading Router, with proxy at", routerProxyAddress); + const Router = await ethers.getContractFactory("Router"); + await upgrades.upgradeProxy(routerProxyAddress, Router); + + console.log(`Router successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading AttestationRegistry, with proxy at", attestationProxyAddress); + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + const attestationRegistry = await upgrades.upgradeProxy(attestationProxyAddress, AttestationRegistry); + + await attestationRegistry.incrementVersionNumber(); + + console.log(`AttestationRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading ModuleRegistry, with proxy at", moduleProxyAddress); + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + await upgrades.upgradeProxy(moduleProxyAddress, ModuleRegistry); + + console.log(`ModuleRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading PortalRegistry, with proxy at", portalProxyAddress); + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + await upgrades.upgradeProxy(portalProxyAddress, PortalRegistry); + + console.log(`PortalRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading SchemaRegistry, with proxy at", schemaProxyAddress); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + await upgrades.upgradeProxy(schemaProxyAddress, SchemaRegistry); + + console.log(`SchemaRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + const routerImplementationAddress = await upgrades.erc1967.getImplementationAddress(routerProxyAddress); + + await run("verify:verify", { + address: routerProxyAddress, + }); + + console.log(`Router successfully upgraded and verified!`); + console.log(`Proxy is at ${routerProxyAddress}`); + console.log(`Implementation is at ${routerImplementationAddress}`); + + console.log(`\n----\n`); + + const attestationImplementationAddress = await upgrades.erc1967.getImplementationAddress(attestationProxyAddress); + + await run("verify:verify", { + address: attestationProxyAddress, + }); + + const newVersion = await attestationRegistry.getVersionNumber(); + + console.log(`AttestationRegistry successfully upgraded to version ${newVersion} and verified!`); + console.log(`Proxy is at ${attestationProxyAddress}`); + console.log(`Implementation is at ${attestationImplementationAddress}`); + + console.log(`\n----\n`); + + const moduleImplementationAddress = await upgrades.erc1967.getImplementationAddress(moduleProxyAddress); + + await run("verify:verify", { + address: moduleProxyAddress, + }); + + console.log(`ModuleRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${moduleProxyAddress}`); + console.log(`Implementation is at ${moduleImplementationAddress}`); + + console.log(`\n----\n`); + + const portalImplementationAddress = await upgrades.erc1967.getImplementationAddress(portalProxyAddress); + + await run("verify:verify", { + address: portalProxyAddress, + }); + + console.log(`PortalRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${portalProxyAddress}`); + console.log(`Implementation is at ${portalImplementationAddress}`); + + console.log(`\n----\n`); + + const schemaImplementationAddress = await upgrades.erc1967.getImplementationAddress(schemaProxyAddress); + + await run("verify:verify", { + address: schemaProxyAddress, + }); + + console.log(`SchemaRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${schemaProxyAddress}`); + console.log(`Implementation is at ${schemaImplementationAddress}`); + + console.log(`\n----\n`); + + console.log(`** SUMMARY **`); + console.log(`Router = ${routerProxyAddress}`); + console.log(`AttestationRegistry = ${attestationProxyAddress}`); + console.log(`ModuleRegistry = ${moduleProxyAddress}`); + console.log(`PortalRegistry = ${portalProxyAddress}`); + console.log(`SchemaRegistry = ${schemaProxyAddress}`); + + console.log(`END SCRIPT`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/script/upgrade/upgradeModuleRegistry.ts b/script/upgrade/upgradeModuleRegistry.ts deleted file mode 100644 index 9b066197..00000000 --- a/script/upgrade/upgradeModuleRegistry.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ethers, run, upgrades } from "hardhat"; -import dotenv from "dotenv"; - -dotenv.config({ path: "../.env" }); - -async function main() { - const proxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; - console.log("Upgrading ModuleRegistry, with proxy at", proxyAddress); - const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); - await upgrades.upgradeProxy(proxyAddress, ModuleRegistry); - const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); - - await run("verify:verify", { - address: proxyAddress, - }); - - console.log(`ModuleRegistry successfully upgraded and verified!`); - console.log(`Proxy is at ${proxyAddress}`); - console.log(`Implementation is at ${implementationAddress}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/script/upgrade/upgradePortalRegistry.ts b/script/upgrade/upgradePortalRegistry.ts deleted file mode 100644 index 7a0873f4..00000000 --- a/script/upgrade/upgradePortalRegistry.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ethers, run, upgrades } from "hardhat"; -import dotenv from "dotenv"; - -dotenv.config({ path: "../.env" }); - -async function main() { - const proxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; - console.log("Upgrading PortalRegistry, with proxy at", proxyAddress); - const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); - await upgrades.upgradeProxy(proxyAddress, PortalRegistry); - const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); - - await run("verify:verify", { - address: proxyAddress, - }); - - console.log(`PortalRegistry successfully upgraded and verified!`); - console.log(`Proxy is at ${proxyAddress}`); - console.log(`Implementation is at ${implementationAddress}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/script/upgrade/upgradeRouter.ts b/script/upgrade/upgradeRouter.ts deleted file mode 100644 index dab75a40..00000000 --- a/script/upgrade/upgradeRouter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ethers, run, upgrades } from "hardhat"; -import dotenv from "dotenv"; - -dotenv.config({ path: "../.env" }); - -async function main() { - const proxyAddress = process.env.ROUTER_ADDRESS ?? ""; - console.log("Upgrading Router, with proxy at", proxyAddress); - const Router = await ethers.getContractFactory("Router"); - await upgrades.upgradeProxy(proxyAddress, Router); - const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); - - await run("verify:verify", { - address: proxyAddress, - }); - - console.log(`Router successfully upgraded and verified!`); - console.log(`Proxy is at ${proxyAddress}`); - console.log(`Implementation is at ${implementationAddress}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/script/upgrade/upgradeSchemaRegistry.ts b/script/upgrade/upgradeSchemaRegistry.ts deleted file mode 100644 index 47ea6677..00000000 --- a/script/upgrade/upgradeSchemaRegistry.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ethers, run, upgrades } from "hardhat"; -import dotenv from "dotenv"; - -dotenv.config({ path: "../.env" }); - -async function main() { - const proxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; - console.log("Upgrading SchemaRegistry, with proxy at", proxyAddress); - const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); - await upgrades.upgradeProxy(proxyAddress, SchemaRegistry); - const implementationAddress = await upgrades.erc1967.getImplementationAddress(proxyAddress); - - await run("verify:verify", { - address: proxyAddress, - }); - - console.log(`SchemaRegistry successfully upgraded and verified!`); - console.log(`Proxy is at ${proxyAddress}`); - console.log(`Implementation is at ${implementationAddress}`); -} - -// We recommend this pattern to be able to use async/await everywhere -// and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/tsconfig.json b/tsconfig.json index 574e785c..76d87175 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,19 @@ { "compilerOptions": { - "target": "es2020", - "module": "commonjs", + "target": "ESNext", + "allowJs": false, + "skipLibCheck": true, "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true, "strict": true, - "skipLibCheck": true, - "resolveJsonModule": true - } + "forceConsistentCasingInFileNames": true, + "module": "commonjs", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "typechain-types"] } From 1e11f0fe6e138ddfde43b5e618eb2e28bbff9e49 Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Tue, 12 Sep 2023 11:54:13 +0200 Subject: [PATCH 04/10] feat: As an Issuer, I want my module(s) not to be upgradeable (#179) --- src/example/MsgSenderModule.sol | 8 ++++---- test/example/MsgSenderModule.t.sol | 12 +----------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/example/MsgSenderModule.sol b/src/example/MsgSenderModule.sol index d195c57a..8b114e07 100644 --- a/src/example/MsgSenderModule.sol +++ b/src/example/MsgSenderModule.sol @@ -4,15 +4,15 @@ pragma solidity 0.8.21; import { AbstractModule } from "../interface/AbstractModule.sol"; // solhint-disable-next-line max-line-length import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; -import { Initializable } from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import { AttestationPayload } from "../types/Structs.sol"; /** * @title Msg Sender Module * @author Consensys * @notice This contract is an example of a module, able to check if the transaction sender is a given address + * @dev A module should not be initializable (to prevent it from being upgradeable) */ -contract MsgSenderModule is IERC165Upgradeable, AbstractModule, Initializable { +contract MsgSenderModule is IERC165Upgradeable, AbstractModule { /// @dev The address expected by this module address public expectedMsgSender; @@ -20,9 +20,9 @@ contract MsgSenderModule is IERC165Upgradeable, AbstractModule, Initializable { error WrongTransactionSender(); /** - * @notice Contract initialization + * @param _expectedMsgSender the expected caller to be validated against */ - function initialize(address _expectedMsgSender) public initializer { + constructor(address _expectedMsgSender) { expectedMsgSender = _expectedMsgSender; } diff --git a/test/example/MsgSenderModule.t.sol b/test/example/MsgSenderModule.t.sol index b6d30149..5a83ea7c 100644 --- a/test/example/MsgSenderModule.t.sol +++ b/test/example/MsgSenderModule.t.sol @@ -15,11 +15,9 @@ contract MsgSenderModuleTest is Test { AttestationPayload private attestationPayload; event ModuleRegistered(string name, string description, address moduleAddress); - event Initialized(uint8 version); function setUp() public { - msgSenderModule = new MsgSenderModule(); - msgSenderModule.initialize(expectedMsgSender); + msgSenderModule = new MsgSenderModule(expectedMsgSender); attestationPayload = AttestationPayload( bytes32(uint256(1)), @@ -29,14 +27,6 @@ contract MsgSenderModuleTest is Test { ); } - function testInitialize() public { - msgSenderModule = new MsgSenderModule(); - vm.expectEmit(); - emit Initialized(1); - msgSenderModule.initialize(expectedMsgSender); - assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); - } - function testCorrectMsgSenderAddress() public { assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); bytes[] memory validationPayload = new bytes[](0); From 37d721dafaee87fbf57f7d8600b9712b040ff7eb Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Tue, 12 Sep 2023 12:21:52 +0200 Subject: [PATCH 05/10] fix: Modules shouldn't need an array of validation payloads + chore: Optimize modules for gas (#181) --- src/ModuleRegistry.sol | 8 ++++---- src/example/CorrectModule.sol | 6 ++---- src/example/MsgSenderModule.sol | 5 ++--- src/interface/AbstractModule.sol | 4 ++-- src/interface/AbstractPortal.sol | 14 +++++++------- test/example/MsgSenderModule.t.sol | 18 ++++-------------- 6 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/ModuleRegistry.sol b/src/ModuleRegistry.sol index b709f778..2803de7b 100644 --- a/src/ModuleRegistry.sol +++ b/src/ModuleRegistry.sol @@ -123,23 +123,23 @@ contract ModuleRegistry is OwnableUpgradeable { /** Execute the run method for all given Modules that are registered * @param modulesAddresses the addresses of the registered modules * @param attestationPayload the payload to attest - * @param validationPayload the payloads to check for each module + * @param validationPayloads the payloads to check for each module (one payload per module) * @dev check if modules are registered and execute run method for each module */ function runModules( address[] memory modulesAddresses, AttestationPayload memory attestationPayload, - bytes[] memory validationPayload + bytes[] memory validationPayloads ) public { // If no modules provided, bypass module validation if (modulesAddresses.length == 0) return; // Each module involved must have a corresponding item from the validation payload - if (modulesAddresses.length != validationPayload.length) revert ModuleValidationPayloadMismatch(); + if (modulesAddresses.length != validationPayloads.length) revert ModuleValidationPayloadMismatch(); // For each module check if it is registered and call run method for (uint32 i = 0; i < modulesAddresses.length; i++) { if (!isRegistered(modulesAddresses[i])) revert ModuleNotRegistered(); - AbstractModule(modulesAddresses[i]).run(attestationPayload, validationPayload, tx.origin); + AbstractModule(modulesAddresses[i]).run(attestationPayload, validationPayloads[i], tx.origin); } } diff --git a/src/example/CorrectModule.sol b/src/example/CorrectModule.sol index 77de4b09..5fb01f19 100644 --- a/src/example/CorrectModule.sol +++ b/src/example/CorrectModule.sol @@ -11,11 +11,9 @@ contract CorrectModule is AbstractModule, IERC165Upgradeable { function run( AttestationPayload memory /*attestationPayload*/, - bytes[] memory validationPayload, + bytes memory validationPayload, address /*txSender*/ - ) public pure override returns (bytes[] memory) { - return (validationPayload); - } + ) public pure override {} function supportsInterface(bytes4 interfaceID) public pure override returns (bool) { return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; diff --git a/src/example/MsgSenderModule.sol b/src/example/MsgSenderModule.sol index 8b114e07..f5e17e66 100644 --- a/src/example/MsgSenderModule.sol +++ b/src/example/MsgSenderModule.sol @@ -31,10 +31,9 @@ contract MsgSenderModule is IERC165Upgradeable, AbstractModule { */ function run( AttestationPayload memory /*_attestationPayload*/, - bytes[] memory _validationPayload, + bytes memory /*_validationPayload*/, address _txSender - ) public view override returns (bytes[] memory validationPayload) { - validationPayload = _validationPayload; + ) public view override { if (_txSender != expectedMsgSender) { revert WrongTransactionSender(); } diff --git a/src/interface/AbstractModule.sol b/src/interface/AbstractModule.sol index 4776fca3..76ffdc84 100644 --- a/src/interface/AbstractModule.sol +++ b/src/interface/AbstractModule.sol @@ -6,7 +6,7 @@ import { AttestationPayload } from "../types/Structs.sol"; abstract contract AbstractModule { function run( AttestationPayload memory attestationPayload, - bytes[] memory validationPayload, + bytes memory validationPayload, address txSender - ) public virtual returns (bytes[] memory moduleValidationPayload); + ) public virtual; } diff --git a/src/interface/AbstractPortal.sol b/src/interface/AbstractPortal.sol index a7aaae44..b0c2e1b5 100644 --- a/src/interface/AbstractPortal.sol +++ b/src/interface/AbstractPortal.sol @@ -39,14 +39,14 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { /** * @notice attest the schema with given attestationPayload and validationPayload * @param attestationPayload the payload to attest - * @param validationPayload the payload to validate via the modules to issue the attestations + * @param validationPayloads the payloads to validate via the modules to issue the attestations * @dev Runs all modules for the portal and registers the attestation using AttestationRegistry */ function attest( AttestationPayload memory attestationPayload, - bytes[] memory validationPayload + bytes[] memory validationPayloads ) public payable virtual { - if (modules.length != 0) _runModules(attestationPayload, validationPayload); + if (modules.length != 0) _runModules(attestationPayload, validationPayloads); _beforeAttest(attestationPayload, msg.value); @@ -114,12 +114,12 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { /** * @notice Runs all the modules linked to the Portal to check their logic against the validation payload * @param attestationPayload the attestation payload supposed to be attested - * @param validationPayload the list of payloads used by modules + * @param validationPayloads the list of payloads used by modules * @dev Each module must have its own item in the list of validation payloads */ - function _runModules(AttestationPayload memory attestationPayload, bytes[] memory validationPayload) internal { - if (modules.length != validationPayload.length) revert ModulePayloadMismatch(); - moduleRegistry.runModules(modules, attestationPayload, validationPayload); + function _runModules(AttestationPayload memory attestationPayload, bytes[] memory validationPayloads) internal { + if (modules.length != validationPayloads.length) revert ModulePayloadMismatch(); + moduleRegistry.runModules(modules, attestationPayload, validationPayloads); } /** diff --git a/test/example/MsgSenderModule.t.sol b/test/example/MsgSenderModule.t.sol index 5a83ea7c..0e250ba8 100644 --- a/test/example/MsgSenderModule.t.sol +++ b/test/example/MsgSenderModule.t.sol @@ -29,18 +29,17 @@ contract MsgSenderModuleTest is Test { function testCorrectMsgSenderAddress() public { assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); - bytes[] memory validationPayload = new bytes[](0); + bytes memory validationPayload = new bytes(0); address msgSender = expectedMsgSender; - bytes[] memory _validationPayload = msgSenderModule.run(attestationPayload, validationPayload, msgSender); - - assertBytesArrayEq(_validationPayload, validationPayload); + msgSenderModule.run(attestationPayload, validationPayload, msgSender); } function testIncorrectMsgSenderAddress() public { assertEq(msgSenderModule.expectedMsgSender(), expectedMsgSender); - bytes[] memory validationPayload = new bytes[](0); + bytes memory validationPayload = new bytes(0); address incorrectMsgSender = address(1); + vm.expectRevert(MsgSenderModule.WrongTransactionSender.selector); msgSenderModule.run(attestationPayload, validationPayload, incorrectMsgSender); } @@ -51,13 +50,4 @@ contract MsgSenderModuleTest is Test { bool isAbstractModuleSupported = msgSenderModule.supportsInterface(type(AbstractModule).interfaceId); assertEq(isAbstractModuleSupported, true); } - - function assertBytesArrayEq(bytes[] memory actualBytesArray, bytes[] memory expectedBytesArray) public { - // Compare bytes[] arrays using assertEq - require(expectedBytesArray.length == actualBytesArray.length, "Number of elements are not equal"); - - for (uint256 i = 0; i < expectedBytesArray.length; i++) { - assertEq(expectedBytesArray[i], actualBytesArray[i]); - } - } } From d46ccd07f455f8530631445431ea1828e1ec92ef Mon Sep 17 00:00:00 2001 From: Satyajeet Kolhapure <77279246+satyajeetkolhapure@users.noreply.github.com> Date: Tue, 12 Sep 2023 16:18:00 +0100 Subject: [PATCH 06/10] feat: As a user, I want the schema context field to be updateable (#185) Co-authored-by: Satyajeet Kolhapure --- src/SchemaRegistry.sol | 11 +++++++++++ test/SchemaRegistry.t.sol | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/SchemaRegistry.sol b/src/SchemaRegistry.sol index 9c1318ad..89ee16c5 100644 --- a/src/SchemaRegistry.sol +++ b/src/SchemaRegistry.sol @@ -107,6 +107,17 @@ contract SchemaRegistry is OwnableUpgradeable { emit SchemaCreated(schemaId, name, description, context, schemaString); } + /** Update a context field of schema : + * @param schemaId the schema ID + * @param context the Schema context + * @dev Retrieve the Schema with given ID and update its context with new value + */ + function updateContext(bytes32 schemaId, string memory context) public onlyIssuers(msg.sender) { + if (!isRegistered(schemaId)) revert SchemaNotRegistered(); + if (bytes(context).length == 0) revert SchemaContextMissing(); + schemas[schemaId].context = context; + } + /** * @notice Gets a schema by its identifier * @param schemaId the schema ID diff --git a/test/SchemaRegistry.t.sol b/test/SchemaRegistry.t.sol index 5a8ed7cf..cbe9c243 100644 --- a/test/SchemaRegistry.t.sol +++ b/test/SchemaRegistry.t.sol @@ -108,6 +108,46 @@ contract SchemaRegistryTest is Test { vm.stopPrank(); } + function testUpdateContext() public { + vm.expectEmit(); + emit SchemaCreated(expectedId, expectedName, expectedDescription, expectedContext, expectedString); + vm.startPrank(user); + + // create a schema + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + assertEq(schemaRegistry.getSchema(expectedId).context, expectedContext); + + // update the context + string memory newContext = "New context"; + schemaRegistry.updateContext(expectedId, newContext); + assertEq(schemaRegistry.getSchema(expectedId).context, newContext); + + vm.stopPrank(); + } + + function testCannotUpdateContextWithInvalidIssuer() public { + vm.expectRevert(SchemaRegistry.OnlyIssuer.selector); + vm.startPrank(makeAddr("InvalidIssuer")); + schemaRegistry.updateContext(expectedId, "New context"); + vm.stopPrank(); + } + + function testCannotUpdateContextWithSchemaNotRegistered() public { + vm.startPrank(user); + vm.expectRevert(SchemaRegistry.SchemaNotRegistered.selector); + schemaRegistry.updateContext("Invalid ID", "New context"); + vm.stopPrank(); + } + + function testCannotUpdateContextWithSchemaContextMissing() public { + vm.startPrank(user); + schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); + + vm.expectRevert(SchemaRegistry.SchemaContextMissing.selector); + schemaRegistry.updateContext(expectedId, ""); + vm.stopPrank(); + } + function testGetSchema() public { vm.startPrank(user); schemaRegistry.createSchema(expectedName, expectedDescription, expectedContext, expectedString); From 0481ff305a155df34a6a5b6afb3d3e9dbe4683e5 Mon Sep 17 00:00:00 2001 From: ollie <67156692+0xEillo@users.noreply.github.com> Date: Wed, 13 Sep 2023 12:18:25 +0200 Subject: [PATCH 07/10] feature: As an Issuer, I want to benefit from a payable Module#183 (#184) --- .gitmodules | 3 ++ hardhat.config.ts | 4 +-- lib/openzeppelin-contracts | 1 + src/ModuleRegistry.sol | 27 ++++++--------- src/example/CorrectModule.sol | 11 ++----- src/example/EASPortal.sol | 4 +-- src/example/MsgSenderModule.sol | 14 ++------ src/example/PayableModule.sol | 46 ++++++++++++++++++++++++++ src/interface/AbstractModule.sol | 13 ++++++-- src/interface/AbstractPortal.sol | 35 ++++++++------------ src/portal/DefaultPortal.sol | 4 +-- test/AttestationRegistry.t.sol | 1 - test/ModuleRegistry.t.sol | 9 +++-- test/PortalRegistry.t.sol | 1 - test/Router.t.sol | 1 - test/SchemaRegistry.t.sol | 1 - test/example/EASPortal.t.sol | 1 - test/example/MsgSenderModule.t.sol | 9 ++--- test/example/PayableModule.t.sol | 53 ++++++++++++++++++++++++++++++ test/mocks/ModuleRegistryMock.sol | 3 +- test/mocks/ValidPortalMock.sol | 4 +-- test/portal/DefaultPortal.t.sol | 1 - 22 files changed, 159 insertions(+), 87 deletions(-) create mode 160000 lib/openzeppelin-contracts create mode 100644 src/example/PayableModule.sol create mode 100644 test/example/PayableModule.t.sol diff --git a/.gitmodules b/.gitmodules index b6afba79..5ee5fc62 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,6 @@ branch = "release-v4.9" path = "lib/openzeppelin-contracts-upgradeable" url = "https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable" +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/hardhat.config.ts b/hardhat.config.ts index f1c98413..19667d99 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -22,11 +22,11 @@ const config: HardhatUserConfig = { hardhat: {}, "linea-goerli": { url: `https://linea-goerli.infura.io/v3/${process.env.INFURA_KEY ?? ""}`, - accounts: [process.env.PRIVATE_KEY ?? ""], + accounts: [process.env.PRIVATE_KEY ?? "0000000000000000000000000000000000000000000000000000000000000000"], }, linea: { url: `https://linea-mainnet.infura.io/v3/${process.env.INFURA_KEY ?? ""}`, - accounts: [process.env.PRIVATE_KEY ?? ""], + accounts: [process.env.PRIVATE_KEY ?? "0000000000000000000000000000000000000000000000000000000000000000"], }, }, paths: { diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 00000000..fd81a96f --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90 diff --git a/src/ModuleRegistry.sol b/src/ModuleRegistry.sol index 2803de7b..be12aa70 100644 --- a/src/ModuleRegistry.sol +++ b/src/ModuleRegistry.sol @@ -96,24 +96,14 @@ contract ModuleRegistry is OwnableUpgradeable { string memory description, address moduleAddress ) public onlyIssuers(msg.sender) { - if (bytes(name).length == 0) { - revert ModuleNameMissing(); - } - + if (bytes(name).length == 0) revert ModuleNameMissing(); // Check if moduleAddress is a smart contract address - if (!isContractAddress(moduleAddress)) { - revert ModuleAddressInvalid(); - } - + if (!isContractAddress(moduleAddress)) revert ModuleAddressInvalid(); // Check if module has implemented AbstractModule - if (!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModule).interfaceId)) { + if (!ERC165CheckerUpgradeable.supportsInterface(moduleAddress, type(AbstractModule).interfaceId)) revert ModuleInvalid(); - } - // Module address is used to identify uniqueness of the module - if (bytes(modules[moduleAddress].name).length > 0) { - revert ModuleAlreadyExists(); - } + if (bytes(modules[moduleAddress].name).length > 0) revert ModuleAlreadyExists(); modules[moduleAddress] = Module(moduleAddress, name, description); moduleAddresses.push(moduleAddress); @@ -129,7 +119,8 @@ contract ModuleRegistry is OwnableUpgradeable { function runModules( address[] memory modulesAddresses, AttestationPayload memory attestationPayload, - bytes[] memory validationPayloads + bytes[] memory validationPayloads, + uint256 value ) public { // If no modules provided, bypass module validation if (modulesAddresses.length == 0) return; @@ -139,7 +130,7 @@ contract ModuleRegistry is OwnableUpgradeable { // For each module check if it is registered and call run method for (uint32 i = 0; i < modulesAddresses.length; i++) { if (!isRegistered(modulesAddresses[i])) revert ModuleNotRegistered(); - AbstractModule(modulesAddresses[i]).run(attestationPayload, validationPayloads[i], tx.origin); + AbstractModule(modulesAddresses[i]).run(attestationPayload, validationPayloads[i], tx.origin, value); } } @@ -148,6 +139,8 @@ contract ModuleRegistry is OwnableUpgradeable { * @param attestationsPayloads the payloads to attest * @param validationPayloads the payloads to check for each module * @dev check if modules are registered and execute run method for each module + * @dev NOTE: Currently the bulk run modules does not handle payable modules + * a default value of 0 is used. */ function bulkRunModules( address[] memory modulesAddresses, @@ -155,7 +148,7 @@ contract ModuleRegistry is OwnableUpgradeable { bytes[][] memory validationPayloads ) public { for (uint32 i = 0; i < modulesAddresses.length; i++) { - runModules(modulesAddresses, attestationsPayloads[i], validationPayloads[i]); + runModules(modulesAddresses, attestationsPayloads[i], validationPayloads[i], 0); } } diff --git a/src/example/CorrectModule.sol b/src/example/CorrectModule.sol index 5fb01f19..f963c3cb 100644 --- a/src/example/CorrectModule.sol +++ b/src/example/CorrectModule.sol @@ -3,19 +3,14 @@ pragma solidity 0.8.21; import { AbstractModule } from "../interface/AbstractModule.sol"; import { AttestationPayload } from "../types/Structs.sol"; -// solhint-disable-next-line max-line-length -import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; -contract CorrectModule is AbstractModule, IERC165Upgradeable { +contract CorrectModule is AbstractModule { function test() public {} function run( AttestationPayload memory /*attestationPayload*/, bytes memory validationPayload, - address /*txSender*/ + address /*txSender*/, + uint256 /*value*/ ) public pure override {} - - function supportsInterface(bytes4 interfaceID) public pure override returns (bool) { - return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; - } } diff --git a/src/example/EASPortal.sol b/src/example/EASPortal.sol index 6d5ba425..b3210230 100644 --- a/src/example/EASPortal.sol +++ b/src/example/EASPortal.sol @@ -38,9 +38,9 @@ contract EASPortal is AbstractPortal { /// @notice Error thrown when trying to bulk revoke attestations error NoBulkRevocation(); - function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {} + function withdraw(address payable to, uint256 amount) external override {} - function _afterAttest() internal override {} + function _onAttest(AttestationPayload memory attestation) internal override {} function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} diff --git a/src/example/MsgSenderModule.sol b/src/example/MsgSenderModule.sol index f5e17e66..d7f05d08 100644 --- a/src/example/MsgSenderModule.sol +++ b/src/example/MsgSenderModule.sol @@ -2,8 +2,6 @@ pragma solidity 0.8.21; import { AbstractModule } from "../interface/AbstractModule.sol"; -// solhint-disable-next-line max-line-length -import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; import { AttestationPayload } from "../types/Structs.sol"; /** @@ -12,7 +10,7 @@ import { AttestationPayload } from "../types/Structs.sol"; * @notice This contract is an example of a module, able to check if the transaction sender is a given address * @dev A module should not be initializable (to prevent it from being upgradeable) */ -contract MsgSenderModule is IERC165Upgradeable, AbstractModule { +contract MsgSenderModule is AbstractModule { /// @dev The address expected by this module address public expectedMsgSender; @@ -32,17 +30,11 @@ contract MsgSenderModule is IERC165Upgradeable, AbstractModule { function run( AttestationPayload memory /*_attestationPayload*/, bytes memory /*_validationPayload*/, - address _txSender + address _txSender, + uint256 /*_value*/ ) public view override { if (_txSender != expectedMsgSender) { revert WrongTransactionSender(); } } - - /** - * @notice To check this contract implements the Module interface - */ - function supportsInterface(bytes4 interfaceID) external pure returns (bool) { - return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165Upgradeable).interfaceId; - } } diff --git a/src/example/PayableModule.sol b/src/example/PayableModule.sol new file mode 100644 index 00000000..14a5c82f --- /dev/null +++ b/src/example/PayableModule.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractModule } from "../interface/AbstractModule.sol"; +import { AttestationPayload } from "../types/Structs.sol"; +import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; + +/** + * @title Payable Module + * @author Consensys + * @notice This contract is an example of a module, able to charge a fee for attestations + */ +contract PayableModule is Ownable, AbstractModule { + uint256 public attestationFee; + + /// @notice Error thrown when an invalid attestation fee is provided + error InvalidAttestationFee(); + + /** + * @param _attestationFee The fee required to attest + */ + constructor(uint256 _attestationFee) { + attestationFee = _attestationFee; + } + + /** + * @notice Set the fee required to attest + * @param _attestationFee The fee required to attest + */ + function setFee(uint256 _attestationFee) public onlyOwner { + attestationFee = _attestationFee; + } + + /** + * @notice The main method for the module, running the check + * @param _value The value sent for the attestation + */ + function run( + AttestationPayload memory /*_attestationPayload*/, + bytes memory /*_validationPayload*/, + address /*_txSender*/, + uint256 _value + ) public view override { + if (_value < attestationFee) revert InvalidAttestationFee(); + } +} diff --git a/src/interface/AbstractModule.sol b/src/interface/AbstractModule.sol index 76ffdc84..8c7fda6d 100644 --- a/src/interface/AbstractModule.sol +++ b/src/interface/AbstractModule.sol @@ -2,11 +2,20 @@ pragma solidity 0.8.21; import { AttestationPayload } from "../types/Structs.sol"; +import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -abstract contract AbstractModule { +abstract contract AbstractModule is IERC165 { function run( AttestationPayload memory attestationPayload, bytes memory validationPayload, - address txSender + address txSender, + uint256 value ) public virtual; + + /** + * @notice To check this contract implements the Module interface + */ + function supportsInterface(bytes4 interfaceID) public pure virtual override returns (bool) { + return interfaceID == type(AbstractModule).interfaceId || interfaceID == type(IERC165).interfaceId; + } } diff --git a/src/interface/AbstractPortal.sol b/src/interface/AbstractPortal.sol index b0c2e1b5..c940813f 100644 --- a/src/interface/AbstractPortal.sol +++ b/src/interface/AbstractPortal.sol @@ -17,8 +17,6 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { AttestationRegistry public attestationRegistry; PortalRegistry public portalRegistry; - /// @notice Error thrown when the numbers of modules to go through and payloads for them is not the same - error ModulePayloadMismatch(); /// @notice Error thrown when someone else than the portal's owner is trying to revoke error OnlyPortalOwner(); @@ -46,13 +44,11 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { AttestationPayload memory attestationPayload, bytes[] memory validationPayloads ) public payable virtual { - if (modules.length != 0) _runModules(attestationPayload, validationPayloads); + moduleRegistry.runModules(modules, attestationPayload, validationPayloads, msg.value); - _beforeAttest(attestationPayload, msg.value); + _onAttest(attestationPayload); attestationRegistry.attest(attestationPayload, _getAttester()); - - _afterAttest(); } /** @@ -64,9 +60,11 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads ) public payable virtual { - _onBulkAttest(attestationsPayloads, validationPayloads); // Run all modules for all payloads moduleRegistry.bulkRunModules(modules, attestationsPayloads, validationPayloads); + + _onBulkAttest(attestationsPayloads, validationPayloads); + // Register attestations using the attestation registry attestationRegistry.bulkAttest(attestationsPayloads, _getAttester()); } @@ -80,7 +78,9 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { */ function revoke(bytes32 attestationId, bytes32 replacedBy) public virtual { if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + _onRevoke(attestationId, replacedBy); + attestationRegistry.revoke(attestationId, replacedBy); } @@ -91,6 +91,7 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { */ function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public virtual { _onBulkRevoke(attestationIds, replacedBy); + attestationRegistry.bulkRevoke(attestationIds, replacedBy); } @@ -112,27 +113,17 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { } /** - * @notice Runs all the modules linked to the Portal to check their logic against the validation payload - * @param attestationPayload the attestation payload supposed to be attested - * @param validationPayloads the list of payloads used by modules - * @dev Each module must have its own item in the list of validation payloads + * @notice Optional method to withdraw funds from the Portal + * @param to the address to send the funds to + * @param amount the amount to withdraw */ - function _runModules(AttestationPayload memory attestationPayload, bytes[] memory validationPayloads) internal { - if (modules.length != validationPayloads.length) revert ModulePayloadMismatch(); - moduleRegistry.runModules(modules, attestationPayload, validationPayloads); - } + function withdraw(address payable to, uint256 amount) external virtual; /** * @notice Optional method run before a payload is attested * @param attestationPayload the attestation payload supposed to be attested - * @param value the optional ETH value paid for this attestation - */ - function _beforeAttest(AttestationPayload memory attestationPayload, uint256 value) internal virtual; - - /** - * @notice Optional method run after a payload is attested */ - function _afterAttest() internal virtual; + function _onAttest(AttestationPayload memory attestationPayload) internal virtual; /** * @notice Optional method run when attesting a batch of payloads diff --git a/src/portal/DefaultPortal.sol b/src/portal/DefaultPortal.sol index e901c0a0..99e28ed7 100644 --- a/src/portal/DefaultPortal.sol +++ b/src/portal/DefaultPortal.sol @@ -11,9 +11,9 @@ import { AttestationPayload } from "../types/Structs.sol"; * @dev This Portal does not add any logic to the AbstractPortal */ contract DefaultPortal is AbstractPortal { - function _beforeAttest(AttestationPayload memory attestation, uint256 value) internal override {} + function withdraw(address payable to, uint256 amount) external override {} - function _afterAttest() internal override {} + function _onAttest(AttestationPayload memory attestation) internal override {} function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} diff --git a/test/AttestationRegistry.t.sol b/test/AttestationRegistry.t.sol index 382203f8..e8d5a67c 100644 --- a/test/AttestationRegistry.t.sol +++ b/test/AttestationRegistry.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { AttestationRegistry } from "../src/AttestationRegistry.sol"; import { PortalRegistryMock } from "./mocks/PortalRegistryMock.sol"; diff --git a/test/ModuleRegistry.t.sol b/test/ModuleRegistry.t.sol index 723546b4..99e01b9a 100644 --- a/test/ModuleRegistry.t.sol +++ b/test/ModuleRegistry.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { ModuleRegistry } from "../src/ModuleRegistry.sol"; import { CorrectModule } from "../src/example/CorrectModule.sol"; @@ -145,7 +144,7 @@ contract ModuleRegistryTest is Test { // Create validation payload bytes[] memory validationPayload = new bytes[](2); - moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload, 0); } function testRunModulesWithIncorrectNumberOfValidationPayload() public { @@ -162,7 +161,7 @@ contract ModuleRegistryTest is Test { bytes[] memory validationPayload = new bytes[](1); vm.expectRevert(ModuleRegistry.ModuleValidationPayloadMismatch.selector); - moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload, 0); } function testRunModulesWithoutSendingModuleAddresses() public { @@ -172,7 +171,7 @@ contract ModuleRegistryTest is Test { // Create validation payload bytes[] memory validationPayload = new bytes[](0); - moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload, 0); } function testRunModulesForUnregisteredModules() public { @@ -186,7 +185,7 @@ contract ModuleRegistryTest is Test { // execute runModules vm.expectRevert(ModuleRegistry.ModuleNotRegistered.selector); - moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload); + moduleRegistry.runModules(moduleAddresses, attestationPayload, validationPayload, 0); } function testBulkRunModules() public { diff --git a/test/PortalRegistry.t.sol b/test/PortalRegistry.t.sol index 6f1cfc53..438517d4 100644 --- a/test/PortalRegistry.t.sol +++ b/test/PortalRegistry.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { PortalRegistry } from "../src/PortalRegistry.sol"; import { CorrectModule } from "../src/example/CorrectModule.sol"; diff --git a/test/Router.t.sol b/test/Router.t.sol index 268e8d32..10cc6b44 100644 --- a/test/Router.t.sol +++ b/test/Router.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { Router } from "../src/Router.sol"; diff --git a/test/SchemaRegistry.t.sol b/test/SchemaRegistry.t.sol index cbe9c243..ac7a48fa 100644 --- a/test/SchemaRegistry.t.sol +++ b/test/SchemaRegistry.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { SchemaRegistry } from "../src/SchemaRegistry.sol"; import { PortalRegistryMock } from "./mocks/PortalRegistryMock.sol"; diff --git a/test/example/EASPortal.t.sol b/test/example/EASPortal.t.sol index fb18c81c..f72e29bc 100644 --- a/test/example/EASPortal.t.sol +++ b/test/example/EASPortal.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { EASPortal } from "../../src/example/EASPortal.sol"; import { Router } from "../../src/Router.sol"; diff --git a/test/example/MsgSenderModule.t.sol b/test/example/MsgSenderModule.t.sol index 0e250ba8..ce0be45b 100644 --- a/test/example/MsgSenderModule.t.sol +++ b/test/example/MsgSenderModule.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { AbstractModule } from "../../src/interface/AbstractModule.sol"; import { MsgSenderModule } from "../../src/example/MsgSenderModule.sol"; import { AttestationPayload } from "../../src/types/Structs.sol"; -// solhint-disable-next-line max-line-length -import { IERC165Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol"; contract MsgSenderModuleTest is Test { MsgSenderModule private msgSenderModule; @@ -32,7 +29,7 @@ contract MsgSenderModuleTest is Test { bytes memory validationPayload = new bytes(0); address msgSender = expectedMsgSender; - msgSenderModule.run(attestationPayload, validationPayload, msgSender); + msgSenderModule.run(attestationPayload, validationPayload, msgSender, 0); } function testIncorrectMsgSenderAddress() public { @@ -41,12 +38,10 @@ contract MsgSenderModuleTest is Test { address incorrectMsgSender = address(1); vm.expectRevert(MsgSenderModule.WrongTransactionSender.selector); - msgSenderModule.run(attestationPayload, validationPayload, incorrectMsgSender); + msgSenderModule.run(attestationPayload, validationPayload, incorrectMsgSender, 0); } function testSupportsInterface() public { - bool isIERC165Supported = msgSenderModule.supportsInterface(type(IERC165Upgradeable).interfaceId); - assertEq(isIERC165Supported, true); bool isAbstractModuleSupported = msgSenderModule.supportsInterface(type(AbstractModule).interfaceId); assertEq(isAbstractModuleSupported, true); } diff --git a/test/example/PayableModule.t.sol b/test/example/PayableModule.t.sol new file mode 100644 index 00000000..445a9493 --- /dev/null +++ b/test/example/PayableModule.t.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Test } from "forge-std/Test.sol"; +import { AbstractModule } from "../../src/interface/AbstractModule.sol"; +import { PayableModule } from "../../src/example/PayableModule.sol"; +import { AttestationPayload } from "../../src/types/Structs.sol"; + +contract PayableModuleTest is Test { + PayableModule private payableModule; + uint256 private attestationFee = 0.01 ether; + AttestationPayload private attestationPayload; + + function setUp() public { + payableModule = new PayableModule(attestationFee); + + attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + } + + function test_PayableModule() public view { + address payable msgSender = payable(address(0x123)); + bytes memory validationPayload = new bytes(0); + + payableModule.run(attestationPayload, validationPayload, msgSender, attestationFee); + } + + function test_PayableModule_setFee() public { + assertEq(payableModule.attestationFee(), 0.01 ether); + payableModule.setFee(0.001 ether); + assertEq(payableModule.attestationFee(), 0.001 ether); + } + + function test_PayableModule_InvalidAttestationFee() public { + address payable msgSender = payable(address(0x123)); + bytes memory validationPayload = new bytes(0); + + vm.expectRevert(PayableModule.InvalidAttestationFee.selector); + payableModule.run(attestationPayload, validationPayload, msgSender, 0 ether); + + vm.expectRevert(PayableModule.InvalidAttestationFee.selector); + payableModule.run(attestationPayload, validationPayload, msgSender, 0.001 ether); + } + + function testSupportsInterface() public { + bool isAbstractModuleSupported = payableModule.supportsInterface(type(AbstractModule).interfaceId); + assertEq(isAbstractModuleSupported, true); + } +} diff --git a/test/mocks/ModuleRegistryMock.sol b/test/mocks/ModuleRegistryMock.sol index 9a9183fc..33f2c86d 100644 --- a/test/mocks/ModuleRegistryMock.sol +++ b/test/mocks/ModuleRegistryMock.sol @@ -12,7 +12,8 @@ contract ModuleRegistryMock { function runModules( address[] memory modulesAddresses, AttestationPayload memory attestationPayload, - bytes[] memory validationPayload + bytes[] memory validationPayload, + uint256 value ) public {} function bulkRunModules( diff --git a/test/mocks/ValidPortalMock.sol b/test/mocks/ValidPortalMock.sol index 2dd84ca4..42e014e1 100644 --- a/test/mocks/ValidPortalMock.sol +++ b/test/mocks/ValidPortalMock.sol @@ -7,9 +7,9 @@ import { AttestationPayload } from "../../src/types/Structs.sol"; contract ValidPortalMock is AbstractPortal { function test() public {} - function _beforeAttest(AttestationPayload memory attestationPayload, uint256 value) internal override {} + function withdraw(address payable to, uint256 amount) external override {} - function _afterAttest() internal override {} + function _onAttest(AttestationPayload memory attestationPayload) internal override {} function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} diff --git a/test/portal/DefaultPortal.t.sol b/test/portal/DefaultPortal.t.sol index c5048ab1..4d59d948 100644 --- a/test/portal/DefaultPortal.t.sol +++ b/test/portal/DefaultPortal.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import { Vm } from "forge-std/Vm.sol"; import { Test } from "forge-std/Test.sol"; import { AbstractPortal } from "../../src/interface/AbstractPortal.sol"; import { DefaultPortal } from "../../src/portal/DefaultPortal.sol"; From f173c0cdc64601c3bdbb8892e8af3de46fb44b77 Mon Sep 17 00:00:00 2001 From: ollie <67156692+0xEillo@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:48:43 +0200 Subject: [PATCH 08/10] fix: add implementation of hooks in abstract portal (#188) --- src/example/EASPortal.sol | 11 ----------- src/interface/AbstractPortal.sol | 32 ++++++++++++++++---------------- src/portal/DefaultPortal.sol | 11 ----------- test/mocks/ValidPortalMock.sol | 15 --------------- 4 files changed, 16 insertions(+), 53 deletions(-) diff --git a/src/example/EASPortal.sol b/src/example/EASPortal.sol index b3210230..ca2daa4d 100644 --- a/src/example/EASPortal.sol +++ b/src/example/EASPortal.sol @@ -40,17 +40,6 @@ contract EASPortal is AbstractPortal { function withdraw(address payable to, uint256 amount) external override {} - function _onAttest(AttestationPayload memory attestation) internal override {} - - function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} - - function _onBulkAttest( - AttestationPayload[] memory attestationsPayloads, - bytes[][] memory validationPayloads - ) internal override {} - - function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} - function attest(AttestationRequest memory attestationRequest) public payable { bytes[] memory validationPayload = new bytes[](0); diff --git a/src/interface/AbstractPortal.sol b/src/interface/AbstractPortal.sol index c940813f..1befdafe 100644 --- a/src/interface/AbstractPortal.sol +++ b/src/interface/AbstractPortal.sol @@ -34,6 +34,13 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { portalRegistry = PortalRegistry(router.getPortalRegistry()); } + /** + * @notice Optional method to withdraw funds from the Portal + * @param to the address to send the funds to + * @param amount the amount to withdraw + */ + function withdraw(address payable to, uint256 amount) external virtual; + /** * @notice attest the schema with given attestationPayload and validationPayload * @param attestationPayload the payload to attest @@ -113,17 +120,18 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { } /** - * @notice Optional method to withdraw funds from the Portal - * @param to the address to send the funds to - * @param amount the amount to withdraw + * @notice Defines the address of the entity issuing attestations to the subject + * @dev We strongly encourage a reflection when overriding this rule: who should be set as the attester? */ - function withdraw(address payable to, uint256 amount) external virtual; + function _getAttester() public view virtual returns (address) { + return msg.sender; + } /** * @notice Optional method run before a payload is attested * @param attestationPayload the attestation payload supposed to be attested */ - function _onAttest(AttestationPayload memory attestationPayload) internal virtual; + function _onAttest(AttestationPayload memory attestationPayload) internal virtual {} /** * @notice Optional method run when attesting a batch of payloads @@ -133,27 +141,19 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { function _onBulkAttest( AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads - ) internal virtual; + ) internal virtual {} /** * @notice Optional method run when an attestation is revoked or replaced * @param attestationId the attestation ID to revoke * @param replacedBy the replacing attestation ID */ - function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal virtual; + function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal virtual {} /** * @notice Optional method run when a batch of attestations are revoked or replaced * @param attestationIds the attestations IDs to revoke * @param replacedBy the replacing attestations IDs */ - function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal virtual; - - /** - * @notice Defines the address of the entity issuing attestations to the subject - * @dev We strongly encourage a reflection when overriding this rule: who should be set as the attester? - */ - function _getAttester() public view virtual returns (address) { - return msg.sender; - } + function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal virtual {} } diff --git a/src/portal/DefaultPortal.sol b/src/portal/DefaultPortal.sol index 99e28ed7..93a76ae6 100644 --- a/src/portal/DefaultPortal.sol +++ b/src/portal/DefaultPortal.sol @@ -12,15 +12,4 @@ import { AttestationPayload } from "../types/Structs.sol"; */ contract DefaultPortal is AbstractPortal { function withdraw(address payable to, uint256 amount) external override {} - - function _onAttest(AttestationPayload memory attestation) internal override {} - - function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} - - function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} - - function _onBulkAttest( - AttestationPayload[] memory attestationsPayloads, - bytes[][] memory validationPayloads - ) internal override {} } diff --git a/test/mocks/ValidPortalMock.sol b/test/mocks/ValidPortalMock.sol index 42e014e1..89d9b6ef 100644 --- a/test/mocks/ValidPortalMock.sol +++ b/test/mocks/ValidPortalMock.sol @@ -8,19 +8,4 @@ contract ValidPortalMock is AbstractPortal { function test() public {} function withdraw(address payable to, uint256 amount) external override {} - - function _onAttest(AttestationPayload memory attestationPayload) internal override {} - - function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal override {} - - function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal override {} - - function _onBulkAttest( - AttestationPayload[] memory attestationsPayloads, - bytes[][] memory validationPayloads - ) internal override {} - - function _getAttester() public view override returns (address) { - return msg.sender; - } } From 4aac39271e033d000db22ff64d6f844a759a461b Mon Sep 17 00:00:00 2001 From: ollie <67156692+0xEillo@users.noreply.github.com> Date: Fri, 15 Sep 2023 16:48:47 +0200 Subject: [PATCH 09/10] feat: add replace attestation feature (#196) Co-authored-by: Alain Nicolas --- src/AttestationRegistry.sol | 62 +++++++--- src/example/EASPortal.sol | 4 +- src/interface/AbstractPortal.sol | 97 ++++++++++----- src/portal/DefaultPortal.sol | 1 - test/AttestationRegistry.t.sol | 159 +++++++++++++++---------- test/example/EASPortal.t.sol | 4 +- test/mocks/AttestationRegistryMock.sol | 27 ++++- test/mocks/ValidPortalMock.sol | 1 - test/portal/DefaultPortal.t.sol | 58 +++++++-- 9 files changed, 283 insertions(+), 130 deletions(-) diff --git a/src/AttestationRegistry.sol b/src/AttestationRegistry.sol index 3c3772c9..a60c9f62 100644 --- a/src/AttestationRegistry.sol +++ b/src/AttestationRegistry.sol @@ -34,17 +34,19 @@ contract AttestationRegistry is OwnableUpgradeable { error AttestationSubjectFieldEmpty(); /// @notice Error thrown when an attestation data field is empty error AttestationDataFieldEmpty(); + /// @notice Error thrown when an attempt is made to bulk replace with mismatched parameter array lengths + error ArrayLengthMismatch(); /// @notice Error thrown when an attempt is made to revoke an attestation that was already revoked error AlreadyRevoked(); /// @notice Error thrown when an attempt is made to revoke an attestation based on a non-revocable schema error AttestationNotRevocable(); - /// @notice Error thrown when attempting to bulk revoke attestations without the same number of replacing attestations - error BulkRevocationInvalidParams(); /// @notice Event emitted when an attestation is registered event AttestationRegistered(bytes32 indexed attestationId); + /// @notice Event emitted when an attestation is replaced + event AttestationReplaced(bytes32 attestationId, bytes32 replacedBy); /// @notice Event emitted when an attestation is revoked - event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); + event AttestationRevoked(bytes32 attestationId); /// @notice Event emitted when the version number is incremented event VersionUpdated(uint16 version); @@ -147,11 +149,42 @@ contract AttestationRegistry is OwnableUpgradeable { } /** - * @notice Revokes an attestation for given identifier and can replace it by an other one - * @param attestationId the attestation ID to revoke - * @param replacedBy the replacing attestation ID (leave empty to just revoke) + * @notice Replaces an attestation for the given identifier and replaces it with a new attestation + * @param attestationId the ID of the attestation to replace + * @param attestationPayload the attestation payload to create the new attestation and register it + * @param attester the account address issuing the attestation + */ + function replace(bytes32 attestationId, AttestationPayload calldata attestationPayload, address attester) public { + attest(attestationPayload, attester); + revoke(attestationId); + bytes32 replacedBy = bytes32(abi.encode(attestationIdCounter)); + attestations[attestationId].replacedBy = replacedBy; + + emit AttestationReplaced(attestationId, replacedBy); + } + + /** + * @notice Replaces attestations for given identifiers and replaces them with new attestations + * @param attestationIds the list of IDs of the attestations to replace + * @param attestationPayloads the list of attestation payloads to create the new attestations and register them + * @param attester the account address issuing the attestation */ - function revoke(bytes32 attestationId, bytes32 replacedBy) public { + function bulkReplace( + bytes32[] calldata attestationIds, + AttestationPayload[] calldata attestationPayloads, + address attester + ) public { + if (attestationIds.length != attestationPayloads.length) revert ArrayLengthMismatch(); + for (uint256 i = 0; i < attestationIds.length; i++) { + replace(attestationIds[i], attestationPayloads[i], attester); + } + } + + /** + * @notice Revokes an attestation for a given identifier + * @param attestationId the ID of the attestation to revoke + */ + function revoke(bytes32 attestationId) public { if (!isRegistered(attestationId)) revert AttestationNotAttested(); if (attestations[attestationId].revoked) revert AlreadyRevoked(); if (msg.sender != attestations[attestationId].portal) revert OnlyAttestingPortal(); @@ -160,21 +193,16 @@ contract AttestationRegistry is OwnableUpgradeable { attestations[attestationId].revoked = true; attestations[attestationId].revocationDate = uint64(block.timestamp); - if (isRegistered(replacedBy)) attestations[attestationId].replacedBy = replacedBy; - - emit AttestationRevoked(attestationId, replacedBy); + emit AttestationRevoked(attestationId); } /** - * @notice Bulk revokes attestations for given identifiers and can replace them by new ones - * @param attestationIds the attestations IDs to revoke - * @param replacedBy the replacing attestations IDs (leave an ID empty to just revoke) + * @notice Bulk revokes a list of attestations for the given identifiers + * @param attestationIds the IDs of the attestations to revoke */ - function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) external { - if (attestationIds.length != replacedBy.length) revert BulkRevocationInvalidParams(); - + function bulkRevoke(bytes32[] memory attestationIds) external { for (uint256 i = 0; i < attestationIds.length; i++) { - revoke(attestationIds[i], replacedBy[i]); + revoke(attestationIds[i]); } } diff --git a/src/example/EASPortal.sol b/src/example/EASPortal.sol index ca2daa4d..a3b22af4 100644 --- a/src/example/EASPortal.sol +++ b/src/example/EASPortal.sol @@ -74,11 +74,11 @@ contract EASPortal is AbstractPortal { } } - function revoke(bytes32 /*attestationId*/, bytes32 /*replacedBy*/) public pure override { + function _onRevoke(bytes32 /*attestationId*/) internal pure override { revert NoRevocation(); } - function bulkRevoke(bytes32[] memory /*attestationIds*/, bytes32[] memory /*replacedBy*/) public pure override { + function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal pure override { revert NoBulkRevocation(); } diff --git a/src/interface/AbstractPortal.sol b/src/interface/AbstractPortal.sol index 1befdafe..11637aa0 100644 --- a/src/interface/AbstractPortal.sol +++ b/src/interface/AbstractPortal.sol @@ -47,10 +47,7 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { * @param validationPayloads the payloads to validate via the modules to issue the attestations * @dev Runs all modules for the portal and registers the attestation using AttestationRegistry */ - function attest( - AttestationPayload memory attestationPayload, - bytes[] memory validationPayloads - ) public payable virtual { + function attest(AttestationPayload memory attestationPayload, bytes[] memory validationPayloads) public payable { moduleRegistry.runModules(modules, attestationPayload, validationPayloads, msg.value); _onAttest(attestationPayload); @@ -66,40 +63,71 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { function bulkAttest( AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads - ) public payable virtual { - // Run all modules for all payloads + ) public payable { moduleRegistry.bulkRunModules(modules, attestationsPayloads, validationPayloads); _onBulkAttest(attestationsPayloads, validationPayloads); - // Register attestations using the attestation registry attestationRegistry.bulkAttest(attestationsPayloads, _getAttester()); } /** - * @notice Revokes the attestation for the given identifier and can replace it by a new one - * @param attestationId the attestation ID to revoke - * @param replacedBy the replacing attestation ID (leave empty to just revoke) + * @notice Replaces the attestation for the given identifier and replaces it with a new attestation + * @param attestationId the ID of the attestation to replace + * @param attestationPayload the attestation payload to create the new attestation and register it + * @param validationPayloads the payloads to validate via the modules to issue the attestation + * @dev Runs all modules for the portal and registers the attestation using AttestationRegistry + */ + function replace( + bytes32 attestationId, + AttestationPayload memory attestationPayload, + bytes[] memory validationPayloads + ) public payable { + moduleRegistry.runModules(modules, attestationPayload, validationPayloads, msg.value); + + _onReplace(attestationId, attestationPayload); + + attestationRegistry.replace(attestationId, attestationPayload, _getAttester()); + } + + /** + * @notice Bulk replaces the attestation for the given identifiers and replaces them with new attestations + * @param attestationIds the list of IDs of the attestations to replace + * @param attestationsPayloads the list of attestation payloads to create the new attestations and register them + * @param validationPayloads the payloads to validate via the modules to issue the attestations + */ + function bulkReplace( + bytes32[] memory attestationIds, + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) public payable { + moduleRegistry.bulkRunModules(modules, attestationsPayloads, validationPayloads); + + _onBulkReplace(attestationIds, attestationsPayloads, validationPayloads); + + attestationRegistry.bulkReplace(attestationIds, attestationsPayloads, _getAttester()); + } + + /** + * @notice Revokes an attestation for the given identifier + * @param attestationId the ID of the attestation to revoke * @dev By default, revocation is only possible by the portal owner * We strongly encourage implementing such a rule in your Portal if you intend on overriding this method */ - function revoke(bytes32 attestationId, bytes32 replacedBy) public virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + function revoke(bytes32 attestationId) public { + _onRevoke(attestationId); - _onRevoke(attestationId, replacedBy); - - attestationRegistry.revoke(attestationId, replacedBy); + attestationRegistry.revoke(attestationId); } /** - * @notice Bulk revokes attestations for given identifiers and can replace them by new ones - * @param attestationIds the attestations IDs to revoke - * @param replacedBy the replacing attestations IDs (leave an ID empty to just revoke) + * @notice Bulk revokes a list of attestations for the given identifiers + * @param attestationIds the IDs of the attestations to revoke */ - function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public virtual { - _onBulkRevoke(attestationIds, replacedBy); + function bulkRevoke(bytes32[] memory attestationIds) public { + _onBulkRevoke(attestationIds); - attestationRegistry.bulkRevoke(attestationIds, replacedBy); + attestationRegistry.bulkRevoke(attestationIds); } /** @@ -133,6 +161,13 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { */ function _onAttest(AttestationPayload memory attestationPayload) internal virtual {} + /** + * @notice Optional method run when an attestation is replaced + * @param attestationId the ID of the attestation being replaced + * @param attestationPayload the attestation payload to create attestation and register it + */ + function _onReplace(bytes32 attestationId, AttestationPayload memory attestationPayload) internal virtual {} + /** * @notice Optional method run when attesting a batch of payloads * @param attestationsPayloads the payloads to attest @@ -143,17 +178,25 @@ abstract contract AbstractPortal is Initializable, IERC165Upgradeable { bytes[][] memory validationPayloads ) internal virtual {} + function _onBulkReplace( + bytes32[] memory attestationIds, + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal virtual {} + /** * @notice Optional method run when an attestation is revoked or replaced - * @param attestationId the attestation ID to revoke - * @param replacedBy the replacing attestation ID + * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner */ - function _onRevoke(bytes32 attestationId, bytes32 replacedBy) internal virtual {} + function _onRevoke(bytes32 /*attestationId*/) internal virtual { + if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + } /** * @notice Optional method run when a batch of attestations are revoked or replaced - * @param attestationIds the attestations IDs to revoke - * @param replacedBy the replacing attestations IDs + * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner */ - function _onBulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) internal virtual {} + function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual { + if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + } } diff --git a/src/portal/DefaultPortal.sol b/src/portal/DefaultPortal.sol index 93a76ae6..067ac041 100644 --- a/src/portal/DefaultPortal.sol +++ b/src/portal/DefaultPortal.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.21; import { AbstractPortal } from "../interface/AbstractPortal.sol"; -import { AttestationPayload } from "../types/Structs.sol"; /** * @title Default Portal diff --git a/test/AttestationRegistry.t.sol b/test/AttestationRegistry.t.sol index e8d5a67c..342539f2 100644 --- a/test/AttestationRegistry.t.sol +++ b/test/AttestationRegistry.t.sol @@ -21,8 +21,9 @@ contract AttestationRegistryTest is Test { event Initialized(uint8 version); event AttestationRegistered(bytes32 indexed attestationId); event BulkAttestationsRegistered(Attestation[] attestations); - event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); - event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + event AttestationReplaced(bytes32 attestationId, bytes32 replacedBy); + event AttestationRevoked(bytes32 attestationId); + event BulkAttestationsRevoked(bytes32[] attestationId); event VersionUpdated(uint16 version); function setUp() public { @@ -177,6 +178,87 @@ contract AttestationRegistryTest is Test { assertTrue(isRegistered2); } + function test_replace(AttestationPayload memory attestationPayload) public { + vm.assume(attestationPayload.subject.length != 0); + vm.assume(attestationPayload.attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + Attestation memory attestation = _createAttestation(attestationPayload, 1); + vm.prank(portal); + attestationRegistry.attest(attestationPayload, attester); + + vm.prank(portal); + vm.expectEmit(true, true, true, true); + emit AttestationReplaced(attestation.attestationId, bytes32(abi.encode(2))); + attestationRegistry.replace(attestation.attestationId, attestationPayload, attester); + } + + function test_bulkReplace(AttestationPayload[2] memory attestationPayloads) public { + vm.assume(attestationPayloads[0].subject.length != 0); + vm.assume(attestationPayloads[0].attestationData.length != 0); + vm.assume(attestationPayloads[1].subject.length != 0); + vm.assume(attestationPayloads[1].attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayloads[0].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayloads[1].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + Attestation memory attestation1 = _createAttestation(attestationPayloads[0], 1); + Attestation memory attestation2 = _createAttestation(attestationPayloads[1], 2); + + Attestation[] memory attestations = new Attestation[](2); + attestations[0] = attestation1; + attestations[1] = attestation2; + + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationPayloads[0]; + payloadsToAttest[1] = attestationPayloads[1]; + + bytes32[] memory attestationIds = new bytes32[](2); + attestationIds[0] = attestation1.attestationId; + attestationIds[1] = attestation2.attestationId; + + vm.startPrank(portal); + attestationRegistry.bulkAttest(payloadsToAttest, attester); + + attestationRegistry.bulkReplace(attestationIds, payloadsToAttest, attester); + } + + function test_bulkReplace_ArrayLengthMismatch(AttestationPayload[2] memory attestationPayloads) public { + vm.assume(attestationPayloads[0].subject.length != 0); + vm.assume(attestationPayloads[0].attestationData.length != 0); + vm.assume(attestationPayloads[1].subject.length != 0); + vm.assume(attestationPayloads[1].attestationData.length != 0); + + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + attestationPayloads[0].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayloads[1].schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + + Attestation memory attestation1 = _createAttestation(attestationPayloads[0], 1); + Attestation memory attestation2 = _createAttestation(attestationPayloads[1], 2); + + Attestation[] memory attestations = new Attestation[](2); + attestations[0] = attestation1; + attestations[1] = attestation2; + + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationPayloads[0]; + payloadsToAttest[1] = attestationPayloads[1]; + + bytes32[] memory attestationIds = new bytes32[](3); + attestationIds[0] = attestation1.attestationId; + attestationIds[1] = attestation2.attestationId; + attestationIds[2] = bytes32(abi.encode(3)); + + vm.startPrank(portal); + attestationRegistry.bulkAttest(payloadsToAttest, attester); + + vm.expectRevert(AttestationRegistry.ArrayLengthMismatch.selector); + attestationRegistry.bulkReplace(attestationIds, payloadsToAttest, attester); + } + function test_revoke(AttestationPayload memory attestationPayload) public { vm.assume(attestationPayload.subject.length != 0); vm.assume(attestationPayload.attestationData.length != 0); @@ -192,20 +274,18 @@ contract AttestationRegistryTest is Test { assertEq(registeredAttestation.attestationId, bytes32(abi.encode(1))); assertFalse(registeredAttestation.revoked); assertEq(registeredAttestation.revocationDate, 0); - assertEq(registeredAttestation.replacedBy, bytes32(0)); assertEq(registeredAttestation.portal, portal); assertEq(registeredAttestation.attester, attester); vm.expectEmit(true, true, true, true); - emit AttestationRevoked(attestationId, bytes32(0)); - attestationRegistry.revoke(attestationId, bytes32(0)); + emit AttestationRevoked(attestationId); + attestationRegistry.revoke(attestationId); vm.stopPrank(); // Assert final state is a revoked attestation Attestation memory revokedAttestation = attestationRegistry.getAttestation(bytes32(abi.encode(1))); assertTrue(revokedAttestation.revoked); assertEq(revokedAttestation.revocationDate, block.timestamp); - assertEq(revokedAttestation.replacedBy, bytes32(0)); } function test_revoke_AttestationAlreadyRevoked(AttestationPayload memory attestationPayload) public { @@ -218,18 +298,18 @@ contract AttestationRegistryTest is Test { attestationRegistry.attest(attestationPayload, attester); vm.expectEmit(); - emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(0)); - attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + emit AttestationRevoked(bytes32(abi.encode(1))); + attestationRegistry.revoke(bytes32(abi.encode(1))); vm.expectRevert(AttestationRegistry.AlreadyRevoked.selector); - attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + attestationRegistry.revoke(bytes32(abi.encode(1))); vm.stopPrank(); } function test_revoke_AttestationNotAttested() public { vm.expectRevert(AttestationRegistry.AttestationNotAttested.selector); - attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + attestationRegistry.revoke(bytes32(abi.encode(1))); } function test_revoke_OnlyAttestingPortal(AttestationPayload memory attestationPayload) public { @@ -244,7 +324,7 @@ contract AttestationRegistryTest is Test { vm.expectRevert(AttestationRegistry.OnlyAttestingPortal.selector); vm.prank(user); - attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + attestationRegistry.revoke(bytes32(abi.encode(1))); } function test_revoke_AttestationNotRevocable(AttestationPayload memory attestationPayload) public { @@ -268,42 +348,11 @@ contract AttestationRegistryTest is Test { attestationRegistry.attest(attestationPayload, attester); vm.expectRevert(AttestationRegistry.AttestationNotRevocable.selector); - attestationRegistry.revoke(bytes32(abi.encode(1)), ""); + attestationRegistry.revoke(bytes32(abi.encode(1))); vm.stopPrank(); } - function test_revokeAndReplace( - AttestationPayload memory attestationPayloadOrigin, - AttestationPayload memory attestationPayloadReplacement - ) public { - SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); - vm.assume(attestationPayloadOrigin.subject.length != 0); - vm.assume(attestationPayloadOrigin.attestationData.length != 0); - attestationPayloadOrigin.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); - vm.assume(attestationPayloadReplacement.subject.length != 0); - vm.assume(attestationPayloadReplacement.attestationData.length != 0); - attestationPayloadReplacement.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); - schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); - vm.startPrank(portal, attester); - - attestationRegistry.attest(attestationPayloadOrigin, attester); - attestationRegistry.attest(attestationPayloadReplacement, attester); - - // Do revert and replace the attestation - vm.expectEmit(true, true, true, true); - emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(abi.encode(2))); - attestationRegistry.revoke(bytes32(abi.encode(1)), bytes32(abi.encode(2))); - - vm.stopPrank(); - - // Assert final state is a revoked and replaced attestation - Attestation memory revokedAttestation = attestationRegistry.getAttestation(bytes32(abi.encode(1))); - assertTrue(revokedAttestation.revoked); - assertEq(revokedAttestation.revocationDate, block.timestamp); - assertEq(revokedAttestation.replacedBy, bytes32(abi.encode(2))); - } - function test_bulkRevoke(AttestationPayload[3] memory attestationPayloads) public { vm.assume(attestationPayloads[0].subject.length != 0); vm.assume(attestationPayloads[0].attestationData.length != 0); @@ -335,7 +384,6 @@ contract AttestationRegistryTest is Test { assertEq(registeredAttestation1.attestationId, attestationId1); assertFalse(registeredAttestation1.revoked); assertEq(registeredAttestation1.revocationDate, 0); - assertEq(registeredAttestation1.replacedBy, bytes32(0)); assertEq(registeredAttestation1.portal, portal); assertEq(registeredAttestation1.attester, attester); @@ -344,7 +392,6 @@ contract AttestationRegistryTest is Test { assertEq(registeredAttestation2.attestationId, attestationId2); assertFalse(registeredAttestation2.revoked); assertEq(registeredAttestation2.revocationDate, 0); - assertEq(registeredAttestation2.replacedBy, bytes32(0)); assertEq(registeredAttestation2.portal, portal); assertEq(registeredAttestation2.attester, attester); @@ -356,37 +403,21 @@ contract AttestationRegistryTest is Test { replacingAttestations[1] = attestationId3; vm.expectEmit(true, true, true, true); - emit AttestationRevoked(attestationsToRevoke[0], replacingAttestations[0]); + emit AttestationRevoked(attestationsToRevoke[0]); vm.expectEmit(true, true, true, true); - emit AttestationRevoked(attestationsToRevoke[1], replacingAttestations[1]); + emit AttestationRevoked(attestationsToRevoke[1]); - attestationRegistry.bulkRevoke(attestationsToRevoke, replacingAttestations); + attestationRegistry.bulkRevoke(attestationsToRevoke); vm.stopPrank(); // Assert final state is a revoked attestation and a replaced attestation Attestation memory revokedAttestation1 = attestationRegistry.getAttestation(attestationId1); assertTrue(revokedAttestation1.revoked); assertEq(revokedAttestation1.revocationDate, block.timestamp); - assertEq(revokedAttestation1.replacedBy, bytes32(0)); Attestation memory revokedAttestation2 = attestationRegistry.getAttestation(attestationId2); assertTrue(revokedAttestation2.revoked); assertEq(revokedAttestation2.revocationDate, block.timestamp); - assertEq(revokedAttestation2.replacedBy, attestationId3); - } - - function test_bulkRevoke_InvalidParams() public { - bytes32 attestationId1 = bytes32(abi.encode(1)); - bytes32 attestationId2 = bytes32(abi.encode(2)); - - bytes32[] memory attestationsToRevoke = new bytes32[](2); - attestationsToRevoke[0] = attestationId1; - attestationsToRevoke[1] = attestationId2; - bytes32[] memory replacingAttestations = new bytes32[](1); - replacingAttestations[0] = bytes32(0); - - vm.expectRevert(AttestationRegistry.BulkRevocationInvalidParams.selector); - attestationRegistry.bulkRevoke(attestationsToRevoke, replacingAttestations); } function test_isRevocable() public { diff --git a/test/example/EASPortal.t.sol b/test/example/EASPortal.t.sol index f72e29bc..3205b6b4 100644 --- a/test/example/EASPortal.t.sol +++ b/test/example/EASPortal.t.sol @@ -139,7 +139,7 @@ contract EASPortalTest is Test { function test_revoke() public { vm.expectRevert(EASPortal.NoRevocation.selector); - easPortal.revoke(bytes32(uint256(1)), bytes32(uint256(1))); + easPortal.revoke(bytes32(uint256(1))); } function test_bulkRevoke() public { @@ -152,7 +152,7 @@ contract EASPortalTest is Test { replacingAttestations[1] = bytes32(uint256(3)); vm.expectRevert(EASPortal.NoBulkRevocation.selector); - easPortal.bulkRevoke(attestationsToRevoke, replacingAttestations); + easPortal.bulkRevoke(attestationsToRevoke); } function testSupportsInterface() public { diff --git a/test/mocks/AttestationRegistryMock.sol b/test/mocks/AttestationRegistryMock.sol index 9f27511e..c7d09434 100644 --- a/test/mocks/AttestationRegistryMock.sol +++ b/test/mocks/AttestationRegistryMock.sol @@ -9,9 +9,10 @@ contract AttestationRegistryMock { mapping(bytes32 attestationId => Attestation attestation) private attestations; event AttestationRegistered(); + event AttestationReplaced(); event BulkAttestationsRegistered(); - event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); - event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + event AttestationRevoked(bytes32 attestationId); + event BulkAttestationsRevoked(bytes32[] attestationId); function test() public {} @@ -46,14 +47,28 @@ contract AttestationRegistryMock { emit BulkAttestationsRegistered(); } - function revoke(bytes32 attestationId, bytes32 replacedBy) public { + function replace(bytes32 /*attestationId*/, AttestationPayload calldata attestationPayload, address attester) public { + require(bytes32(attestationPayload.schemaId) != 0, "Invalid attestationPayload"); + require(attester != address(0), "Invalid attester"); + + emit AttestationRegistered(); + emit AttestationReplaced(); + } + + function bulkReplace( + bytes32[] calldata attestationId, + AttestationPayload[] calldata attestationPayload, + address attester + ) public {} + + function revoke(bytes32 attestationId) public { require(bytes32(attestationId) != 0, "Invalid attestation"); - emit AttestationRevoked(attestationId, replacedBy); + emit AttestationRevoked(attestationId); } - function bulkRevoke(bytes32[] memory attestationIds, bytes32[] memory replacedBy) public { + function bulkRevoke(bytes32[] memory attestationIds) public { require(attestationIds.length > 0, "Invalid attestation"); - emit BulkAttestationsRevoked(attestationIds, replacedBy); + emit BulkAttestationsRevoked(attestationIds); } function getVersionNumber() public view returns (uint16) { diff --git a/test/mocks/ValidPortalMock.sol b/test/mocks/ValidPortalMock.sol index 89d9b6ef..a9480651 100644 --- a/test/mocks/ValidPortalMock.sol +++ b/test/mocks/ValidPortalMock.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.21; import { AbstractPortal } from "../../src/interface/AbstractPortal.sol"; -import { AttestationPayload } from "../../src/types/Structs.sol"; contract ValidPortalMock is AbstractPortal { function test() public {} diff --git a/test/portal/DefaultPortal.t.sol b/test/portal/DefaultPortal.t.sol index 4d59d948..e601cf6f 100644 --- a/test/portal/DefaultPortal.t.sol +++ b/test/portal/DefaultPortal.t.sol @@ -28,8 +28,8 @@ contract DefaultPortalTest is Test { event BulkAttestationsRegistered(); event ModulesRunForAttestation(); event ModulesBulkRunForAttestation(); - event AttestationRevoked(bytes32 attestationId, bytes32 replacedBy); - event BulkAttestationsRevoked(bytes32[] attestationId, bytes32[] replacedBy); + event AttestationRevoked(bytes32 attestationId); + event BulkAttestationsRevoked(bytes32[] attestationId); function setUp() public { modules.push(address(correctModule)); @@ -106,6 +106,46 @@ contract DefaultPortalTest is Test { defaultPortal.bulkAttest(payloadsToAttest, validationPayloads); } + function test_replace() public { + // Create attestation payload + AttestationPayload memory attestationPayload = AttestationPayload( + bytes32(uint256(1)), + uint64(block.timestamp + 1 days), + bytes("subject"), + new bytes(1) + ); + // Create validation payload + bytes[] memory validationPayload = new bytes[](2); + vm.expectEmit(true, true, true, true); + emit AttestationRegistered(); + defaultPortal.attest(attestationPayload, validationPayload); + defaultPortal.replace(bytes32(abi.encode(1)), attestationPayload, validationPayload); + } + + function test_bulkReplace(AttestationPayload[2] memory attestationPayloads) public { + vm.assume(bytes32(attestationPayloads[0].schemaId) != 0); + vm.assume(bytes32(attestationPayloads[1].schemaId) != 0); + // Create attestations payloads + AttestationPayload[] memory payloadsToAttest = new AttestationPayload[](2); + payloadsToAttest[0] = attestationPayloads[0]; + payloadsToAttest[1] = attestationPayloads[1]; + + // Create validation payloads + bytes[] memory validationPayload1 = new bytes[](1); + bytes[] memory validationPayload2 = new bytes[](1); + + bytes[][] memory validationPayloads = new bytes[][](2); + validationPayloads[0] = validationPayload1; + validationPayloads[1] = validationPayload2; + + bytes32[] memory attestationIds = new bytes32[](2); + attestationIds[0] = bytes32(abi.encode(1)); + attestationIds[1] = bytes32(abi.encode(2)); + + defaultPortal.bulkAttest(payloadsToAttest, validationPayloads); + defaultPortal.bulkReplace(attestationIds, payloadsToAttest, validationPayloads); + } + function test_revoke_byPortalOwner() public { // Create attestation payload AttestationPayload memory attestationPayload = AttestationPayload( @@ -127,8 +167,8 @@ contract DefaultPortalTest is Test { // Revoke the attestation as portal owner vm.prank(portalOwner); vm.expectEmit(true, true, true, true); - emit AttestationRevoked(bytes32(abi.encode(1)), bytes32(0)); - defaultPortal.revoke(bytes32(abi.encode(1)), ""); + emit AttestationRevoked(bytes32(abi.encode(1))); + defaultPortal.revoke(bytes32(abi.encode(1))); } function test_revokeFail_OnlyOwner() public { @@ -152,20 +192,18 @@ contract DefaultPortalTest is Test { // Revoke the attestation as a random user vm.prank(makeAddr("random")); vm.expectRevert(AbstractPortal.OnlyPortalOwner.selector); - defaultPortal.revoke(bytes32(abi.encode(1)), ""); + defaultPortal.revoke(bytes32(abi.encode(1))); } function test_bulkRevoke() public { bytes32[] memory attestationsToRevoke = new bytes32[](2); attestationsToRevoke[0] = bytes32("1"); attestationsToRevoke[1] = bytes32("2"); - bytes32[] memory replacingAttestations = new bytes32[](2); - replacingAttestations[0] = bytes32(0); - replacingAttestations[1] = bytes32(0); vm.expectEmit(true, true, true, true); - emit BulkAttestationsRevoked(attestationsToRevoke, replacingAttestations); - defaultPortal.bulkRevoke(attestationsToRevoke, replacingAttestations); + emit BulkAttestationsRevoked(attestationsToRevoke); + vm.prank(portalOwner); + defaultPortal.bulkRevoke(attestationsToRevoke); } function testSupportsInterface() public { From 56d5ece2e352fe8d7a72e890c0c5868ae9e26c32 Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Mon, 18 Sep 2023 14:32:37 +0200 Subject: [PATCH 10/10] chore: minor fixes on the scripts (#197) --- .openzeppelin/unknown-59140.json | 1364 +++++++++++++++++++++- .openzeppelin/unknown-59144.json | 686 +++++++++++ README.md | 21 +- package.json | 8 +- script/upgrade/forceUpgradeEverything.ts | 163 +++ 5 files changed, 2229 insertions(+), 13 deletions(-) create mode 100644 script/upgrade/forceUpgradeEverything.ts diff --git a/.openzeppelin/unknown-59140.json b/.openzeppelin/unknown-59140.json index c62d79cf..78d21b58 100644 --- a/.openzeppelin/unknown-59140.json +++ b/.openzeppelin/unknown-59140.json @@ -5,19 +5,19 @@ }, "proxies": [ { - "address": "0xC765F28096F6121C2F2b82D35A4346280164428b", + "address": "0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5", "kind": "transparent" }, { - "address": "0x1a20b2CFA134686306436D2c9f778D7eC6c43A43", + "address": "0xC765F28096F6121C2F2b82D35A4346280164428b", "kind": "transparent" }, { - "address": "0x506f88a5Ca8D5F001f2909b029738A40042e42a6", + "address": "0x1a20b2CFA134686306436D2c9f778D7eC6c43A43", "kind": "transparent" }, { - "address": "0x736c78b2f2cBf4F921E8551b2acB6A5Edc9177D5", + "address": "0x506f88a5Ca8D5F001f2909b029738A40042e42a6", "kind": "transparent" }, { @@ -1552,6 +1552,1362 @@ } } } + }, + "3354397cdd6b936261be9fe704079273a944f9c472090d34c4caf5377f5779b1": { + "address": "0x2ff05A30f2CC53754E44b2CdCD7deAe2A5585d4f", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3853_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3853_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3853_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "d3839952abe24ccc6cd8803a91942cfbedf96e5be08d5c3ab72758d5edd7a91d": { + "address": "0xC4A1f3553f4bE4C07be7d70Ecbb9Cd67ee22A299", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3885_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3885_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3885_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "d99b3b345be3281a62d350dd3f4b0dbee11a149a42369670b897db21539dad09": { + "address": "0x2fcCfC76566621A3c1F424970c89a7Cd2D603989", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3878_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3878_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3878_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "7cb0f5d61af565dfb5f94a78e471d8d9ed42c8ee97eddcd926d395437ca8b435": { + "address": "0x4423F69F699B63456DdeB97e46F909c08D61029a", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:15" + }, + { + "label": "schemas", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Schema)3862_storage)", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:17" + }, + { + "label": "schemaIds", + "offset": 0, + "slot": "103", + "type": "t_array(t_bytes32)dyn_storage", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:19" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Schema)3862_storage)": { + "label": "mapping(bytes32 => struct Schema)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Schema)3862_storage": { + "label": "struct Schema", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "context", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "schema", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "3354397cdd6b936261be9fe704079273a944f9c472090d34c4caf5377f5779b1": { + "address": "0x2ff05A30f2CC53754E44b2CdCD7deAe2A5585d4f", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3853_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3853_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3853_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": ["0x2ff05A30f2CC53754E44b2CdCD7deAe2A5585d4f", "0x69Ae216B5CE47Fe5Ff48F36367F0A4d5c9C6C581"] + }, + "d3839952abe24ccc6cd8803a91942cfbedf96e5be08d5c3ab72758d5edd7a91d": { + "address": "0xC4A1f3553f4bE4C07be7d70Ecbb9Cd67ee22A299", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3885_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3885_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3885_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": ["0xC4A1f3553f4bE4C07be7d70Ecbb9Cd67ee22A299", "0xc70a8a53bB389b1FDD2d4a0CF0f865c7866175b4"] + }, + "d99b3b345be3281a62d350dd3f4b0dbee11a149a42369670b897db21539dad09": { + "address": "0x2fcCfC76566621A3c1F424970c89a7Cd2D603989", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3800", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3878_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3800": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3878_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3878_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": ["0x2fcCfC76566621A3c1F424970c89a7Cd2D603989", "0xbcbD81b00033FFCEd2AbFaf6DfA8c3f68CE0e67e"] + }, + "7cb0f5d61af565dfb5f94a78e471d8d9ed42c8ee97eddcd926d395437ca8b435": { + "address": "0x4423F69F699B63456DdeB97e46F909c08D61029a", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3333", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:15" + }, + { + "label": "schemas", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Schema)3395_storage)", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:17" + }, + { + "label": "schemaIds", + "offset": 0, + "slot": "103", + "type": "t_array(t_bytes32)dyn_storage", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:19" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3333": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Schema)3395_storage)": { + "label": "mapping(bytes32 => struct Schema)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Schema)3395_storage": { + "label": "struct Schema", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "context", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "schema", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": ["0x4423F69F699B63456DdeB97e46F909c08D61029a", "0x2aF74120BD6078F6641d63aD69Eb5e63eC692874"] } } } diff --git a/.openzeppelin/unknown-59144.json b/.openzeppelin/unknown-59144.json index 6f7d0205..1c593aa1 100644 --- a/.openzeppelin/unknown-59144.json +++ b/.openzeppelin/unknown-59144.json @@ -1209,6 +1209,692 @@ } } } + }, + "3354397cdd6b936261be9fe704079273a944f9c472090d34c4caf5377f5779b1": { + "address": "0x4c5A945c0b2B61dcdae8eb273fBA9bAF80Bd7b3F", + "txHash": "0x00dcf3f5efe5a2c956f527df528c0073907c01a5db169fd54807f5fcbdd93dc3", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3333", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:16" + }, + { + "label": "version", + "offset": 20, + "slot": "101", + "type": "t_uint16", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:18" + }, + { + "label": "attestationIdCounter", + "offset": 22, + "slot": "101", + "type": "t_uint32", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:19" + }, + { + "label": "attestations", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Attestation)3386_storage)", + "contract": "AttestationRegistry", + "src": "src/AttestationRegistry.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3333": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Attestation)3386_storage)": { + "label": "mapping(bytes32 => struct Attestation)", + "numberOfBytes": "32" + }, + "t_struct(Attestation)3386_storage": { + "label": "struct Attestation", + "members": [ + { + "label": "attestationId", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "schemaId", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "replacedBy", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "attester", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "portal", + "type": "t_address", + "offset": 0, + "slot": "4" + }, + { + "label": "attestedDate", + "type": "t_uint64", + "offset": 20, + "slot": "4" + }, + { + "label": "expirationDate", + "type": "t_uint64", + "offset": 0, + "slot": "5" + }, + { + "label": "revocationDate", + "type": "t_uint64", + "offset": 8, + "slot": "5" + }, + { + "label": "version", + "type": "t_uint16", + "offset": 16, + "slot": "5" + }, + { + "label": "revoked", + "type": "t_bool", + "offset": 18, + "slot": "5" + }, + { + "label": "subject", + "type": "t_bytes_storage", + "offset": 0, + "slot": "6" + }, + { + "label": "attestationData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": [ + "0x4c5A945c0b2B61dcdae8eb273fBA9bAF80Bd7b3F", + "0xd835587924c763e9A9Ee5867Bc5644FDBa7aD0f9", + "0xe5D42F8EE8CC0E9bbC25A58FA09AD723d9C92A38" + ] + }, + "d3839952abe24ccc6cd8803a91942cfbedf96e5be08d5c3ab72758d5edd7a91d": { + "address": "0x9b207fD880EBe1e19b90f3DFd84652e05f1Af524", + "txHash": "0xdbd5490198bb982c238fa9304a0881cba159011c8d0e1ac75e4cb66b0136931a", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3333", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:18" + }, + { + "label": "modules", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Module)3418_storage)", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:20" + }, + { + "label": "moduleAddresses", + "offset": 0, + "slot": "103", + "type": "t_array(t_address)dyn_storage", + "contract": "ModuleRegistry", + "src": "src/ModuleRegistry.sol:22" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3333": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(Module)3418_storage)": { + "label": "mapping(address => struct Module)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Module)3418_storage": { + "label": "struct Module", + "members": [ + { + "label": "moduleAddress", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "allAddresses": ["0x9b207fD880EBe1e19b90f3DFd84652e05f1Af524", "0xB6a628b775F56AC649064479acAEECA76ccfc21C"] + }, + "d99b3b345be3281a62d350dd3f4b0dbee11a149a42369670b897db21539dad09": { + "address": "0xa8Fa37CB5a883f885c8E2392784995452F85651A", + "txHash": "0x1a18bb2a39aefe94a6275f37344756df10b350027b46a358fc9e35796f8d85a0", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3333", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:18" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)3411_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:20" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:22" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:24" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRouter)3333": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)3411_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)3411_storage": { + "label": "struct Portal", + "members": [ + { + "label": "id", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerAddress", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "modules", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "isRevocable", + "type": "t_bool", + "offset": 0, + "slot": "3" + }, + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "4" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "ownerName", + "type": "t_string_storage", + "offset": 0, + "slot": "6" + } + ], + "numberOfBytes": "224" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "7cb0f5d61af565dfb5f94a78e471d8d9ed42c8ee97eddcd926d395437ca8b435": { + "address": "0x55C006227f819268F935441Db245b39a108aB95c", + "txHash": "0xaeed4f9c7de515b134912a1d5946fd31beccd040ace2177de3c801db218ca0b3", + "layout": { + "solcVersion": "0.8.21", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol:94" + }, + { + "label": "router", + "offset": 0, + "slot": "101", + "type": "t_contract(IRouter)3333", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:15" + }, + { + "label": "schemas", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_bytes32,t_struct(Schema)3395_storage)", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:17" + }, + { + "label": "schemaIds", + "offset": 0, + "slot": "103", + "type": "t_array(t_bytes32)dyn_storage", + "contract": "SchemaRegistry", + "src": "src/SchemaRegistry.sol:19" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRouter)3333": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_struct(Schema)3395_storage)": { + "label": "mapping(bytes32 => struct Schema)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Schema)3395_storage": { + "label": "struct Schema", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "context", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "schema", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/README.md b/README.md index 6b759bfd..972f475a 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,9 @@ upgradable to the new local versions. ### Recreate the network files +:warning: Note: this script must only be run on a branch/commit corresponding to the version of the contracts deployed +on the targeted network!. + Run `pnpm run check:upgradeable:goerli` or `pnpm run check:upgradeable` to re-generate the network files describing the deployed contracts. This can be useful if the file was lost/modified since the last upgrade or the first deployment. @@ -220,15 +223,21 @@ deployed contracts. This can be useful if the file was lost/modified since the l ### On the Linea Goerli testnet: -1. Check your `.env` file contains the address of the proxy for the contract you want to upgrade -2. Run `pnpm run upgrade:ContractName:goerli`, replacing `ContractName` with the contract you want to upgrade -3. Alternatively, you can upgrade all contracts at once via `pnpm run upgrade:all:goerli` +1. Check that your `.env` file contains the address of all the proxies +2. Upgrade only the implementations that changed since the last upgrade via the `pnpm run upgrade:all:goerli` command +3. _Optional_: Upgrade all the implementations by forcing their re-deployment via the + `pnpm run upgrade:all:goerli:force` command + +:warning: Note: Forcing the redeployment of all the implementations is more expensive! ### On the Linea mainnet: -1. Check your `.env` file contains the address of the proxy for the contract you want to upgrade -2. Run `pnpm run upgrade:ContractName`, replacing `ContractName` with the contract you want to upgrade -3. Alternatively, you can upgrade all contracts at once via `pnpm run upgrade:all` +1. Check that your `.env` file contains the address of all the proxies +2. Upgrade only the implementations that changed since the last upgrade via the `pnpm run upgrade:all` command +3. _Optional_: Upgrade all the implementations by forcing their re-deployment via the `pnpm run upgrade:all:force` + command + +:warning: Note: Forcing the redeployment of all the implementations is more expensive! ## Contracts addresses diff --git a/package.json b/package.json index af950128..58c0adeb 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,13 @@ "prepare": "husky install", "prettier:check": "prettier --check \"**/*.{json,md,svg,yml,sol,ts}\"", "prettier:write": "prettier --write \"**/*.{json,md,svg,yml,sol,ts}\"", - "reimport": "npx hardhat run --network linea script/upgrade/upgradeEverything.ts", - "reimport:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeEverything.ts", + "reimport": "npx hardhat run --network linea script/recreateNetworkFile.ts", + "reimport:goerli": "npx hardhat run --network linea-goerli script/recreateNetworkFile.ts", "test": "forge test", "upgrade:all": "npx hardhat run --network linea script/upgrade/upgradeEverything.ts", - "upgrade:all:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeEverything.ts" + "upgrade:all:force": "npx hardhat run --network linea script/upgrade/forceUgradeEverything.ts", + "upgrade:all:goerli": "npx hardhat run --network linea-goerli script/upgrade/upgradeEverything.ts", + "upgrade:all:goerli:force": "npx hardhat run --network linea-goerli script/upgrade/forceUgradeEverything.ts" }, "devDependencies": { "@nomicfoundation/hardhat-ethers": "^3.0.4", diff --git a/script/upgrade/forceUpgradeEverything.ts b/script/upgrade/forceUpgradeEverything.ts new file mode 100644 index 00000000..4f51d027 --- /dev/null +++ b/script/upgrade/forceUpgradeEverything.ts @@ -0,0 +1,163 @@ +import { ethers, run, upgrades } from "hardhat"; +import dotenv from "dotenv"; + +dotenv.config({ path: "../.env" }); + +async function main() { + console.log(`START SCRIPT`); + + const routerProxyAddress = process.env.ROUTER_ADDRESS; + if (!routerProxyAddress) { + throw new Error("Router proxy address not found"); + } + + const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? ""; + if (!attestationProxyAddress) { + throw new Error("Attestation proxy address not found"); + } + + const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? ""; + if (!moduleProxyAddress) { + throw new Error("Module proxy address not found"); + } + + const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; + if (!portalProxyAddress) { + throw new Error("Portal proxy address not found"); + } + + const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? ""; + if (!schemaProxyAddress) { + throw new Error("Schema proxy address not found"); + } + + console.log("Upgrading Router, with proxy at", routerProxyAddress); + const Router = await ethers.getContractFactory("Router"); + await upgrades.upgradeProxy(routerProxyAddress, Router, { + redeployImplementation: "always", + }); + + console.log(`Router successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading AttestationRegistry, with proxy at", attestationProxyAddress); + const AttestationRegistry = await ethers.getContractFactory("AttestationRegistry"); + const attestationRegistry = await upgrades.upgradeProxy(attestationProxyAddress, AttestationRegistry, { + redeployImplementation: "always", + }); + + await attestationRegistry.incrementVersionNumber(); + + console.log(`AttestationRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading ModuleRegistry, with proxy at", moduleProxyAddress); + const ModuleRegistry = await ethers.getContractFactory("ModuleRegistry"); + await upgrades.upgradeProxy(moduleProxyAddress, ModuleRegistry, { + redeployImplementation: "always", + }); + + console.log(`ModuleRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading PortalRegistry, with proxy at", portalProxyAddress); + const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); + await upgrades.upgradeProxy(portalProxyAddress, PortalRegistry, { + redeployImplementation: "always", + }); + + console.log(`PortalRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + console.log("Upgrading SchemaRegistry, with proxy at", schemaProxyAddress); + const SchemaRegistry = await ethers.getContractFactory("SchemaRegistry"); + await upgrades.upgradeProxy(schemaProxyAddress, SchemaRegistry, { + redeployImplementation: "always", + }); + + console.log(`SchemaRegistry successfully upgraded!`); + + console.log(`\n----\n`); + + const routerImplementationAddress = await upgrades.erc1967.getImplementationAddress(routerProxyAddress); + + await run("verify:verify", { + address: routerProxyAddress, + }); + + console.log(`Router successfully upgraded and verified!`); + console.log(`Proxy is at ${routerProxyAddress}`); + console.log(`Implementation is at ${routerImplementationAddress}`); + + console.log(`\n----\n`); + + const attestationImplementationAddress = await upgrades.erc1967.getImplementationAddress(attestationProxyAddress); + + await run("verify:verify", { + address: attestationProxyAddress, + }); + + const newVersion = await attestationRegistry.getVersionNumber(); + + console.log(`AttestationRegistry successfully upgraded to version ${newVersion} and verified!`); + console.log(`Proxy is at ${attestationProxyAddress}`); + console.log(`Implementation is at ${attestationImplementationAddress}`); + + console.log(`\n----\n`); + + const moduleImplementationAddress = await upgrades.erc1967.getImplementationAddress(moduleProxyAddress); + + await run("verify:verify", { + address: moduleProxyAddress, + }); + + console.log(`ModuleRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${moduleProxyAddress}`); + console.log(`Implementation is at ${moduleImplementationAddress}`); + + console.log(`\n----\n`); + + const portalImplementationAddress = await upgrades.erc1967.getImplementationAddress(portalProxyAddress); + + await run("verify:verify", { + address: portalProxyAddress, + }); + + console.log(`PortalRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${portalProxyAddress}`); + console.log(`Implementation is at ${portalImplementationAddress}`); + + console.log(`\n----\n`); + + const schemaImplementationAddress = await upgrades.erc1967.getImplementationAddress(schemaProxyAddress); + + await run("verify:verify", { + address: schemaProxyAddress, + }); + + console.log(`SchemaRegistry successfully upgraded and verified!`); + console.log(`Proxy is at ${schemaProxyAddress}`); + console.log(`Implementation is at ${schemaImplementationAddress}`); + + console.log(`\n----\n`); + + console.log(`** SUMMARY **`); + console.log(`Router = ${routerProxyAddress}`); + console.log(`AttestationRegistry = ${attestationProxyAddress}`); + console.log(`ModuleRegistry = ${moduleProxyAddress}`); + console.log(`PortalRegistry = ${portalProxyAddress}`); + console.log(`SchemaRegistry = ${schemaProxyAddress}`); + + console.log(`END SCRIPT`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main().catch((error) => { + console.error(error); + process.exitCode = 1; +});