diff --git a/contracts/script/upgrade/checkImplementations.ts b/contracts/script/upgrade/checkImplementations.ts index 444e0aba..de16c6e1 100644 --- a/contracts/script/upgrade/checkImplementations.ts +++ b/contracts/script/upgrade/checkImplementations.ts @@ -21,8 +21,7 @@ async function main() { console.log("Checking PortalRegistry..."); const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); - // @ts-expect-error-next-line - constructorArgs is not part of the type - await upgrades.validateImplementation(PortalRegistry, { constructorArgs: [false] }); + await upgrades.validateImplementation(PortalRegistry); console.log("PortalRegistry OK"); console.log("Checking SchemaRegistry..."); diff --git a/contracts/script/upgrade/checkUpgradeability.ts b/contracts/script/upgrade/checkUpgradeability.ts index d51db723..b147560f 100644 --- a/contracts/script/upgrade/checkUpgradeability.ts +++ b/contracts/script/upgrade/checkUpgradeability.ts @@ -31,10 +31,8 @@ async function main() { const portalRegistryProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? ""; const PortalRegistry = await ethers.getContractFactory("PortalRegistry"); - // @ts-expect-error-next-line - constructorArgs is not part of the type await upgrades.validateUpgrade(portalRegistryProxyAddress, PortalRegistry, { kind: "transparent", - constructorArgs: [false], }); console.log("Checking SchemaRegistry..."); diff --git a/contracts/src/AttestationReader.sol b/contracts/src/AttestationReader.sol index 81d62708..ddf097f9 100644 --- a/contracts/src/AttestationReader.sol +++ b/contracts/src/AttestationReader.sol @@ -98,7 +98,7 @@ contract AttestationReader is RouterManager { bytes32(0), subject, veraxAttestation.attester, - PortalRegistry(router.getPortalRegistry()).getPortalByAddress(veraxAttestation.portal).isRevocable, + PortalRegistry(router.getPortalRegistry()).getPortalRevocability(veraxAttestation.portal), veraxAttestation.attestationData ); } diff --git a/contracts/src/AttestationRegistry.sol b/contracts/src/AttestationRegistry.sol index 3e5d028f..bda1c0d0 100644 --- a/contracts/src/AttestationRegistry.sol +++ b/contracts/src/AttestationRegistry.sol @@ -101,10 +101,12 @@ contract AttestationRegistry is RouterManager { } /** - * @notice Registers an attestation to the AttestationRegistry - * @param attestationPayload the attestation payload to create attestation and register it - * @param attester the account address issuing the attestation - * @dev This method is only callable by a registered Portal + * @notice Registers an attestation in the AttestationRegistry. + * @param attestationPayload The payload used to create and register the attestation. + * @param attester The address of the account issuing the attestation. + * @dev This function can only be called by a registered Portal. + * @dev While it might not align with typical business rules, it is technically + * possible to register expired attestations. */ function attest(AttestationPayload calldata attestationPayload, address attester) public onlyPortals(msg.sender) { // Verify the schema id exists @@ -118,6 +120,7 @@ contract AttestationRegistry is RouterManager { attestationIdCounter++; // Generate the full attestation ID, padded with the chain prefix bytes32 id = generateAttestationId(attestationIdCounter); + assert(id != 0x0 && !isRegistered(id)); // Create attestation attestations[id] = Attestation( id, @@ -152,6 +155,7 @@ contract AttestationRegistry is RouterManager { attestationIdCounter++; // Generate the full attestation ID, padded with the chain prefix bytes32 id = generateAttestationId(attestationIdCounter); + assert(id != 0x0 && !isRegistered(id)); // Create attestation attestations[id] = Attestation( id, @@ -245,7 +249,7 @@ contract AttestationRegistry is RouterManager { */ function isRevocable(address portalId) public view returns (bool) { PortalRegistry portalRegistry = PortalRegistry(router.getPortalRegistry()); - return portalRegistry.getPortalByAddress(portalId).isRevocable; + return portalRegistry.getPortalRevocability(portalId); } /** @@ -293,20 +297,23 @@ contract AttestationRegistry is RouterManager { } /** - * @notice Checks if an address owns a given attestation following ERC-1155 + * @notice Checks if an address owns a valid attestation following the ERC-1155 interface * @param account The address of the token holder * @param id ID of the attestation * @return The _owner's balance of the attestations on a given attestation ID + * @dev Only considers non-revoked, non-replaced and non-expired attestations */ function balanceOf(address account, uint256 id) public view returns (uint256) { bytes32 attestationId = generateAttestationId(id); Attestation memory attestation = attestations[attestationId]; - if (attestation.subject.length > 20 && keccak256(attestation.subject) == keccak256(abi.encode(account))) { - return 1; - } - if (attestation.subject.length == 20 && keccak256(attestation.subject) == keccak256(abi.encodePacked(account))) { - return 1; - } + + if (attestation.attestationId == bytes32(0)) return 0; + if (attestation.revoked == true) return 0; + if (attestation.expirationDate != 0 && attestation.expirationDate < block.timestamp) return 0; + + if (attestation.subject.length == 32 && abi.decode(attestation.subject, (address)) == account) return 1; + if (attestation.subject.length == 20 && address(uint160(bytes20(attestation.subject))) == account) return 1; + return 0; } @@ -340,6 +347,9 @@ contract AttestationRegistry is RouterManager { * @return The next attestation ID */ function getNextAttestationId() public view returns (bytes32) { - return generateAttestationId(attestationIdCounter + 1); + uint256 nextattestationId = attestationIdCounter + 1; + bytes32 id = generateAttestationId(nextattestationId); + assert(id != 0x0 && !isRegistered(id)); + return id; } } diff --git a/contracts/src/PortalRegistry.sol b/contracts/src/PortalRegistry.sol index b8eb2d97..204d31a0 100644 --- a/contracts/src/PortalRegistry.sol +++ b/contracts/src/PortalRegistry.sol @@ -64,16 +64,17 @@ contract PortalRegistry is RouterManager { event IsTestnetUpdated(bool isTestnet); /// @custom:oz-upgrades-unsafe-allow constructor - constructor(bool _isTestnet) { + constructor() { _disableInitializers(); - isTestnet = _isTestnet; } /** - * @notice Contract initialization + * @notice Contract initialization with testnet status + * @param _isTestnet Boolean indicating if the deployment is on a testnet */ - function initialize() public initializer { + function initialize(bool _isTestnet) public initializer { __Ownable_init(); + isTestnet = _isTestnet; } /** @@ -221,6 +222,26 @@ contract PortalRegistry is RouterManager { return portals[id]; } + /** + * @notice Get the owner address of a Portal + * @param portalAddress The address of the Portal + * @return The Portal owner address + */ + function getPortalOwner(address portalAddress) external view returns (address) { + if (!isRegistered(portalAddress)) revert PortalNotRegistered(); + return portals[portalAddress].ownerAddress; + } + + /** + * @notice Get a Portal's revocability + * @param portalAddress The address of the Portal + * @return The Portal revocability + */ + function getPortalRevocability(address portalAddress) external view returns (bool) { + if (!isRegistered(portalAddress)) revert PortalNotRegistered(); + return portals[portalAddress].isRevocable; + } + /** * @notice Check if a Portal is registered * @param id The address of the Portal diff --git a/contracts/src/SchemaRegistry.sol b/contracts/src/SchemaRegistry.sol index f474bbef..96e0b78b 100644 --- a/contracts/src/SchemaRegistry.sol +++ b/contracts/src/SchemaRegistry.sol @@ -29,8 +29,6 @@ contract SchemaRegistry is RouterManager { error SchemaContextAlreadyUpdated(); /// @notice Error thrown when a non-allowlisted user tries to call a forbidden method error OnlyAllowlisted(); - /// @notice Error thrown when any address which is not a portal registry tries to call a method - error OnlyPortalRegistry(); /// @notice Error thrown when a non-assigned issuer tries to call a method that can only be called by an assigned issuer error OnlyAssignedIssuer(); /// @notice Error thrown when an invalid Issuer address is given @@ -72,16 +70,6 @@ contract SchemaRegistry is RouterManager { _; } - /** - * @notice Checks if the caller is the portal registry. - * @param caller the caller address - */ - modifier onlyPortalRegistry(address caller) { - bool isCallerPortalRegistry = router.getPortalRegistry() == caller; - if (!isCallerPortalRegistry) revert OnlyPortalRegistry(); - _; - } - /** * @dev Changes the address for the Router * @param _router the new Router address diff --git a/contracts/src/abstracts/AbstractPortal.sol b/contracts/src/abstracts/AbstractPortal.sol index ba9e753b..ecf1b1da 100644 --- a/contracts/src/abstracts/AbstractPortal.sol +++ b/contracts/src/abstracts/AbstractPortal.sol @@ -22,7 +22,7 @@ abstract contract AbstractPortal is IPortal, ERC165 { AttestationRegistry public attestationRegistry; PortalRegistry public portalRegistry; - /// @notice Error thrown when someone else than the portal's owner is trying to revoke + /// @notice Error thrown when someone else than the portal's owner is trying to revoke or replace error OnlyPortalOwner(); /// @notice Error thrown when withdrawing funds fails @@ -42,14 +42,19 @@ abstract contract AbstractPortal is IPortal, ERC165 { portalRegistry = PortalRegistry(router.getPortalRegistry()); } + /// @notice Modifier to enforce only the portal owner can perform certain actions + modifier onlyPortalOwner() { + if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + _; + } + /** * @notice Withdraw funds from the Portal * @param to the address to send the funds to * @param amount the amount to withdraw * @dev Only the Portal owner can withdraw funds */ - function withdraw(address payable to, uint256 amount) external virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + function withdraw(address payable to, uint256 amount) external virtual onlyPortalOwner { (bool s, ) = to.call{ value: amount }(""); if (!s) revert WithdrawFail(); } @@ -310,6 +315,16 @@ abstract contract AbstractPortal is IPortal, ERC165 { uint256 value ) internal virtual {} + /** + * @notice Optional method run when attesting a batch of payloads + * @param attestationsPayloads the payloads to attest + * @param validationPayloads the payloads to validate in order to issue the attestations + */ + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal virtual {} + /** * @notice Optional method run when an attestation is replaced * @dev IMPORTANT NOTE: By default, replacement is only possible by the portal owner @@ -317,25 +332,14 @@ abstract contract AbstractPortal is IPortal, ERC165 { * @param attestationPayload the attestation payload to create attestation and register it * @param attester the address of the attester * @param value the value sent with the attestation + * @dev This method now uses the `onlyPortalOwner` modifier to enforce ownership rules */ function _onReplace( bytes32 attestationId, AttestationPayload memory attestationPayload, address attester, uint256 value - ) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } - - /** - * @notice Optional method run when attesting a batch of payloads - * @param attestationsPayloads the payloads to attest - * @param validationPayloads the payloads to validate in order to issue the attestations - */ - function _onBulkAttest( - AttestationPayload[] memory attestationsPayloads, - bytes[][] memory validationPayloads - ) internal virtual {} + ) internal virtual onlyPortalOwner {} /** * @notice Optional method run when replacing a batch of payloads @@ -343,28 +347,25 @@ abstract contract AbstractPortal is IPortal, ERC165 { * @param attestationIds the IDs of the attestations being replaced * @param attestationsPayloads the payloads to replace * @param validationPayloads the payloads to validate in order to replace the attestations + * @dev This method now uses the `onlyPortalOwner` modifier to enforce ownership rules */ function _onBulkReplace( bytes32[] memory attestationIds, AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads - ) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + ) internal virtual onlyPortalOwner {} /** - * @notice Optional method run when an attestation is revoked or replaced + * @notice Optional method run when an attestation is revoked * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner + * @dev This method now uses the `onlyPortalOwner` modifier to enforce ownership rules */ - function _onRevoke(bytes32 /*attestationId*/) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onRevoke(bytes32 attestationId) internal virtual onlyPortalOwner {} /** * @notice Optional method run when a batch of attestations are revoked or replaced * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner + * @dev This method now uses the `onlyPortalOwner` modifier to enforce ownership rules */ - function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onBulkRevoke(bytes32[] memory attestationIds) internal virtual onlyPortalOwner {} } diff --git a/contracts/src/abstracts/AbstractPortalV2.sol b/contracts/src/abstracts/AbstractPortalV2.sol index cce873da..ab2a16f0 100644 --- a/contracts/src/abstracts/AbstractPortalV2.sol +++ b/contracts/src/abstracts/AbstractPortalV2.sol @@ -44,14 +44,21 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { portalRegistry = PortalRegistry(router.getPortalRegistry()); } + /** + * @notice Modifier to enforce only the portal owner can perform certain actions. + */ + modifier onlyPortalOwner() { + if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + _; + } + /** * @notice Withdraw funds from the Portal * @param to the address to send the funds to * @param amount the amount to withdraw * @dev Only the Portal owner can withdraw funds */ - function withdraw(address payable to, uint256 amount) external virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); + function withdraw(address payable to, uint256 amount) external virtual onlyPortalOwner { (bool s, ) = to.call{ value: amount }(""); if (!s) revert WithdrawFail(); } @@ -112,7 +119,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { bytes32 attestationId, AttestationPayload memory attestationPayload, bytes[] memory validationPayloads - ) public payable { + ) public payable onlyPortalOwner { moduleRegistry.runModulesV2( modules, attestationPayload, @@ -141,7 +148,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { bytes32[] memory attestationIds, AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads - ) public { + ) public onlyPortalOwner { moduleRegistry.bulkRunModulesV2( modules, attestationsPayloads, @@ -162,7 +169,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { * @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) public { + function revoke(bytes32 attestationId) public onlyPortalOwner { _onRevoke(attestationId); attestationRegistry.revoke(attestationId); @@ -172,7 +179,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { * @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) public { + function bulkRevoke(bytes32[] memory attestationIds) public onlyPortalOwner { _onBulkRevoke(attestationIds); attestationRegistry.bulkRevoke(attestationIds); @@ -189,7 +196,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { /** * @notice Verifies that a specific interface is implemented by the Portal, following ERC-165 specification * @param interfaceID the interface identifier checked in this call - * @return The list of modules addresses linked to the Portal + * @return True if the interface is supported, false otherwise */ function supportsInterface(bytes4 interfaceID) public view virtual override returns (bool) { return @@ -207,10 +214,7 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { } /** - * @notice Optional method run before a payload is attested - * @param attestationPayload the attestation payload to attest - * @param validationPayloads the payloads to validate via the modules - * @param value the value sent with the attestation + * @notice Optional hooks for specific operations */ function _onAttest( AttestationPayload memory attestationPayload, @@ -218,6 +222,16 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { uint256 value ) internal virtual {} + /** + * @notice Optional method run when attesting a batch of payloads + * @param attestationsPayloads the payloads to attest + * @param validationPayloads the payloads to validate in order to issue the attestations + */ + function _onBulkAttest( + AttestationPayload[] memory attestationsPayloads, + bytes[][] memory validationPayloads + ) internal virtual {} + /** * @notice Optional method run when an attestation is replaced * @dev IMPORTANT NOTE: By default, replacement is only possible by the portal owner @@ -231,18 +245,6 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { AttestationPayload memory attestationPayload, address attester, uint256 value - ) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } - - /** - * @notice Optional method run when attesting a batch of payloads - * @param attestationsPayloads the payloads to attest - * @param validationPayloads the payloads to validate in order to issue the attestations - */ - function _onBulkAttest( - AttestationPayload[] memory attestationsPayloads, - bytes[][] memory validationPayloads ) internal virtual {} /** @@ -256,23 +258,17 @@ abstract contract AbstractPortalV2 is IPortal, ERC165 { bytes32[] memory attestationIds, AttestationPayload[] memory attestationsPayloads, bytes[][] memory validationPayloads - ) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + ) internal virtual {} /** * @notice Optional method run when an attestation is revoked or replaced * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner */ - function _onRevoke(bytes32 /*attestationId*/) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onRevoke(bytes32 /*attestationId*/) internal virtual {} /** * @notice Optional method run when a batch of attestations are revoked or replaced * @dev IMPORTANT NOTE: By default, revocation is only possible by the portal owner */ - function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual {} } diff --git a/contracts/src/examples/portals/EASPortal.sol b/contracts/src/examples/portals/EASPortal.sol index 56bd8c57..44b815b8 100644 --- a/contracts/src/examples/portals/EASPortal.sol +++ b/contracts/src/examples/portals/EASPortal.sol @@ -48,9 +48,6 @@ contract EASPortal is AbstractPortalV2 { */ constructor(address[] memory modules, address router) AbstractPortalV2(modules, router) {} - /// @inheritdoc AbstractPortalV2 - function withdraw(address payable to, uint256 amount) external override {} - /** * @notice Issues a Verax attestation based on an EAS attestation * @param attestationRequest the EAS payload to attest diff --git a/contracts/src/examples/portals/PausablePortal.sol b/contracts/src/examples/portals/PausablePortal.sol index 75fae50d..bd502ee1 100644 --- a/contracts/src/examples/portals/PausablePortal.sol +++ b/contracts/src/examples/portals/PausablePortal.sol @@ -70,9 +70,7 @@ contract PausablePortal is AbstractPortalV2, Pausable, Ownable { AttestationPayload memory /*attestationPayload*/, address /*attester*/, uint256 /*value*/ - ) internal virtual override whenNotPaused { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + ) internal virtual override whenNotPaused {} /** * @inheritdoc AbstractPortalV2 @@ -82,23 +80,17 @@ contract PausablePortal is AbstractPortalV2, Pausable, Ownable { bytes32[] memory /*attestationIds*/, AttestationPayload[] memory /*attestationsPayloads*/, bytes[][] memory /*validationPayloads*/ - ) internal virtual override whenNotPaused { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + ) internal virtual override whenNotPaused {} /** * @inheritdoc AbstractPortalV2 * @dev Only the owner of the portal can revoke an attestation */ - function _onRevoke(bytes32 /*attestationId*/) internal virtual override whenNotPaused { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onRevoke(bytes32 /*attestationId*/) internal virtual override whenNotPaused {} /** * @inheritdoc AbstractPortalV2 * @dev Only the owner of the portal can bulk revoke attestations */ - function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual override whenNotPaused { - if (msg.sender != portalRegistry.getPortalByAddress(address(this)).ownerAddress) revert OnlyPortalOwner(); - } + function _onBulkRevoke(bytes32[] memory /*attestationIds*/) internal virtual override whenNotPaused {} } diff --git a/contracts/src/stdlib/ECDSAModule.sol b/contracts/src/stdlib/ECDSAModule.sol index cf76e0d3..c40610dc 100644 --- a/contracts/src/stdlib/ECDSAModule.sol +++ b/contracts/src/stdlib/ECDSAModule.sol @@ -29,7 +29,7 @@ contract ECDSAModule is AbstractModule { event SignersAuthorized(address indexed portal, address[] signers, bool[] authorizationStatus); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/ECDSAModuleV2.sol b/contracts/src/stdlib/ECDSAModuleV2.sol index a5250e6a..d9edfcc4 100644 --- a/contracts/src/stdlib/ECDSAModuleV2.sol +++ b/contracts/src/stdlib/ECDSAModuleV2.sol @@ -31,7 +31,7 @@ contract ECDSAModuleV2 is AbstractModuleV2 { event SignersAuthorized(address indexed portal, address[] signers, bool[] authorizationStatus); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/ERC1271Module.sol b/contracts/src/stdlib/ERC1271Module.sol index 98595185..43cd45fc 100644 --- a/contracts/src/stdlib/ERC1271Module.sol +++ b/contracts/src/stdlib/ERC1271Module.sol @@ -27,7 +27,7 @@ contract ERC1271Module is ERC1271, AbstractModule { error InvalidSignature(string msg); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/ERC1271ModuleV2.sol b/contracts/src/stdlib/ERC1271ModuleV2.sol index 1b37c857..2cc20509 100644 --- a/contracts/src/stdlib/ERC1271ModuleV2.sol +++ b/contracts/src/stdlib/ERC1271ModuleV2.sol @@ -38,7 +38,7 @@ contract ERC1271ModuleV2 is AbstractModuleV2 { event SignersAuthorized(address indexed portal, address[] signers, bool[] authorizationStatus); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/FeeModule.sol b/contracts/src/stdlib/FeeModule.sol index fdc0639d..b913f8c5 100644 --- a/contracts/src/stdlib/FeeModule.sol +++ b/contracts/src/stdlib/FeeModule.sol @@ -21,7 +21,7 @@ contract FeeModule is AbstractModule { error InvalidAttestationFee(); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/FeeModuleV2.sol b/contracts/src/stdlib/FeeModuleV2.sol index 502398b1..4a1fbbb5 100644 --- a/contracts/src/stdlib/FeeModuleV2.sol +++ b/contracts/src/stdlib/FeeModuleV2.sol @@ -23,7 +23,7 @@ contract FeeModuleV2 is AbstractModuleV2 { error InvalidAttestationFee(); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/SchemaModule.sol b/contracts/src/stdlib/SchemaModule.sol index f5c40b1d..f1ac4a42 100644 --- a/contracts/src/stdlib/SchemaModule.sol +++ b/contracts/src/stdlib/SchemaModule.sol @@ -22,7 +22,7 @@ contract SchemaModule is AbstractModule { error SchemaNotAuthorized(); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/SchemaModuleV2.sol b/contracts/src/stdlib/SchemaModuleV2.sol index 33165e6b..e6e5d3e9 100644 --- a/contracts/src/stdlib/SchemaModuleV2.sol +++ b/contracts/src/stdlib/SchemaModuleV2.sol @@ -26,7 +26,7 @@ contract SchemaModuleV2 is AbstractModuleV2 { event SchemasAuthorized(address indexed portal, bytes32[] schemas, bool[] authorizedStatus); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/SenderModule.sol b/contracts/src/stdlib/SenderModule.sol index 8728988c..dc84fb73 100644 --- a/contracts/src/stdlib/SenderModule.sol +++ b/contracts/src/stdlib/SenderModule.sol @@ -21,7 +21,7 @@ contract SenderModule is AbstractModule { error UnauthorizedSender(); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/src/stdlib/SenderModuleV2.sol b/contracts/src/stdlib/SenderModuleV2.sol index 28db9579..4ae73621 100644 --- a/contracts/src/stdlib/SenderModuleV2.sol +++ b/contracts/src/stdlib/SenderModuleV2.sol @@ -25,7 +25,7 @@ contract SenderModuleV2 is AbstractModuleV2 { event SendersAuthorized(address indexed portal, address[] senders, bool[] authorizedStatus); modifier onlyPortalOwner(address portal) { - if (msg.sender != portalRegistry.getPortalByAddress(portal).ownerAddress) revert OnlyPortalOwner(); + if (msg.sender != portalRegistry.getPortalOwner(portal)) revert OnlyPortalOwner(); _; } diff --git a/contracts/test/AttestationReader.t.sol b/contracts/test/AttestationReader.t.sol index 7f64d108..72598415 100644 --- a/contracts/test/AttestationReader.t.sol +++ b/contracts/test/AttestationReader.t.sol @@ -156,7 +156,7 @@ contract AttestationReaderTest is Test { bytes32(0), abi.decode(attestationPayload.subject, (address)), attester, - PortalRegistry(router.getPortalRegistry()).getPortalByAddress(portal).isRevocable, + PortalRegistry(router.getPortalRegistry()).getPortalRevocability(portal), attestationPayload.attestationData ); return attestation; diff --git a/contracts/test/AttestationRegistry.t.sol b/contracts/test/AttestationRegistry.t.sol index 9c2cfe6e..5d1be427 100644 --- a/contracts/test/AttestationRegistry.t.sol +++ b/contracts/test/AttestationRegistry.t.sol @@ -598,7 +598,7 @@ contract AttestationRegistryTest is Test { vm.stopPrank(); } - function test_balanceOf_notFound(AttestationPayload memory attestationPayload) public { + function test_balanceOf_attestationNotFound(AttestationPayload memory attestationPayload) public { vm.assume(attestationPayload.subject.length != 0); vm.assume(attestationPayload.attestationData.length != 0); SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); @@ -606,37 +606,97 @@ contract AttestationRegistryTest is Test { schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); vm.startPrank(portal); - attestationPayload.subject = abi.encode(address(1234)); + attestationPayload.subject = abi.encode(address(1)); + attestationRegistry.attest(attestationPayload, attester); + + uint256 balance = attestationRegistry.balanceOf(address(1), 1234); + assertEq(balance, 0); + } + + function test_balanceOf_attestationRevoked() public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + AttestationPayload memory attestationPayload; + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayload.expirationDate = 0; + attestationPayload.subject = abi.encode(address(1)); + attestationPayload.attestationData = abi.encode("data"); + + vm.startPrank(portal); attestationRegistry.attest(attestationPayload, attester); + vm.startPrank(portal); + attestationRegistry.revoke(0x0003000000000000000000000000000000000000000000000000000000000001); uint256 balance = attestationRegistry.balanceOf(address(1), 1); assertEq(balance, 0); } - function test_balanceOf_subjectEncodedAddress(AttestationPayload memory attestationPayload) public { - vm.assume(attestationPayload.subject.length != 0); - vm.assume(attestationPayload.attestationData.length != 0); + function test_balanceOf_attestationExpired() public { + // Sets the block timestamp to 1641070800 + vm.warp(1641070800); + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + AttestationPayload memory attestationPayload; attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayload.expirationDate = block.timestamp > 1 days ? uint64(block.timestamp - 1 days) : 0; + attestationPayload.subject = abi.encode(address(1)); + attestationPayload.attestationData = abi.encode("data"); + + vm.startPrank(portal); + attestationRegistry.attest(attestationPayload, attester); + + uint256 balance = attestationRegistry.balanceOf(address(1), 1); + assertEq(balance, 0); + } + + function test_balanceOf_subjectNotFound() public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + AttestationPayload memory attestationPayload; + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayload.expirationDate = 0; + attestationPayload.subject = abi.encode(address(1234)); + attestationPayload.attestationData = abi.encode("data"); + vm.startPrank(portal); + attestationRegistry.attest(attestationPayload, attester); + + uint256 balance = attestationRegistry.balanceOf(address(1), 1); + assertEq(balance, 0); + } + + function test_balanceOf_subjectEncodedAddress() public { + SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); + schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); + + AttestationPayload memory attestationPayload; + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayload.expirationDate = 0; attestationPayload.subject = abi.encode(address(1)); + attestationPayload.attestationData = abi.encode("data"); + + vm.startPrank(portal); attestationRegistry.attest(attestationPayload, attester); uint256 balance = attestationRegistry.balanceOf(address(1), 1); assertEq(balance, 1); } - function test_balanceOf_subjectPackedEncodedAddress(AttestationPayload memory attestationPayload) public { - vm.assume(attestationPayload.subject.length != 0); - vm.assume(attestationPayload.attestationData.length != 0); + function test_balanceOf_subjectPackedEncodedAddress() public { SchemaRegistryMock schemaRegistryMock = SchemaRegistryMock(router.getSchemaRegistry()); - attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); schemaRegistryMock.createSchema("name", "description", "context", "schemaString"); - vm.startPrank(portal); + AttestationPayload memory attestationPayload; + attestationPayload.schemaId = schemaRegistryMock.getIdFromSchemaString("schemaString"); + attestationPayload.expirationDate = 0; attestationPayload.subject = abi.encodePacked(address(1)); + attestationPayload.attestationData = abi.encode("data"); + + vm.startPrank(portal); attestationRegistry.attest(attestationPayload, attester); uint256 balance = attestationRegistry.balanceOf(address(1), 1); diff --git a/contracts/test/DefaultPortal.t.sol b/contracts/test/DefaultPortal.t.sol index 0863b517..e897a199 100644 --- a/contracts/test/DefaultPortal.t.sol +++ b/contracts/test/DefaultPortal.t.sol @@ -51,7 +51,7 @@ contract DefaultPortalTest is Test { assertEq(address(defaultPortal.moduleRegistry()), address(moduleRegistryMock)); assertEq(address(defaultPortal.attestationRegistry()), address(attestationRegistryMock)); assertEq(address(defaultPortal.portalRegistry()), address(portalRegistryMock)); - assertEq(portalRegistryMock.getPortalByAddress(address(defaultPortal)).ownerAddress, portalOwner); + assertEq(portalRegistryMock.getPortalOwner(address(defaultPortal)), portalOwner); } function test_getModules() public view { @@ -323,6 +323,17 @@ contract DefaultPortalTest is Test { defaultPortal.bulkRevoke(attestationsToRevoke); } + function test_bulkRevoke_OnlyOwner() public { + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = bytes32("1"); + attestationsToRevoke[1] = bytes32("2"); + + // Revoke the attestation as a random user + vm.prank(makeAddr("random")); + vm.expectRevert(AbstractPortal.OnlyPortalOwner.selector); + defaultPortal.bulkRevoke(attestationsToRevoke); + } + function test_supportsInterface() public view { bool isIERC165Supported = defaultPortal.supportsInterface(type(ERC165Upgradeable).interfaceId); assertEq(isIERC165Supported, true); diff --git a/contracts/test/DefaultPortalV2.t.sol b/contracts/test/DefaultPortalV2.t.sol index 89e46b17..47c732c8 100644 --- a/contracts/test/DefaultPortalV2.t.sol +++ b/contracts/test/DefaultPortalV2.t.sol @@ -51,7 +51,7 @@ contract DefaultPortalV2Test is Test { assertEq(address(defaultPortal.moduleRegistry()), address(moduleRegistryMock)); assertEq(address(defaultPortal.attestationRegistry()), address(attestationRegistryMock)); assertEq(address(defaultPortal.portalRegistry()), address(portalRegistryMock)); - assertEq(portalRegistryMock.getPortalByAddress(address(defaultPortal)).ownerAddress, portalOwner); + assertEq(portalRegistryMock.getPortalOwner(address(defaultPortal)), portalOwner); } function test_getModules() public view { @@ -243,6 +243,17 @@ contract DefaultPortalV2Test is Test { defaultPortal.bulkRevoke(attestationsToRevoke); } + function test_bulkRevoke_OnlyOwner() public { + bytes32[] memory attestationsToRevoke = new bytes32[](2); + attestationsToRevoke[0] = bytes32("1"); + attestationsToRevoke[1] = bytes32("2"); + + // Revoke the attestation as a random user + vm.prank(makeAddr("random")); + vm.expectRevert(AbstractPortalV2.OnlyPortalOwner.selector); + defaultPortal.bulkRevoke(attestationsToRevoke); + } + function test_supportsInterface() public view { bool isIERC165Supported = defaultPortal.supportsInterface(type(ERC165Upgradeable).interfaceId); assertEq(isIERC165Supported, true); diff --git a/contracts/test/PortalRegistry.t.sol b/contracts/test/PortalRegistry.t.sol index d9895ec9..a5e0467e 100644 --- a/contracts/test/PortalRegistry.t.sol +++ b/contracts/test/PortalRegistry.t.sol @@ -40,7 +40,7 @@ contract PortalRegistryTest is Test { router = new Router(); router.initialize(); - portalRegistry = new PortalRegistry(false); + portalRegistry = new PortalRegistry(); router.updatePortalRegistry(address(portalRegistry)); moduleRegistryAddress = address(new ModuleRegistryMock()); @@ -61,11 +61,11 @@ contract PortalRegistryTest is Test { function test_initialize_ContractAlreadyInitialized() public { vm.expectRevert("Initializable: contract is already initialized"); - portalRegistry.initialize(); + portalRegistry.initialize(false); } function test_updateRouter() public { - PortalRegistry testPortalRegistry = new PortalRegistry(false); + PortalRegistry testPortalRegistry = new PortalRegistry(); vm.expectEmit(true, true, true, true); emit RouterUpdated(address(1)); @@ -76,7 +76,7 @@ contract PortalRegistryTest is Test { } function test_updateRouter_RouterInvalid() public { - PortalRegistry testPortalRegistry = new PortalRegistry(false); + PortalRegistry testPortalRegistry = new PortalRegistry(); vm.expectRevert(RouterManager.RouterInvalid.selector); vm.prank(address(0)); @@ -84,7 +84,7 @@ contract PortalRegistryTest is Test { } function test_updateRouter_RouterAlreadyUpdated() public { - PortalRegistry testPortalRegistry = new PortalRegistry(false); + PortalRegistry testPortalRegistry = new PortalRegistry(); vm.expectEmit(true, true, true, true); emit RouterUpdated(address(1)); vm.prank(address(0)); @@ -138,32 +138,19 @@ contract PortalRegistryTest is Test { portalRegistry.setIssuer(issuerAddress); } - function test_setIsTestnet_true() public { - bool isTestnet = portalRegistry.getIsTestnet(); - assertEq(isTestnet, false); - - vm.prank(address(0)); - vm.expectEmit(); - emit IsTestnetUpdated(true); - portalRegistry.setIsTestnet(true); - - isTestnet = portalRegistry.getIsTestnet(); - assertEq(isTestnet, true); - } - - function test_setIsTestnet_false() public { - PortalRegistry testnetPortalRegistry = new PortalRegistry(true); + function test_setIsTestnet() public { + PortalRegistry testnetPortalRegistry = new PortalRegistry(); bool isTestnet = testnetPortalRegistry.getIsTestnet(); - assertEq(isTestnet, true); + assertEq(isTestnet, false); vm.prank(address(0)); vm.expectEmit(); - emit IsTestnetUpdated(false); - testnetPortalRegistry.setIsTestnet(false); + emit IsTestnetUpdated(true); + testnetPortalRegistry.setIsTestnet(true); isTestnet = testnetPortalRegistry.getIsTestnet(); - assertEq(isTestnet, false); + assertEq(isTestnet, true); } function test_setIsTestnet_OnlyOwner() public { @@ -345,11 +332,39 @@ contract PortalRegistryTest is Test { portalRegistry.deployDefaultPortal(modules, expectedName, expectedDescription, true, expectedOwnerName); } - function test_getPortals_PortalNotRegistered() public { + function test_getPortalByAddress_PortalNotRegistered() public { vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); portalRegistry.getPortalByAddress(address(validPortalMock)); } + function test_getPortalOwner() public { + address portalAddress = address(validPortalMock); + vm.prank(user); + portalRegistry.register(portalAddress, expectedName, expectedDescription, true, expectedOwnerName); + + address ownerAddress = portalRegistry.getPortalOwner(portalAddress); + assertEq(ownerAddress, user); + } + + function test_getPortalOwner_PortalNotRegistered() public { + vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); + portalRegistry.getPortalOwner(address(validPortalMock)); + } + + function test_getPortalRevocability() public { + address portalAddress = address(validPortalMock); + vm.prank(user); + portalRegistry.register(portalAddress, expectedName, expectedDescription, true, expectedOwnerName); + + bool revocability = portalRegistry.getPortalRevocability(portalAddress); + assertEq(revocability, true); + } + + function test_getPortalRevocability_PortalNotRegistered() public { + vm.expectRevert(PortalRegistry.PortalNotRegistered.selector); + portalRegistry.getPortalRevocability(address(validPortalMock)); + } + function test_isRegistered() public { assertEq(portalRegistry.isRegistered(address(validPortalMock)), false); vm.prank(user); @@ -358,13 +373,16 @@ contract PortalRegistryTest is Test { } function test_isAllowlisted_Testnet() public { - PortalRegistry testnetPortalRegistry = new PortalRegistry(true); + PortalRegistry testnetPortalRegistry = new PortalRegistry(); + vm.prank(address(0)); + testnetPortalRegistry.setIsTestnet(true); + address userAddress = makeAddr("User"); assertEq(testnetPortalRegistry.isAllowlisted(userAddress), true); } function test_isAllowlisted_Testnet_fail() public { - PortalRegistry mainnetPortalRegistry = new PortalRegistry(false); + PortalRegistry mainnetPortalRegistry = new PortalRegistry(); address userAddress = makeAddr("User"); assertEq(mainnetPortalRegistry.isAllowlisted(userAddress), false); } @@ -383,7 +401,10 @@ contract PortalRegistryTest is Test { } function test_isAllowlisted_TestnetAndIssuer() public { - PortalRegistry testnetPortalRegistry = new PortalRegistry(true); + PortalRegistry testnetPortalRegistry = new PortalRegistry(); + vm.prank(address(0)); + testnetPortalRegistry.setIsTestnet(true); + address userAddress = makeAddr("User"); vm.prank(address(0)); testnetPortalRegistry.setIssuer(userAddress); @@ -391,7 +412,7 @@ contract PortalRegistryTest is Test { } function test_isAllowlisted_TestnetAndIssuer_fail() public { - PortalRegistry mainnetPortalRegistry = new PortalRegistry(false); + PortalRegistry mainnetPortalRegistry = new PortalRegistry(); address userAddress = makeAddr("User"); assertEq(mainnetPortalRegistry.isAllowlisted(userAddress), false); } diff --git a/contracts/test/examples/portals/EASPortal.t.sol b/contracts/test/examples/portals/EASPortal.t.sol index 771191e4..9c67ae5b 100644 --- a/contracts/test/examples/portals/EASPortal.t.sol +++ b/contracts/test/examples/portals/EASPortal.t.sol @@ -7,6 +7,7 @@ import { Router } from "../../../src/Router.sol"; import { AbstractPortalV2 } from "../../../src/abstracts/AbstractPortalV2.sol"; import { AttestationRegistryMock } from "../../mocks/AttestationRegistryMock.sol"; import { ModuleRegistryMock } from "../../mocks/ModuleRegistryMock.sol"; +import { PortalRegistryMock } from "../../mocks/PortalRegistryMock.sol"; import { ERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; contract EASPortalTest is Test { @@ -14,6 +15,7 @@ contract EASPortalTest is Test { EASPortal public easPortal; address[] public modules = new address[](0); ModuleRegistryMock public moduleRegistryMock = new ModuleRegistryMock(); + PortalRegistryMock public portalRegistryMock = new PortalRegistryMock(); AttestationRegistryMock public attestationRegistryMock = new AttestationRegistryMock(); Router public router = new Router(); @@ -24,9 +26,12 @@ contract EASPortalTest is Test { function setUp() public { router.initialize(); router.updateModuleRegistry(address(moduleRegistryMock)); + router.updatePortalRegistry(address(portalRegistryMock)); router.updateAttestationRegistry(address(attestationRegistryMock)); easPortal = new EASPortal(modules, address(router)); + + portalRegistryMock.register(address(easPortal), "EASPortal", "EASPortal description", false, "EAS"); } function test_attest() public { @@ -134,6 +139,7 @@ contract EASPortalTest is Test { function test_revoke() public { vm.expectRevert(EASPortal.NoRevocation.selector); + vm.prank(address(this)); easPortal.revoke(bytes32(uint256(1))); } @@ -147,6 +153,7 @@ contract EASPortalTest is Test { replacingAttestations[1] = bytes32(uint256(3)); vm.expectRevert(EASPortal.NoBulkRevocation.selector); + vm.prank(address(this)); easPortal.bulkRevoke(attestationsToRevoke); } diff --git a/contracts/test/integration/AttestationRegistryMass.t.sol b/contracts/test/integration/AttestationRegistryMass.t.sol index cd0a8ae6..4f9b1a51 100644 --- a/contracts/test/integration/AttestationRegistryMass.t.sol +++ b/contracts/test/integration/AttestationRegistryMass.t.sol @@ -38,7 +38,7 @@ contract AttestationRegistryMassTest is Test { vm.prank(address(0)); attestationRegistry.updateRouter(address(router)); - portalRegistry = new PortalRegistry(false); + portalRegistry = new PortalRegistry(); router.updatePortalRegistry(address(portalRegistry)); vm.prank(address(0)); portalRegistry.updateRouter(address(router)); diff --git a/contracts/test/integration/IssuersPortal.t.sol b/contracts/test/integration/IssuersPortal.t.sol index 0b310565..435aff04 100644 --- a/contracts/test/integration/IssuersPortal.t.sol +++ b/contracts/test/integration/IssuersPortal.t.sol @@ -16,7 +16,7 @@ contract IssuersPortalTest is Test { address public issuerAddress = makeAddr("issuer"); Router public router = new Router(); SchemaRegistry public schemaRegistry = new SchemaRegistry(); - PortalRegistry public portalRegistry = new PortalRegistry(false); + PortalRegistry public portalRegistry = new PortalRegistry(); ModuleRegistry public moduleRegistry = new ModuleRegistry(); AttestationRegistry public attestationRegistry = new AttestationRegistry(); IssuersModuleV2 public issuersModule; diff --git a/contracts/test/mocks/PortalRegistryMock.sol b/contracts/test/mocks/PortalRegistryMock.sol index b115e9c3..4cc907e5 100644 --- a/contracts/test/mocks/PortalRegistryMock.sol +++ b/contracts/test/mocks/PortalRegistryMock.sol @@ -32,6 +32,14 @@ contract PortalRegistryMock { return portals[id]; } + function getPortalOwner(address portalAddress) external view returns (address) { + return portals[portalAddress].ownerAddress; + } + + function getPortalRevocability(address portalAddress) external view returns (bool) { + return portals[portalAddress].isRevocable; + } + function setIssuer(address issuer) public { issuers[issuer] = true; } diff --git a/contracts/test/mocks/PortalRegistryNotAllowlistedMock.sol b/contracts/test/mocks/PortalRegistryNotAllowlistedMock.sol index c6f39545..18a2fbf3 100644 --- a/contracts/test/mocks/PortalRegistryNotAllowlistedMock.sol +++ b/contracts/test/mocks/PortalRegistryNotAllowlistedMock.sol @@ -32,6 +32,14 @@ contract PortalRegistryNotAllowlistedMock { return portals[id]; } + function getPortalOwner(address portalAddress) external view returns (address) { + return portals[portalAddress].ownerAddress; + } + + function getPortalRevocability(address portalAddress) external view returns (bool) { + return portals[portalAddress].isRevocable; + } + function setIssuer(address issuer) public { issuers[issuer] = true; } diff --git a/sdk/doc/cli-examples.md b/sdk/doc/cli-examples.md index 1da7d54f..60eca9ff 100644 --- a/sdk/doc/cli-examples.md +++ b/sdk/doc/cli-examples.md @@ -41,6 +41,10 @@ pnpm portal getPortalByAddress '{\"portalAddress\":\"0x8b833796869b5debb9b06370d6d47016f0d7973b\"}' + pnpm portal getPortalOwner '{\"portalAddress\":\"0x8b833796869b5debb9b06370d6d47016f0d7973b\"}' + + pnpm portal getPortalRevocability '{\"portalAddress\":\"0x8b833796869b5debb9b06370d6d47016f0d7973b\"}' + pnpm portal isPortalRegistered '{\"portalAddress\":\"0x8b833796869b5debb9b06370d6d47016f0d7973b\"}' pnpm portal getPortalsNumber diff --git a/sdk/examples/portal/portalExamples.ts b/sdk/examples/portal/portalExamples.ts index 3475a626..25c3a9fc 100644 --- a/sdk/examples/portal/portalExamples.ts +++ b/sdk/examples/portal/portalExamples.ts @@ -399,6 +399,24 @@ export default class PortalExamples { console.log(await this.veraxSdk.portal.getPortalByAddress(portalAddress)); } + if (methodName.toLowerCase() == "getPortalOwner".toLowerCase() || methodName == "") { + let params; + if (argv !== "") params = JSON.parse(argv); + const portalAddress = params?.portalAddress + ? (params.portalAddress as Address) + : "0x8b833796869b5debb9b06370d6d47016f0d7973b"; + console.log(await this.veraxSdk.portal.getPortalOwner(portalAddress)); + } + + if (methodName.toLowerCase() == "getPortalRevocability".toLowerCase() || methodName == "") { + let params; + if (argv !== "") params = JSON.parse(argv); + const portalAddress = params?.portalAddress + ? (params.portalAddress as Address) + : "0x8b833796869b5debb9b06370d6d47016f0d7973b"; + console.log(await this.veraxSdk.portal.getPortalRevocability(portalAddress)); + } + if (methodName.toLowerCase() == "getPortalsNumber".toLowerCase() || methodName == "") { console.log(await this.veraxSdk.portal.getPortalsNumber()); } diff --git a/sdk/src/abi/PortalRegistry.ts b/sdk/src/abi/PortalRegistry.ts index 13c29868..dc8cc790 100644 --- a/sdk/src/abi/PortalRegistry.ts +++ b/sdk/src/abi/PortalRegistry.ts @@ -195,6 +195,44 @@ export const abiPortalRegistry = [ stateMutability: "view", type: "function", }, + { + inputs: [ + { + internalType: "address", + name: "portalAddress", + type: "address", + }, + ], + name: "getPortalOwner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "portalAddress", + type: "address", + }, + ], + name: "getPortalRevocability", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, { inputs: [], name: "initialize", diff --git a/sdk/src/dataMapper/PortalDataMapper.ts b/sdk/src/dataMapper/PortalDataMapper.ts index 1907477a..252c1715 100644 --- a/sdk/src/dataMapper/PortalDataMapper.ts +++ b/sdk/src/dataMapper/PortalDataMapper.ts @@ -302,6 +302,24 @@ export default class PortalDataMapper extends BaseDataMapper