From 68aa16d117746b294578c038c7ded391dccb6bc2 Mon Sep 17 00:00:00 2001 From: Builddddder Date: Tue, 24 Oct 2023 13:30:30 +0800 Subject: [PATCH 1/5] Add SchemaCheckerModule --- .../examples/modules/SchemaCheckerModule.sol | 28 ++++++++++ .../test/example/SchemaCheckerModule.t.sol | 55 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 contracts/src/examples/modules/SchemaCheckerModule.sol create mode 100644 contracts/test/example/SchemaCheckerModule.t.sol diff --git a/contracts/src/examples/modules/SchemaCheckerModule.sol b/contracts/src/examples/modules/SchemaCheckerModule.sol new file mode 100644 index 00000000..7ef432f1 --- /dev/null +++ b/contracts/src/examples/modules/SchemaCheckerModule.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { AbstractModule } from "../../interface/AbstractModule.sol"; +import { AttestationPayload } from "../../types/Structs.sol"; + +contract SchemaCheckerModule is AbstractModule { + + error InvalidSchemaId(); + struct Profile { + address issuer; + bytes32 schemaId; + uint64 issueDate; + } + function run( + AttestationPayload memory attestationPayload, + bytes memory /*validationPayload*/, + address /*txSender*/, + uint256 /*value*/ + ) public view override { + Profile memory issuerProfile; + (issuerProfile.issuer, issuerProfile.schemaId, issuerProfile.issueDate) = + abi.decode(attestationPayload.attestationData, (address, bytes32, uint64)); + if (issuerProfile.schemaId != attestationPayload.schemaId) { + revert InvalidSchemaId(); + } + } +} diff --git a/contracts/test/example/SchemaCheckerModule.t.sol b/contracts/test/example/SchemaCheckerModule.t.sol new file mode 100644 index 00000000..46f369ec --- /dev/null +++ b/contracts/test/example/SchemaCheckerModule.t.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.21; + +import { Test } from "forge-std/Test.sol"; +import { AbstractModule } from "../../src/interface/AbstractModule.sol"; +import { SchemaCheckerModule } from "../../src/examples/modules/SchemaCheckerModule.sol"; +import { AttestationPayload } from "../../src/types/Structs.sol"; + +contract SchemaCheckerModuleTest is Test { + SchemaCheckerModule private schemaCheckerModule; + address internal issuer; + + event ModuleRegistered(string name, string description, address moduleAddress); + + function setUp() public { + issuer = makeAddr("issuer"); + schemaCheckerModule = new SchemaCheckerModule(); + vm.deal(issuer, 1 ether); + } + + function test_SchemaCheckerModule_verifySchemaId() public { + address user = makeAddr("user"); + bytes32 schemaId = bytes32(uint256(1234)); + uint64 issueDate = 0; + AttestationPayload memory attestationPayload = AttestationPayload( + schemaId, + 0, + abi.encode(user), + abi.encode(issuer, schemaId, issueDate) + ); + + schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); + } + + function test_SchemaCheckerModule_InvalidSchemaId() public { + address user = makeAddr("user"); + bytes32 schemaId = bytes32(uint256(1234)); + uint64 issueDate = 0; + AttestationPayload memory attestationPayload = AttestationPayload( + schemaId, + 0, + abi.encode(user), + abi.encode(issuer, bytes32(uint256(4321)), issueDate) + ); + + vm.expectRevert(SchemaCheckerModule.InvalidSchemaId.selector); + schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); + + } + + function test_EcRecoverModule_supportsInterface() public { + bool isAbstractModuleSupported = schemaCheckerModule.supportsInterface(type(AbstractModule).interfaceId); + assertEq(isAbstractModuleSupported, true); + } +} From 227fad1313020a2fdfe88d6ba708feb348c3d94f Mon Sep 17 00:00:00 2001 From: Builddddder Date: Tue, 24 Oct 2023 13:39:14 +0800 Subject: [PATCH 2/5] Run prettier --- .../examples/modules/SchemaCheckerModule.sol | 17 ++++++++++++++--- .../test/example/SchemaCheckerModule.t.sol | 3 +-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/contracts/src/examples/modules/SchemaCheckerModule.sol b/contracts/src/examples/modules/SchemaCheckerModule.sol index 7ef432f1..c5d16843 100644 --- a/contracts/src/examples/modules/SchemaCheckerModule.sol +++ b/contracts/src/examples/modules/SchemaCheckerModule.sol @@ -4,14 +4,23 @@ pragma solidity 0.8.21; import { AbstractModule } from "../../interface/AbstractModule.sol"; import { AttestationPayload } from "../../types/Structs.sol"; +/** + * @title Schema checker Module + * @notice This contract illustrates a valid Module that is used to check the schema that an attestation is based on + */ contract SchemaCheckerModule is AbstractModule { - error InvalidSchemaId(); struct Profile { address issuer; bytes32 schemaId; uint64 issueDate; } + + /** + * @notice This method is used to run the module's validation logic + * @param attestationPayload - AttestationPayload containing the user address as `subject` and nonce as `attestationData` + * @param validationPayload - Payload encoded with abi.encode(uint256).toEthSignedMessageHash().sign(signer) + */ function run( AttestationPayload memory attestationPayload, bytes memory /*validationPayload*/, @@ -19,8 +28,10 @@ contract SchemaCheckerModule is AbstractModule { uint256 /*value*/ ) public view override { Profile memory issuerProfile; - (issuerProfile.issuer, issuerProfile.schemaId, issuerProfile.issueDate) = - abi.decode(attestationPayload.attestationData, (address, bytes32, uint64)); + (issuerProfile.issuer, issuerProfile.schemaId, issuerProfile.issueDate) = abi.decode( + attestationPayload.attestationData, + (address, bytes32, uint64) + ); if (issuerProfile.schemaId != attestationPayload.schemaId) { revert InvalidSchemaId(); } diff --git a/contracts/test/example/SchemaCheckerModule.t.sol b/contracts/test/example/SchemaCheckerModule.t.sol index 46f369ec..790378da 100644 --- a/contracts/test/example/SchemaCheckerModule.t.sol +++ b/contracts/test/example/SchemaCheckerModule.t.sol @@ -28,7 +28,7 @@ contract SchemaCheckerModuleTest is Test { abi.encode(user), abi.encode(issuer, schemaId, issueDate) ); - + schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); } @@ -45,7 +45,6 @@ contract SchemaCheckerModuleTest is Test { vm.expectRevert(SchemaCheckerModule.InvalidSchemaId.selector); schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); - } function test_EcRecoverModule_supportsInterface() public { From aab1e1c7454049ad7f284b1beaa602a284a6a360 Mon Sep 17 00:00:00 2001 From: Builddddder Date: Tue, 24 Oct 2023 13:41:36 +0800 Subject: [PATCH 3/5] Remove useless parameter comments --- contracts/src/examples/modules/SchemaCheckerModule.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/src/examples/modules/SchemaCheckerModule.sol b/contracts/src/examples/modules/SchemaCheckerModule.sol index c5d16843..2db99ac9 100644 --- a/contracts/src/examples/modules/SchemaCheckerModule.sol +++ b/contracts/src/examples/modules/SchemaCheckerModule.sol @@ -19,7 +19,6 @@ contract SchemaCheckerModule is AbstractModule { /** * @notice This method is used to run the module's validation logic * @param attestationPayload - AttestationPayload containing the user address as `subject` and nonce as `attestationData` - * @param validationPayload - Payload encoded with abi.encode(uint256).toEthSignedMessageHash().sign(signer) */ function run( AttestationPayload memory attestationPayload, From 83254b4f03f34ae5d71899dbef73e88f38a09ab0 Mon Sep 17 00:00:00 2001 From: Builddddder Date: Wed, 25 Oct 2023 00:08:19 +0800 Subject: [PATCH 4/5] Use hard coded schema-id --- contracts/src/examples/modules/SchemaCheckerModule.sol | 8 ++------ contracts/test/example/SchemaCheckerModule.t.sol | 9 ++++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/contracts/src/examples/modules/SchemaCheckerModule.sol b/contracts/src/examples/modules/SchemaCheckerModule.sol index 2db99ac9..95ab77d4 100644 --- a/contracts/src/examples/modules/SchemaCheckerModule.sol +++ b/contracts/src/examples/modules/SchemaCheckerModule.sol @@ -26,13 +26,9 @@ contract SchemaCheckerModule is AbstractModule { address /*txSender*/, uint256 /*value*/ ) public view override { - Profile memory issuerProfile; - (issuerProfile.issuer, issuerProfile.schemaId, issuerProfile.issueDate) = abi.decode( - attestationPayload.attestationData, - (address, bytes32, uint64) - ); - if (issuerProfile.schemaId != attestationPayload.schemaId) { + if (keccak256(abi.encodePacked(attestationPayload.schemaId)) != keccak256(abi.encode(bytes32("12345678")))) { revert InvalidSchemaId(); } + abi.decode(attestationPayload.attestationData, (address, bytes32, uint64)); } } diff --git a/contracts/test/example/SchemaCheckerModule.t.sol b/contracts/test/example/SchemaCheckerModule.t.sol index 790378da..dbfd1887 100644 --- a/contracts/test/example/SchemaCheckerModule.t.sol +++ b/contracts/test/example/SchemaCheckerModule.t.sol @@ -18,15 +18,14 @@ contract SchemaCheckerModuleTest is Test { vm.deal(issuer, 1 ether); } - function test_SchemaCheckerModule_verifySchemaId() public { + function test_SchemaCheckerModule_matchSchemaId() public { address user = makeAddr("user"); - bytes32 schemaId = bytes32(uint256(1234)); uint64 issueDate = 0; AttestationPayload memory attestationPayload = AttestationPayload( - schemaId, + bytes32("12345678"), 0, abi.encode(user), - abi.encode(issuer, schemaId, issueDate) + abi.encode(issuer, "112334", issueDate) ); schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); @@ -47,7 +46,7 @@ contract SchemaCheckerModuleTest is Test { schemaCheckerModule.run(attestationPayload, bytes("0000"), user, 0); } - function test_EcRecoverModule_supportsInterface() public { + function test_SchemaCheckerModule_supportsInterface() public { bool isAbstractModuleSupported = schemaCheckerModule.supportsInterface(type(AbstractModule).interfaceId); assertEq(isAbstractModuleSupported, true); } From baeba8be8fd6ee7133f4d69c1660a4e1cca9c038 Mon Sep 17 00:00:00 2001 From: Builddddder Date: Wed, 25 Oct 2023 18:30:40 +0800 Subject: [PATCH 5/5] Add comment to illustrate the profile --- contracts/src/examples/modules/SchemaCheckerModule.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/src/examples/modules/SchemaCheckerModule.sol b/contracts/src/examples/modules/SchemaCheckerModule.sol index 95ab77d4..2e1a308a 100644 --- a/contracts/src/examples/modules/SchemaCheckerModule.sol +++ b/contracts/src/examples/modules/SchemaCheckerModule.sol @@ -10,6 +10,9 @@ import { AttestationPayload } from "../../types/Structs.sol"; */ contract SchemaCheckerModule is AbstractModule { error InvalidSchemaId(); + /* + * @notice This is an example of how to check the attestation payload encoding/decoding, based on a "Profile Schema" + */ struct Profile { address issuer; bytes32 schemaId; @@ -17,6 +20,7 @@ contract SchemaCheckerModule is AbstractModule { } /** + * @inheritdoc AbstractModule * @notice This method is used to run the module's validation logic * @param attestationPayload - AttestationPayload containing the user address as `subject` and nonce as `attestationData` */