Skip to content

Commit aedd3da

Browse files
[hebao] Update SignatureUtil and ERC1271 support (#1741)
* Update SignatureUtil.sol * fix compile errors * fix ERC1271Module and test * fix a bug in SignatureUtil.sol * ERC1271Module.sol refine * Improve signature check dong (#1743) * remove support of legacy erc1271 * remove support of legacy erc1271 * remove support of legacy erc1271 * fix test Co-authored-by: kongliangzhong <[email protected]>
1 parent 30912dd commit aedd3da

File tree

5 files changed

+61
-184
lines changed

5 files changed

+61
-184
lines changed

packages/hebao_v1/contracts/lib/ERC1271.sol

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,8 @@
33
pragma solidity ^0.7.0;
44

55
abstract contract ERC1271 {
6-
7-
// bytes4(keccak256("isValidSignature(bytes,bytes)")
8-
bytes4 constant internal ERC1271_MAGICVALUE_BS = 0x20c13b0b;
9-
106
// bytes4(keccak256("isValidSignature(bytes32,bytes)")
11-
bytes4 constant internal ERC1271_MAGICVALUE_B32 = 0x1626ba7e;
12-
13-
bytes4 constant internal ERC1271_SELECTOR_BS = bytes4(
14-
keccak256(bytes("isValidSignature(bytes,bytes)"))
15-
);
16-
17-
bytes4 constant internal ERC1271_SELECTOR_B32 = bytes4(
18-
keccak256(bytes("isValidSignature(bytes32,bytes)"))
19-
);
20-
21-
function isValidSignature(
22-
bytes memory _data,
23-
bytes memory _signature)
24-
public
25-
view
26-
virtual
27-
returns (bytes4 magicValueBS);
7+
bytes4 constant internal ERC1271_MAGICVALUE = 0x1626ba7e;
288

299
function isValidSignature(
3010
bytes32 _hash,

packages/hebao_v1/contracts/lib/SignatureUtil.sol

Lines changed: 32 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ pragma experimental ABIEncoderV2;
55

66
import "../thirdparty/BytesUtil.sol";
77
import "./AddressUtil.sol";
8+
import "./ERC1271.sol";
89
import "./MathUint.sol";
910

1011

1112
/// @title SignatureUtil
1213
/// @author Daniel Wang - <[email protected]>
13-
/// @dev This method supports multihash standard. Each signature's first byte indicates
14-
/// the signature's type, the second byte indicates the signature's length, therefore,
15-
/// each signature will have 2 extra bytes prefix. Mulitple signatures are concatenated
16-
/// together.
14+
/// @dev This method supports multihash standard. Each signature's last byte indicates
15+
/// the signature's type.
1716
library SignatureUtil
1817
{
1918
using BytesUtil for bytes;
@@ -28,16 +27,7 @@ library SignatureUtil
2827
WALLET // deprecated
2928
}
3029

31-
bytes4 constant internal ERC1271_MAGICVALUE_BS = 0x20c13b0b;
32-
bytes4 constant internal ERC1271_MAGICVALUE_B32 = 0x1626ba7e;
33-
34-
bytes4 constant internal ERC1271_SELECTOR_BS = bytes4(
35-
keccak256(bytes("isValidSignature(bytes,bytes)"))
36-
);
37-
38-
bytes4 constant internal ERC1271_SELECTOR_B32 = bytes4(
39-
keccak256(bytes("isValidSignature(bytes32,bytes)"))
40-
);
30+
bytes4 constant internal ERC1271_MAGICVALUE = 0x1626ba7e;
4131

4232
function verifySignatures(
4333
bytes32 signHash,
@@ -47,45 +37,19 @@ library SignatureUtil
4737
internal
4838
view
4939
returns (bool)
50-
{
51-
return verifySignatures(abi.encodePacked(signHash), signers, signatures);
52-
}
53-
54-
function verifySignatures(
55-
bytes memory data,
56-
address[] memory signers,
57-
bytes[] memory signatures
58-
)
59-
internal
60-
view
61-
returns (bool)
6240
{
6341
require(signers.length == signatures.length, "BAD_SIGNATURE_DATA");
6442
address lastSigner;
6543
for (uint i = 0; i < signers.length; i++) {
6644
require(signers[i] > lastSigner, "INVALID_SIGNERS_ORDER");
6745
lastSigner = signers[i];
68-
if (!verifySignature(data, signers[i], signatures[i])) {
46+
if (!verifySignature(signHash, signers[i], signatures[i])) {
6947
return false;
7048
}
7149
}
7250
return true;
7351
}
7452

75-
function verifySignature(
76-
bytes memory data,
77-
address signer,
78-
bytes memory signature
79-
)
80-
internal
81-
view
82-
returns (bool)
83-
{
84-
return signer.isContract() ?
85-
verifyERC1271Signature(data, signer, signature) :
86-
verifyEOASignature(data, signer, signature);
87-
}
88-
8953
function verifySignature(
9054
bytes32 signHash,
9155
address signer,
@@ -95,7 +59,13 @@ library SignatureUtil
9559
view
9660
returns (bool)
9761
{
98-
return verifySignature(abi.encodePacked(signHash), signer, signature);
62+
if (signer == address(0)) {
63+
return false;
64+
}
65+
66+
return signer.isContract()?
67+
verifyERC1271Signature(signHash, signer, signature):
68+
verifyEOASignature(signHash, signer, signature);
9969
}
10070

10171
function recoverECDSASigner(
@@ -132,28 +102,14 @@ library SignatureUtil
132102
}
133103
}
134104

135-
function recoverECDSASigner(
136-
bytes memory data,
137-
bytes memory signature
138-
)
139-
internal
140-
pure
141-
returns (address addr1, address addr2)
142-
{
143-
if (data.length == 32) {
144-
addr1 = recoverECDSASigner(data.toBytes32(0), signature);
145-
}
146-
addr2 = recoverECDSASigner(keccak256(data), signature);
147-
}
148-
149105
function verifyEOASignature(
150-
bytes memory data,
106+
bytes32 signHash,
151107
address signer,
152108
bytes memory signature
153109
)
154110
private
155111
pure
156-
returns (bool)
112+
returns (bool success)
157113
{
158114
if (signer == address(0)) {
159115
return false;
@@ -162,67 +118,32 @@ library SignatureUtil
162118
uint signatureTypeOffset = signature.length.sub(1);
163119
SignatureType signatureType = SignatureType(signature.toUint8(signatureTypeOffset));
164120

165-
bytes memory stripped = signature.slice(0, signatureTypeOffset);
121+
// Strip off the last byte of the signature by updating the length
122+
assembly {
123+
mstore(signature, signatureTypeOffset)
124+
}
166125

167126
if (signatureType == SignatureType.EIP_712) {
168-
(address addr1, address addr2) = recoverECDSASigner(data, stripped);
169-
return addr1 == signer || addr2 == signer;
127+
success = (signer == recoverECDSASigner(signHash, signature));
170128
} else if (signatureType == SignatureType.ETH_SIGN) {
171-
if (data.length == 32) {
172-
bytes32 hash = keccak256(
173-
abi.encodePacked("\x19Ethereum Signed Message:\n32", data.toBytes32(0))
174-
);
175-
if (recoverECDSASigner(hash, stripped) == signer) {
176-
return true;
177-
}
178-
}
179129
bytes32 hash = keccak256(
180-
abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(data))
130+
abi.encodePacked("\x19Ethereum Signed Message:\n32", signHash)
181131
);
182-
return recoverECDSASigner(hash, stripped) == signer;
132+
success = (signer == recoverECDSASigner(hash, signature));
183133
} else {
184-
return false;
134+
success = false;
185135
}
186-
}
187136

188-
function verifyERC1271Signature(
189-
bytes memory data,
190-
address signer,
191-
bytes memory signature
192-
)
193-
private
194-
view
195-
returns (bool)
196-
{
197-
return data.length == 32 &&
198-
verifyERC1271WithBytes32(data.toBytes32(0), signer, signature) ||
199-
verifyERC1271WithBytes(data, signer, signature);
200-
}
137+
// Restore the signature length
138+
assembly {
139+
mstore(signature, add(signatureTypeOffset, 1))
140+
}
201141

202-
function verifyERC1271WithBytes(
203-
bytes memory data,
204-
address signer,
205-
bytes memory signature
206-
)
207-
private
208-
view
209-
returns (bool)
210-
{
211-
bytes memory callData = abi.encodeWithSelector(
212-
ERC1271_SELECTOR_BS,
213-
data,
214-
signature
215-
);
216-
(bool success, bytes memory result) = signer.staticcall(callData);
217-
return (
218-
success &&
219-
result.length == 32 &&
220-
result.toBytes4(0) == ERC1271_MAGICVALUE_BS
221-
);
142+
return success;
222143
}
223144

224-
function verifyERC1271WithBytes32(
225-
bytes32 hash,
145+
function verifyERC1271Signature(
146+
bytes32 signHash,
226147
address signer,
227148
bytes memory signature
228149
)
@@ -231,15 +152,15 @@ library SignatureUtil
231152
returns (bool)
232153
{
233154
bytes memory callData = abi.encodeWithSelector(
234-
ERC1271_SELECTOR_B32,
235-
hash,
155+
ERC1271.isValidSignature.selector,
156+
signHash,
236157
signature
237158
);
238159
(bool success, bytes memory result) = signer.staticcall(callData);
239160
return (
240161
success &&
241162
result.length == 32 &&
242-
result.toBytes4(0) == ERC1271_MAGICVALUE_B32
163+
result.toBytes4(0) == ERC1271_MAGICVALUE
243164
);
244165
}
245166
}

packages/hebao_v1/contracts/modules/OfficialGuardian.sol

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,21 @@ import "../thirdparty/BytesUtil.sol";
1212
/// @author Freeman Zhong - <[email protected]>
1313
contract OfficialGuardian is OwnerManagable, ERC1271
1414
{
15-
using SignatureUtil for bytes;
15+
using SignatureUtil for bytes32;
1616
mapping (address => bool) public whitelist;
1717

1818
function isValidSignature(
19-
bytes32 _hash,
19+
bytes32 _signHash,
2020
bytes memory _signature
2121
)
2222
public
2323
view
2424
override
2525
returns (bytes4)
2626
{
27-
(address addr1, address addr2) = abi.encodePacked(_hash).recoverECDSASigner(_signature);
28-
return isManager(addr1) || isManager(addr2) ? ERC1271_MAGICVALUE_B32 : bytes4(0);
29-
}
30-
31-
function isValidSignature(
32-
bytes memory _data,
33-
bytes memory _signature
34-
)
35-
public
36-
view
37-
override
38-
returns (bytes4)
39-
{
40-
(address addr1, address addr2) = _data.recoverECDSASigner(_signature);
41-
return isManager(addr1) || isManager(addr2) ? ERC1271_MAGICVALUE_BS : bytes4(0);
27+
return isManager(_signHash.recoverECDSASigner(_signature))?
28+
ERC1271_MAGICVALUE:
29+
bytes4(0);
4230
}
4331

4432
function addWhitelist(address target, bool toAdd)

packages/hebao_v1/contracts/modules/core/ERC1271Module.sol

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ abstract contract ERC1271Module is ERC1271, BaseModule
2626
pure
2727
returns (bytes4[] memory methods)
2828
{
29-
methods = new bytes4[](2);
30-
methods[0] = ERC1271_SELECTOR_BS;
31-
methods[1] = ERC1271_SELECTOR_B32;
29+
methods = new bytes4[](1);
30+
methods[0] = ERC1271.isValidSignature.selector;
3231
}
3332

3433
// Will use msg.sender to detect the wallet, so this function should be called through
@@ -39,38 +38,24 @@ abstract contract ERC1271Module is ERC1271, BaseModule
3938
// The verificaiton of Wallet1's signature will succeed if the final EOA's signature is
4039
// valid.
4140
function isValidSignature(
42-
bytes memory _data,
41+
bytes32 _signHash,
4342
bytes memory _signature
4443
)
4544
public
4645
view
4746
override
48-
returns (bytes4)
47+
returns (bytes4 magicValue)
4948
{
5049
address wallet = msg.sender;
5150
(uint _lock,) = controller().securityStore().getLock(wallet);
5251
if (_lock > block.timestamp) { // wallet locked
5352
return 0;
5453
}
5554

56-
if (_data.verifySignature(Wallet(wallet).owner(), _signature)) {
57-
return ERC1271_MAGICVALUE_BS;
55+
if (_signHash.verifySignature(Wallet(wallet).owner(), _signature)) {
56+
return ERC1271_MAGICVALUE;
5857
} else {
5958
return 0;
6059
}
6160
}
62-
63-
function isValidSignature(
64-
bytes32 _hash,
65-
bytes memory _signature)
66-
public
67-
view
68-
override
69-
returns (bytes4 magicValue)
70-
{
71-
magicValue = isValidSignature(abi.encodePacked(_hash), _signature);
72-
if (magicValue == ERC1271_MAGICVALUE_BS) {
73-
magicValue = ERC1271_MAGICVALUE_B32;
74-
}
75-
}
7661
}

0 commit comments

Comments
 (0)