Skip to content

Commit 482efe5

Browse files
committed
test: update tests to use eip712
1 parent 397f612 commit 482efe5

19 files changed

+229
-189
lines changed

src/legacy/LiquidityBridgeContract.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2;
44

55
import "../interfaces/IBridge.sol";
66
import "./Quotes.sol";
7-
import "../libraries/SignatureValidator.sol";
7+
import "./SignatureValidator.sol";
88
import "@rsksmart/btc-transaction-solidity-helper/contracts/BtcUtils.sol";
99
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
1010
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";

src/legacy/LiquidityBridgeContractV2.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2;
44

55
import "../interfaces/IBridge.sol";
66
import "./QuotesV2.sol";
7-
import "../libraries/SignatureValidator.sol";
7+
import "./SignatureValidator.sol";
88
import "@rsksmart/btc-transaction-solidity-helper/contracts/BtcUtils.sol";
99
import "@rsksmart/btc-transaction-solidity-helper/contracts/OpCodes.sol";
1010
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

src/legacy/SignatureValidator.sol

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.25;
3+
4+
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
5+
6+
library SignatureValidator {
7+
8+
using ECDSA for bytes32;
9+
10+
error IncorrectSignature(address expectedAddress, bytes32 usedHash, bytes signature);
11+
error ZeroAddress();
12+
/**
13+
@dev Verfies signature against address
14+
@param addr The signing address
15+
@param quoteHash The hash of the signed data
16+
@param signature The signature containing v, r and s
17+
@return True if the signature is valid, false otherwise.
18+
*/
19+
function verify(address addr, bytes32 quoteHash, bytes memory signature) public pure returns (bool) {
20+
21+
if (addr == address(0)) {
22+
revert ZeroAddress();
23+
}
24+
25+
if (signature.length != 65) {
26+
revert IncorrectSignature(addr, quoteHash, signature);
27+
}
28+
29+
30+
bytes32 r;
31+
bytes32 s;
32+
uint8 v;
33+
34+
assembly {
35+
r := mload(add(signature, 0x20))
36+
s := mload(add(signature, 0x40))
37+
v := byte(0, mload(add(signature, 0x60)))
38+
}
39+
// TODO use EIP712 compatible format instead
40+
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
41+
bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, quoteHash));
42+
return prefixedHash.recover(v, r, s) == addr;
43+
}
44+
}

src/libraries/Quotes.sol

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,16 @@ library Quotes {
5151
/// @dev Due to the number of fields present in the struct, we'll just use the hash of the quote and the
5252
/// address of the liquidity provider offering it to calculate the EIP712 hash. In this way we avoid issues
5353
/// with stack depth limits and future modifications to the type hash based on changes in the struct.
54-
/// @dev keccak256("PegInQuote(address liquidityProvider, bytes32 quoteHash)")
55-
bytes32 public constant PEG_IN_QUOTE_TYPE_HASH = 0x04b6a5fb6a85d659a648dd600fb93f123bec1a7d0ae71b7c33b1d850b3a6da05;
54+
/// @dev keccak256("PegInQuote(address liquidityProvider,bytes32 quoteHash)")
55+
bytes32 public constant PEG_IN_QUOTE_TYPE_HASH = 0x82b0b35cb5a2b2130657be6794570d328b06b7687bdff463bce4a0cc24a880a2;
5656

5757
/// @notice The type hash of the PegOutQuote struct for EIP712
5858
/// @dev Due to the number of fields present in the struct, we'll just use the hash of the quote and the
5959
/// address of the liquidity provider offering it to calculate the EIP712 hash. In this way we avoid issues
6060
/// with stack depth limits and future modifications to the type hash based on changes in the struct.
61-
/// @dev keccak256("PegOutQuote(address liquidityProvider, bytes32 quoteHash)")
62-
// TODO validar en jira
61+
/// @dev keccak256("PegOutQuote(address liquidityProvider,bytes32 quoteHash)")
6362
bytes32 public constant PEG_OUT_QUOTE_TYPE_HASH =
64-
0x91061380a398473c20ee77839e0df2d1d1cf5dcc79ae90e660f8c6973d17765f;
63+
0x940deda477f28e6fd80f8307aea1edb500dbd4ee20815878162fec9001fab898;
6564

6665
error AmountTooLow(uint256 value, uint256 target);
6766

src/libraries/SignatureValidator.sol

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ library SignatureValidator {
1212
/**
1313
@dev Verfies signature against address
1414
@param addr The signing address
15-
@param eip712Hash The EIP712 hash of the signed data, this contract expects
16-
it to be already prefixed with the EIP712 domain separator
15+
@param messageHash The hash of the signed message, the SignatureValidator won't perform any
16+
modification on the message. If this is used for EIP712, this contract expects it to be the
17+
final hash (domain hash + hashStruct)
1718
@param signature The signature containing v, r and s
1819
@return True if the signature is valid, false otherwise.
1920
*/
20-
function verify(address addr, bytes32 eip712Hash, bytes memory signature) public pure returns (bool) {
21+
function verify(address addr, bytes32 messageHash, bytes memory signature) public pure returns (bool) {
2122

2223
if (addr == address(0)) {
2324
revert ZeroAddress();
2425
}
2526

2627
if (signature.length != 65) {
27-
revert IncorrectSignature(addr, eip712Hash, signature);
28+
revert IncorrectSignature(addr, messageHash, signature);
2829
}
29-
return eip712Hash.recover(signature) == addr;
30+
return messageHash.recover(signature) == addr;
3031
}
3132
}

test/fuzz/libraries/SignatureValidator.fuzz.t.sol

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ contract SignatureValidatorFuzzTest is Test {
3333
);
3434
bytes memory signature = abi.encodePacked(r, s, v);
3535

36-
bool result = signatureValidator.verify(signer, messageHash, signature);
36+
bool result = signatureValidator.verify(
37+
signer,
38+
ethSignedMessageHash,
39+
signature
40+
);
3741
assertTrue(result, "Valid signature should verify");
3842
}
3943

@@ -284,10 +288,18 @@ contract SignatureValidatorFuzzTest is Test {
284288

285289
// Signature 1 should verify for addr1, not addr2
286290
assertTrue(
287-
signatureValidator.verify(addr1, messageHash, signature)
291+
signatureValidator.verify(
292+
addr1,
293+
ethSignedMessageHash,
294+
signature
295+
)
288296
);
289297
assertFalse(
290-
signatureValidator.verify(addr2, messageHash, signature)
298+
signatureValidator.verify(
299+
addr2,
300+
ethSignedMessageHash,
301+
signature
302+
)
291303
);
292304
}
293305

@@ -301,10 +313,18 @@ contract SignatureValidatorFuzzTest is Test {
301313

302314
// Signature 2 should verify for addr2, not addr1
303315
assertTrue(
304-
signatureValidator.verify(addr2, messageHash, signature)
316+
signatureValidator.verify(
317+
addr2,
318+
ethSignedMessageHash,
319+
signature
320+
)
305321
);
306322
assertFalse(
307-
signatureValidator.verify(addr1, messageHash, signature)
323+
signatureValidator.verify(
324+
addr1,
325+
ethSignedMessageHash,
326+
signature
327+
)
308328
);
309329
}
310330
}

test/fuzz/pegin/PegInFuzzTestBase.sol

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,37 @@ abstract contract PegInFuzzTestBase is PegInTestBase {
136136

137137
// ============ Signature Helpers ============
138138

139-
/// @notice Signs a quote hash with the appropriate LP private key
139+
/// @notice Signs a quote with the appropriate LP private key
140140
/// @param signer The signer address (must be one of the registered LPs)
141-
/// @param quoteHash The hash of the quote to sign
141+
/// @param quote The quote to sign
142142
/// @return signature The EIP-191 signature
143143
function signFuzzQuote(
144144
address signer,
145-
bytes32 quoteHash
145+
Quotes.PegInQuote memory quote
146+
) internal view returns (bytes memory) {
147+
uint256 privateKey;
148+
if (signer == fullLp) {
149+
privateKey = fullLpKey;
150+
} else if (signer == pegInLp) {
151+
privateKey = pegInLpKey;
152+
} else if (signer == pegOutLp) {
153+
privateKey = pegOutLpKey;
154+
} else {
155+
revert("Unknown signer");
156+
}
157+
158+
bytes32 eip712Hash = pegInContract.hashPegInQuoteEIP712(quote);
159+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, eip712Hash);
160+
return abi.encodePacked(r, s, v);
161+
}
162+
163+
/// @notice Signs a message hash with the appropriate LP private key
164+
/// @param signer The signer address (must be one of the registered LPs)
165+
/// @param messageHash The message hash to sign
166+
/// @return signature The signature of the message hash
167+
function signMessageHash(
168+
address signer,
169+
bytes32 messageHash
146170
) internal view returns (bytes memory) {
147171
uint256 privateKey;
148172
if (signer == fullLp) {
@@ -155,13 +179,7 @@ abstract contract PegInFuzzTestBase is PegInTestBase {
155179
revert("Unknown signer");
156180
}
157181

158-
bytes32 ethSignedMessageHash = keccak256(
159-
abi.encodePacked("\x19Ethereum Signed Message:\n32", quoteHash)
160-
);
161-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
162-
privateKey,
163-
ethSignedMessageHash
164-
);
182+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, messageHash);
165183
return abi.encodePacked(r, s, v);
166184
}
167185

test/fuzz/pegin/PegInRegisterTiming.fuzz.t.sol

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
3939
fuzzUser,
4040
fullLp
4141
);
42-
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
42+
bytes32 eip712Hash = pegInContract.hashPegInQuoteEIP712(quote);
4343

4444
// First do callForUser to set state to CALL_DONE
4545
vm.prank(fullLp);
4646
pegInContract.callForUser{value: callValue}(quote);
4747

4848
// Sign a different hash (wrong signature)
49-
vm.assume(randomHash != quoteHash);
50-
bytes memory wrongSignature = signFuzzQuote(pegInLp, randomHash);
49+
vm.assume(randomHash != eip712Hash);
50+
bytes memory wrongSignature = signMessageHash(pegInLp, randomHash);
5151

5252
vm.expectRevert(
5353
abi.encodeWithSelector(
5454
SignatureValidator.IncorrectSignature.selector,
5555
fullLp,
56-
quoteHash,
56+
eip712Hash,
5757
wrongSignature
5858
)
5959
);
@@ -78,20 +78,20 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
7878
fuzzUser,
7979
fullLp
8080
);
81-
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
81+
bytes32 eip712Hash = pegInContract.hashPegInQuoteEIP712(quote);
8282

8383
// First do callForUser
8484
vm.prank(fullLp);
8585
pegInContract.callForUser{value: callValue}(quote);
8686

8787
// Sign with wrong LP (pegInLp instead of fullLp)
88-
bytes memory wrongSignature = signFuzzQuote(pegInLp, quoteHash);
88+
bytes memory wrongSignature = signFuzzQuote(pegInLp, quote);
8989

9090
vm.expectRevert(
9191
abi.encodeWithSelector(
9292
SignatureValidator.IncorrectSignature.selector,
9393
fullLp,
94-
quoteHash,
94+
eip712Hash,
9595
wrongSignature
9696
)
9797
);
@@ -120,8 +120,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
120120
fuzzUser,
121121
fullLp
122122
);
123-
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
124-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
123+
bytes memory signature = signFuzzQuote(fullLp, quote);
125124

126125
// First do callForUser
127126
vm.prank(fullLp);
@@ -158,7 +157,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
158157
fullLp
159158
);
160159
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
161-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
160+
bytes memory signature = signFuzzQuote(fullLp, quote);
162161

163162
uint256 peginAmount = getTotalQuoteValue(quote);
164163

@@ -222,8 +221,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
222221
fuzzUser,
223222
fullLp
224223
);
225-
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
226-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
224+
bytes memory signature = signFuzzQuote(fullLp, quote);
227225

228226
// Setup bridge to return confirmations error
229227
int256 BRIDGE_UNPROCESSABLE_ERROR = -303;
@@ -261,8 +259,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
261259
fuzzUser,
262260
fullLp
263261
);
264-
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
265-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
262+
bytes memory signature = signFuzzQuote(fullLp, quote);
266263

267264
// Setup bridge to return unexpected error
268265
bridgeMock.setPeginError(errorCode);
@@ -301,7 +298,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
301298
fullLp
302299
);
303300
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
304-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
301+
bytes memory signature = signFuzzQuote(fullLp, quote);
305302

306303
// Setup BTC block headers
307304
bytes memory firstHeader = createBtcBlockHeader(
@@ -355,7 +352,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
355352
fullLp
356353
);
357354
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
358-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
355+
bytes memory signature = signFuzzQuote(fullLp, quote);
359356

360357
// Setup BTC block headers
361358
bytes memory firstHeader = createBtcBlockHeader(
@@ -411,7 +408,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
411408
fullLp
412409
);
413410
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
414-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
411+
bytes memory signature = signFuzzQuote(fullLp, quote);
415412

416413
uint256 peginAmount = getTotalQuoteValue(quote);
417414

@@ -467,7 +464,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
467464
fullLp
468465
);
469466
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
470-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
467+
bytes memory signature = signFuzzQuote(fullLp, quote);
471468

472469
uint256 peginAmount = getTotalQuoteValue(quote);
473470

@@ -530,7 +527,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
530527
fullLp
531528
);
532529
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
533-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
530+
bytes memory signature = signFuzzQuote(fullLp, quote);
534531

535532
uint256 peginAmount = getTotalQuoteValue(quote);
536533
uint256 totalPaid = peginAmount + extraPaid;
@@ -595,7 +592,7 @@ contract PegInRegisterTimingFuzzTest is PegInFuzzTestBase {
595592
fullLp
596593
);
597594
bytes32 quoteHash = pegInContract.hashPegInQuote(quote);
598-
bytes memory signature = signFuzzQuote(fullLp, quoteHash);
595+
bytes memory signature = signFuzzQuote(fullLp, quote);
599596

600597
uint256 peginAmount = getTotalQuoteValue(quote);
601598
vm.assume(underpayment < peginAmount);

test/fuzz/pegout/BtcTransactionParsing.fuzz.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ contract BtcTransactionParsingFuzzTest is PegOutFuzzTestBase {
268268
);
269269

270270
bytes32 quoteHash = pegOutContract.hashPegOutQuote(quote);
271-
bytes memory signature = signFuzzQuote(pegOutLp, quoteHash);
271+
bytes memory signature = signFuzzQuote(pegOutLp, quote);
272272

273273
// Deposit
274274
vm.prank(fuzzUser);
@@ -314,7 +314,7 @@ contract BtcTransactionParsingFuzzTest is PegOutFuzzTestBase {
314314
);
315315

316316
bytes32 quoteHash = pegOutContract.hashPegOutQuote(quote);
317-
bytes memory signature = signFuzzQuote(pegOutLp, quoteHash);
317+
bytes memory signature = signFuzzQuote(pegOutLp, quote);
318318

319319
// Deposit
320320
vm.prank(fuzzUser);

0 commit comments

Comments
 (0)