-
Notifications
You must be signed in to change notification settings - Fork 77
Expand file tree
/
Copy pathMultiSignatureECDSAValidator.sol
More file actions
133 lines (119 loc) · 4.84 KB
/
MultiSignatureECDSAValidator.sol
File metadata and controls
133 lines (119 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ECDSA} from "solady/utils/ECDSA.sol";
import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol";
import {IValidator, IHook} from "../interfaces/IERC7579Modules.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 MultiSignatureECDSAValidator is IValidator, IHook {
event OwnerRegistered(address indexed kernel, address indexed owner);
mapping(address => ECDSAValidatorStorage) public ecdsaValidatorStorage;
function onInstall(bytes calldata _data) external payable override {
if (_isInitialized(msg.sender)) revert AlreadyInitialized(msg.sender);
address owner = address(bytes20(_data[0:20]));
ecdsaValidatorStorage[msg.sender].owner = owner;
emit OwnerRegistered(msg.sender, owner);
}
function onUninstall(bytes calldata) external payable override {
if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender);
delete ecdsaValidatorStorage[msg.sender];
}
function isModuleType(uint256 typeID) external pure override returns (bool) {
return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_HOOK;
}
function isInitialized(address smartAccount) external view override returns (bool) {
return _isInitialized(smartAccount);
}
function _isInitialized(address smartAccount) internal view returns (bool) {
return ecdsaValidatorStorage[smartAccount].owner != address(0);
}
function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)
external
payable
override
returns (uint256)
{
bytes calldata sig = userOp.signature;
address owner = ecdsaValidatorStorage[msg.sender].owner;
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 recovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != recovered) {
return SIG_VALIDATION_FAILED_UINT;
}
return SIG_VALIDATION_SUCCESS_UINT;
}
function isValidSignatureWithSender(address, bytes32 hash, bytes calldata sig)
external
view
override
returns (bytes4)
{
address owner = ecdsaValidatorStorage[msg.sender].owner;
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 recovered = ECDSA.recover(ethRoot, ecdsaSig);
if (owner != recovered) {
return ERC1271_INVALID;
}
return ERC1271_MAGICVALUE;
}
function preCheck(address msgSender, uint256 value, bytes calldata)
external
payable
override
returns (bytes memory)
{
require(msgSender == ecdsaValidatorStorage[msg.sender].owner, "ECDSAValidator: sender is not owner");
return hex"";
}
function postCheck(bytes calldata hookData, bool success, bytes calldata res) external payable override {}
}