From f00bebb79c2c76bc1fccc116e54616ea8af58d6f Mon Sep 17 00:00:00 2001 From: adnpark Date: Fri, 3 May 2024 00:35:22 +0900 Subject: [PATCH 1/3] feat: change contract name and add dummy signature verification --- ...ECDSAValidator.sol => MultiChainValidator.sol} | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) rename src/validator/{MultiSignatureECDSAValidator.sol => MultiChainValidator.sol} (84%) diff --git a/src/validator/MultiSignatureECDSAValidator.sol b/src/validator/MultiChainValidator.sol similarity index 84% rename from src/validator/MultiSignatureECDSAValidator.sol rename to src/validator/MultiChainValidator.sol index 7c8ae6a..020bfe4 100644 --- a/src/validator/MultiSignatureECDSAValidator.sol +++ b/src/validator/MultiChainValidator.sol @@ -19,7 +19,9 @@ struct ECDSAValidatorStorage { address owner; } -contract MultiSignatureECDSAValidator is IValidator, IHook { +bytes constant DUMMY_ECDSA_SIG = hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; + +contract MultiChainValidator is IValidator, IHook { event OwnerRegistered(address indexed kernel, address indexed owner); mapping(address => ECDSAValidatorStorage) public ecdsaValidatorStorage; @@ -69,8 +71,15 @@ contract MultiSignatureECDSAValidator is IValidator, IHook { } 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"); + // if the signature is a dummy signature, then use dummyUserOpHash instead of real userOpHash + if (keccak256(ecdsaSig) == keccak256(DUMMY_ECDSA_SIG)) { + (bytes32 dummyUserOpHash, bytes32[] memory proof) = abi.decode(sig[97:], (bytes32, bytes32[])); + require(MerkleProofLib.verify(proof, merkleRoot, dummyUserOpHash), "hash is not in proof"); + // otherwise, use real userOpHash + } else { + 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; From d59b4cbaf25d626b7dd23ce8f1956033dcfcc8d0 Mon Sep 17 00:00:00 2001 From: adnpark Date: Tue, 7 May 2024 19:51:29 +0900 Subject: [PATCH 2/3] feat: add dummy signature verification to multi chain signer --- ...tiSignatureSigner.sol => MultiChainSigner.sol} | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) rename src/signer/{MultiSignatureSigner.sol => MultiChainSigner.sol} (83%) diff --git a/src/signer/MultiSignatureSigner.sol b/src/signer/MultiChainSigner.sol similarity index 83% rename from src/signer/MultiSignatureSigner.sol rename to src/signer/MultiChainSigner.sol index fe21f10..49c8c69 100644 --- a/src/signer/MultiSignatureSigner.sol +++ b/src/signer/MultiChainSigner.sol @@ -20,7 +20,9 @@ struct ECDSAValidatorStorage { address owner; } -contract MultiSignatureECDSASigner is SignerBase { +bytes constant DUMMY_ECDSA_SIG = hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; + +contract MultiChainSigner is SignerBase { mapping(address => uint256) public usedIds; mapping(bytes32 id => mapping(address wallet => address)) public signer; @@ -70,8 +72,15 @@ contract MultiSignatureECDSASigner is SignerBase { } 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"); + // if the signature is a dummy signature, then use dummyUserOpHash instead of real userOpHash + if (keccak256(ecdsaSig) == keccak256(DUMMY_ECDSA_SIG)) { + (bytes32 dummyUserOpHash, bytes32[] memory proof) = abi.decode(sig[97:], (bytes32, bytes32[])); + require(MerkleProofLib.verify(proof, merkleRoot, dummyUserOpHash), "hash is not in proof"); + // otherwise, use real userOpHash + } else { + 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; From 2ee49e483ed9e419574aaa66497be3947d08d857 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 8 May 2024 01:55:21 +0900 Subject: [PATCH 3/3] fmt --- src/signer/MultiChainSigner.sol | 5 +++-- src/validator/MultiChainValidator.sol | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/signer/MultiChainSigner.sol b/src/signer/MultiChainSigner.sol index 49c8c69..de2f5c5 100644 --- a/src/signer/MultiChainSigner.sol +++ b/src/signer/MultiChainSigner.sol @@ -20,7 +20,8 @@ struct ECDSAValidatorStorage { address owner; } -bytes constant DUMMY_ECDSA_SIG = hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; +bytes constant DUMMY_ECDSA_SIG = + hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; contract MultiChainSigner is SignerBase { mapping(address => uint256) public usedIds; @@ -76,7 +77,7 @@ contract MultiChainSigner is SignerBase { if (keccak256(ecdsaSig) == keccak256(DUMMY_ECDSA_SIG)) { (bytes32 dummyUserOpHash, bytes32[] memory proof) = abi.decode(sig[97:], (bytes32, bytes32[])); require(MerkleProofLib.verify(proof, merkleRoot, dummyUserOpHash), "hash is not in proof"); - // otherwise, use real userOpHash + // otherwise, use real userOpHash } else { bytes32[] memory proof = abi.decode(sig[97:], (bytes32[])); require(MerkleProofLib.verify(proof, merkleRoot, userOpHash), "hash is not in proof"); diff --git a/src/validator/MultiChainValidator.sol b/src/validator/MultiChainValidator.sol index 020bfe4..0c9dfb2 100644 --- a/src/validator/MultiChainValidator.sol +++ b/src/validator/MultiChainValidator.sol @@ -19,7 +19,8 @@ struct ECDSAValidatorStorage { address owner; } -bytes constant DUMMY_ECDSA_SIG = hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; +bytes constant DUMMY_ECDSA_SIG = + hex"fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"; contract MultiChainValidator is IValidator, IHook { event OwnerRegistered(address indexed kernel, address indexed owner); @@ -75,7 +76,7 @@ contract MultiChainValidator is IValidator, IHook { if (keccak256(ecdsaSig) == keccak256(DUMMY_ECDSA_SIG)) { (bytes32 dummyUserOpHash, bytes32[] memory proof) = abi.decode(sig[97:], (bytes32, bytes32[])); require(MerkleProofLib.verify(proof, merkleRoot, dummyUserOpHash), "hash is not in proof"); - // otherwise, use real userOpHash + // otherwise, use real userOpHash } else { bytes32[] memory proof = abi.decode(sig[97:], (bytes32[])); require(MerkleProofLib.verify(proof, merkleRoot, userOpHash), "hash is not in proof");