Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: support v1 encoding in program types #1832

Merged
merged 95 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
c68b6d6
chore: use temp sway and forc branch
danielbate Mar 5, 2024
365bfd1
lint: forc
danielbate Mar 5, 2024
68e91c5
chore: temp disable forc format
danielbate Mar 5, 2024
d6520c7
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 5, 2024
25aed94
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 6, 2024
0a101f7
feat: validate u8 decode in script
danielbate Mar 8, 2024
1c5c268
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 8, 2024
f3fc8fe
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 10, 2024
0cfb8db
test: u8 u16 tuple
danielbate Mar 10, 2024
3289207
test: u8 u16 u32 tuple
danielbate Mar 10, 2024
9fe2cfc
test: u8 u16 u32 u64 tuple
danielbate Mar 10, 2024
f13094b
test: u8 u16 u32 u64 bool tuple
danielbate Mar 10, 2024
a7e0a3b
test: b256 script decode
danielbate Mar 10, 2024
89f63cc
test: b512 scrip
danielbate Mar 10, 2024
afdf766
chore: reanme script functions
danielbate Mar 11, 2024
5322609
feat: b256 script decode
danielbate Mar 11, 2024
e19268e
feat: str script decode
danielbate Mar 11, 2024
81223de
feat: std str script decode
danielbate Mar 11, 2024
647449e
feat: str slice script decode
danielbate Mar 11, 2024
42b0b54
feat: struct enum vec script decode
danielbate Mar 12, 2024
c9b3ac9
test: fix struct
danielbate Mar 12, 2024
daa3f2f
test: use more complex struct
danielbate Mar 12, 2024
275d969
chore: add todo to mixed struct test
danielbate Mar 12, 2024
693aa38
test: add option to complex struct
danielbate Mar 12, 2024
47ca00e
feat: support bytes script decode and fix option
danielbate Mar 14, 2024
cc89150
feat: support tuple script decode
danielbate Mar 14, 2024
8bf6a06
feat: vec decode script
danielbate Mar 14, 2024
e6518c6
feat: vec decode script
danielbate Mar 14, 2024
6715cfd
feat: validate all script decode types
danielbate Mar 14, 2024
547c9a4
chore: re enable forc format
danielbate Mar 14, 2024
c50fbbb
feat: encode number struct script
danielbate Mar 14, 2024
9195757
feat: support script encode
danielbate Mar 14, 2024
4d621e2
feat: predicate u8 echo
danielbate Mar 15, 2024
1734e31
feat: support predicate all types
danielbate Mar 18, 2024
c92f6d8
chore: use other sway branch
danielbate Mar 18, 2024
816684e
chore: fix author for predicate echo toml
danielbate Mar 20, 2024
13c38bf
feat: remove size validation from option coder
danielbate Mar 21, 2024
78e898a
feat: add v1 encoding for configurables
danielbate Mar 21, 2024
d1c3551
feat: support v1 encoding in contracts for all types
danielbate Mar 21, 2024
6ff22af
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 21, 2024
39eb40f
chore: forc format
danielbate Mar 21, 2024
fb209ad
feat: support str slice in v1
danielbate Mar 21, 2024
db59129
feat: add test for nested heap
danielbate Mar 21, 2024
d16ba80
chore: fix experimental forc workspace
danielbate Mar 21, 2024
302ecb3
feat: test for raw slice
danielbate Mar 21, 2024
348f297
chore: changeset
danielbate Mar 21, 2024
351b94e
chore: remove comment
danielbate Mar 21, 2024
e64be8c
chore: doc blocks
danielbate Mar 21, 2024
c04ac65
chore: fix changeset
danielbate Mar 21, 2024
106d7b8
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Mar 22, 2024
0d3adbf
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Mar 25, 2024
fddada5
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Mar 25, 2024
acab5e3
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 28, 2024
bcd915e
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 28, 2024
6d7c20c
feat: upgrade to forc 0.52.0
danielbate Mar 28, 2024
8960f54
chore: linting
danielbate Mar 28, 2024
2fdb48d
chore: linting
danielbate Mar 28, 2024
8ecd5c9
chore: add missing test groups
danielbate Mar 28, 2024
b80d39e
feat: support forc 0.51.1
danielbate Mar 28, 2024
515c52b
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Mar 28, 2024
0f6ee0a
chore: support forc .52.0 with sway patch branch
danielbate Mar 28, 2024
8788e0b
Merge branch 'db/feat/support-v1-encoding' of https://github.com/Fuel…
danielbate Mar 28, 2024
ab0fef2
Merge branch 'master' of https://github.com/FuelLabs/fuels-ts into db…
danielbate Mar 29, 2024
ff58279
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Mar 29, 2024
2c7a48e
chore: support forc 52 in experimetnal
danielbate Mar 29, 2024
f7fd54a
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 1, 2024
fe5d6a2
chore: pass predicate arguments as array
danielbate Apr 1, 2024
7ebd3b6
chore: type hit predicate test
danielbate Apr 1, 2024
fab8763
chore: regen changeset
danielbate Apr 1, 2024
52403c7
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 1, 2024
48e5da8
Merge branch 'master' into db/feat/support-v1-encoding
petertonysmith94 Apr 2, 2024
1c7e83d
Merge branch 'master' into db/feat/support-v1-encoding
arboleya Apr 2, 2024
204f481
chore: redudant array conversion in byte coder
danielbate Apr 2, 2024
fd97156
Merge branch 'db/feat/support-v1-encoding' of https://github.com/Fuel…
danielbate Apr 2, 2024
c1f9a79
feat: add private function to v1 option coder
danielbate Apr 2, 2024
e8c95bd
feat: add private function to v1 option coder
danielbate Apr 2, 2024
f6a4658
chore: format contract call script comments
danielbate Apr 2, 2024
5f37abd
feat: add assertion to predicate test
danielbate Apr 2, 2024
7fd52ba
feat: add default encoding to function fragment
danielbate Apr 2, 2024
e17cb15
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 2, 2024
1f64bd8
feat: add type hint to getScriptDatav0
danielbate Apr 2, 2024
163d140
feat: add type hint to getScriptDatav1
danielbate Apr 2, 2024
29cbe1b
feat: add byte coder tests for byte array
danielbate Apr 2, 2024
b8728d9
Merge branch 'db/feat/support-v1-encoding' of https://github.com/Fuel…
danielbate Apr 2, 2024
8c938e8
feat: implement encoding version type
danielbate Apr 3, 2024
9d6f321
feat: correctly set enum name
danielbate Apr 3, 2024
d323cc4
chore: rebuild
danielbate Apr 3, 2024
6d08a1f
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 3, 2024
7b96710
feat: use forc 52.1 for experimental projects
danielbate Apr 3, 2024
239011b
chore: update link ABI
danielbate Apr 3, 2024
dd17734
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 3, 2024
1974015
test: add b256 b512 vec tests
danielbate Apr 3, 2024
d422101
Merge branch 'master' into db/feat/support-v1-encoding
Dhaiwat10 Apr 4, 2024
f0ae3ed
Merge branch 'master' into db/feat/support-v1-encoding
danielbate Apr 4, 2024
12e725c
test: fix revert assertion
danielbate Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/light-bikes-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fuel-ts/abi-coder": minor
"@fuel-ts/forc": minor
"@fuel-ts/program": minor
---

feat!: support `v1` encoding in program types
22 changes: 16 additions & 6 deletions packages/abi-coder/src/FunctionFragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import type { DecodedValue, InputValue } from './encoding/coders/AbstractCoder';
import { ByteCoder } from './encoding/coders/v0/ByteCoder';
import { TupleCoder } from './encoding/coders/v0/TupleCoder';
import { VecCoder } from './encoding/coders/v0/VecCoder';
import { StdStringCoder } from './encoding/coders/v1/StdStringCoder';
import { TupleCoder as TupleCoderV1 } from './encoding/coders/v1/TupleCoder';
import type {
JsonAbi,
JsonAbiArgument,
JsonAbiFunction,
JsonAbiFunctionAttribute,
} from './types/JsonAbi';
import { OPTION_CODER_TYPE } from './utils/constants';
import { ENCODING_V1, OPTION_CODER_TYPE } from './utils/constants';
import type { Uint8ArrayWithDynamicData } from './utils/utilities';
import { isPointerType, unpackDynamicData, findOrThrow, isHeapType } from './utils/utilities';

Expand All @@ -27,6 +29,8 @@ export class FunctionFragment<
> {
readonly signature: string;
readonly selector: string;
readonly selectorBytes: Uint8Array;
readonly encoding?: string;
readonly name: string;
readonly jsonFn: JsonAbiFunction;
readonly attributes: readonly JsonAbiFunctionAttribute[];
Expand All @@ -44,6 +48,8 @@ export class FunctionFragment<
this.name = name;
this.signature = FunctionFragment.getSignature(this.jsonAbi, this.jsonFn);
this.selector = FunctionFragment.getFunctionSelector(this.signature);
this.selectorBytes = new StdStringCoder().encode(name);
danielbate marked this conversation as resolved.
Show resolved Hide resolved
this.encoding = this.jsonAbi.encoding;
petertonysmith94 marked this conversation as resolved.
Show resolved Hide resolved
this.isInputDataPointer = this.#isInputDataPointer();
this.outputMetadata = {
isHeapType: this.#isOutputDataHeap(),
Expand Down Expand Up @@ -113,12 +119,14 @@ export class FunctionFragment<
const coders = nonEmptyInputs.map((t) =>
AbiCoder.getCoder(this.jsonAbi, t, {
isRightPadded: nonEmptyInputs.length > 1,
encoding: this.encoding,
})
);

const coder = new TupleCoder(coders);
const results: Uint8ArrayWithDynamicData = coder.encode(shallowCopyValues);

if (this.encoding === ENCODING_V1) {
return new TupleCoderV1(coders).encode(shallowCopyValues);
}
const results: Uint8ArrayWithDynamicData = new TupleCoder(coders).encode(shallowCopyValues);
return unpackDynamicData(results, offset, results.byteLength);
}

Expand Down Expand Up @@ -182,7 +190,7 @@ export class FunctionFragment<

const result = nonEmptyInputs.reduce(
(obj: { decoded: unknown[]; offset: number }, input) => {
const coder = AbiCoder.getCoder(this.jsonAbi, input);
const coder = AbiCoder.getCoder(this.jsonAbi, input, { encoding: this.encoding });
const [decodedValue, decodedValueByteSize] = coder.decode(bytes, obj.offset);

return {
Expand All @@ -206,7 +214,9 @@ export class FunctionFragment<
}

const bytes = arrayify(data);
const coder = AbiCoder.getCoder(this.jsonAbi, this.jsonFn.output);
const coder = AbiCoder.getCoder(this.jsonAbi, this.jsonFn.output, {
encoding: this.encoding,
});

return coder.decode(bytes, 0) as [DecodedValue | undefined, number];
}
Expand Down
1 change: 1 addition & 0 deletions packages/abi-coder/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class Interface<TAbi extends JsonAbi = JsonAbi> {

return AbiCoder.encode(this.jsonAbi, configurable.configurableType, value, {
isRightPadded: true,
encoding: this.jsonAbi.encoding,
});
}

Expand Down
9 changes: 0 additions & 9 deletions packages/abi-coder/src/encoding/coders/v0/ByteCoder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,6 @@ describe('ByteCoder', () => {
expect(actual).toStrictEqual(expected);
});

it('should throw when value to encode is not array', async () => {
danielbate marked this conversation as resolved.
Show resolved Hide resolved
const coder = new ByteCoder();
const nonArrayInput = { ...[1] };
await expectToThrowFuelError(
() => coder.encode(nonArrayInput),
new FuelError(ErrorCode.ENCODE_ERROR, 'Expected array value.')
);
});

it('should decode a byte', () => {
const coder = new ByteCoder();
const input = new Uint8Array([
Expand Down
11 changes: 4 additions & 7 deletions packages/abi-coder/src/encoding/coders/v0/ByteCoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ export class ByteCoder extends Coder<number[], Uint8Array> {
super('struct', 'struct Bytes', BASE_VECTOR_OFFSET);
}

encode(value: number[]): Uint8Array {
if (!Array.isArray(value)) {
throw new FuelError(ErrorCode.ENCODE_ERROR, `Expected array value.`);
}

encode(value: number[] | Uint8Array): Uint8Array {
const parts: Uint8Array[] = [];

// pointer (ptr)
Expand All @@ -42,8 +38,9 @@ export class ByteCoder extends Coder<number[], Uint8Array> {
return concatWithDynamicData(parts);
}

#getPaddedData(value: number[]): Uint8Array {
const data: Uint8Array[] = [Uint8Array.from(value)];
#getPaddedData(value: number[] | Uint8Array): Uint8Array {
const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
const data: Uint8Array[] = [Uint8Array.from(bytes)];
petertonysmith94 marked this conversation as resolved.
Show resolved Hide resolved

const paddingLength = (WORD_SIZE - (value.length % WORD_SIZE)) % WORD_SIZE;
if (paddingLength) {
Expand Down
3 changes: 1 addition & 2 deletions packages/abi-coder/src/encoding/coders/v0/OptionCoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ export class OptionCoder<TCoders extends Record<string, Coder>> extends EnumCode
}

decode(data: Uint8Array, offset: number): [DecodedValueOf<TCoders>, number] {
// An empty option will be one less than the expected encoded length
if (data.length < this.encodedLength - 1) {
if (data.length < this.encodedLength) {
danielbate marked this conversation as resolved.
Show resolved Hide resolved
throw new FuelError(ErrorCode.DECODE_ERROR, `Invalid option data size.`);
}

Expand Down
10 changes: 3 additions & 7 deletions packages/abi-coder/src/encoding/coders/v1/ByteCoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@ export class ByteCoder extends Coder<number[], Uint8Array> {
super('struct', 'struct Bytes', WORD_SIZE);
}

encode(value: number[]): Uint8Array {
if (!Array.isArray(value)) {
throw new FuelError(ErrorCode.ENCODE_ERROR, `Expected array value.`);
}

const bytes = new Uint8Array(value);
const lengthBytes = new BigNumberCoder('u64').encode(value.length);
encode(value: number[] | Uint8Array): Uint8Array {
const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
const lengthBytes = new BigNumberCoder('u64').encode(bytes.length);

return new Uint8Array([...lengthBytes, ...bytes]);
}
Expand Down
35 changes: 35 additions & 0 deletions packages/abi-coder/src/encoding/coders/v1/OptionCoder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Coder } from '../AbstractCoder';

import type { InputValueOf, DecodedValueOf } from './EnumCoder';
import { EnumCoder } from './EnumCoder';

type SwayOption<T> = { None: [] } | { Some: T };
export type Option<T> = T | undefined;

export class OptionCoder<TCoders extends Record<string, Coder>> extends EnumCoder<TCoders> {
petertonysmith94 marked this conversation as resolved.
Show resolved Hide resolved
encode(value: InputValueOf<TCoders>): Uint8Array {
const result = super.encode(this.toSwayOption(value) as unknown as InputValueOf<TCoders>);
return result;
}

toSwayOption(input: InputValueOf<TCoders>): SwayOption<unknown> {
danielbate marked this conversation as resolved.
Show resolved Hide resolved
if (input !== undefined) {
return { Some: input };
}

return { None: [] };
}

decode(data: Uint8Array, offset: number): [DecodedValueOf<TCoders>, number] {
const [decoded, newOffset] = super.decode(data, offset);
return [this.toOption(decoded) as DecodedValueOf<TCoders>, newOffset];
}

toOption(output?: DecodedValueOf<TCoders>): Option<unknown> {
danielbate marked this conversation as resolved.
Show resolved Hide resolved
if (output && 'Some' in output) {
return output.Some;
}

return undefined;
}
}
3 changes: 2 additions & 1 deletion packages/abi-coder/src/encoding/coders/v1/StructCoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { concatBytes } from '@fuel-ts/utils';

import type { TypesOfCoder } from '../AbstractCoder';
import { Coder } from '../AbstractCoder';
import { OptionCoder } from '../v0/OptionCoder';

import { OptionCoder } from './OptionCoder';

type InputValueOf<TCoders extends Record<string, Coder>> = {
[P in keyof TCoders]: TypesOfCoder<TCoders[P]>['Input'];
Expand Down
12 changes: 4 additions & 8 deletions packages/abi-coder/src/encoding/strategies/getCoderV1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ import { ArrayCoder } from '../coders/v0/ArrayCoder';
import { B256Coder } from '../coders/v0/B256Coder';
import { B512Coder } from '../coders/v0/B512Coder';
import { BigNumberCoder } from '../coders/v0/BigNumberCoder';
import { OptionCoder } from '../coders/v0/OptionCoder';
import { BooleanCoder } from '../coders/v1/BooleanCoder';
import { ByteCoder } from '../coders/v1/ByteCoder';
import { EnumCoder } from '../coders/v1/EnumCoder';
import { NumberCoder } from '../coders/v1/NumberCoder';
import { OptionCoder } from '../coders/v1/OptionCoder';
import { RawSliceCoder } from '../coders/v1/RawSliceCoder';
import { StdStringCoder } from '../coders/v1/StdStringCoder';
import { StrSliceCoder } from '../coders/v1/StrSliceCoder';
import { StringCoder } from '../coders/v1/StringCoder';
import { StructCoder } from '../coders/v1/StructCoder';
import { TupleCoder } from '../coders/v1/TupleCoder';
Expand Down Expand Up @@ -79,6 +80,8 @@ export const getCoder: GetCoderFn = (
return new ByteCoder();
case STD_STRING_CODER_TYPE:
return new StdStringCoder();
case STR_SLICE_CODER_TYPE:
return new StrSliceCoder();
default:
break;
}
Expand Down Expand Up @@ -149,13 +152,6 @@ export const getCoder: GetCoderFn = (
return new TupleCoder(coders as Coder[]);
}

if (resolvedAbiType.type === STR_SLICE_CODER_TYPE) {
throw new FuelError(
ErrorCode.INVALID_DATA,
'String slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`'
);
}

throw new FuelError(
ErrorCode.CODER_NOT_FOUND,
`Coder not found: ${JSON.stringify(resolvedAbiType)}.`
Expand Down
2 changes: 2 additions & 0 deletions packages/abi-coder/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@ export {
ASSET_ID_LEN,
CONTRACT_ID_LEN,
calculateVmTxMemory,
ENCODING_V0,
ENCODING_V1,
} from './utils/constants';
export { BigNumberCoder } from './encoding/coders/v0/BigNumberCoder';
2 changes: 1 addition & 1 deletion packages/forc/VERSION_EXPERIMENTAL
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.51.1
0.52.0
89 changes: 89 additions & 0 deletions packages/fuel-gauge/src/experimental-contract.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { readFileSync } from 'fs';
import type { Contract } from 'fuels';
import { bn } from 'fuels';
import { join } from 'path';

import { setup } from './utils';

let contractInstance: Contract;

const U8_MAX = 2 ** 8 - 1;
const U16_MAX = 2 ** 16 - 1;
const U32_MAX = 2 ** 32 - 1;
const U64_MAX = bn(2).pow(64).sub(1);
const U256_MAX = bn(2).pow(256).sub(1);
const B512 =
'0x8e9dda6f7793745ac5aacf9e907cae30b2a01fdf0d23b7750a85c6a44fca0c29f0906f9d1f1e92e6a1fb3c3dcef3cc3b3cdbaae27e47b9d9a4c6a4fce4cf16b2';

/**
* @group node
*/
describe('Experimental Contract', () => {
beforeAll(async () => {
const projectName = 'contract-echo';
const path = join(
__dirname,
`../test/fixtures/forc-projects-experimental/${projectName}/out/release/${projectName}`
);
const contractBytecode = readFileSync(`${path}.bin`);
const abi = JSON.parse(readFileSync(`${path}-abi.json`, 'utf8'));

contractInstance = await setup({ contractBytecode, abi });
});

it('echos mixed struct with all types', async () => {
const struct = {
a: U8_MAX,
b: U16_MAX,
c: U32_MAX,
d: U64_MAX,
e: U256_MAX,
f: '0xbebd3baab326f895289ecbd4210cf886ce41952316441ae4cac35f00f0e882a6',
g: B512,
native: 'Pending',
mixed: { Value: true },
grades: [1, 4, 6, 22],
fuel: 'fuel',
hello: 'Hello World',
opt: 42,
nada: undefined,
bytes: Uint8Array.from([40, 41, 42]),
tuple: [U8_MAX, U16_MAX, U32_MAX, 'fuel'],
vec_u8: [40, 41, 42],
str_slice: 'fuel',
deep: {
a: U8_MAX,
b: U16_MAX,
c: U32_MAX,
d: U64_MAX,
e: U256_MAX,
f: '0xbebd3baab326f895289ecbd4210cf886ce41952316441ae4cac35f00f0e882a6',
g: B512,
native: 'Pending',
mixed: { Value: true },
grades: [1, 4, 6, 22],
fuel: 'fuel',
hello: 'Hello World',
opt: 42,
nada: undefined,
bytes: Uint8Array.from([40, 41, 42]),
tuple: [U8_MAX, U16_MAX, U32_MAX, 'fuel'],
vec_u8: [40, 41, 42],
even_deeper: {
nested_vec: [1, 2, 3, 4, 5],
nested_str: 'fuel labs',
nested_raw: [88, 89, 90, 100],
},
},
};

const { value } = await contractInstance.functions.echo_struct(struct).call();
expect(value).toStrictEqual(struct);
});

it('extracts str slice from revert', async () => {
await expect(contractInstance.functions.test_revert().call()).rejects.toThrow(
/The script reverted with reason RequireFailed/
);
});
});
Loading
Loading