Skip to content

Commit

Permalink
multisignature signer (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
leekt authored Apr 17, 2024
1 parent 9a37972 commit b8442f2
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 4 deletions.
119 changes: 119 additions & 0 deletions src/signer/MultiSignatureSigner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {ECDSA} from "solady/utils/ECDSA.sol";
import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol";
import {ISigner} from "../interfaces/IERC7579Modules.sol";
import {SignerBase} from "../sdk/moduleBase/SignerBase.sol";
import {PackedUserOperation} from "../interfaces/PackedUserOperation.sol";
import {
SIG_VALIDATION_SUCCESS_UINT,
SIG_VALIDATION_FAILED_UINT,
MODULE_TYPE_VALIDATOR,
MODULE_TYPE_HOOK,
ERC1271_MAGICVALUE,
ERC1271_INVALID
} from "../types/Constants.sol";

struct ECDSAValidatorStorage {
address owner;
}

contract MultiSignatureECDSASigner is SignerBase {
mapping(address => uint256) public usedIds;
mapping(bytes32 id => mapping(address wallet => address)) public signer;
event SignerRegistered(address indexed kernel, bytes32 indexed id, address indexed owner);
error NoSignerRegistered();

function isInitialized(address wallet) external view override returns (bool) {
return usedIds[wallet] > 0;
}

function _signerOninstall(bytes32 id, bytes calldata _data) internal override {
if(signer[id][msg.sender] == address(0)) {
usedIds[msg.sender]++;
}
signer[id][msg.sender] = address(bytes20(_data[0:20]));
emit SignerRegistered(msg.sender, id, address(bytes20(_data[0:20])));
}

function _signerOnUninstall(bytes32 id, bytes calldata) internal override {
if(signer[id][msg.sender] == address(0)) {
revert NoSignerRegistered();
}
delete signer[id][msg.sender];
usedIds[msg.sender]--;
}

function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
payable
override
returns (uint256)
{
bytes calldata sig = userOp.signature;
address owner = signer[id][msg.sender];
if (sig.length == 65) {
// simple ecdsa verification
if (owner == ECDSA.recover(userOpHash, sig)) {
return SIG_VALIDATION_SUCCESS_UINT;
}
bytes32 ethHash = ECDSA.toEthSignedMessageHash(userOpHash);
address recovered = ECDSA.recover(ethHash, sig);
if (owner != recovered) {
return SIG_VALIDATION_FAILED_UINT;
}
return SIG_VALIDATION_SUCCESS_UINT;
}
bytes memory ecdsaSig = sig[0:65];
bytes32 merkleRoot = bytes32(sig[65:97]);
bytes32[] memory proof = abi.decode(sig[97:], (bytes32[]));
require(MerkleProofLib.verify(proof, merkleRoot, userOpHash), "hash is not in proof");
// simple ecdsa verification
if (owner == ECDSA.recover(merkleRoot, ecdsaSig)) {
return SIG_VALIDATION_SUCCESS_UINT;
}
bytes32 ethRoot = ECDSA.toEthSignedMessageHash(merkleRoot);
address merkleRecovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != merkleRecovered) {
return SIG_VALIDATION_FAILED_UINT;
}
return SIG_VALIDATION_SUCCESS_UINT;
}

function checkSignature(bytes32 id, address sender, bytes32 hash, bytes calldata sig)
external
view
override
returns (bytes4)
{
address owner = signer[id][msg.sender];
if (sig.length == 65) {
// simple ecdsa verification
if (owner == ECDSA.recover(hash, sig)) {
return ERC1271_MAGICVALUE;
}
bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash);
address recovered = ECDSA.recover(ethHash, sig);
if (owner != recovered) {
return ERC1271_INVALID;
}
return ERC1271_MAGICVALUE;
}
bytes memory ecdsaSig = sig[0:65];
bytes32 merkleRoot = bytes32(sig[65:97]);
bytes32[] memory proof = abi.decode(sig[97:], (bytes32[]));
require(MerkleProofLib.verify(proof, merkleRoot, hash), "hash is not in proof");
// simple ecdsa verification
if (owner == ECDSA.recover(merkleRoot, ecdsaSig)) {
return ERC1271_MAGICVALUE;
}
bytes32 ethRoot = ECDSA.toEthSignedMessageHash(merkleRoot);
address merkleRecovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != merkleRecovered) {
return ERC1271_INVALID;
}
return ERC1271_MAGICVALUE;
}
}
8 changes: 4 additions & 4 deletions src/validator/MultiSignatureECDSAValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ contract MultiSignatureECDSAValidator is IValidator, IHook {
return SIG_VALIDATION_SUCCESS_UINT;
}
bytes32 ethRoot = ECDSA.toEthSignedMessageHash(merkleRoot);
address recovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != recovered) {
address merkleRecovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != merkleRecovered) {
return SIG_VALIDATION_FAILED_UINT;
}
return SIG_VALIDATION_SUCCESS_UINT;
Expand Down Expand Up @@ -112,8 +112,8 @@ contract MultiSignatureECDSAValidator is IValidator, IHook {
return ERC1271_MAGICVALUE;
}
bytes32 ethRoot = ECDSA.toEthSignedMessageHash(merkleRoot);
address recovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != recovered) {
address merkleRecovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != merkleRecovered) {
return ERC1271_INVALID;
}
return ERC1271_MAGICVALUE;
Expand Down

0 comments on commit b8442f2

Please sign in to comment.