From b9e50141a21ea4a703c7e55cf0c70c63c971f34b Mon Sep 17 00:00:00 2001 From: boyuanx Date: Mon, 16 Sep 2024 12:11:06 -0700 Subject: [PATCH] Add new schema hook example --- src/03-schema-hook-2/DataAttester.sol | 40 +++++++++++ src/03-schema-hook-2/DataValidatorHook.sol | 84 ++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/03-schema-hook-2/DataAttester.sol create mode 100644 src/03-schema-hook-2/DataValidatorHook.sol diff --git a/src/03-schema-hook-2/DataAttester.sol b/src/03-schema-hook-2/DataAttester.sol new file mode 100644 index 0000000..654bd0f --- /dev/null +++ b/src/03-schema-hook-2/DataAttester.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { ISP } from "@ethsign/sign-protocol-evm/src/interfaces/ISP.sol"; +import { Attestation } from "@ethsign/sign-protocol-evm/src/models/Attestation.sol"; +import { DataLocation } from "@ethsign/sign-protocol-evm/src/models/DataLocation.sol"; + +contract DataAttester is Ownable { + ISP public spInstance; + uint64 public schemaId; + + constructor() Ownable(_msgSender()) { } + + function setSPInstance(address instance) external onlyOwner { + spInstance = ISP(instance); + } + + function setSchemaID(uint64 schemaId_) external onlyOwner { + schemaId = schemaId_; + } + + function attest(address recipient, uint256 someNumber) external returns (uint64) { + bytes[] memory recipients = new bytes[](2); + recipients[0] = abi.encode(recipient); + Attestation memory a = Attestation({ + schemaId: schemaId, + linkedAttestationId: 0, + attestTimestamp: 0, + revokeTimestamp: 0, + attester: address(this), + validUntil: 0, + dataLocation: DataLocation.ONCHAIN, + revoked: false, + recipients: recipients, + data: abi.encode(someNumber) + }); + return spInstance.attest(a, "", "", ""); + } +} diff --git a/src/03-schema-hook-2/DataValidatorHook.sol b/src/03-schema-hook-2/DataValidatorHook.sol new file mode 100644 index 0000000..4ff6284 --- /dev/null +++ b/src/03-schema-hook-2/DataValidatorHook.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; +import { ISP } from "@ethsign/sign-protocol-evm/src/interfaces/ISP.sol"; +import { ISPHook } from "@ethsign/sign-protocol-evm/src/interfaces/ISPHook.sol"; +import { Attestation } from "@ethsign/sign-protocol-evm/src/models/Attestation.sol"; + +// @dev This contract manages attestation data validation logic. +contract DataValidator is Ownable { + uint256 public threshold; + + error NumberBelowThreshold(); + + constructor() Ownable(_msgSender()) { } + + function setThreshold(uint256 threshold_) external onlyOwner { + threshold = threshold_; + } + + function _checkThreshold(uint256 number) internal view { + // solhint-disable-next-line custom-errors + require(number >= threshold, NumberBelowThreshold()); + } +} + +// @dev This contract implements the actual schema hook. +contract DataValidatorHook is ISPHook, DataValidator { + error UnsupportedOperation(); + + function didReceiveAttestation( + address, // attester + uint64, // schemaId + uint64 attestationId, + bytes calldata // extraData + ) + external + payable + { + Attestation memory attestation = ISP(_msgSender()).getAttestation(attestationId); + _checkThreshold(abi.decode(attestation.data, (uint256))); + } + + function didReceiveAttestation( + address, // attester + uint64, // schemaId + uint64, // attestationId + IERC20, // resolverFeeERC20Token + uint256, // resolverFeeERC20Amount + bytes calldata // extraData + ) + external + pure + { + revert UnsupportedOperation(); + } + + function didReceiveRevocation( + address, // attester + uint64, // schemaId + uint64, // attestationId + bytes calldata // extraData + ) + external + payable + { + revert UnsupportedOperation(); + } + + function didReceiveRevocation( + address, // attester + uint64, // schemaId + uint64, // attestationId + IERC20, // resolverFeeERC20Token + uint256, // resolverFeeERC20Amount + bytes calldata // extraData + ) + external + pure + { + revert UnsupportedOperation(); + } +}