Skip to content

Commit

Permalink
refactor: replace all bigints to use bn.js library instead (#468)
Browse files Browse the repository at this point in the history
  • Loading branch information
LuizAsFight authored Sep 6, 2022
1 parent b8cb5df commit 7ad3d79
Show file tree
Hide file tree
Showing 86 changed files with 2,446 additions and 1,893 deletions.
26 changes: 26 additions & 0 deletions .changeset/silent-beans-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
"@fuel-ts/abi-coder": patch
"@fuel-ts/address": patch
"@fuel-ts/constants": patch
"@fuel-ts/contract": patch
"@fuel-ts/example-contract": patch
"fuels": patch
"@fuel-ts/hasher": patch
"@fuel-ts/hdwallet": patch
"@fuel-ts/interfaces": patch
"@fuel-ts/math": patch
"@fuel-ts/merkle": patch
"@fuel-ts/merkle-shared": patch
"@fuel-ts/merklesum": patch
"@fuel-ts/predicate": patch
"@fuel-ts/providers": patch
"@fuel-ts/script": patch
"@fuel-ts/signer": patch
"@fuel-ts/sparsemerkle": patch
"@fuel-ts/testcases": patch
"@fuel-ts/transactions": patch
"typechain-target-fuels": patch
"@fuel-ts/wallet": patch
---

Refactor to use bn.js instead of bigint.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ console.log(new Wallet("0x0000...0000"));
## Calling Contracts

```ts
import { Wallet, Contract } from "fuels";
import { Wallet, Contract, BigNumberish, BN } from "fuels";
import abi from "./abi.json";

const wallet = new Wallet("0x..."); // private key with coins
Expand All @@ -86,7 +86,7 @@ const contract = new Contract(contractId, abi, wallet);
// All contract methods are available under functions
// with the correct types
const { transactionId, value } = await contract.functions
.foo<[string], bigint>("bar")
.foo<[BigNumberish], BN>("bar")
.call();

console.log(transactionId, value);
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ console.log(new Wallet("0x0000...0000"));
## Calling Contracts

```ts
import { Wallet, Contract } from "fuels";
import { Wallet, Contract, BigNumberish, BN } from "fuels";
import abi from "./abi.json";

const wallet = new Wallet("0x..."); // private key with coins
Expand All @@ -63,7 +63,7 @@ const contract = new Contract(contractId, abi, wallet);
// All contract methods are available under functions
// with the correct types
const { transactionId, value } = await contract.functions
.foo<[string], bigint>("bar")
.foo<[BigNumberish], BN>("bar")
.call();

console.log(transactionId, value);
Expand Down
27 changes: 15 additions & 12 deletions packages/abi-coder/src/abi-coder.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { hexlify } from '@ethersproject/bytes';
import { bn, toHex } from '@fuel-ts/math';

import AbiCoder from './abi-coder';
import type { DecodedValue } from './coders/abstract-coder';
Expand Down Expand Up @@ -55,7 +56,7 @@ describe('AbiCoder', () => {
},
];

const encoded = abiCoder.encode(types, [[1, 2, 3]]);
const encoded = abiCoder.encode(types, [[1, toHex(2), bn(3)]]);

expect(hexlify(encoded)).toBe('0x000000000000000100000000000000020000000000000003');
});
Expand Down Expand Up @@ -150,16 +151,18 @@ describe('AbiCoder', () => {
'0x0000000000000000000000000000000100000000000000010000000000000001000000000000000d00000000000000250000000000000025000000000000000d000000000000000d00000000000000250000000000000001'
);
const decoded = abiCoder.decode(types, encoded) as DecodedValue[];
expect(Array.from(decoded)).toEqual([
{
foo: [true, true],
},
true,
[
{ foo: 13n, bar: 37n },
{ bar: 13n, foo: 37n },
],
[{ foo: 13n, bar: 37n }, true],
]);
expect(JSON.stringify(Array.from(decoded))).toEqual(
JSON.stringify([
{
foo: [true, true],
},
true,
[
{ foo: bn(13), bar: bn(37) },
{ foo: bn(37), bar: bn(13) },
],
[{ foo: bn(13), bar: bn(37) }, true],
])
);
});
});
4 changes: 3 additions & 1 deletion packages/abi-coder/src/abi-coder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import OptionCoder from './coders/option';
import StringCoder from './coders/string';
import StructCoder from './coders/struct';
import TupleCoder from './coders/tuple';
import U64Coder from './coders/u64';
import {
arrayRegEx,
enumRegEx,
Expand All @@ -38,8 +39,9 @@ export default class AbiCoder {
case 'u8':
case 'u16':
case 'u32':
case 'u64':
return new NumberCoder(param.type);
case 'u64':
return new U64Coder();
case 'bool':
return new BooleanCoder();
case 'byte':
Expand Down
32 changes: 14 additions & 18 deletions packages/abi-coder/src/coders/__snapshots__/coders.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exports[`BooleanCoder as a boolean can encode false then decode false 1`] = `"0x

exports[`BooleanCoder as a boolean can encode true then decode true 1`] = `"0x0000000000000001"`;

exports[`ByteCoder as a byte can encode "0x00" then decode 0 1`] = `"0x0000000000000000"`;
exports[`ByteCoder as a byte can encode "0x0" then decode 0 1`] = `"0x0000000000000000"`;

exports[`ByteCoder as a byte can encode "0xff" then decode 255 1`] = `"0x00000000000000ff"`;

Expand All @@ -24,46 +24,42 @@ exports[`EnumCoder as a [enum TestEnum; 4] can encode [[Object], [Object], [Obje

exports[`EnumCoder as a enum TestEnum can encode {"a": true} then decode {"a": true} 1`] = `"0x00000000000000000000000000000001"`;

exports[`EnumCoder as a enum TestEnum can encode {"b": 1337} then decode {"b": 1337n} 1`] = `"0x00000000000000010000000000000539"`;
exports[`EnumCoder as a enum TestEnum can encode {"b": [BN]} then decode {"b": [BN]} 1`] = `"0x00000000000000010000000000000539"`;

exports[`NumberCoder as a u8 can encode 0 then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u8 can encode 0n then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u8 can encode 255 then decode 255 1`] = `"0x00000000000000ff"`;

exports[`NumberCoder as a u8 can encode 255n then decode 255 1`] = `"0x00000000000000ff"`;

exports[`NumberCoder as a u16 can encode 0 then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u16 can encode 0n then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u16 can encode 65535 then decode 65535 1`] = `"0x000000000000ffff"`;

exports[`NumberCoder as a u16 can encode 65535n then decode 65535 1`] = `"0x000000000000ffff"`;

exports[`NumberCoder as a u32 can encode 0 then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u32 can encode 0n then decode 0 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u32 can encode 4294967295 then decode 4294967295 1`] = `"0x00000000ffffffff"`;

exports[`NumberCoder as a u32 can encode 4294967295n then decode 4294967295 1`] = `"0x00000000ffffffff"`;
exports[`NumberCoder as a u64 can encode "0x64" then decode "0x64" 1`] = `"0x0000000000000064"`;

exports[`NumberCoder as a u64 can encode "0xff" then decode "0xff" 1`] = `"0x00000000000000ff"`;

exports[`NumberCoder as a u64 can encode 0 then decode 0n 1`] = `"0x0000000000000000"`;
exports[`NumberCoder as a u64 can encode "0xffffffffffffffff" then decode "0xffffffffffffffff" 1`] = `"0xffffffffffffffff"`;

exports[`NumberCoder as a u64 can encode 0n then decode 0n 1`] = `"0x0000000000000000"`;
exports[`NumberCoder as a u64 can encode 0 then decode "0x0" 1`] = `"0x0000000000000000"`;

exports[`NumberCoder as a u64 can encode 18446744073709551615n then decode 18446744073709551615n 1`] = `"0xffffffffffffffff"`;
exports[`NumberCoder as a u64 can encode 65535 then decode "0xffff" 1`] = `"0x000000000000ffff"`;

exports[`NumberCoder as a u64 can encode 4294967295 then decode "0xffffffff" 1`] = `"0x00000000ffffffff"`;

exports[`StringCoder as a str[0] can encode "" then decode "" 1`] = `"0x"`;

exports[`StringCoder as a str[255] can encode "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" then decode "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 1`] = `"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616100"`;

exports[`StructCoder as a struct TestStruct can encode {"a": true, "b": 1337} then decode {"a": true, "b": 1337n} 1`] = `"0x00000000000000010000000000000539"`;
exports[`StructCoder as a struct TestStruct can encode {"a": true, "b": [BN]} then decode {"a": true, "b": [BN]} 1`] = `"0x00000000000000010000000000000539"`;

exports[`StructCoder as a struct TestStruct can encode {"a": true, "b": 1337} then decode {"a": true, "b": [BN]} 1`] = `"0x00000000000000010000000000000539"`;

exports[`StructCoder as a struct TestStruct can encode {} then decode {} 1`] = `"0x"`;

exports[`TupleCoder as a () can encode [] then decode [] 1`] = `"0x"`;

exports[`TupleCoder as a (u64, u64) can encode [13, 37] then decode [13n, 37n] 1`] = `"0x000000000000000d0000000000000025"`;
exports[`TupleCoder as a (u64, u64) can encode [13, 37] then decode [[BN], [BN]] 1`] = `"0x000000000000000d0000000000000025"`;
4 changes: 3 additions & 1 deletion packages/abi-coder/src/coders/abstract-coder.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { BytesLike } from '@ethersproject/bytes';
import { Logger } from '@ethersproject/logger';
import type { BN } from '@fuel-ts/math';

const logger = new Logger(process.env.BUILD_VERSION || '~');

type Primitive = string | number | boolean | bigint;
type Primitive = string | number | boolean;

/**
* The type of value you can provide to `Coder.encode`
*/
export type InputValue =
| Primitive
| BN
| BytesLike
| InputValue[]
| { [key: string]: InputValue }
Expand Down
11 changes: 5 additions & 6 deletions packages/abi-coder/src/coders/b256.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { hexlify, arrayify } from '@ethersproject/bytes';
import { toBigInt } from '@fuel-ts/math';
import { arrayify } from '@ethersproject/bytes';
import { bn, toHex } from '@fuel-ts/math';

import Coder from './abstract-coder';

Expand All @@ -23,14 +23,13 @@ export default class B256Coder extends Coder<string, string> {

decode(data: Uint8Array, offset: number): [string, number] {
let bytes = data.slice(offset, offset + 32);

if (toBigInt(bytes) === 0n) {
const decoded = bn(bytes);
if (decoded.isZero()) {
bytes = new Uint8Array(32);
}

if (bytes.length !== 32) {
this.throwError('Invalid size for b256', bytes);
}
return [hexlify(bytes), offset + 32];
return [toHex(bytes, 32), offset + 32];
}
}
13 changes: 6 additions & 7 deletions packages/abi-coder/src/coders/boolean.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { zeroPad } from '@ethersproject/bytes';
import { toArray, toBigInt } from '@fuel-ts/math';
import { bn, toBytes } from '@fuel-ts/math';

import Coder from './abstract-coder';

Expand All @@ -12,23 +11,23 @@ export default class BooleanCoder extends Coder<boolean, boolean> {
let bytes;

try {
bytes = toArray(value ? 1 : 0);
bytes = toBytes(value ? 1 : 0);
} catch (error) {
this.throwError('Invalid bool', value);
}
if (bytes.length > 1) {
this.throwError('Invalid bool', value);
}

return zeroPad(bytes, 8);
return toBytes(bytes, 8);
}

decode(data: Uint8Array, offset: number): [boolean, number] {
const bytes = toBigInt(data.slice(offset, offset + 8));
if (bytes === 0n) {
const bytes = bn(data.slice(offset, offset + 8));
if (bytes.isZero()) {
return [false, offset + 8];
}
if (bytes !== 1n) {
if (!bytes.eq(bn(1))) {
this.throwError('Invalid boolean value', bytes);
}
return [true, offset + 8];
Expand Down
14 changes: 5 additions & 9 deletions packages/abi-coder/src/coders/byte.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { zeroPad } from '@ethersproject/bytes';
import { toArray, toBigInt } from '@fuel-ts/math';
import { bn, toBytes } from '@fuel-ts/math';

import Coder from './abstract-coder';

Expand All @@ -12,21 +11,18 @@ export default class ByteCoder extends Coder<number, number> {
let bytes;

try {
bytes = toArray(value);
bytes = toBytes(value, 1);
} catch (error) {
this.throwError('Invalid Byte', value);
}
if (bytes.length > 1) {
this.throwError('Invalid Byte', value);
}

return zeroPad(bytes, 8);
return toBytes(bytes, 8);
}

decode(data: Uint8Array, offset: number): [number, number] {
const bytes = data.slice(offset, offset + 8);
const value = toBigInt(bytes);
if (value > 255n) {
const value = bn(bytes);
if (value.gt(bn(255))) {
this.throwError('Invalid Byte', value);
}
const byte = Number(value);
Expand Down
Loading

1 comment on commit 7ad3d79

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 89.95% 3214/3573
🟡 Branches 70.3% 594/845
🟢 Functions 87.5% 644/736
🟢 Lines 89.81% 3084/3434

Test suite run success

486 tests passing in 44 suites.

Report generated by 🧪jest coverage report action from 7ad3d79

Please sign in to comment.