Skip to content

Commit

Permalink
Add erc 1271 module implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Builddddder committed Oct 23, 2023
1 parent c877819 commit e4dfaf4
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
87 changes: 87 additions & 0 deletions contracts/src/examples/modules/ERC1271Module.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { ECDSA } from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
import { Strings } from "openzeppelin-contracts/contracts/utils/Strings.sol";

import { AbstractModule } from "../interface/AbstractModule.sol";
import { AttestationPayload } from "../types/Structs.sol";

import "forge-std/console.sol";

contract ERC1271Module is AbstractModule {
address public owner;
constructor(address _owner) {
owner = _owner;
}

/**
* @notice Recover the signer of hash, assuming it's an EOA account
* @dev Only for EthSign signatures
* @param _hash Hash of message that was signed
* @param _signature Signature encoded as (bytes32 r, bytes32 s, uint8 v)
*/
function recoverSigner(
bytes32 _hash,
bytes memory _signature
) internal pure returns (address signer) {
require(_signature.length == 65, "Invalid signature length");
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(_signature, 0x20))
s := mload(add(_signature, 0x40))
v := byte(0, mload(add(_signature, 0x60)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert("SignatureValidator#recoverSigner: invalid signature 's' value");
}
if (v != 27 && v != 28) {
revert("SignatureValidator#recoverSigner: invalid signature 'v' value");
}

//address signee = abi.decode(attestationPayload.subject, (address));
//uint256 nonce = abi.decode(attestationPayload.attestationData, (uint256));
//bytes memory message = abi.encodePacked(signee, nonce);
//bytes32 digest = keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));

signer = ecrecover(_hash, v, r, s);
// Prevent signer from being 0x0
require(
signer != address(0x0),
"SignatureValidator#recoverSigner: INVALID_SIGNER"
);
return signer;
}

/**
* @notice Verifies that the signer is the owner of the signing contract.
*/
function isValidSignature(
bytes32 _hash,
bytes memory _signature
) internal view returns (bytes4) {
// Validate signatures
address signer = recoverSigner(_hash, _signature);
if (signer == owner) {
return 0x1626ba7e;
} else {
return 0xffffffff;
}
}

function run(
AttestationPayload memory attestationPayload,
bytes memory validationPayload,
address txSender,
uint256 /*value*/
) public view override {
require(txSender == owner, "Invalid sender");
address signee = abi.decode(attestationPayload.subject, (address));
uint256 nonce = abi.decode(attestationPayload.attestationData, (uint256));
bytes memory message = abi.encodePacked(signee, nonce);
bytes32 digest = keccak256(bytes.concat("\x19Ethereum Signed Message:\n", message));
require(isValidSignature(digest, validationPayload) == 0x1626ba7e, "SignatureValidator#isValidSignature: INVALID_SIGNER");
}
}
52 changes: 52 additions & 0 deletions contracts/test/example/ERC1271Module.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { Test } from "forge-std/Test.sol";
import { ECDSA } from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol";
import { AbstractModule } from "../../src/interface/AbstractModule.sol";
import { ERC1271Module } from "../../src/example/ERC1271Module.sol";
import { AttestationPayload } from "../../src/types/Structs.sol";
import "forge-std/console.sol";

contract ERC1271ModuleTest is Test {
ERC1271Module private erc1271Module;
uint256 internal signerPrivateKey;
address internal signerAddress;

event ModuleRegistered(string name, string description, address moduleAddress);

function setUp() public {
(signerAddress, signerPrivateKey) = makeAddrAndKey("veraxUser");
erc1271Module = new ERC1271Module(signerAddress);
vm.deal(signerAddress, 1 ether);
}

function test_ERC1271Module_verifySignature() public {
address user = makeAddr("user");
uint256 nonce = 1234567;
AttestationPayload memory attestationPayload = AttestationPayload(
bytes32(uint256(1234)),
0,
abi.encode(user),
abi.encode(nonce)
);

bytes32 hash = keccak256(bytes.concat("\x19Ethereum Signed Message:\n", abi.encodePacked(user, nonce)));
/*console.log(message.length);
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash
mstore(0x1c, message) // 0x1c (28) is the length of the prefix
hash := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}*/
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKey, hash);

bytes memory signature = abi.encodePacked(r, s, v);

erc1271Module.run(attestationPayload, signature, signerAddress, 0);
}

function test_EcRecoverModule_supportsInterface() public {
bool isAbstractModuleSupported = erc1271Module.supportsInterface(type(AbstractModule).interfaceId);
assertEq(isAbstractModuleSupported, true);
}
}

0 comments on commit e4dfaf4

Please sign in to comment.