Skip to content

Commit af284de

Browse files
committed
test: fix ecdsa tests with ethers v6
1 parent 16aefc0 commit af284de

File tree

12 files changed

+117
-123
lines changed

12 files changed

+117
-123
lines changed

packages/integration-tests/scripts/bridgeETH.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
getBlock,
1313
FUEL_CALL_TX_PARAMS,
1414
} from '@fuel-bridge/test-utils';
15-
import { parseEther } from 'ethers/lib/utils';
15+
import { parseEther } from 'ethers';
1616
import {
1717
Address,
1818
BN,

packages/integration-tests/tests/transfer_eth.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from '@fuel-bridge/test-utils';
1313
import chai from 'chai';
1414
import type { BigNumber, Signer } from 'ethers';
15-
import { parseEther } from 'ethers/lib/utils';
15+
import { parseEther } from 'ethers';
1616
import { Address, BN, BaseAssetId, padFirst12BytesOfEvmAddress } from 'fuels';
1717
import type {
1818
AbstractAddress,
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { BytesLike } from 'ethers';
2-
import { utils } from 'ethers';
2+
import { sha256 } from 'ethers';
33

44
// The primary hash function for Fuel.
55
export default function hash(data: BytesLike): string {
6-
return utils.sha256(data);
6+
return sha256(data);
77
}

packages/solidity-contracts/protocol/utils.ts

+19-46
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,33 @@
11
// Helper functions for testing
22
import type { BigNumberish, BytesLike } from 'ethers';
3-
import { BigNumber as BN, BigNumber, ethers } from 'ethers';
3+
import {
4+
Wallet,
5+
toUtf8Bytes,
6+
keccak256,
7+
randomBytes,
8+
toBeHex,
9+
hexlify,
10+
solidityPacked,
11+
} from 'ethers';
412

513
import type BlockHeader from './blockHeader';
614
import { ZERO, EMPTY } from './constants';
7-
import hash from './cryptography';
815

9-
export const DEPOSIT_TO_CONTRACT_FLAG = ethers.utils
10-
.keccak256(ethers.utils.toUtf8Bytes('DEPOSIT_TO_CONTRACT'))
11-
.substring(0, 4);
16+
export const DEPOSIT_TO_CONTRACT_FLAG = keccak256(
17+
toUtf8Bytes('DEPOSIT_TO_CONTRACT')
18+
).substring(0, 4);
1219

1320
export function randomAddress(): string {
14-
return hash(
15-
BN.from(Math.floor(Math.random() * 1_000_000)).toHexString()
16-
).slice(0, 42);
21+
return Wallet.createRandom().address;
1722
}
1823

1924
export function randomBytes32(): string {
20-
return hash(BN.from(Math.floor(Math.random() * 1_000_000)).toHexString());
21-
}
22-
23-
export function randomInt(max: number): number {
24-
return Math.floor(Math.random() * max);
25-
}
26-
27-
export function randomBytes(length: number): string {
28-
return hash(
29-
BN.from(Math.floor(Math.random() * 1_000_000)).toHexString()
30-
).slice(0, length * 2 + 2);
31-
}
32-
33-
export function uintToBytes32(i: number): string {
34-
const value = BN.from(i).toHexString();
35-
let trimmedValue = value.slice(2);
36-
trimmedValue = '0'.repeat(64 - trimmedValue.length).concat(trimmedValue);
37-
return '0x'.concat(trimmedValue);
38-
}
39-
40-
export function padUint(value: BN): string {
41-
// uint256 is encoded as 32 bytes, so pad that string.
42-
let trimmedValue = value.toHexString().slice(2);
43-
trimmedValue = '0'.repeat(64 - trimmedValue.length).concat(trimmedValue);
44-
return '0x'.concat(trimmedValue);
45-
}
46-
47-
export function padBytes(value: string): string {
48-
let trimmedValue = value.slice(2);
49-
trimmedValue = '0'.repeat(64 - trimmedValue.length).concat(trimmedValue);
50-
return '0x'.concat(trimmedValue);
25+
return hexlify(randomBytes(32));
5126
}
5227

5328
export function tai64Time(millis: number): string {
54-
const zeroPointOffset = '4611686018427387914';
55-
return BN.from(Math.floor(millis / 1000))
56-
.add(zeroPointOffset)
57-
.toHexString();
29+
const zeroPointOffset = BigInt('4611686018427387914');
30+
return toBeHex(BigInt(Math.floor(millis / 1000)) + zeroPointOffset);
5831
}
5932

6033
// Computes data for message
@@ -75,10 +48,10 @@ export function computeMessageData(
7548
'bytes32',
7649
'uint256',
7750
];
78-
const values: (string | number | BN | BytesLike | BigNumberish)[] = [
51+
const values: (string | number | bigint | BytesLike | BigNumberish)[] = [
7952
fuelContractId,
8053
tokenAddress,
81-
BigNumber.from(tokenId),
54+
BigInt(tokenId),
8255
from,
8356
to,
8457
amount,
@@ -94,7 +67,7 @@ export function computeMessageData(
9467
}
9568
}
9669

97-
return ethers.utils.solidityPack(typings, values);
70+
return solidityPacked(typings, values);
9871
}
9972

10073
// Create a simple block
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,12 @@
1-
import type { Signature } from 'ethers';
2-
import type { SigningKey } from 'ethers/lib/utils';
3-
import { ethers } from 'hardhat';
1+
import type { SigningKey } from 'ethers';
2+
import { toBeArray } from 'ethers';
43

54
// Sign a messag with a signer, returning the signature object (v, r, s components)
6-
export async function componentSign(
7-
signer: SigningKey,
8-
message: string
9-
): Promise<Signature> {
10-
const flatSig = await signer.signDigest(ethers.utils.arrayify(message));
11-
const sig = ethers.utils.splitSignature(flatSig);
12-
return sig;
5+
export function componentSign(signer: SigningKey, message: string) {
6+
return signer.sign(toBeArray(message));
137
}
148

159
// Sign a message with as signer, returning a 64-byte compact ECDSA signature
16-
export async function compactSign(
17-
signer: SigningKey,
18-
message: string
19-
): Promise<string> {
20-
const sig = await componentSign(signer, message);
21-
22-
const compactSig = sig.r.concat(sig._vs.slice(2));
23-
return compactSig;
10+
export function compactSign(signer: SigningKey, message: string) {
11+
return componentSign(signer, message).compactSerialized;
2412
}

packages/solidity-contracts/scripts/grantComitterRole.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { StaticJsonRpcProvider } from '@ethersproject/providers';
22
import { ethers } from 'ethers';
3-
import { isAddress } from 'ethers/lib/utils';
3+
import { isAddress } from 'ethers';
44

55
import { FuelChainState__factory } from '../typechain';
66

packages/solidity-contracts/test/ecdsa.ts

+20-26
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,38 @@
11
import chai from 'chai';
2-
import type { Contract } from 'ethers';
3-
import { BigNumber as BN } from 'ethers';
4-
import { SigningKey } from 'ethers/lib/utils';
2+
import { SigningKey, randomBytes, hexlify, ZeroHash, toBeHex } from 'ethers';
53
import { ethers } from 'hardhat';
64

75
import { componentSign } from '../protocol/validators';
6+
import type { MockCryptography } from '../typechain';
87

98
const { expect } = chai;
109

11-
const SECP256K1N = BN.from(
10+
const SECP256K1N = BigInt(
1211
'0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
1312
);
1413

1514
describe('ECDSA', async () => {
16-
let mockCrypto: Contract;
15+
let mockCrypto: MockCryptography;
1716
let signer: SigningKey;
1817
before(async () => {
19-
const mockCryptoFactory = await ethers.getContractFactory(
20-
'MockCryptography'
21-
);
22-
mockCrypto = await mockCryptoFactory.deploy();
23-
await mockCrypto.deployed();
18+
mockCrypto = await ethers.deployContract('MockCryptography');
2419

2520
signer = new SigningKey(
2621
'0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d'
2722
);
2823
});
2924

3025
it('rejects component signatures with high s-value', async () => {
31-
const msg = ethers.utils.hexlify(ethers.utils.randomBytes(32));
26+
const msg = hexlify(randomBytes(32));
3227
const sig = await componentSign(signer, msg);
33-
const vOrig = BN.from(sig.v).sub(27); // take v as 0 or 1
28+
const vOrig = BigInt(sig.v) - 27n; // take v as 0 or 1
3429

3530
// flip v and ensure it is 27 or 28
36-
const vFlipped = vOrig.xor(1).add(27);
31+
const vFlipped = (vOrig ^ 1n) + 27n;
3732
// flip s to secp256k1n - original s. This defines a unique
3833
// signature over the same data, which we want to reject.
39-
const sFlipped = SECP256K1N.sub(sig.s);
40-
const badSig = { v: vFlipped, r: sig.r, s: sFlipped };
34+
const sFlipped = SECP256K1N - BigInt(sig.s);
35+
const badSig = { v: vFlipped, r: sig.r, s: toBeHex(sFlipped) };
4136

4237
await expect(
4338
mockCrypto.addressFromSignatureComponents(
@@ -50,10 +45,10 @@ describe('ECDSA', async () => {
5045
});
5146

5247
it('rejects component signatures from the zero address', async () => {
53-
const msg = ethers.utils.hexlify(ethers.utils.randomBytes(32));
54-
const sig = await componentSign(signer, msg);
48+
const msg = hexlify(randomBytes(32));
49+
const sig = componentSign(signer, msg);
5550
// an r value < 1 makes the signature invalid. ecrecover will return 0x0
56-
const badSig = { v: sig.v, r: ethers.constants.HashZero, s: sig.s };
51+
const badSig = { v: sig.v, r: ZeroHash, s: sig.s };
5752

5853
await expect(
5954
mockCrypto.addressFromSignatureComponents(
@@ -66,27 +61,26 @@ describe('ECDSA', async () => {
6661
});
6762

6863
it('rejects invalid compact signatures', async () => {
69-
const msg = ethers.utils.hexlify(ethers.utils.randomBytes(32));
70-
const sig = await componentSign(signer, msg);
64+
const msg = hexlify(randomBytes(32));
65+
const sig = componentSign(signer, msg);
7166

7267
// an r value < 1 makes the signature invalid. ecrecover will return 0x0
73-
const badRValue = ethers.constants.HashZero;
68+
const badRValue = ZeroHash;
7469

75-
const badSigCompact = badRValue.concat(sig._vs.slice(2));
70+
const badSigCompact = badRValue.concat(sig.yParityAndS.slice(2));
7671
await expect(
7772
mockCrypto.addressFromSignature(badSigCompact, msg)
7873
).to.be.revertedWith('signature-invalid');
74+
// // signature too short
7975

80-
// signature too short
81-
82-
const shortSig = sig.r.concat(sig._vs.slice(4));
76+
const shortSig = sig.r.concat(sig.yParityAndS.slice(4));
8377
await expect(
8478
mockCrypto.addressFromSignature(shortSig, msg)
8579
).to.be.revertedWith('signature-invalid-length');
8680

8781
// signature too long
8882

89-
const longSig = sig.r.concat(sig._vs.slice(2)).concat('aa');
83+
const longSig = sig.r.concat(sig.yParityAndS.slice(2)).concat('aa');
9084
await expect(
9185
mockCrypto.addressFromSignature(longSig, msg)
9286
).to.be.revertedWith('signature-invalid-length');

packages/solidity-contracts/test/messagesOutgoingV2.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
33
import chai from 'chai';
44
import type { BigNumber } from 'ethers';
55
import { BigNumber as BN, constants } from 'ethers';
6-
import { parseEther } from 'ethers/lib/utils';
6+
import { parseEther } from 'ethers';
77
import { deployments, ethers, upgrades } from 'hardhat';
88

99
import { randomBytes, randomBytes32 } from '../protocol/utils';

packages/solidity-contracts/test/utils/encodeErc20DepositMessage.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { BigNumberish, BytesLike } from 'ethers';
2-
import { BigNumber, utils } from 'ethers';
2+
import { zeroPadValue as hexZeroPadLeft, toBeHex } from 'ethers';
33

44
import { computeMessageData } from '../../protocol/utils';
5-
const { hexZeroPad } = utils;
65

76
/**
87
* @description Encodes an erc20 deposit message the same way the FuelERC20Gateway contract does
@@ -17,9 +16,9 @@ export function encodeErc20DepositMessage(
1716
) {
1817
return computeMessageData(
1918
fuelContractId,
20-
hexZeroPad(typeof token === 'string' ? token : token.address, 32),
21-
hexZeroPad(BigNumber.from(0).toHexString(), 32),
22-
hexZeroPad(typeof sender === 'string' ? sender : sender.address, 32),
19+
hexZeroPadLeft(typeof token === 'string' ? token : token.address, 32),
20+
hexZeroPadLeft(toBeHex(BigInt(0)), 32),
21+
hexZeroPadLeft(typeof sender === 'string' ? sender : sender.address, 32),
2322
to,
2423
amount,
2524
data

packages/test-utils/src/utils/fuels/getTokenId.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { concat, sha256 } from 'ethers/lib/utils';
1+
import { concat, sha256 } from 'ethers';
22
import type { Contract } from 'fuels';
33
import { ZeroBytes32 } from 'fuels';
44

packages/test-utils/src/utils/logs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Token } from '@fuel-bridge/solidity-contracts/typechain';
22
import type { Signer } from 'ethers';
3-
import { formatEther } from 'ethers/lib/utils';
3+
import { formatEther } from 'ethers';
44
import type { WalletUnlocked } from 'fuels';
55

66
import {

0 commit comments

Comments
 (0)