From 9a0302585d79963c235d72cb4d8e88404c8f39b2 Mon Sep 17 00:00:00 2001 From: Alain Nicolas Date: Fri, 8 Dec 2023 11:00:40 +0100 Subject: [PATCH] feat: As an Admin, I want to revoke a Portal that was registered (#439) --- contracts/.openzeppelin/unknown-59140.json | 225 ++++++++++++++++++--- contracts/.openzeppelin/unknown-59144.json | 225 ++++++++++++++++++--- contracts/package.json | 2 +- contracts/src/PortalRegistry.sol | 32 ++- contracts/test/PortalRegistry.t.sol | 55 ++++- 5 files changed, 488 insertions(+), 51 deletions(-) diff --git a/contracts/.openzeppelin/unknown-59140.json b/contracts/.openzeppelin/unknown-59140.json index 0e13c8cd..340581cc 100644 --- a/contracts/.openzeppelin/unknown-59140.json +++ b/contracts/.openzeppelin/unknown-59140.json @@ -2301,7 +2301,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "AttestationReader", "src": "src/AttestationReader.sol:17" }, @@ -2309,7 +2309,7 @@ "label": "easRegistry", "offset": 0, "slot": "102", - "type": "t_contract(IEAS)7361", + "type": "t_contract(IEAS)7468", "contract": "AttestationReader", "src": "src/AttestationReader.sol:18" } @@ -2331,11 +2331,11 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IEAS)7361": { + "t_contract(IEAS)7468": { "label": "contract IEAS", "numberOfBytes": "20" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -3304,7 +3304,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "ModuleRegistry", "src": "src/ModuleRegistry.sol:19" }, @@ -3312,7 +3312,7 @@ "label": "modules", "offset": 0, "slot": "102", - "type": "t_mapping(t_address,t_struct(Module)8807_storage)", + "type": "t_mapping(t_address,t_struct(Module)8914_storage)", "contract": "ModuleRegistry", "src": "src/ModuleRegistry.sol:21" }, @@ -3346,11 +3346,11 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, - "t_mapping(t_address,t_struct(Module)8807_storage)": { + "t_mapping(t_address,t_struct(Module)8914_storage)": { "label": "mapping(address => struct Module)", "numberOfBytes": "32" }, @@ -3358,7 +3358,7 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Module)8807_storage": { + "t_struct(Module)8914_storage": { "label": "struct Module", "members": [ { @@ -3782,7 +3782,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "SchemaRegistry", "src": "src/SchemaRegistry.sol:16" }, @@ -3790,7 +3790,7 @@ "label": "schemas", "offset": 0, "slot": "102", - "type": "t_mapping(t_bytes32,t_struct(Schema)8784_storage)", + "type": "t_mapping(t_bytes32,t_struct(Schema)8891_storage)", "contract": "SchemaRegistry", "src": "src/SchemaRegistry.sol:18" }, @@ -3836,7 +3836,7 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -3844,7 +3844,7 @@ "label": "mapping(bytes32 => address)", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(Schema)8784_storage)": { + "t_mapping(t_bytes32,t_struct(Schema)8891_storage)": { "label": "mapping(bytes32 => struct Schema)", "numberOfBytes": "32" }, @@ -3852,7 +3852,7 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Schema)8784_storage": { + "t_struct(Schema)8891_storage": { "label": "struct Schema", "members": [ { @@ -3945,7 +3945,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "AttestationRegistry", "src": "src/AttestationRegistry.sol:17" }, @@ -3969,7 +3969,7 @@ "label": "attestations", "offset": 0, "slot": "102", - "type": "t_mapping(t_bytes32,t_struct(Attestation)8775_storage)", + "type": "t_mapping(t_bytes32,t_struct(Attestation)8882_storage)", "contract": "AttestationRegistry", "src": "src/AttestationRegistry.sol:22" }, @@ -4007,15 +4007,15 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, - "t_mapping(t_bytes32,t_struct(Attestation)8775_storage)": { + "t_mapping(t_bytes32,t_struct(Attestation)8882_storage)": { "label": "mapping(bytes32 => struct Attestation)", "numberOfBytes": "32" }, - "t_struct(Attestation)8775_storage": { + "t_struct(Attestation)8882_storage": { "label": "struct Attestation", "members": [ { @@ -4168,7 +4168,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7706", "contract": "PortalRegistry", "src": "src/PortalRegistry.sol:20" }, @@ -4176,7 +4176,7 @@ "label": "portals", "offset": 0, "slot": "102", - "type": "t_mapping(t_address,t_struct(Portal)8800_storage)", + "type": "t_mapping(t_address,t_struct(Portal)9096_storage)", "contract": "PortalRegistry", "src": "src/PortalRegistry.sol:22" }, @@ -4218,7 +4218,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7706": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -4226,7 +4226,7 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_struct(Portal)8800_storage)": { + "t_mapping(t_address,t_struct(Portal)9096_storage)": { "label": "mapping(address => struct Portal)", "numberOfBytes": "32" }, @@ -4234,7 +4234,184 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Portal)8800_storage": { + "t_struct(Portal)9096_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" + } + }, + "namespaces": {} + } + }, + "4354fba979d8af67ae201159e1b7f7c6048ac523a759db0e2d448b58a54cde2a": { + "address": "0x179Ff9a17ff079f5BEA2e6Cab69927CE2efd3309", + "txHash": "0xa256c5d91fe83b1f303754b97b3605074588b1282cd5b4e97714dfb0a193a0f3", + "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)7517", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:21" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)8907_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:23" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:25" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:27" + } + ], + "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)7517": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)8907_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)8907_storage": { "label": "struct Portal", "members": [ { diff --git a/contracts/.openzeppelin/unknown-59144.json b/contracts/.openzeppelin/unknown-59144.json index d345b213..4d7b20a8 100644 --- a/contracts/.openzeppelin/unknown-59144.json +++ b/contracts/.openzeppelin/unknown-59144.json @@ -1949,7 +1949,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "AttestationReader", "src": "src/AttestationReader.sol:17" }, @@ -1957,7 +1957,7 @@ "label": "easRegistry", "offset": 0, "slot": "102", - "type": "t_contract(IEAS)7361", + "type": "t_contract(IEAS)7468", "contract": "AttestationReader", "src": "src/AttestationReader.sol:18" } @@ -1979,11 +1979,11 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IEAS)7361": { + "t_contract(IEAS)7468": { "label": "contract IEAS", "numberOfBytes": "20" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -2264,7 +2264,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "ModuleRegistry", "src": "src/ModuleRegistry.sol:19" }, @@ -2272,7 +2272,7 @@ "label": "modules", "offset": 0, "slot": "102", - "type": "t_mapping(t_address,t_struct(Module)8807_storage)", + "type": "t_mapping(t_address,t_struct(Module)8914_storage)", "contract": "ModuleRegistry", "src": "src/ModuleRegistry.sol:21" }, @@ -2306,11 +2306,11 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, - "t_mapping(t_address,t_struct(Module)8807_storage)": { + "t_mapping(t_address,t_struct(Module)8914_storage)": { "label": "mapping(address => struct Module)", "numberOfBytes": "32" }, @@ -2318,7 +2318,7 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Module)8807_storage": { + "t_struct(Module)8914_storage": { "label": "struct Module", "members": [ { @@ -2742,7 +2742,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "SchemaRegistry", "src": "src/SchemaRegistry.sol:16" }, @@ -2750,7 +2750,7 @@ "label": "schemas", "offset": 0, "slot": "102", - "type": "t_mapping(t_bytes32,t_struct(Schema)8784_storage)", + "type": "t_mapping(t_bytes32,t_struct(Schema)8891_storage)", "contract": "SchemaRegistry", "src": "src/SchemaRegistry.sol:18" }, @@ -2796,7 +2796,7 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -2804,7 +2804,7 @@ "label": "mapping(bytes32 => address)", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(Schema)8784_storage)": { + "t_mapping(t_bytes32,t_struct(Schema)8891_storage)": { "label": "mapping(bytes32 => struct Schema)", "numberOfBytes": "32" }, @@ -2812,7 +2812,7 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Schema)8784_storage": { + "t_struct(Schema)8891_storage": { "label": "struct Schema", "members": [ { @@ -2905,7 +2905,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7517", "contract": "AttestationRegistry", "src": "src/AttestationRegistry.sol:17" }, @@ -2929,7 +2929,7 @@ "label": "attestations", "offset": 0, "slot": "102", - "type": "t_mapping(t_bytes32,t_struct(Attestation)8775_storage)", + "type": "t_mapping(t_bytes32,t_struct(Attestation)8882_storage)", "contract": "AttestationRegistry", "src": "src/AttestationRegistry.sol:22" }, @@ -2967,15 +2967,15 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7517": { "label": "contract IRouter", "numberOfBytes": "20" }, - "t_mapping(t_bytes32,t_struct(Attestation)8775_storage)": { + "t_mapping(t_bytes32,t_struct(Attestation)8882_storage)": { "label": "mapping(bytes32 => struct Attestation)", "numberOfBytes": "32" }, - "t_struct(Attestation)8775_storage": { + "t_struct(Attestation)8882_storage": { "label": "struct Attestation", "members": [ { @@ -3128,7 +3128,7 @@ "label": "router", "offset": 0, "slot": "101", - "type": "t_contract(IRouter)7410", + "type": "t_contract(IRouter)7706", "contract": "PortalRegistry", "src": "src/PortalRegistry.sol:20" }, @@ -3136,7 +3136,7 @@ "label": "portals", "offset": 0, "slot": "102", - "type": "t_mapping(t_address,t_struct(Portal)8800_storage)", + "type": "t_mapping(t_address,t_struct(Portal)9096_storage)", "contract": "PortalRegistry", "src": "src/PortalRegistry.sol:22" }, @@ -3178,7 +3178,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IRouter)7410": { + "t_contract(IRouter)7706": { "label": "contract IRouter", "numberOfBytes": "20" }, @@ -3186,7 +3186,7 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_struct(Portal)8800_storage)": { + "t_mapping(t_address,t_struct(Portal)9096_storage)": { "label": "mapping(address => struct Portal)", "numberOfBytes": "32" }, @@ -3194,7 +3194,184 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Portal)8800_storage": { + "t_struct(Portal)9096_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" + } + }, + "namespaces": {} + } + }, + "4354fba979d8af67ae201159e1b7f7c6048ac523a759db0e2d448b58a54cde2a": { + "address": "0xf6cFD951c6c2BD1Ac8f53ff314a0D01f0443f0ee", + "txHash": "0xedabe31d56fae478cb9be3f8da4cb63b44b5c1bdd22c7e37948ee2814e294dbc", + "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)7517", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:21" + }, + { + "label": "portals", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_struct(Portal)8907_storage)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:23" + }, + { + "label": "issuers", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_address,t_bool)", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:25" + }, + { + "label": "portalAddresses", + "offset": 0, + "slot": "104", + "type": "t_array(t_address)dyn_storage", + "contract": "PortalRegistry", + "src": "src/PortalRegistry.sol:27" + } + ], + "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)7517": { + "label": "contract IRouter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(Portal)8907_storage)": { + "label": "mapping(address => struct Portal)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Portal)8907_storage": { "label": "struct Portal", "members": [ { diff --git a/contracts/package.json b/contracts/package.json index 638cd23d..2e0b9524 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -32,7 +32,7 @@ "massImport:attest": "npx hardhat run script/massImport/massImport.ts --network", "reimport": "npx hardhat run script/recreateNetworkFile.ts --network", "test": "forge test", - "upgrade:": "npx hardhat run script/upgrade/upgradeEverything.ts --network", + "upgrade": "npx hardhat run script/upgrade/upgradeEverything.ts --network", "upgrade:force": "npx hardhat run script/upgrade/forceUpgradeEverything.ts --network" }, "devDependencies": { diff --git a/contracts/src/PortalRegistry.sol b/contracts/src/PortalRegistry.sol index 6a1b9fa1..137b908e 100644 --- a/contracts/src/PortalRegistry.sol +++ b/contracts/src/PortalRegistry.sol @@ -10,6 +10,7 @@ import { SchemaRegistry } from "./SchemaRegistry.sol"; import { Portal } from "./types/Structs.sol"; import { IRouter } from "./interfaces/IRouter.sol"; import { IPortal } from "./interfaces/IPortal.sol"; +import { uncheckedInc256 } from "./Common.sol"; /** * @title Portal Registry @@ -44,12 +45,14 @@ contract PortalRegistry is OwnableUpgradeable { /// @notice Error thrown when attempting to get a Portal that is not registered error PortalNotRegistered(); - /// @notice Event emitted when a Portal registered + /// @notice Event emitted when a Portal is registered event PortalRegistered(string name, string description, address portalAddress); /// @notice Event emitted when a new issuer is added event IssuerAdded(address issuerAddress); /// @notice Event emitted when the issuer is removed event IssuerRemoved(address issuerAddress); + /// @notice Event emitted when a Portal is revoked + event PortalRevoked(address portalAddress); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { @@ -155,6 +158,33 @@ contract PortalRegistry is OwnableUpgradeable { emit PortalRegistered(name, description, id); } + /** + * @notice Revokes a Portal from the PortalRegistry + * @param id the portal address + * @dev Only the registry owner can call this method + */ + function revoke(address id) public onlyOwner { + if (!isRegistered(id)) revert PortalNotRegistered(); + + portals[id] = Portal(address(0), address(0), new address[](0), false, "", "", ""); + + uint256 portalAddressIndex; + for (uint256 i = 0; i < portalAddresses.length; i = uncheckedInc256(i)) { + if (portalAddresses[i] == id) { + portalAddressIndex = i; + } + } + + if (portalAddressIndex >= portalAddresses.length) { + revert PortalNotRegistered(); + } + + portalAddresses[portalAddressIndex] = portalAddresses[portalAddresses.length - 1]; + portalAddresses.pop(); + + emit PortalRevoked(id); + } + /** * @notice Deploys and registers a clone of default portal * @param modules the modules addresses diff --git a/contracts/test/PortalRegistry.t.sol b/contracts/test/PortalRegistry.t.sol index 43622b69..d2a8539c 100644 --- a/contracts/test/PortalRegistry.t.sol +++ b/contracts/test/PortalRegistry.t.sol @@ -31,6 +31,7 @@ contract PortalRegistryTest is Test { event PortalRegistered(string name, string description, address portalAddress); event IssuerAdded(address issuerAddress); event IssuerRemoved(address issuerAddress); + event PortalRevoked(address portalAddress); function setUp() public { router = new Router(); @@ -104,7 +105,7 @@ contract PortalRegistryTest is Test { } function test_register() public { - // Register a portal implmenting AbstractPortal + // Register a portal implementing AbstractPortal vm.expectEmit(); emit PortalRegistered(expectedName, expectedDescription, address(validPortalMock)); vm.prank(user); @@ -190,6 +191,58 @@ contract PortalRegistryTest is Test { portalRegistry.register(address(invalidPortalMock), expectedName, expectedDescription, true, expectedOwnerName); } + function test_revoke() public { + address portalAddress = address(iPortalImplementation); + vm.expectEmit(); + emit PortalRegistered("IPortalImplementation", "IPortalImplementation description", portalAddress); + vm.prank(user); + portalRegistry.register( + portalAddress, + "IPortalImplementation", + "IPortalImplementation description", + true, + expectedOwnerName + ); + + uint256 portalCount = portalRegistry.getPortalsCount(); + assertEq(portalCount, 1); + + Portal memory expectedPortal = Portal( + portalAddress, + user, + new address[](0), + true, + "IPortalImplementation", + "IPortalImplementation description", + expectedOwnerName + ); + + Portal memory registeredPortal = portalRegistry.getPortalByAddress(portalAddress); + _assertPortal(registeredPortal, expectedPortal); + + vm.prank(address(0)); + emit PortalRevoked(portalAddress); + portalRegistry.revoke(portalAddress); + + portalCount = portalRegistry.getPortalsCount(); + assertEq(portalCount, 0); + + vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); + portalRegistry.getPortalByAddress(portalAddress); + } + + function test_revoke_OnlyOwner() public { + vm.prank(makeAddr("randomAddress")); + vm.expectRevert("Ownable: caller is not the owner"); + portalRegistry.revoke(address(validPortalMock)); + } + + function test_revoke_NotRegistered() public { + vm.prank(address(0)); + vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); + portalRegistry.revoke(makeAddr("randomAddress")); + } + function test_deployDefaultPortal() public { CorrectModule correctModule = new CorrectModule(); address[] memory modules = new address[](1);