From 372cb49a642dcb9f32936f1131af0d73a69e6fb6 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sun, 20 Aug 2023 23:14:03 -0700 Subject: [PATCH 01/55] prep new bytes --- packages/abi-coder/src/constants.ts | 1 + packages/abi-coder/src/utilities.ts | 4 ++-- .../fixtures/forc-projects/Forc.toml | 1 + .../fixtures/forc-projects/bytes/Forc.toml | 3 +++ .../fixtures/forc-projects/bytes/src/main.sw | 19 +++++++++++++++++++ packages/fuel-gauge/src/bytes.test.ts | 17 +++++++++++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 packages/fuel-gauge/fixtures/forc-projects/bytes/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw create mode 100644 packages/fuel-gauge/src/bytes.test.ts diff --git a/packages/abi-coder/src/constants.ts b/packages/abi-coder/src/constants.ts index 2541e321a0a..38ada977afe 100644 --- a/packages/abi-coder/src/constants.ts +++ b/packages/abi-coder/src/constants.ts @@ -1,5 +1,6 @@ export const OPTION_CODER_TYPE = 'enum Option'; export const VEC_CODER_TYPE = 'struct Vec'; +export const BYTE_CODER_TYPE = 'struct Bytes'; export const stringRegEx = /str\[(?[0-9]+)\]/; export const arrayRegEx = /\[(?[\w\s\\[\]]+);\s*(?[0-9]+)\]/; export const structRegEx = /^struct (?\w+)$/; diff --git a/packages/abi-coder/src/utilities.ts b/packages/abi-coder/src/utilities.ts index 69aba2a5ec6..7fa4c099e2c 100644 --- a/packages/abi-coder/src/utilities.ts +++ b/packages/abi-coder/src/utilities.ts @@ -2,7 +2,7 @@ import type { BytesLike } from '@ethersproject/bytes'; import { concat, arrayify } from '@ethersproject/bytes'; import { U64Coder } from './coders/u64'; -import { VEC_CODER_TYPE, WORD_SIZE } from './constants'; +import { BYTE_CODER_TYPE, VEC_CODER_TYPE, WORD_SIZE } from './constants'; export type DynamicData = { [pointerIndex: number]: Uint8ArrayWithDynamicData; @@ -139,7 +139,7 @@ export const isPointerType = (type: string) => { } }; -export const isHeapType = (type: string) => type === VEC_CODER_TYPE; +export const isHeapType = (type: string) => type === VEC_CODER_TYPE || type === BYTE_CODER_TYPE; export function findOrThrow( arr: readonly T[], diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 9cd0c6828d6..86d1f16e342 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -5,6 +5,7 @@ members = [ "advanced-logging-other-contract-abi", "auth_testing_abi", "auth_testing_contract", + "bytes", "call-test-contract", "configurable-contract", "collision_in_fn_names", diff --git a/packages/fuel-gauge/fixtures/forc-projects/bytes/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/bytes/Forc.toml new file mode 100644 index 00000000000..f67a8ec9a33 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/bytes/Forc.toml @@ -0,0 +1,3 @@ +[project] +license = "Apache-2.0" +name = "bytes" diff --git a/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw new file mode 100644 index 00000000000..b8b49662894 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw @@ -0,0 +1,19 @@ +contract; + +use std::bytes::Bytes; + +abi MyContract { + fn return_bytes(len: u8) -> Bytes; +} + +impl MyContract for Contract { + fn return_bytes(len: u8) -> Bytes { + let mut bytes = Bytes::new(); + let mut i: u8 = 0; + while i < len { + bytes.push(i); + i += 1u8; + } + bytes + } +} \ No newline at end of file diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts new file mode 100644 index 00000000000..0b1be14acb5 --- /dev/null +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -0,0 +1,17 @@ +import { type Contract } from 'fuels'; + +import { getSetupContract } from './utils'; + +const setupContract = getSetupContract('bytes'); +let contractInstance: Contract; +beforeAll(async () => { + contractInstance = await setupContract(); +}); + +describe('Bytes Tests', () => { + it('should test bytes input/output', async () => { + const INPUT = 10; + + const { value } = await contractInstance.functions.return_bytes(INPUT).call(); + }); +}); From a4d39c858227d0da6c6756c633e8e9cb787bac02 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Fri, 25 Aug 2023 21:33:51 -0700 Subject: [PATCH 02/55] add setup --- packages/abi-coder/src/abi-coder.ts | 4 ++ packages/abi-coder/src/coders/bytes.test.ts | 33 +++++++++++ .../abi-coder/src/coders/raw-slice.test.ts | 33 +++++++++++ .../fixtures/forc-projects/Forc.toml | 1 + .../fixtures/forc-projects/bytes/src/main.sw | 39 +++++++++++++ .../forc-projects/raw-slice/Forc.toml | 3 + .../forc-projects/raw-slice/src/main.sw | 58 +++++++++++++++++++ packages/fuel-gauge/src/bytes.test.ts | 2 + 8 files changed, 173 insertions(+) create mode 100644 packages/abi-coder/src/coders/bytes.test.ts create mode 100644 packages/abi-coder/src/coders/raw-slice.test.ts create mode 100644 packages/fuel-gauge/fixtures/forc-projects/raw-slice/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw diff --git a/packages/abi-coder/src/abi-coder.ts b/packages/abi-coder/src/abi-coder.ts index 1c34fb32c52..fea808f5e2f 100644 --- a/packages/abi-coder/src/abi-coder.ts +++ b/packages/abi-coder/src/abi-coder.ts @@ -7,6 +7,7 @@ import { ArrayCoder } from './coders/array'; import { B256Coder } from './coders/b256'; import { B512Coder } from './coders/b512'; import { BooleanCoder } from './coders/boolean'; +import { ByteCoder } from './coders/byte'; import { EnumCoder } from './coders/enum'; import { NumberCoder } from './coders/number'; import { OptionCoder } from './coders/option'; @@ -23,6 +24,7 @@ import { tupleRegEx, OPTION_CODER_TYPE, VEC_CODER_TYPE, + BYTE_CODER_TYPE, } from './constants'; import type { JsonAbi, JsonAbiArgument } from './json-abi'; import { ResolvedAbiType } from './resolved-abi-type'; @@ -64,6 +66,8 @@ export abstract class AbiCoder { return new B256Coder(); case 'struct B512': return new B512Coder(); + case BYTE_CODER_TYPE: + return new ByteCoder(); default: break; } diff --git a/packages/abi-coder/src/coders/bytes.test.ts b/packages/abi-coder/src/coders/bytes.test.ts new file mode 100644 index 00000000000..68ae403a4b9 --- /dev/null +++ b/packages/abi-coder/src/coders/bytes.test.ts @@ -0,0 +1,33 @@ +import { ByteCoder } from './byte'; + +describe('ByteCoder', () => { + it('should encode a byte', () => { + const coder = new ByteCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + const expected = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + + const actual = coder.encode(input); + + expect(actual).toEqual(expected); + }); + + it('should decode a byte', () => { + const coder = new ByteCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + const expected = [8, 6, 7]; + + const [actual, newOffset] = coder.decode(input, 0); + + expect(actual).toEqual(expected); + expect(newOffset).toEqual(24); + }); +}); diff --git a/packages/abi-coder/src/coders/raw-slice.test.ts b/packages/abi-coder/src/coders/raw-slice.test.ts new file mode 100644 index 00000000000..34a0333ce41 --- /dev/null +++ b/packages/abi-coder/src/coders/raw-slice.test.ts @@ -0,0 +1,33 @@ +import { RawSliceCoder } from './raw-slice'; + +describe('RawSliceCoder', () => { + it('should encode a raw-slice', () => { + const coder = new RawSliceCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + const expected = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + + const actual = coder.encode(input); + + expect(actual).toEqual(expected); + }); + + it('should decode a raw-slice', () => { + const coder = new RawSliceCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + ]); + const expected = [8, 6, 7]; + + const [actual, newOffset] = coder.decode(input, 0); + + expect(actual).toEqual(expected); + expect(newOffset).toEqual(24); + }); +}); diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 86d1f16e342..41a064db952 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -25,6 +25,7 @@ members = [ "predicate-with-configurable", "predicate-u32", "predicate-vector-types", + "raw-slice", "revert-error", "script-main-args", "script-main-return-struct", diff --git a/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw index b8b49662894..fd91c5e4353 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw +++ b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw @@ -2,11 +2,50 @@ contract; use std::bytes::Bytes; +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn expected_bytes() -> Bytes { + let mut bytes = Bytes::new(); + + bytes.push(40); + bytes.push(41); + bytes.push(42); + + bytes +} + abi MyContract { + fn accept_bytes(bytes: Bytes); + fn accept_nested_bytes(wrapper: Wrapper>); fn return_bytes(len: u8) -> Bytes; } impl MyContract for Contract { + fn accept_bytes(bytes: Bytes) { + require(bytes == expected_bytes(), "given bytes didn't match the expected bytes"); + } + + fn accept_nested_bytes(wrapper: Wrapper>) { + if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum { + require(enum_bytes == expected_bytes(), "wrapper.inner_enum didn't carry the expected bytes"); + } else { + require(false, "enum was not of variant Second"); + } + + let inner_vec = wrapper.inner; + require(inner_vec.len() == 2, "Expected wrapper.inner vector to have 2 elements"); + require(inner_vec.get(0).unwrap() == expected_bytes(), "wrapper.inner[0] didn't match expectation"); + require(inner_vec.get(1).unwrap() == expected_bytes(), "wrapper.inner[1] didn't match expectation"); + } + fn return_bytes(len: u8) -> Bytes { let mut bytes = Bytes::new(); let mut i: u8 = 0; diff --git a/packages/fuel-gauge/fixtures/forc-projects/raw-slice/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/Forc.toml new file mode 100644 index 00000000000..296855f7eb1 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/Forc.toml @@ -0,0 +1,3 @@ +[project] +license = "Apache-2.0" +name = "raw-slice" diff --git a/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw new file mode 100644 index 00000000000..7ad5be05780 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw @@ -0,0 +1,58 @@ +contract; + +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +abi RawSliceContract { + fn return_raw_slice(length: u64) -> raw_slice; + fn accept_raw_slice(slice: raw_slice); + fn accept_nested_raw_slice(wrapper: Wrapper>); +} + +fn validate_raw_slice(input: raw_slice) { + let vec: Vec = Vec::from(input); + require(vec.len() == 3, "raw slice len is not 3"); + require(vec.get(2).unwrap() == 42, "expected 3rd slice entry to be 42"); + require(vec.get(1).unwrap() == 41, "expected 2nd slice entry to be 41"); + require(vec.get(0).unwrap() == 40, "expected 1st slice entry to be 40"); +} + +fn validate_vec(vec: Vec) { + require(vec.len() == 2, "vec should have two elements"); + validate_raw_slice(vec.get(0).unwrap()); + validate_raw_slice(vec.get(1).unwrap()); +} + +impl RawSliceContract for Contract { + fn return_raw_slice(length: u64) -> raw_slice { + let mut vec = Vec::new(); + let mut counter = 0; + while counter < length { + vec.push(counter); + counter = counter + 1; + } + vec.as_raw_slice() + } + + fn accept_raw_slice(slice: raw_slice) { + validate_raw_slice(slice); + } + + fn accept_nested_raw_slice(wrapper: Wrapper>) { + if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum + { + validate_raw_slice(enum_raw_slice); + } else { + require(false, "enum was not of variant Second"); + } + + validate_vec(wrapper.inner); + } +} \ No newline at end of file diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 0b1be14acb5..a5da5b7228b 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -13,5 +13,7 @@ describe('Bytes Tests', () => { const INPUT = 10; const { value } = await contractInstance.functions.return_bytes(INPUT).call(); + + expect(value).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); }); }); From f0a44f39d75e114d45f4519939cb38968797b5cc Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Tue, 29 Aug 2023 23:01:45 -0700 Subject: [PATCH 03/55] fix test --- packages/abi-coder/src/coders/byte.ts | 26 ++++++++++++++++++++++++++ packages/fuel-gauge/src/bytes.test.ts | 12 ++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 packages/abi-coder/src/coders/byte.ts diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts new file mode 100644 index 00000000000..a624d578bb3 --- /dev/null +++ b/packages/abi-coder/src/coders/byte.ts @@ -0,0 +1,26 @@ +import { toBytes, toHex, bn } from '@fuel-ts/math'; + +import { BASE_VECTOR_OFFSET } from '../utilities'; + +import { Coder } from './abstract-coder'; +import { U64Coder } from './u64'; + +const MEMORY_SIZE_OF_U8 = 1; + +export class ByteCoder extends Coder { + constructor() { + super('struct', 'struct Bytes', MEMORY_SIZE_OF_U8); + } + + encode(value: number): Uint8Array { + return new Uint8Array(); + } + + decode(data: Uint8Array, offset: number): [Uint8Array, number] { + const len = data.slice(16, 24); + const length = bn(new U64Coder().decode(len, 0)[0]).toNumber(); + const byteData = data.slice(BASE_VECTOR_OFFSET, BASE_VECTOR_OFFSET + length * 8); + + return [byteData, offset + 8]; + } +} diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index a5da5b7228b..4b339d15e89 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -9,11 +9,19 @@ beforeAll(async () => { }); describe('Bytes Tests', () => { - it('should test bytes input/output', async () => { + it('should test bytes output', async () => { const INPUT = 10; const { value } = await contractInstance.functions.return_bytes(INPUT).call(); - expect(value).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + expect(value).toStrictEqual(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + }); + + it('should test bytes output [100 items]', async () => { + const INPUT = 100; + + const { value } = await contractInstance.functions.return_bytes(INPUT).call(); + + expect(value).toStrictEqual(new Uint8Array(Array.from({ length: 100 }, (e, i) => i))); }); }); From a77f152cfec8bf55f057c612d1d43c565a885d6f Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Tue, 29 Aug 2023 23:05:54 -0700 Subject: [PATCH 04/55] refactor --- packages/abi-coder/src/coders/byte.test.ts | 30 +++++++++++++++++++ packages/abi-coder/src/coders/byte.ts | 2 +- packages/abi-coder/src/coders/bytes.test.ts | 33 --------------------- 3 files changed, 31 insertions(+), 34 deletions(-) create mode 100644 packages/abi-coder/src/coders/byte.test.ts delete mode 100644 packages/abi-coder/src/coders/bytes.test.ts diff --git a/packages/abi-coder/src/coders/byte.test.ts b/packages/abi-coder/src/coders/byte.test.ts new file mode 100644 index 00000000000..35dda310261 --- /dev/null +++ b/packages/abi-coder/src/coders/byte.test.ts @@ -0,0 +1,30 @@ +import { ByteCoder } from './byte'; + +describe('ByteCoder', () => { + it('should encode a byte', () => { + const coder = new ByteCoder(); + const input = 10; + const expected = new Uint8Array([ + 0, 0, 0, 0, 3, 255, 255, 225, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 10, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + ]); + + const actual = coder.encode(input); + + expect(actual).toEqual(expected); + }); + + it('should decode a byte', () => { + const coder = new ByteCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 3, 255, 255, 225, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 10, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + ]); + const expected = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + const [actual, newOffset] = coder.decode(input, 0); + + expect(actual).toEqual(expected); + expect(newOffset).toEqual(24); + }); +}); diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index a624d578bb3..d854eb4687d 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -21,6 +21,6 @@ export class ByteCoder extends Coder { const length = bn(new U64Coder().decode(len, 0)[0]).toNumber(); const byteData = data.slice(BASE_VECTOR_OFFSET, BASE_VECTOR_OFFSET + length * 8); - return [byteData, offset + 8]; + return [byteData, offset + BASE_VECTOR_OFFSET]; } } diff --git a/packages/abi-coder/src/coders/bytes.test.ts b/packages/abi-coder/src/coders/bytes.test.ts deleted file mode 100644 index 68ae403a4b9..00000000000 --- a/packages/abi-coder/src/coders/bytes.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ByteCoder } from './byte'; - -describe('ByteCoder', () => { - it('should encode a byte', () => { - const coder = new ByteCoder(); - const input = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, - ]); - const expected = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, - ]); - - const actual = coder.encode(input); - - expect(actual).toEqual(expected); - }); - - it('should decode a byte', () => { - const coder = new ByteCoder(); - const input = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, - ]); - const expected = [8, 6, 7]; - - const [actual, newOffset] = coder.decode(input, 0); - - expect(actual).toEqual(expected); - expect(newOffset).toEqual(24); - }); -}); From e575cb2f54ad642f9791df5dddb8aded20c2c197 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 00:17:31 -0700 Subject: [PATCH 05/55] adjust --- packages/abi-coder/src/abi-coder.ts | 3 ++ packages/abi-coder/src/coders/byte.ts | 35 ++++++++++++++++--- packages/abi-coder/src/coders/raw-slice.ts | 22 ++++++++++++ packages/fuel-gauge/src/raw-slice.test.ts | 40 ++++++++++++++++++++++ 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 packages/abi-coder/src/coders/raw-slice.ts create mode 100644 packages/fuel-gauge/src/raw-slice.test.ts diff --git a/packages/abi-coder/src/abi-coder.ts b/packages/abi-coder/src/abi-coder.ts index fea808f5e2f..f1b2749363d 100644 --- a/packages/abi-coder/src/abi-coder.ts +++ b/packages/abi-coder/src/abi-coder.ts @@ -11,6 +11,7 @@ import { ByteCoder } from './coders/byte'; import { EnumCoder } from './coders/enum'; import { NumberCoder } from './coders/number'; import { OptionCoder } from './coders/option'; +import { RawSliceCoder } from './coders/raw-slice'; import { StringCoder } from './coders/string'; import { StructCoder } from './coders/struct'; import { TupleCoder } from './coders/tuple'; @@ -60,6 +61,8 @@ export abstract class AbiCoder { case 'u64': case 'raw untyped ptr': return new U64Coder(); + case 'raw untyped slice': + return new RawSliceCoder(); case 'bool': return new BooleanCoder(); case 'b256': diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index d854eb4687d..5f9440fe858 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -1,19 +1,44 @@ -import { toBytes, toHex, bn } from '@fuel-ts/math'; +import type { BytesLike } from '@ethersproject/bytes'; +import { bn } from '@fuel-ts/math'; -import { BASE_VECTOR_OFFSET } from '../utilities'; +import type { Uint8ArrayWithDynamicData } from '../utilities'; +import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; import { Coder } from './abstract-coder'; +import { NumberCoder } from './number'; import { U64Coder } from './u64'; const MEMORY_SIZE_OF_U8 = 1; -export class ByteCoder extends Coder { +export class ByteCoder extends Coder { constructor() { super('struct', 'struct Bytes', MEMORY_SIZE_OF_U8); } - encode(value: number): Uint8Array { - return new Uint8Array(); + encode(value: number[]): Uint8Array { + if (!Array.isArray(value)) { + this.throwError('expected array value', value); + } + + const parts: Uint8Array[] = []; + + // pointer (ptr) + const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); + const u8Coder = new NumberCoder('u8'); + // pointer dynamicData, encode the vector now and attach to its pointer + pointer.dynamicData = { + 0: concatWithDynamicData(value as unknown as BytesLike[]), + }; + + parts.push(pointer); + + // capacity (cap) + parts.push(new U64Coder().encode(value.length)); + + // length (len) + parts.push(new U64Coder().encode(value.length)); + + return concatWithDynamicData(parts); } decode(data: Uint8Array, offset: number): [Uint8Array, number] { diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts new file mode 100644 index 00000000000..1b3f0fd9295 --- /dev/null +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -0,0 +1,22 @@ +import type { BN } from '@fuel-ts/math'; + +import { Coder } from './abstract-coder'; +import { ArrayCoder } from './array'; +import { U64Coder } from './u64'; + +export class RawSliceCoder extends Coder { + constructor() { + super('struct', 'struct Bytes', 1); + } + + encode(value: number[]): Uint8Array { + return new Uint8Array(); + } + + decode(data: Uint8Array, offset: number): [BN[], number] { + const internalCoder = new ArrayCoder(new U64Coder(), data.length / 8); + const decoded = internalCoder.decode(data, offset); + + return decoded; + } +} diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts new file mode 100644 index 00000000000..fa9411e2135 --- /dev/null +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -0,0 +1,40 @@ +import type { BN } from 'fuels'; +import { type Contract } from 'fuels'; + +import { getSetupContract } from './utils'; + +const setupContract = getSetupContract('raw-slice'); +let contractInstance: Contract; +beforeAll(async () => { + contractInstance = await setupContract(); +}); + +describe('Raw Slice Tests', () => { + it('should test raw slice output', async () => { + const INPUT = 10; + + const { value } = await contractInstance.functions.return_raw_slice(INPUT).call(); + + expect(value.map((v: BN) => v.toNumber())).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + }); + + it('should test raw slice input', async () => { + const INPUT = [40, 41, 42]; + + await contractInstance.functions.accept_raw_slice(INPUT).call(); + + expect(true).toBeTruthy(); + }); + + it('should test raw slice input [nested]', async () => { + const slice = [40, 41, 42]; + const INPUT = { + inner: [slice, slice], + inner_enum: { Second: slice }, + }; + + await contractInstance.functions.accept_nested_raw_slice(INPUT).call(); + + expect(true).toBeTruthy(); + }); +}); From 02aaec0dd32a174fdf74b64de709845b670ab0db Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 11:09:26 -0700 Subject: [PATCH 06/55] tests --- packages/fuel-gauge/src/bytes.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 4b339d15e89..6abb442756e 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -24,4 +24,13 @@ describe('Bytes Tests', () => { expect(value).toStrictEqual(new Uint8Array(Array.from({ length: 100 }, (e, i) => i))); }); + + it('should test bytes input', async () => { + const INPUT = [40, 41, 42]; + + await contractInstance.functions.accept_bytes(INPUT).call(); + + expect(true).toBeTruthy(); + }); + }); From 977794097e2c5af99fff20dc52bbaa69a9e6f049 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 11:31:15 -0700 Subject: [PATCH 07/55] improve tests --- packages/abi-coder/src/coders/byte.test.ts | 15 +++++++++------ packages/fuel-gauge/src/bytes.test.ts | 11 +++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/abi-coder/src/coders/byte.test.ts b/packages/abi-coder/src/coders/byte.test.ts index 35dda310261..bbedba51ced 100644 --- a/packages/abi-coder/src/coders/byte.test.ts +++ b/packages/abi-coder/src/coders/byte.test.ts @@ -1,17 +1,20 @@ +import type { Uint8ArrayWithDynamicData } from '../utilities'; + import { ByteCoder } from './byte'; describe('ByteCoder', () => { it('should encode a byte', () => { const coder = new ByteCoder(); - const input = 10; - const expected = new Uint8Array([ - 0, 0, 0, 0, 3, 255, 255, 225, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 10, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, ]); + expected.dynamicData = { + 0: new Uint8Array([1, 2, 3]), + }; - const actual = coder.encode(input); + const actual = coder.encode([1, 2, 3]); - expect(actual).toEqual(expected); + expect(actual).toStrictEqual(expected); }); it('should decode a byte', () => { diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 6abb442756e..600c50c0b6a 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -33,4 +33,15 @@ describe('Bytes Tests', () => { expect(true).toBeTruthy(); }); + it('should test bytes input [nested]', async () => { + const bytes = [40, 41, 42]; + const INPUT = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + + await contractInstance.functions.accept_nested_bytes(INPUT).call(); + + expect(true).toBeTruthy(); + }); }); From ad5d4e5b67c97b1e5af93b6292580a460b400cc1 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 11:57:19 -0700 Subject: [PATCH 08/55] aDJUST --- packages/abi-coder/src/coders/byte.ts | 2 -- .../abi-coder/src/coders/raw-slice.test.ts | 30 ++++++++++--------- packages/abi-coder/src/coders/raw-slice.ts | 28 ++++++++++++++++- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index 5f9440fe858..73b4c3f5335 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -5,7 +5,6 @@ import type { Uint8ArrayWithDynamicData } from '../utilities'; import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; import { Coder } from './abstract-coder'; -import { NumberCoder } from './number'; import { U64Coder } from './u64'; const MEMORY_SIZE_OF_U8 = 1; @@ -24,7 +23,6 @@ export class ByteCoder extends Coder { // pointer (ptr) const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); - const u8Coder = new NumberCoder('u8'); // pointer dynamicData, encode the vector now and attach to its pointer pointer.dynamicData = { 0: concatWithDynamicData(value as unknown as BytesLike[]), diff --git a/packages/abi-coder/src/coders/raw-slice.test.ts b/packages/abi-coder/src/coders/raw-slice.test.ts index 34a0333ce41..50b8561f1bc 100644 --- a/packages/abi-coder/src/coders/raw-slice.test.ts +++ b/packages/abi-coder/src/coders/raw-slice.test.ts @@ -1,33 +1,35 @@ +import type { BN } from '@fuel-ts/math'; + +import type { Uint8ArrayWithDynamicData } from '../utilities'; + import { RawSliceCoder } from './raw-slice'; describe('RawSliceCoder', () => { it('should encode a raw-slice', () => { const coder = new RawSliceCoder(); - const input = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, - ]); - const expected = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 24, ]); + expected.dynamicData = { + 0: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3]), + }; - const actual = coder.encode(input); + const actual = coder.encode([1, 2, 3]); - expect(actual).toEqual(expected); + expect(actual).toStrictEqual(expected); }); it('should decode a raw-slice', () => { const coder = new RawSliceCoder(); const input = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 41, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9, ]); - const expected = [8, 6, 7]; const [actual, newOffset] = coder.decode(input, 0); - expect(actual).toEqual(expected); - expect(newOffset).toEqual(24); + expect(actual.map((v: BN) => v.toNumber())).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + expect(newOffset).toEqual(80); }); }); diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts index 1b3f0fd9295..c49a0fc0dcc 100644 --- a/packages/abi-coder/src/coders/raw-slice.ts +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -1,7 +1,13 @@ +import type { BytesLike } from '@ethersproject/bytes'; import type { BN } from '@fuel-ts/math'; +import { WORD_SIZE } from '../constants'; +import type { Uint8ArrayWithDynamicData } from '../utilities'; +import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; + import { Coder } from './abstract-coder'; import { ArrayCoder } from './array'; +import { NumberCoder } from './number'; import { U64Coder } from './u64'; export class RawSliceCoder extends Coder { @@ -10,7 +16,27 @@ export class RawSliceCoder extends Coder { } encode(value: number[]): Uint8Array { - return new Uint8Array(); + if (!Array.isArray(value)) { + this.throwError('expected array value', value); + } + + const parts: Uint8Array[] = []; + const coder = new U64Coder(); + + // pointer (ptr) + const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); + + // pointer dynamicData, encode the vector now and attach to its pointer + pointer.dynamicData = { + 0: concatWithDynamicData(value.map((v) => coder.encode(v))), + }; + + parts.push(pointer); + + // length (len) + parts.push(new U64Coder().encode(value.length * WORD_SIZE)); + + return concatWithDynamicData(parts); } decode(data: Uint8Array, offset: number): [BN[], number] { From 766931878e3816af910bc62cb84474f2389d5b9f Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 12:52:34 -0700 Subject: [PATCH 09/55] refactor --- packages/abi-coder/src/coders/raw-slice.test.ts | 2 +- packages/abi-coder/src/coders/raw-slice.ts | 6 ++---- packages/abi-coder/src/utilities.ts | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/abi-coder/src/coders/raw-slice.test.ts b/packages/abi-coder/src/coders/raw-slice.test.ts index 50b8561f1bc..adf81641101 100644 --- a/packages/abi-coder/src/coders/raw-slice.test.ts +++ b/packages/abi-coder/src/coders/raw-slice.test.ts @@ -8,7 +8,7 @@ describe('RawSliceCoder', () => { it('should encode a raw-slice', () => { const coder = new RawSliceCoder(); const expected: Uint8ArrayWithDynamicData = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 24, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 24, ]); expected.dynamicData = { 0: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3]), diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts index c49a0fc0dcc..8ee151465b5 100644 --- a/packages/abi-coder/src/coders/raw-slice.ts +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -1,13 +1,11 @@ -import type { BytesLike } from '@ethersproject/bytes'; import type { BN } from '@fuel-ts/math'; import { WORD_SIZE } from '../constants'; import type { Uint8ArrayWithDynamicData } from '../utilities'; -import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; +import { BASE_RAW_SLICE_OFFSET, concatWithDynamicData } from '../utilities'; import { Coder } from './abstract-coder'; import { ArrayCoder } from './array'; -import { NumberCoder } from './number'; import { U64Coder } from './u64'; export class RawSliceCoder extends Coder { @@ -24,7 +22,7 @@ export class RawSliceCoder extends Coder { const coder = new U64Coder(); // pointer (ptr) - const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); + const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_RAW_SLICE_OFFSET); // pointer dynamicData, encode the vector now and attach to its pointer pointer.dynamicData = { diff --git a/packages/abi-coder/src/utilities.ts b/packages/abi-coder/src/utilities.ts index 7fa4c099e2c..50d24168ac2 100644 --- a/packages/abi-coder/src/utilities.ts +++ b/packages/abi-coder/src/utilities.ts @@ -15,6 +15,9 @@ export type Uint8ArrayWithDynamicData = Uint8Array & { const VEC_PROPERTY_SPACE = 3; // ptr + cap + length export const BASE_VECTOR_OFFSET = VEC_PROPERTY_SPACE * WORD_SIZE; +const RAW_SLICE_PROPERTY_SPACE = 2; // ptr + length +export const BASE_RAW_SLICE_OFFSET = RAW_SLICE_PROPERTY_SPACE * WORD_SIZE; + // this is a fork of @ethersproject/bytes:concat // this collects individual dynamicData data and relocates it to top level export function concatWithDynamicData(items: ReadonlyArray): Uint8ArrayWithDynamicData { From cd228225a65f1560c766ef2317612cf876115352 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 13:59:49 -0700 Subject: [PATCH 10/55] add tests --- .../test/fixtures/exhaustive-examples-abi.ts | 414 ++++++++++-------- packages/abi-coder/test/interface.test.ts | 22 + .../exhaustive-examples/src/main.sw | 5 + 3 files changed, 270 insertions(+), 171 deletions(-) diff --git a/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts b/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts index 2587a847a64..af6262a6344 100644 --- a/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts +++ b/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts @@ -12,16 +12,16 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 49, + type: 52, typeArguments: null, }, { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -35,7 +35,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 40, + type: 41, typeArguments: null, }, { @@ -74,7 +74,7 @@ export const exhaustiveExamplesAbi = { }, { name: '__tuple_element', - type: 58, + type: 61, typeArguments: null, }, ], @@ -86,27 +86,27 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 59, + type: 62, typeArguments: null, }, { name: '__tuple_element', - type: 50, + type: 53, typeArguments: [ { name: '', - type: 51, + type: 54, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], }, { name: '', - type: 38, + type: 39, typeArguments: null, }, ], @@ -137,22 +137,22 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -166,11 +166,11 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -189,38 +189,38 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 57, + type: 60, typeArguments: null, }, { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], @@ -234,7 +234,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 59, + type: 62, typeArguments: null, }, { @@ -249,16 +249,16 @@ export const exhaustiveExamplesAbi = { }, { name: '__tuple_element', - type: 39, + type: 40, typeArguments: null, }, { name: '__tuple_element', - type: 50, + type: 53, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, { @@ -277,11 +277,11 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 57, + type: 60, typeArguments: null, }, ], @@ -307,7 +307,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 38, + type: 39, typeArguments: null, }, ], @@ -319,7 +319,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 46, + type: 48, typeArguments: null, }, ], @@ -331,7 +331,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 49, + type: 52, typeArguments: null, }, ], @@ -343,7 +343,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 47, + type: 49, typeArguments: [ { name: '', @@ -352,7 +352,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -378,7 +378,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 57, + type: 60, typeArguments: null, }, ], @@ -402,7 +402,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 38, + type: 39, typeArguments: null, }, ], @@ -414,7 +414,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 59, + type: 62, typeArguments: null, }, ], @@ -426,11 +426,11 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 43, + type: 45, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, { @@ -498,7 +498,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'b', - type: 58, + type: 61, typeArguments: null, }, ], @@ -515,7 +515,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'VariantTwo', - type: 58, + type: 61, typeArguments: null, }, ], @@ -532,21 +532,21 @@ export const exhaustiveExamplesAbi = { }, { name: 'b', - type: 49, + type: 52, typeArguments: null, }, { name: 'c', - type: 50, + type: 53, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, { name: '', - type: 49, + type: 52, typeArguments: null, }, ], @@ -560,16 +560,16 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'num', - type: 59, + type: 62, typeArguments: null, }, { name: 'vec', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -583,7 +583,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'Foo', - type: 58, + type: 61, typeArguments: null, }, { @@ -605,7 +605,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'Foo', - type: 58, + type: 61, typeArguments: null, }, { @@ -676,24 +676,30 @@ export const exhaustiveExamplesAbi = { }, { typeId: 38, - type: 'str[3]', + type: 'raw untyped slice', components: null, typeParameters: null, }, { typeId: 39, - type: 'str[4]', + type: 'str[3]', components: null, typeParameters: null, }, { typeId: 40, - type: 'str[5]', + type: 'str[4]', components: null, typeParameters: null, }, { typeId: 41, + type: 'str[5]', + components: null, + typeParameters: null, + }, + { + typeId: 42, type: 'struct ArrWithGenericStruct', components: [ { @@ -705,7 +711,7 @@ export const exhaustiveExamplesAbi = { typeParameters: [35], }, { - typeId: 42, + typeId: 43, type: 'struct B512', components: [ { @@ -717,7 +723,24 @@ export const exhaustiveExamplesAbi = { typeParameters: null, }, { - typeId: 43, + typeId: 44, + type: 'struct Bytes', + components: [ + { + name: 'buf', + type: 50, + typeArguments: null, + }, + { + name: 'len', + type: 61, + typeArguments: null, + }, + ], + typeParameters: null, + }, + { + typeId: 45, type: 'struct MyGenericStruct', components: [ { @@ -731,7 +754,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], @@ -740,19 +763,19 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 44, + typeId: 46, type: 'struct MyOtherStruct', components: [ { name: 'bom', - type: 58, + type: 61, typeArguments: null, }, ], typeParameters: null, }, { - typeId: 45, + typeId: 47, type: 'struct MyStruct', components: [ { @@ -762,19 +785,19 @@ export const exhaustiveExamplesAbi = { }, { name: 'dummy_b', - type: 58, + type: 61, typeArguments: null, }, ], typeParameters: null, }, { - typeId: 46, + typeId: 48, type: 'struct MyStructWithEnum', components: [ { name: 'bim', - type: 38, + type: 39, typeArguments: null, }, { @@ -786,7 +809,7 @@ export const exhaustiveExamplesAbi = { typeParameters: null, }, { - typeId: 47, + typeId: 49, type: 'struct MyStructWithGeneric', components: [ { @@ -796,7 +819,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'bam', - type: 51, + type: 54, typeArguments: [ { name: '', @@ -807,7 +830,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'bom', - type: 50, + type: 53, typeArguments: [ { name: '', @@ -825,7 +848,24 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 48, + typeId: 50, + type: 'struct RawBytes', + components: [ + { + name: 'ptr', + type: 37, + typeArguments: null, + }, + { + name: 'cap', + type: 61, + typeArguments: null, + }, + ], + typeParameters: null, + }, + { + typeId: 51, type: 'struct RawVec', components: [ { @@ -835,14 +875,14 @@ export const exhaustiveExamplesAbi = { }, { name: 'cap', - type: 58, + type: 61, typeArguments: null, }, ], typeParameters: [34], }, { - typeId: 49, + typeId: 52, type: 'struct SimpleStruct', components: [ { @@ -852,14 +892,14 @@ export const exhaustiveExamplesAbi = { }, { name: 'b', - type: 57, + type: 60, typeArguments: null, }, ], typeParameters: null, }, { - typeId: 50, + typeId: 53, type: 'struct StructA', components: [ { @@ -876,7 +916,7 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 51, + typeId: 54, type: 'struct StructB', components: [ { @@ -888,7 +928,7 @@ export const exhaustiveExamplesAbi = { typeParameters: [34], }, { - typeId: 52, + typeId: 55, type: 'struct StructWithImplicitGenerics', components: [ { @@ -905,21 +945,21 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 53, + typeId: 56, type: 'struct StructWithVector', components: [ { name: 'num', - type: 59, + type: 62, typeArguments: null, }, { name: 'vec', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -928,29 +968,29 @@ export const exhaustiveExamplesAbi = { typeParameters: null, }, { - typeId: 54, + typeId: 57, type: 'struct Test', components: [ { name: 'foo', - type: 58, + type: 61, typeArguments: null, }, { name: 'bar', - type: 58, + type: 61, typeArguments: null, }, ], typeParameters: null, }, { - typeId: 55, + typeId: 58, type: 'struct Vec', components: [ { name: 'buf', - type: 48, + type: 51, typeArguments: [ { name: '', @@ -961,32 +1001,32 @@ export const exhaustiveExamplesAbi = { }, { name: 'len', - type: 58, + type: 61, typeArguments: null, }, ], typeParameters: [34], }, { - typeId: 56, + typeId: 59, type: 'u16', components: null, typeParameters: null, }, { - typeId: 57, + typeId: 60, type: 'u32', components: null, typeParameters: null, }, { - typeId: 58, + typeId: 61, type: 'u64', components: null, typeParameters: null, }, { - typeId: 59, + typeId: 62, type: 'u8', components: null, typeParameters: null, @@ -997,16 +1037,16 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'a', - type: 49, + type: 52, typeArguments: null, }, { name: 'x', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1031,7 +1071,7 @@ export const exhaustiveExamplesAbi = { name: 'array_of_structs', output: { name: '', - type: 38, + type: 39, typeArguments: null, }, attributes: null, @@ -1072,7 +1112,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 41, + type: 42, typeArguments: [ { name: '', @@ -1085,7 +1125,7 @@ export const exhaustiveExamplesAbi = { name: 'array_with_generic_struct', output: { name: '', - type: 41, + type: 42, typeArguments: [ { name: '', @@ -1116,14 +1156,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 42, + type: 43, typeArguments: null, }, ], name: 'b_512', output: { name: '', - type: 42, + type: 43, typeArguments: null, }, attributes: null, @@ -1144,11 +1184,27 @@ export const exhaustiveExamplesAbi = { }, attributes: null, }, + { + inputs: [ + { + name: 'arg', + type: 44, + typeArguments: null, + }, + ], + name: 'bytes', + output: { + name: '', + type: 44, + typeArguments: null, + }, + attributes: null, + }, { inputs: [ { name: 'arg1', - type: 43, + type: 45, typeArguments: [ { name: '', @@ -1157,7 +1213,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1174,7 +1230,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'arg4', - type: 44, + type: 46, typeArguments: null, }, ], @@ -1190,14 +1246,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 58, + type: 61, typeArguments: null, }, ], name: 'entry_one', output: { name: '', - type: 58, + type: 61, typeArguments: null, }, attributes: null, @@ -1254,19 +1310,19 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'my_u64', - type: 58, + type: 61, typeArguments: null, }, { name: 'my_struct', - type: 45, + type: 47, typeArguments: null, }, ], name: 'my_struct', output: { name: '', - type: 58, + type: 61, typeArguments: null, }, attributes: null, @@ -1279,7 +1335,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1292,13 +1348,29 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], }, attributes: null, }, + { + inputs: [ + { + name: 'arg', + type: 38, + typeArguments: null, + }, + ], + name: 'raw_slice', + output: { + name: '', + type: 38, + typeArguments: null, + }, + attributes: null, + }, { inputs: [], name: 'return_configurables', @@ -1313,11 +1385,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1326,11 +1398,11 @@ export const exhaustiveExamplesAbi = { name: 'simple_vector', output: { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1341,14 +1413,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 40, + type: 41, typeArguments: null, }, ], name: 'string', output: { name: '', - type: 40, + type: 41, typeArguments: null, }, attributes: null, @@ -1357,11 +1429,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 51, + type: 54, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1370,11 +1442,11 @@ export const exhaustiveExamplesAbi = { name: 'struct_generic_simple', output: { name: '', - type: 51, + type: 54, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1385,14 +1457,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 49, + type: 52, typeArguments: null, }, ], name: 'struct_simple', output: { name: '', - type: 49, + type: 52, typeArguments: null, }, attributes: null, @@ -1401,7 +1473,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 52, + type: 55, typeArguments: [ { name: '', @@ -1410,7 +1482,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1419,7 +1491,7 @@ export const exhaustiveExamplesAbi = { name: 'struct_with_implicitGenerics', output: { name: '', - type: 52, + type: 55, typeArguments: [ { name: '', @@ -1428,7 +1500,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1439,7 +1511,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 51, + type: 54, typeArguments: [ { name: '', @@ -1452,7 +1524,7 @@ export const exhaustiveExamplesAbi = { name: 'struct_with_tuple', output: { name: '', - type: 51, + type: 54, typeArguments: [ { name: '', @@ -1467,19 +1539,19 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'a', - type: 58, + type: 61, typeArguments: null, }, { name: 'b', - type: 58, + type: 61, typeArguments: null, }, ], name: 'sum', output: { name: '', - type: 58, + type: 61, typeArguments: null, }, attributes: null, @@ -1488,14 +1560,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'test', - type: 54, + type: 57, typeArguments: null, }, ], name: 'sum_test', output: { name: '', - type: 58, + type: 61, typeArguments: null, }, attributes: null, @@ -1583,22 +1655,22 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], }, { name: 'y', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1616,38 +1688,38 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 57, + type: 60, typeArguments: null, }, { name: 'y', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], }, { name: 'z', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], }, { name: 'q', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 58, + type: 61, typeArguments: null, }, ], @@ -1665,14 +1737,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 56, + type: 59, typeArguments: null, }, ], name: 'u_16', output: { name: '', - type: 56, + type: 59, typeArguments: null, }, attributes: null, @@ -1681,14 +1753,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 57, + type: 60, typeArguments: null, }, ], name: 'u_32', output: { name: '', - type: 57, + type: 60, typeArguments: null, }, attributes: null, @@ -1697,14 +1769,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 58, + type: 61, typeArguments: null, }, ], name: 'u_64', output: { name: '', - type: 58, + type: 61, typeArguments: null, }, attributes: null, @@ -1713,14 +1785,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 59, + type: 62, typeArguments: null, }, ], name: 'u_8', output: { name: '', - type: 59, + type: 62, typeArguments: null, }, attributes: null, @@ -1729,7 +1801,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 55, + type: 58, typeArguments: [ { name: '', @@ -1742,7 +1814,7 @@ export const exhaustiveExamplesAbi = { name: 'vector_boolean', output: { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', @@ -1789,14 +1861,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 53, + type: 56, typeArguments: null, }, ], name: 'vector_inside_struct', output: { name: '', - type: 53, + type: 56, typeArguments: null, }, attributes: null, @@ -1805,15 +1877,15 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 57, + type: 60, typeArguments: null, }, ], @@ -1824,15 +1896,15 @@ export const exhaustiveExamplesAbi = { name: 'vector_inside_vector', output: { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 57, + type: 60, typeArguments: null, }, ], @@ -1845,11 +1917,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1858,11 +1930,11 @@ export const exhaustiveExamplesAbi = { name: 'vector_u8', output: { name: '', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1873,11 +1945,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 55, + type: 58, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, ], @@ -1904,10 +1976,10 @@ export const exhaustiveExamplesAbi = { name: 'U8', configurableType: { name: '', - type: 59, + type: 62, typeArguments: null, }, - offset: 1432, + offset: 1488, }, { name: 'BOOL', @@ -1916,7 +1988,7 @@ export const exhaustiveExamplesAbi = { type: 24, typeArguments: null, }, - offset: 1440, + offset: 1496, }, { name: 'ARRAY', @@ -1925,26 +1997,26 @@ export const exhaustiveExamplesAbi = { type: 18, typeArguments: null, }, - offset: 1448, + offset: 1504, }, { name: 'STR_4', configurableType: { name: '', - type: 39, + type: 40, typeArguments: null, }, - offset: 1472, + offset: 1528, }, { name: 'STRUCT', configurableType: { name: '', - type: 50, + type: 53, typeArguments: [ { name: '', - type: 59, + type: 62, typeArguments: null, }, { @@ -1954,7 +2026,7 @@ export const exhaustiveExamplesAbi = { }, ], }, - offset: 1480, + offset: 1536, }, ], } as const; diff --git a/packages/abi-coder/test/interface.test.ts b/packages/abi-coder/test/interface.test.ts index fb48ccb5e1e..a0d0804806b 100644 --- a/packages/abi-coder/test/interface.test.ts +++ b/packages/abi-coder/test/interface.test.ts @@ -289,6 +289,28 @@ describe('Abi interface', () => { value: { arr: [B256_DECODED, B256_DECODED, B256_DECODED], tuple: [B256_DECODED, U8_MAX] }, encodedValue: [B256_ENCODED, B256_ENCODED, B256_ENCODED, B256_ENCODED, U8_MAX_ENCODED], }, + { + fn: exhaustiveExamplesInterface.functions.bytes, + title: '[struct Bytes]', + value: [[1, 2, 3]], + encodedValue: new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3, + ]), + decodedTransformer: (decoded: unknown | undefined) => Array.from(decoded as Uint8Array), + }, + { + fn: exhaustiveExamplesInterface.functions.raw_slice, + title: '[raw_slice]', + value: [[1, 2, 3]], + encodedValue: new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, + ]), + decodedTransformer: (decoded: unknown | undefined) => { + const data = (decoded as BN[]).slice(2); + return data.map((v: BN) => v.toNumber()); + }, + }, { fn: exhaustiveExamplesInterface.functions.tuple_as_param, title: '[tuple] as param', diff --git a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw index 44f46d5525e..3482c981d62 100644 --- a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw +++ b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw @@ -1,5 +1,6 @@ contract; use std::b512::B512; +use std::bytes::Bytes; enum EnumWithGeneric{ VariantOne: T, @@ -134,6 +135,8 @@ abi MyContract { fn struct_generic_simple(x: StructB) -> StructB; fn struct_with_tuple(x: StructB<(bool, u64)>) -> StructB<(bool, u64)>; fn struct_with_implicitGenerics(arg: StructWithImplicitGenerics) -> StructWithImplicitGenerics; + fn bytes(arg: Bytes) -> Bytes; + fn raw_slice(arg: raw_slice) -> raw_slice; fn tuple_as_param(x: (u8, StructA, str[3]>)) -> (u8, StructA, str[3]>); fn array_simple(x: [u8; 4]) -> [u8; 4]; @@ -200,6 +203,8 @@ impl MyContract for Contract { fn arg_then_vector_u8(a: SimpleStruct, x: Vec) -> (SimpleStruct, Vec) {(a, x)} fn vector_u8_then_arg(x: Vec, y: b256) -> (Vec, b256) {(x, y)} fn struct_with_implicitGenerics(arg: StructWithImplicitGenerics) -> StructWithImplicitGenerics {arg} + fn bytes(arg: Bytes) -> Bytes { arg } + fn raw_slice(arg: raw_slice) -> raw_slice { arg } fn two_u8_vectors(x: Vec, y: Vec) -> (Vec, Vec) {(x, y)} fn u32_then_three_vectors_u64(x: u32, y: Vec, z: Vec, q: Vec) -> (u32, Vec, Vec, Vec) {(x, y, z, q)} From 6fd2a23bb8ed808e1d36765e9fccc4e70a8fedc7 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 15:30:06 -0700 Subject: [PATCH 11/55] refactor --- packages/abi-coder/src/coders/byte.test.ts | 18 ++++++++++++++++-- packages/abi-coder/src/coders/byte.ts | 22 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/abi-coder/src/coders/byte.test.ts b/packages/abi-coder/src/coders/byte.test.ts index bbedba51ced..17c53bbc318 100644 --- a/packages/abi-coder/src/coders/byte.test.ts +++ b/packages/abi-coder/src/coders/byte.test.ts @@ -6,10 +6,10 @@ describe('ByteCoder', () => { it('should encode a byte', () => { const coder = new ByteCoder(); const expected: Uint8ArrayWithDynamicData = new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, ]); expected.dynamicData = { - 0: new Uint8Array([1, 2, 3]), + 0: new Uint8Array([1, 2, 3, 0, 0, 0, 0, 0]), }; const actual = coder.encode([1, 2, 3]); @@ -17,6 +17,20 @@ describe('ByteCoder', () => { expect(actual).toStrictEqual(expected); }); + it('should encode a byte [full word]', () => { + const coder = new ByteCoder(); + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, + ]); + expected.dynamicData = { + 0: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]), + }; + + const actual = coder.encode([1, 2, 3, 4, 5, 6, 7, 8]); + + expect(actual).toStrictEqual(expected); + }); + it('should decode a byte', () => { const coder = new ByteCoder(); const input = new Uint8Array([ diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index 73b4c3f5335..2975a022182 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -1,6 +1,7 @@ -import type { BytesLike } from '@ethersproject/bytes'; +import { arrayify, concat, type BytesLike } from '@ethersproject/bytes'; import { bn } from '@fuel-ts/math'; +import { WORD_SIZE } from '../constants'; import type { Uint8ArrayWithDynamicData } from '../utilities'; import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; @@ -23,15 +24,17 @@ export class ByteCoder extends Coder { // pointer (ptr) const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); - // pointer dynamicData, encode the vector now and attach to its pointer + + // pointer dynamicData, encode the byte vector now and attach to its pointer + const data = this.#getPaddedData(value); pointer.dynamicData = { - 0: concatWithDynamicData(value as unknown as BytesLike[]), + 0: concatWithDynamicData([data]), }; parts.push(pointer); // capacity (cap) - parts.push(new U64Coder().encode(value.length)); + parts.push(new U64Coder().encode(data.byteLength)); // length (len) parts.push(new U64Coder().encode(value.length)); @@ -39,6 +42,17 @@ export class ByteCoder extends Coder { return concatWithDynamicData(parts); } + #getPaddedData(value: number[]): Uint8Array { + const data: Uint8Array[] = [arrayify(value)]; + + const paddingLength = (WORD_SIZE - (value.length % WORD_SIZE)) % WORD_SIZE; + if (paddingLength) { + data.push(new Uint8Array(paddingLength)); + } + + return concat(data); + } + decode(data: Uint8Array, offset: number): [Uint8Array, number] { const len = data.slice(16, 24); const length = bn(new U64Coder().decode(len, 0)[0]).toNumber(); From a74e36bf7d6003079609fefb0baff9d236945b1f Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 15:34:25 -0700 Subject: [PATCH 12/55] adjust --- .../fixtures/forc-projects/bytes/src/main.sw | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw index fd91c5e4353..93b4a6fda7e 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw +++ b/packages/fuel-gauge/fixtures/forc-projects/bytes/src/main.sw @@ -2,6 +2,7 @@ contract; use std::bytes::Bytes; +#[allow(dead_code)] enum SomeEnum { First: bool, Second: T, @@ -15,9 +16,9 @@ struct Wrapper { fn expected_bytes() -> Bytes { let mut bytes = Bytes::new(); - bytes.push(40); - bytes.push(41); - bytes.push(42); + bytes.push(40u8); + bytes.push(41u8); + bytes.push(42u8); bytes } @@ -35,7 +36,10 @@ impl MyContract for Contract { fn accept_nested_bytes(wrapper: Wrapper>) { if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum { - require(enum_bytes == expected_bytes(), "wrapper.inner_enum didn't carry the expected bytes"); + let exp = expected_bytes(); + require(enum_bytes.get(0).unwrap() == exp.get(0).unwrap(), "wrapper.inner_enum 0 didnt match"); + require(enum_bytes.get(1).unwrap() == exp.get(1).unwrap(), "wrapper.inner_enum 1 didnt match"); + require(enum_bytes.get(2).unwrap() == exp.get(2).unwrap(), "wrapper.inner_enum 2 didnt match"); } else { require(false, "enum was not of variant Second"); } From c7bf84237548075f33501c6f78fac5bb77b2a3e9 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 15:35:44 -0700 Subject: [PATCH 13/55] adjust --- .../fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw index 7ad5be05780..7ea541fc69c 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw +++ b/packages/fuel-gauge/fixtures/forc-projects/raw-slice/src/main.sw @@ -1,5 +1,6 @@ contract; +#[allow(dead_code)] enum SomeEnum { First: bool, Second: T, @@ -55,4 +56,4 @@ impl RawSliceContract for Contract { validate_vec(wrapper.inner); } -} \ No newline at end of file +} From f6b5ce74e2002a027312d0a73281b808510541df Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 16:01:28 -0700 Subject: [PATCH 14/55] fix length --- packages/abi-coder/src/coders/raw-slice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts index 8ee151465b5..daccd5727e1 100644 --- a/packages/abi-coder/src/coders/raw-slice.ts +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -10,7 +10,7 @@ import { U64Coder } from './u64'; export class RawSliceCoder extends Coder { constructor() { - super('struct', 'struct Bytes', 1); + super('struct', 'struct Bytes', BASE_RAW_SLICE_OFFSET); } encode(value: number[]): Uint8Array { From 929b74753792652407579476b0a0479a808161d8 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 16:26:54 -0700 Subject: [PATCH 15/55] correct reference --- packages/abi-coder/src/coders/byte.ts | 5 ++--- packages/abi-coder/src/function-fragment.ts | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index 2975a022182..ae37ad536bf 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -8,11 +8,10 @@ import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; import { Coder } from './abstract-coder'; import { U64Coder } from './u64'; -const MEMORY_SIZE_OF_U8 = 1; - export class ByteCoder extends Coder { + static memorySize = 1; constructor() { - super('struct', 'struct Bytes', MEMORY_SIZE_OF_U8); + super('struct', 'struct Bytes', BASE_VECTOR_OFFSET); } encode(value: number[]): Uint8Array { diff --git a/packages/abi-coder/src/function-fragment.ts b/packages/abi-coder/src/function-fragment.ts index 94851a52b1c..364d6a3deca 100644 --- a/packages/abi-coder/src/function-fragment.ts +++ b/packages/abi-coder/src/function-fragment.ts @@ -9,6 +9,7 @@ import { versions } from '@fuel-ts/versions'; import { AbiCoder } from './abi-coder'; import type { DecodedValue, InputValue } from './coders/abstract-coder'; import type { ArrayCoder } from './coders/array'; +import { ByteCoder } from './coders/byte'; import { TupleCoder } from './coders/tuple'; import type { U64Coder } from './coders/u64'; import { VecCoder } from './coders/vec'; @@ -90,6 +91,9 @@ export class FunctionFragment< if (heapCoder instanceof VecCoder) { return heapCoder.coder.encodedLength; } + if (heapCoder instanceof ByteCoder) { + return ByteCoder.memorySize; + } return heapCoder.encodedLength; } catch (e) { From 00dddc8933d97e069345c084dded52355d7fa921 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 21:30:52 -0700 Subject: [PATCH 16/55] refactor --- packages/abi-coder/src/coders/raw-slice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts index daccd5727e1..4e915aae8de 100644 --- a/packages/abi-coder/src/coders/raw-slice.ts +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -10,7 +10,7 @@ import { U64Coder } from './u64'; export class RawSliceCoder extends Coder { constructor() { - super('struct', 'struct Bytes', BASE_RAW_SLICE_OFFSET); + super('raw untyped slice', 'raw untyped slice', BASE_RAW_SLICE_OFFSET); } encode(value: number[]): Uint8Array { From c000caf3cb1682462bfa760c26f092c054a09a51 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 21:46:04 -0700 Subject: [PATCH 17/55] twenty eagles lick? --- .changeset/twenty-eagles-lick.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twenty-eagles-lick.md diff --git a/.changeset/twenty-eagles-lick.md b/.changeset/twenty-eagles-lick.md new file mode 100644 index 00000000000..56d8eb9bf91 --- /dev/null +++ b/.changeset/twenty-eagles-lick.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/abi-coder": minor +--- + +Add support for Bytes and RawSlice From 408426f33d21749d1338ed7961ed3d59f86f3cb6 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 30 Aug 2023 22:04:13 -0700 Subject: [PATCH 18/55] adjust --- packages/abi-coder/test/interface.test.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/abi-coder/test/interface.test.ts b/packages/abi-coder/test/interface.test.ts index a0d0804806b..b6fe071a986 100644 --- a/packages/abi-coder/test/interface.test.ts +++ b/packages/abi-coder/test/interface.test.ts @@ -294,9 +294,14 @@ describe('Abi interface', () => { title: '[struct Bytes]', value: [[1, 2, 3]], encodedValue: new Uint8Array([ - 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3, 0, 0, + 0, 0, 0, ]), - decodedTransformer: (decoded: unknown | undefined) => Array.from(decoded as Uint8Array), + decodedTransformer: (decoded: unknown | undefined) => { + const data = (decoded as BN[]).slice(0, 3); + return Array.from(data); + }, + decodedTransfoarmer: (decoded: unknown | undefined) => Array.from(decoded as Uint8Array), }, { fn: exhaustiveExamplesInterface.functions.raw_slice, From 37b1ae9b6e5b6bc6fa9fecf3b36b739449419255 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Tue, 19 Sep 2023 22:05:41 -0700 Subject: [PATCH 19/55] fix post rename --- packages/abi-coder/src/abi-coder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/abi-coder/src/abi-coder.ts b/packages/abi-coder/src/abi-coder.ts index 254b3ba4b49..e79bf466ba3 100644 --- a/packages/abi-coder/src/abi-coder.ts +++ b/packages/abi-coder/src/abi-coder.ts @@ -26,7 +26,7 @@ import { tupleRegEx, OPTION_CODER_TYPE, VEC_CODER_TYPE, - BYTE_CODER_TYPE, + BYTES_CODER_TYPE, } from './constants'; import type { JsonAbi, JsonAbiArgument } from './json-abi'; import { ResolvedAbiType } from './resolved-abi-type'; @@ -70,7 +70,7 @@ export abstract class AbiCoder { return new B256Coder(); case 'struct B512': return new B512Coder(); - case BYTE_CODER_TYPE: + case BYTES_CODER_TYPE: return new ByteCoder(); default: break; From 3f0ef12153b6a0a1ecc82cb583c43ab365134a7d Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Tue, 19 Sep 2023 22:32:19 -0700 Subject: [PATCH 20/55] catch magic revert number --- packages/program/src/utils.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/program/src/utils.ts b/packages/program/src/utils.ts index 0b527f38e22..8151f28017b 100644 --- a/packages/program/src/utils.ts +++ b/packages/program/src/utils.ts @@ -6,8 +6,13 @@ import { PANIC_REASONS, PANIC_DOC_URL } from './configs'; /** * @hidden */ -const getFailureReason = (reason: string): string => - PANIC_REASONS.includes(reason) ? reason : 'unknown'; +const getFailureReason = (reason: string): string => { + if (PANIC_REASONS.includes(reason)) { + return reason; + } + + return reason === 'Revert(123)' ? 'MismatchedSelector' : 'unknown'; +}; /** * @hidden From b52511547bf86cf51ae73b20d62fa685ff8e1bff Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:07:20 -0700 Subject: [PATCH 21/55] fix mapper --- packages/abi-coder/src/resolved-abi-type.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/abi-coder/src/resolved-abi-type.ts b/packages/abi-coder/src/resolved-abi-type.ts index c0de96901b4..8074e8d775f 100644 --- a/packages/abi-coder/src/resolved-abi-type.ts +++ b/packages/abi-coder/src/resolved-abi-type.ts @@ -152,6 +152,10 @@ export class ResolvedAbiType { return 'rawptr'; } + if (this.type === 'raw untyped slice') { + return 'rawslice'; + } + const strMatch = stringRegEx.exec(this.type)?.groups; if (strMatch) { return `str[${strMatch.length}]`; From 95d898331f3c2a6a4ed954e601d2c638e5f6b038 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:21:03 -0700 Subject: [PATCH 22/55] add sway projects --- .../fixtures/forc-projects/Forc.toml | 2 + .../forc-projects/predicate-bytes/Forc.toml | 7 +++ .../forc-projects/predicate-bytes/src/main.sw | 44 +++++++++++++++++++ .../predicate-raw-slice/Forc.toml | 7 +++ .../predicate-raw-slice/src/main.sw | 30 +++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 4d012ebfe2d..12e6d0f573a 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -15,11 +15,13 @@ members = [ "multi-token-contract", "payable-annotation", "predicate-address", + "predicate-bytes", "predicate-conditional-inputs", "predicate-false", "predicate-main-args-struct", "predicate-main-args-vector", "predicate-multi-args", + "predicate-raw-slice", "predicate-struct", "predicate-triple-sig", "predicate-true", diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml new file mode 100644 index 00000000000..5a88bab0ec6 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate-bytes" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw new file mode 100644 index 00000000000..c795f0eab5f --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-bytes/src/main.sw @@ -0,0 +1,44 @@ +predicate; + +use std::bytes::Bytes; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn expected_bytes() -> Bytes { + let mut bytes = Bytes::new(); + + bytes.push(40u8); + bytes.push(41u8); + bytes.push(42u8); + + bytes +} + +fn valid_bytes(bytes: Bytes) -> bool { + bytes == expected_bytes() +} + +fn valid_vec(arg: Vec) -> bool { + if arg.len() != 2 { + return false; + } + + valid_bytes(arg.get(0).unwrap()) && valid_bytes(arg.get(1).unwrap()) +} + +fn main(wrapper: Wrapper>) -> bool { + if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum { + valid_bytes(enum_bytes) && valid_vec(wrapper.inner) + } else { + false + } +} diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml new file mode 100644 index 00000000000..979cb682cd2 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate-raw-slice" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw new file mode 100644 index 00000000000..19ba59de2ca --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-raw-slice/src/main.sw @@ -0,0 +1,30 @@ +predicate; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn valid_raw_slice(slice: raw_slice) -> bool { + let vec: Vec = Vec::from(slice); + vec.len() == 3 && vec.get(0).unwrap() == 40 && vec.get(1).unwrap() == 41 && vec.get(2).unwrap() == 42 +} + +fn valid_vec(vec: Vec) -> bool { + vec.len() == 2 && valid_raw_slice(vec.get(0).unwrap()) && valid_raw_slice(vec.get(1).unwrap()) +} + +fn main(wrapper: Wrapper>) -> bool { + if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum + { + valid_raw_slice(enum_raw_slice) && valid_vec(wrapper.inner) + } else { + false + } +} From d52848bf7da42c9960399ea79a6341b70ceab129 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:36:07 -0700 Subject: [PATCH 23/55] add predicate bytes test --- packages/fuel-gauge/src/bytes.test.ts | 63 ++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 600c50c0b6a..4d8478da53c 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -1,4 +1,17 @@ -import { type Contract } from 'fuels'; +import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; +import { + type Contract, + bn, + Predicate, + Wallet, + Address, + BaseAssetId, + Provider, + FUEL_NETWORK_URL, +} from 'fuels'; + +import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; +import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; import { getSetupContract } from './utils'; @@ -8,6 +21,16 @@ beforeAll(async () => { contractInstance = await setupContract(); }); +type SomeEnum = { + First?: boolean; + Second?: number[]; +}; + +type Wrapper = { + inner: number[][]; + inner_enum: SomeEnum; +}; + describe('Bytes Tests', () => { it('should test bytes output', async () => { const INPUT = 10; @@ -35,7 +58,7 @@ describe('Bytes Tests', () => { it('should test bytes input [nested]', async () => { const bytes = [40, 41, 42]; - const INPUT = { + const INPUT: Wrapper = { inner: [bytes, bytes], inner_enum: { Second: bytes }, }; @@ -44,4 +67,40 @@ describe('Bytes Tests', () => { expect(true).toBeTruthy(); }); + + it('should test bytes input [predicate-bytes]', async () => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); + const amountToPredicate = 100; + const amountToReceiver = 50; + type MainArgs = [Wrapper]; + const predicate = new Predicate(predicateBytes, wallet.provider, predicateBytesAbi); + + // setup predicate + const setupTx = await wallet.transfer(predicate.address, amountToPredicate, BaseAssetId); + await setupTx.waitForResult(); + + const initialPredicateBalance = await predicate.getBalance(); + const initialReceiverBalance = await receiver.getBalance(); + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + const tx = await predicate.setData(INPUT).transfer(receiver.address, amountToReceiver); + await tx.waitForResult(); + + // Check the balance of the receiver + const finalReceiverBalance = await receiver.getBalance(); + expect(bn(initialReceiverBalance).add(amountToReceiver).toHex()).toEqual( + finalReceiverBalance.toHex() + ); + + // Check we spent the entire predicate hash input + const finalPredicateBalance = await predicate.getBalance(); + expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); + }); }); From 132bf46c2900ccbd86ebbd115c1fd5763d14200c Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:38:38 -0700 Subject: [PATCH 24/55] add predicate raw slice tests --- packages/fuel-gauge/src/raw-slice.test.ts | 65 ++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index fa9411e2135..5dd90573654 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -1,8 +1,31 @@ +import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; import type { BN } from 'fuels'; -import { type Contract } from 'fuels'; +import { + type Contract, + bn, + Predicate, + Wallet, + Address, + BaseAssetId, + Provider, + FUEL_NETWORK_URL, +} from 'fuels'; + +import predicateRawSlice from '../fixtures/forc-projects/predicate-raw-slice'; +import predicateRawSliceAbi from '../fixtures/forc-projects/predicate-raw-slice/out/debug/predicate-raw-slice-abi.json'; import { getSetupContract } from './utils'; +type SomeEnum = { + First?: boolean; + Second?: number[]; +}; + +type Wrapper = { + inner: number[][]; + inner_enum: SomeEnum; +}; + const setupContract = getSetupContract('raw-slice'); let contractInstance: Contract; beforeAll(async () => { @@ -37,4 +60,44 @@ describe('Raw Slice Tests', () => { expect(true).toBeTruthy(); }); + + it('should test raw slice input [predicate-raw slice]', async () => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); + const amountToPredicate = 100; + const amountToReceiver = 50; + type MainArgs = [Wrapper]; + const predicate = new Predicate( + predicateRawSlice, + wallet.provider, + predicateRawSliceAbi + ); + + // setup predicate + const setupTx = await wallet.transfer(predicate.address, amountToPredicate, BaseAssetId); + await setupTx.waitForResult(); + + const initialPredicateBalance = await predicate.getBalance(); + const initialReceiverBalance = await receiver.getBalance(); + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + const tx = await predicate.setData(INPUT).transfer(receiver.address, amountToReceiver); + await tx.waitForResult(); + + // Check the balance of the receiver + const finalReceiverBalance = await receiver.getBalance(); + expect(bn(initialReceiverBalance).add(amountToReceiver).toHex()).toEqual( + finalReceiverBalance.toHex() + ); + + // Check we spent the entire predicate hash input + const finalPredicateBalance = await predicate.getBalance(); + expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); + }); }); From 2f7cc22438c56dc451118ce459c8c4dbd31a213e Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:45:50 -0700 Subject: [PATCH 25/55] add bytes and raw slice sway projects --- .../fixtures/forc-projects/Forc.toml | 2 + .../forc-projects/script-bytes/Forc.toml | 7 +++ .../forc-projects/script-bytes/src/main.sw | 37 ++++++++++++++++ .../forc-projects/script-raw-slice/Forc.toml | 7 +++ .../script-raw-slice/src/main.sw | 44 +++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-bytes/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-bytes/src/main.sw create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/src/main.sw diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 12e6d0f573a..554cc97f7b4 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -30,9 +30,11 @@ members = [ "predicate-vector-types", "raw-slice", "revert-error", + "script-bytes", "script-main-args", "script-main-return-struct", "script-main-two-args", + "script-raw-slice", "script-with-configurable", "script-with-array", "script-with-vector", diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-bytes/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/script-bytes/Forc.toml new file mode 100644 index 00000000000..4bc8df07fff --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-bytes/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "script-bytes" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-bytes/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/script-bytes/src/main.sw new file mode 100644 index 00000000000..17870256bd2 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-bytes/src/main.sw @@ -0,0 +1,37 @@ +script; + +use std::bytes::Bytes; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn expected_bytes() -> Bytes { + let mut bytes = Bytes::new(); + + bytes.push(40u8); + bytes.push(41u8); + bytes.push(42u8); + + bytes +} + +fn main(_arg: u64, wrapper: Wrapper>) { + if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum { + require(enum_bytes == expected_bytes(), "wrapper.inner_enum didn't carry the expected bytes") + } else { + require(false, "enum was not of variant Second"); + } + + let inner_vec = wrapper.inner; + require(inner_vec.len() == 2, "Expected wrapper.inner vector to have 2 elements"); + require(inner_vec.get(0).unwrap() == expected_bytes(), "wrapper.inner[0] didn't match expectation"); + require(inner_vec.get(1).unwrap() == expected_bytes(), "wrapper.inner[1] didn't match expectation"); +} diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/Forc.toml new file mode 100644 index 00000000000..2016d018aba --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "script-raw-slice" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/src/main.sw new file mode 100644 index 00000000000..255b412872b --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-raw-slice/src/main.sw @@ -0,0 +1,44 @@ +script; + +#[allow(dead_code)] +enum SomeEnum { + First: bool, + Second: T, +} + +struct Wrapper { + inner: T, + inner_enum: SomeEnum, +} + +fn validate_raw_slice(input: raw_slice) { + let vec: Vec = Vec::from(input); + require(vec.len() == 3, "raw slice len is not 3"); + require(vec.get(2).unwrap() == 42, "expected 3rd slice entry to be 42"); + require(vec.get(1).unwrap() == 41, "expected 2nd slice entry to be 41"); + require(vec.get(0).unwrap() == 40, "expected 1st slice entry to be 40"); +} + +fn validate_vec(vec: Vec) { + require(vec.len() == 2, "vec should have two elements"); + validate_raw_slice(vec.get(0).unwrap()); + validate_raw_slice(vec.get(1).unwrap()); +} + +fn main(_arg: u64, wrapper: Wrapper>) -> raw_slice { + if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum + { + validate_raw_slice(enum_raw_slice); + } else { + require(false, "enum was not of variant Second"); + } + + validate_vec(wrapper.inner); + + let mut rtn: Vec = Vec::new(); + rtn.push(1); + rtn.push(2); + rtn.push(3); + + rtn.as_raw_slice() +} From 57e3bc5e02f0a18e64b88fd5d87ed1329aca868f Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:50:53 -0700 Subject: [PATCH 26/55] add bytes test for script --- packages/fuel-gauge/src/bytes.test.ts | 31 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 4d8478da53c..f861008b45c 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -13,7 +13,7 @@ import { import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; -import { getSetupContract } from './utils'; +import { getScript, getSetupContract } from './utils'; const setupContract = getSetupContract('bytes'); let contractInstance: Contract; @@ -31,6 +31,15 @@ type Wrapper = { inner_enum: SomeEnum; }; +const setup = async (balance = 5_000) => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[balance, BaseAssetId]]); + + return wallet; +}; + describe('Bytes Tests', () => { it('should test bytes output', async () => { const INPUT = 10; @@ -69,10 +78,7 @@ describe('Bytes Tests', () => { }); it('should test bytes input [predicate-bytes]', async () => { - const provider = await Provider.create(FUEL_NETWORK_URL); - - // Create wallet - const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + const wallet = await setup(); const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); const amountToPredicate = 100; const amountToReceiver = 50; @@ -103,4 +109,19 @@ describe('Bytes Tests', () => { const finalPredicateBalance = await predicate.getBalance(); expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); }); + + it('should test bytes input [script-bytes]', async () => { + const wallet = await setup(); + type MainArgs = [number, Wrapper]; + const scriptInstance = getScript('script-bytes', wallet); + + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + await scriptInstance.functions.main(1, INPUT).call(); + + expect(true).toBe(true); + }); }); From 2fd8c1d583d6a27abd0bd33382e2c84ff28734f9 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 22:52:37 -0700 Subject: [PATCH 27/55] add test for raw slice in script input --- packages/fuel-gauge/src/raw-slice.test.ts | 33 ++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index 5dd90573654..05ea882cb41 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -14,7 +14,7 @@ import { import predicateRawSlice from '../fixtures/forc-projects/predicate-raw-slice'; import predicateRawSliceAbi from '../fixtures/forc-projects/predicate-raw-slice/out/debug/predicate-raw-slice-abi.json'; -import { getSetupContract } from './utils'; +import { getScript, getSetupContract } from './utils'; type SomeEnum = { First?: boolean; @@ -26,6 +26,15 @@ type Wrapper = { inner_enum: SomeEnum; }; +const setup = async (balance = 5_000) => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[balance, BaseAssetId]]); + + return wallet; +}; + const setupContract = getSetupContract('raw-slice'); let contractInstance: Contract; beforeAll(async () => { @@ -61,11 +70,8 @@ describe('Raw Slice Tests', () => { expect(true).toBeTruthy(); }); - it('should test raw slice input [predicate-raw slice]', async () => { - const provider = await Provider.create(FUEL_NETWORK_URL); - - // Create wallet - const wallet = await generateTestWallet(provider, [[5_000, BaseAssetId]]); + it('should test raw slice input [predicate-raw-slice]', async () => { + const wallet = await setup(); const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); const amountToPredicate = 100; const amountToReceiver = 50; @@ -100,4 +106,19 @@ describe('Raw Slice Tests', () => { const finalPredicateBalance = await predicate.getBalance(); expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); }); + + it('should test bytes input [script-raw-slice]', async () => { + const wallet = await setup(); + type MainArgs = [number, Wrapper]; + const scriptInstance = getScript('script-raw-slice', wallet); + + const bytes = [40, 41, 42]; + const INPUT: Wrapper = { + inner: [bytes, bytes], + inner_enum: { Second: bytes }, + }; + await scriptInstance.functions.main(1, INPUT).call(); + + expect(true).toBe(true); + }); }); From 38a38514994be65f880aecab5190f70a193544bb Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 23:13:25 -0700 Subject: [PATCH 28/55] add sway files --- .../fixtures/forc-projects/Forc.toml | 1 + .../forc-projects/std-lib-string/Forc.toml | 7 ++++ .../forc-projects/std-lib-string/src/main.sw | 37 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 packages/fuel-gauge/fixtures/forc-projects/std-lib-string/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/std-lib-string/src/main.sw diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 554cc97f7b4..204e0997e01 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -40,6 +40,7 @@ members = [ "script-with-vector", "script-with-vector-advanced", "script-with-vector-mixed", + "std-lib-string", "storage-test-contract", "token_abi", "token_contract", diff --git a/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/Forc.toml new file mode 100644 index 00000000000..ce43706b3b0 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "std-lib-string" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/src/main.sw new file mode 100644 index 00000000000..ff1cb333a38 --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/std-lib-string/src/main.sw @@ -0,0 +1,37 @@ +contract; + +use std::string::String; +use std::assert::assert_eq; +use std::bytes::Bytes; + +abi MyContract { + fn return_dynamic_string() -> String; + fn accepts_dynamic_string(s: String); +} + +fn validate_string(arg: String) { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + assert_eq(expected_bytes.len(), bytes.len()); + + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i += 1; + } +} + +impl MyContract for Contract { + fn return_dynamic_string() -> String { + String::from_ascii_str("Hello World") + } + + fn accepts_dynamic_string(s: String) { + validate_string(s); + } +} From 8c4020d230bec2f1335373a80c5dbc43484d947a Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 23:14:04 -0700 Subject: [PATCH 29/55] add basic tests --- .../fuel-gauge/src/std-lib-string.test.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/fuel-gauge/src/std-lib-string.test.ts diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts new file mode 100644 index 00000000000..25416b8f1ba --- /dev/null +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -0,0 +1,25 @@ +import { type Contract } from 'fuels'; + +import { getSetupContract } from './utils'; + +const setupContract = getSetupContract('std-lib-string'); +let contractInstance: Contract; +beforeAll(async () => { + contractInstance = await setupContract(); +}); + +describe('std-lib-string Tests', () => { + it('should test std-lib-string return', async () => { + const { value } = await contractInstance.functions.return_dynamic_string().call(); + + expect(value).toStrictEqual('Hello World'); + }); + + it('should test std-lib-string input', async () => { + const INPUT = 'Hello World'; + + await contractInstance.functions.accepts_dynamic_string(INPUT).call(); + + expect(true).toStrictEqual(true); + }); +}); From 6572006b6934d013b918bb8bc0de7255b99c8526 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 23:23:53 -0700 Subject: [PATCH 30/55] setup string Struct --- packages/abi-coder/src/abi-coder.ts | 4 ++++ packages/abi-coder/src/constants.ts | 1 + packages/abi-coder/src/utilities.ts | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/abi-coder/src/abi-coder.ts b/packages/abi-coder/src/abi-coder.ts index e79bf466ba3..cc5070388c5 100644 --- a/packages/abi-coder/src/abi-coder.ts +++ b/packages/abi-coder/src/abi-coder.ts @@ -13,6 +13,7 @@ import { EnumCoder } from './coders/enum'; import { NumberCoder } from './coders/number'; import { OptionCoder } from './coders/option'; import { RawSliceCoder } from './coders/raw-slice'; +import { StdStringCoder } from './coders/stdString'; import { StringCoder } from './coders/string'; import { StructCoder } from './coders/struct'; import { TupleCoder } from './coders/tuple'; @@ -27,6 +28,7 @@ import { OPTION_CODER_TYPE, VEC_CODER_TYPE, BYTES_CODER_TYPE, + STRING_CODER_TYPE, } from './constants'; import type { JsonAbi, JsonAbiArgument } from './json-abi'; import { ResolvedAbiType } from './resolved-abi-type'; @@ -72,6 +74,8 @@ export abstract class AbiCoder { return new B512Coder(); case BYTES_CODER_TYPE: return new ByteCoder(); + case STRING_CODER_TYPE: + return new StdStringCoder(); default: break; } diff --git a/packages/abi-coder/src/constants.ts b/packages/abi-coder/src/constants.ts index 70906ea229a..e46233c610c 100644 --- a/packages/abi-coder/src/constants.ts +++ b/packages/abi-coder/src/constants.ts @@ -1,6 +1,7 @@ export const OPTION_CODER_TYPE = 'enum Option'; export const VEC_CODER_TYPE = 'struct Vec'; export const BYTES_CODER_TYPE = 'struct Bytes'; +export const STRING_CODER_TYPE = 'struct String'; export const stringRegEx = /str\[(?[0-9]+)\]/; export const arrayRegEx = /\[(?[\w\s\\[\]]+);\s*(?[0-9]+)\]/; export const structRegEx = /^struct (?\w+)$/; diff --git a/packages/abi-coder/src/utilities.ts b/packages/abi-coder/src/utilities.ts index 780ff022884..ddc06d91963 100644 --- a/packages/abi-coder/src/utilities.ts +++ b/packages/abi-coder/src/utilities.ts @@ -3,7 +3,7 @@ import { concat, arrayify } from '@ethersproject/bytes'; import { ErrorCode, FuelError } from '@fuel-ts/errors'; import { U64Coder } from './coders/u64'; -import { BYTES_CODER_TYPE, VEC_CODER_TYPE, WORD_SIZE } from './constants'; +import { BYTES_CODER_TYPE, VEC_CODER_TYPE, STRING_CODER_TYPE, WORD_SIZE } from './constants'; export type DynamicData = { [pointerIndex: number]: Uint8ArrayWithDynamicData; @@ -143,7 +143,8 @@ export const isPointerType = (type: string) => { } }; -export const isHeapType = (type: string) => type === VEC_CODER_TYPE || type === BYTES_CODER_TYPE; +export const isHeapType = (type: string) => + type === VEC_CODER_TYPE || type === BYTES_CODER_TYPE || type === STRING_CODER_TYPE; export function findOrThrow( arr: readonly T[], From 2c66e8b618ae3ababb473468440523fcc5f56ce4 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 20 Sep 2023 23:59:18 -0700 Subject: [PATCH 31/55] add basics --- packages/abi-coder/src/coders/stdString.ts | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 packages/abi-coder/src/coders/stdString.ts diff --git a/packages/abi-coder/src/coders/stdString.ts b/packages/abi-coder/src/coders/stdString.ts new file mode 100644 index 00000000000..7cf2c1047dd --- /dev/null +++ b/packages/abi-coder/src/coders/stdString.ts @@ -0,0 +1,60 @@ +import type { BytesLike } from '@ethersproject/bytes'; +import { arrayify, concat, hexlify, stripZeros } from '@ethersproject/bytes'; +import { toUtf8Bytes, toUtf8String } from '@ethersproject/strings'; +import { bn } from '@fuel-ts/math'; + +import { WORD_SIZE } from '../constants'; +import type { Uint8ArrayWithDynamicData } from '../utilities'; +import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; + +import { Coder } from './abstract-coder'; +import { U64Coder } from './u64'; + +export class StdStringCoder extends Coder { + static memorySize = 1; + constructor() { + super('struct', 'struct String', BASE_VECTOR_OFFSET); + } + + encode(value: string): Uint8Array { + const parts: Uint8Array[] = []; + + // pointer (ptr) + const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); + + // pointer dynamicData, encode the string vector now and attach to its pointer + const data = this.#getPaddedData(value); + pointer.dynamicData = { + 0: concatWithDynamicData([data]), + }; + + parts.push(pointer); + + // capacity (cap) + parts.push(new U64Coder().encode(data.byteLength)); + + // length (len) + parts.push(new U64Coder().encode(value.length)); + + return concatWithDynamicData(parts); + } + + #getPaddedData(value: string): Uint8Array { + const data: Uint8Array[] = [toUtf8Bytes(value)]; + + const paddingLength = (WORD_SIZE - (value.length % WORD_SIZE)) % WORD_SIZE; + if (paddingLength) { + data.push(new Uint8Array(paddingLength)); + } + + return concat(data); + } + + decode(data: Uint8Array, offset: number): [string, number] { + const len = data.slice(16, 24); + const length = bn(new U64Coder().decode(len, 0)[0]).toNumber(); + const byteData = data.slice(BASE_VECTOR_OFFSET, BASE_VECTOR_OFFSET + length); + const value = toUtf8String(byteData); + return [value, offset + BASE_VECTOR_OFFSET]; + } +} From a7b72f288e82448593a33a337dbbbf25d43232c7 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:00:27 -0700 Subject: [PATCH 32/55] clean --- packages/abi-coder/src/coders/stdString.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/abi-coder/src/coders/stdString.ts b/packages/abi-coder/src/coders/stdString.ts index 7cf2c1047dd..b853439c5a0 100644 --- a/packages/abi-coder/src/coders/stdString.ts +++ b/packages/abi-coder/src/coders/stdString.ts @@ -1,5 +1,4 @@ -import type { BytesLike } from '@ethersproject/bytes'; -import { arrayify, concat, hexlify, stripZeros } from '@ethersproject/bytes'; +import { concat } from '@ethersproject/bytes'; import { toUtf8Bytes, toUtf8String } from '@ethersproject/strings'; import { bn } from '@fuel-ts/math'; From 6efaa559f1deaddb919b395c656c118464a2607e Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:00:35 -0700 Subject: [PATCH 33/55] tests --- packages/fuel-gauge/src/std-lib-string.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts index 25416b8f1ba..b50ad53e133 100644 --- a/packages/fuel-gauge/src/std-lib-string.test.ts +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -11,8 +11,7 @@ beforeAll(async () => { describe('std-lib-string Tests', () => { it('should test std-lib-string return', async () => { const { value } = await contractInstance.functions.return_dynamic_string().call(); - - expect(value).toStrictEqual('Hello World'); + expect(value).toBe('Hello World'); }); it('should test std-lib-string input', async () => { @@ -20,6 +19,6 @@ describe('std-lib-string Tests', () => { await contractInstance.functions.accepts_dynamic_string(INPUT).call(); - expect(true).toStrictEqual(true); + expect(true).toBe(true); }); }); From 75c2d80dcbebf8e6441db3d3138ff7b9616fbaf3 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:11:37 -0700 Subject: [PATCH 34/55] add tests --- .../abi-coder/src/coders/stdString.test.ts | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 packages/abi-coder/src/coders/stdString.test.ts diff --git a/packages/abi-coder/src/coders/stdString.test.ts b/packages/abi-coder/src/coders/stdString.test.ts new file mode 100644 index 00000000000..c7f82ced30a --- /dev/null +++ b/packages/abi-coder/src/coders/stdString.test.ts @@ -0,0 +1,92 @@ +import type { Uint8ArrayWithDynamicData } from '../utilities'; + +import { StdStringCoder } from './stdString'; + +describe('StdStringCoder', () => { + it('should encode an empty string', () => { + const coder = new StdStringCoder(); + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + expected.dynamicData = { + 0: new Uint8Array([]), + }; + + const actual = coder.encode(''); + expect(actual).toStrictEqual(expected); + }); + + it('should encode [hello world]', () => { + const coder = new StdStringCoder(); + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, + ]); + expected.dynamicData = { + 0: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0]), + }; + + const actual = coder.encode('hello world'); + expect(actual).toStrictEqual(expected); + }); + + it('should encode [H3llo W0rld]', () => { + const coder = new StdStringCoder(); + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, + ]); + expected.dynamicData = { + 0: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0]), + }; + + const actual = coder.encode('hello world'); + expect(actual).toStrictEqual(expected); + }); + + it('should encode [abcdefghijklmnopqrstuvwxyz1234567890]', () => { + const coder = new StdStringCoder(); + const expected: Uint8ArrayWithDynamicData = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 36, + ]); + expected.dynamicData = { + 0: new Uint8Array([ + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 0, 0, 0, 0, + ]), + }; + + const actual = coder.encode('abcdefghijklmnopqrstuvwxyz1234567890'); + expect(actual).toStrictEqual(expected); + }); + + it('should decode a string', () => { + const coder = new StdStringCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 49, 120, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 72, 101, 108, + 108, 111, 32, 87, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + const expected = 'Hello World'; + + const [actual, newOffset] = coder.decode(input, 0); + + expect(actual).toEqual(expected); + expect(newOffset).toEqual(24); + }); + + it('should decode a string [with offset]', () => { + const coder = new StdStringCoder(); + const input = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 49, 120, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 72, 101, 108, + 108, 111, 32, 87, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]); + const expected = 'Hello World'; + + const [actual, newOffset] = coder.decode(input, 16); + + expect(actual).toEqual(expected); + expect(newOffset).toEqual(40); + }); +}); From 2dda98d98548489b685bc8cdcf583c47d39f03f0 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:13:41 -0700 Subject: [PATCH 35/55] update exhaustive --- .../test/sway-projects/exhaustive-examples/src/main.sw | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw index df231ba8fd9..ca2965a81e8 100644 --- a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw +++ b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw @@ -1,6 +1,7 @@ contract; use std::b512::B512; use std::bytes::Bytes; +use std::string::String; enum EnumWithGeneric { VariantOne: T, @@ -135,6 +136,7 @@ abi MyContract { fn struct_with_implicitGenerics(arg: StructWithImplicitGenerics) -> StructWithImplicitGenerics; fn bytes(arg: Bytes) -> Bytes; fn raw_slice(arg: raw_slice) -> raw_slice; + fn dynamic_string(arg: String) -> String; fn tuple_as_param(x: (u8, StructA, str[3]>)) -> (u8, StructA, str[3]>); fn array_simple(x: [u8; 4]) -> [u8; 4]; @@ -196,6 +198,7 @@ impl MyContract for Contract { fn struct_with_implicitGenerics(arg: StructWithImplicitGenerics) -> StructWithImplicitGenerics {arg} fn bytes(arg: Bytes) -> Bytes { arg } fn raw_slice(arg: raw_slice) -> raw_slice { arg } + fn dynamic_string(arg: String) -> String { arg } fn two_u8_vectors(x: Vec, y: Vec) -> (Vec, Vec) {(x, y)} fn u32_then_three_vectors_u64(x: u32, y: Vec, z: Vec, q: Vec) -> (u32, Vec, Vec, Vec) {(x, y, z, q)} From 7b5d675474b9567a534944a84fecacb774ccc471 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:16:42 -0700 Subject: [PATCH 36/55] add sways for predicates and scripts --- .../fixtures/forc-projects/Forc.toml | 2 ++ .../predicate-std-lib-string/Forc.toml | 7 +++++ .../predicate-std-lib-string/src/main.sw | 30 +++++++++++++++++++ .../script-std-lib-string/Forc.toml | 7 +++++ .../script-std-lib-string/src/main.sw | 24 +++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/src/main.sw create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/Forc.toml create mode 100644 packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/src/main.sw diff --git a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml index 204e0997e01..4cbb241bbdd 100644 --- a/packages/fuel-gauge/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/fixtures/forc-projects/Forc.toml @@ -22,6 +22,7 @@ members = [ "predicate-main-args-vector", "predicate-multi-args", "predicate-raw-slice", + "predicate-std-lib-string", "predicate-struct", "predicate-triple-sig", "predicate-true", @@ -35,6 +36,7 @@ members = [ "script-main-return-struct", "script-main-two-args", "script-raw-slice", + "script-std-lib-string", "script-with-configurable", "script-with-array", "script-with-vector", diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/Forc.toml new file mode 100644 index 00000000000..29c4645037a --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "predicate-std-lib-string" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/src/main.sw new file mode 100644 index 00000000000..13594352ffa --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/src/main.sw @@ -0,0 +1,30 @@ +predicate; + +use std::string::String; + +fn validate_string(arg: String) -> bool { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + if expected_bytes.len() != bytes.len() { + return false; + } + + let mut i = 0; + while i < bytes.len() { + if expected_bytes.get(i).unwrap() != bytes.get(i).unwrap() { + return false; + } + i += 1; + } + + true +} + +fn main(_arg_0: u64, _arg_1: u64, arg_2: String) -> bool { + validate_string(arg_2) +} diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/Forc.toml b/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/Forc.toml new file mode 100644 index 00000000000..cdda6fb118b --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["FuelLabs"] +entry = "main.sw" +license = "Apache-2.0" +name = "script-std-lib-string" + +[dependencies] \ No newline at end of file diff --git a/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/src/main.sw b/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/src/main.sw new file mode 100644 index 00000000000..14ed91e311e --- /dev/null +++ b/packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/src/main.sw @@ -0,0 +1,24 @@ +script; + +use std::string::String; + +fn validate_string(arg: String) { + // to be replaced with a simpler assert_eq once + // https://github.com/FuelLabs/sway/issues/4868 is done + let bytes = arg.as_bytes(); + + let inner = String::from_ascii_str("Hello World"); + let expected_bytes = inner.as_bytes(); + + assert_eq(expected_bytes.len(), bytes.len()); + + let mut i = 0; + while i < bytes.len() { + assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); + i += 1; + } +} + +fn main(arg: String) { + validate_string(arg); +} From c6c15f48b7a9a5936f36eeba4767ffa0a1ca9e64 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:22:20 -0700 Subject: [PATCH 37/55] add tests for string --- .../fuel-gauge/src/std-lib-string.test.ts | 71 ++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts index b50ad53e133..aa19c592b1b 100644 --- a/packages/fuel-gauge/src/std-lib-string.test.ts +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -1,6 +1,19 @@ -import { type Contract } from 'fuels'; +import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; +import { + type Contract, + bn, + Predicate, + Wallet, + Address, + BaseAssetId, + Provider, + FUEL_NETWORK_URL, +} from 'fuels'; -import { getSetupContract } from './utils'; +import predicateStdString from '../fixtures/forc-projects/predicate-std-lib-string'; +import predicateStdStringAbi from '../fixtures/forc-projects/predicate-std-lib-string/out/debug/predicate-std-lib-string-abi.json'; + +import { getScript, getSetupContract } from './utils'; const setupContract = getSetupContract('std-lib-string'); let contractInstance: Contract; @@ -8,6 +21,15 @@ beforeAll(async () => { contractInstance = await setupContract(); }); +const setup = async (balance = 5_000) => { + const provider = await Provider.create(FUEL_NETWORK_URL); + + // Create wallet + const wallet = await generateTestWallet(provider, [[balance, BaseAssetId]]); + + return wallet; +}; + describe('std-lib-string Tests', () => { it('should test std-lib-string return', async () => { const { value } = await contractInstance.functions.return_dynamic_string().call(); @@ -21,4 +43,49 @@ describe('std-lib-string Tests', () => { expect(true).toBe(true); }); + + it('should test bytes input [predicate-std-lib-string]', async () => { + const wallet = await setup(); + const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); + const amountToPredicate = 100; + const amountToReceiver = 50; + type MainArgs = [number, number, string]; + const predicate = new Predicate( + predicateStdString, + wallet.provider, + predicateStdStringAbi + ); + + // setup predicate + const setupTx = await wallet.transfer(predicate.address, amountToPredicate, BaseAssetId); + await setupTx.waitForResult(); + + const initialPredicateBalance = await predicate.getBalance(); + const initialReceiverBalance = await receiver.getBalance(); + const tx = await predicate + .setData(1, 2, 'Hello World') + .transfer(receiver.address, amountToReceiver); + await tx.waitForResult(); + + // Check the balance of the receiver + const finalReceiverBalance = await receiver.getBalance(); + expect(bn(initialReceiverBalance).add(amountToReceiver).toHex()).toEqual( + finalReceiverBalance.toHex() + ); + + // Check we spent the entire predicate hash input + const finalPredicateBalance = await predicate.getBalance(); + expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); + }); + + it('should test bytes input [script-std-lib-string]', async () => { + const wallet = await setup(); + type MainArgs = [string]; + const scriptInstance = getScript('script-std-lib-string', wallet); + + const INPUT = 'Hello World'; + await scriptInstance.functions.main(INPUT).call(); + + expect(true).toBe(true); + }); }); From d2bf9ed6c46034afb368f8dce4f563973f649729 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:24:57 -0700 Subject: [PATCH 38/55] update --- packages/abi-coder/src/coders/stdString.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/abi-coder/src/coders/stdString.test.ts b/packages/abi-coder/src/coders/stdString.test.ts index c7f82ced30a..6c7a039cdfe 100644 --- a/packages/abi-coder/src/coders/stdString.test.ts +++ b/packages/abi-coder/src/coders/stdString.test.ts @@ -35,10 +35,10 @@ describe('StdStringCoder', () => { 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, ]); expected.dynamicData = { - 0: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0]), + 0: new Uint8Array([72, 51, 108, 108, 111, 32, 87, 48, 114, 108, 100, 0, 0, 0, 0, 0]), }; - const actual = coder.encode('hello world'); + const actual = coder.encode('H3llo W0rld'); expect(actual).toStrictEqual(expected); }); From 5c28db3195495440b8bcc449074d75072e7a35d2 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 00:32:34 -0700 Subject: [PATCH 39/55] add to interface test --- packages/abi-coder/test/interface.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/abi-coder/test/interface.test.ts b/packages/abi-coder/test/interface.test.ts index 1d042bfb22e..ea635a9c9d4 100644 --- a/packages/abi-coder/test/interface.test.ts +++ b/packages/abi-coder/test/interface.test.ts @@ -307,7 +307,6 @@ describe('Abi interface', () => { const data = (decoded as BN[]).slice(0, 3); return Array.from(data); }, - decodedTransfoarmer: (decoded: unknown | undefined) => Array.from(decoded as Uint8Array), }, { fn: exhaustiveExamplesInterface.functions.raw_slice, @@ -322,6 +321,15 @@ describe('Abi interface', () => { return data.map((v: BN) => v.toNumber()); }, }, + { + fn: exhaustiveExamplesInterface.functions.dynamic_string, + title: '[struct String]', + value: 'H3llo W0rld', + encodedValue: new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, 72, 51, 108, + 108, 111, 32, 87, 48, 114, 108, 100, 0, 0, 0, 0, 0, + ]), + }, { fn: exhaustiveExamplesInterface.functions.tuple_as_param, title: '[tuple] as param', From 5994c121dc4957a0ffc4bfcfb81e300a4db8529a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nedim=20Salki=C4=87?= Date: Thu, 21 Sep 2023 13:24:09 +0200 Subject: [PATCH 40/55] fix: linting warning --- packages/abi-coder/src/coders/byte.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index ae37ad536bf..a53dd1c40ea 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -1,4 +1,4 @@ -import { arrayify, concat, type BytesLike } from '@ethersproject/bytes'; +import { arrayify, concat } from '@ethersproject/bytes'; import { bn } from '@fuel-ts/math'; import { WORD_SIZE } from '../constants'; From ee0e942643ef866e20dc8b4546d70c7bf2054684 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 22:41:29 -0700 Subject: [PATCH 41/55] add cs --- .changeset/honest-plums-work.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/honest-plums-work.md diff --git a/.changeset/honest-plums-work.md b/.changeset/honest-plums-work.md new file mode 100644 index 00000000000..2c23bf5a532 --- /dev/null +++ b/.changeset/honest-plums-work.md @@ -0,0 +1,6 @@ +--- +"@fuel-ts/abi-coder": minor +"@fuel-ts/program": minor +--- + +Add StdString dynamic string type From 3d47dc0ea566242c62d5e924991d1ec68a0b8cc6 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 23:06:30 -0700 Subject: [PATCH 42/55] adjust --- .../exhaustive-examples/src/main.sw | 39 ++++--------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw index df231ba8fd9..6076d90be3c 100644 --- a/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw +++ b/packages/abi-coder/test/sway-projects/exhaustive-examples/src/main.sw @@ -169,38 +169,6 @@ abi MyContract { } impl MyContract for Contract { - fn test_function() -> bool {true} - fn u_8(arg: u8) -> u8 {arg} - fn u_16(arg: u16) -> u16 {arg} - fn u_32(arg: u32) -> u32 {arg} - fn u_64(arg: u64) -> u64 {arg} - fn string(arg: str[5]) -> str[5] {arg} - fn boolean(arg: bool) -> bool {arg} - fn b_256(arg: b256) -> b256 {arg} - fn b_512(arg: B512) -> B512 {arg} - fn two_args(arg1: b256, arg2: bool) -> (b256, bool) {(arg1, arg2)} - fn struct_simple(x: SimpleStruct) -> SimpleStruct { x } - fn struct_generic_simple(x: StructB) -> StructB {x} - fn struct_with_tuple(x: StructB<(bool, u64)>) -> StructB<(bool, u64)> {x} - fn tuple_as_param(x: (u8, StructA, str[3]>)) -> (u8, StructA, str[3]>) {x} - fn vector_boolean(x: Vec) -> Vec {x} - fn vector_u8(x: Vec) -> Vec {x} - fn enum_simple(x: Color) -> Color {x} - fn enum_with_builtin_type(x: EnumWithBuiltinType) -> EnumWithBuiltinType { x } - fn enum_with_structs(x: EnumWithStructs) -> EnumWithStructs {x} - fn array_simple(x: [u8; 4]) -> [u8; 4] { x } - fn array_struct(x: [SimpleStruct; 3]) -> [SimpleStruct; 3] {x} - fn option_u8(x: Option) -> Option {x} - fn arg_then_vector_u8(a: SimpleStruct, x: Vec) -> (SimpleStruct, Vec) {(a, x)} - fn vector_u8_then_arg(x: Vec, y: b256) -> (Vec, b256) {(x, y)} - fn struct_with_implicitGenerics(arg: StructWithImplicitGenerics) -> StructWithImplicitGenerics {arg} - fn bytes(arg: Bytes) -> Bytes { arg } - fn raw_slice(arg: raw_slice) -> raw_slice { arg } - - fn two_u8_vectors(x: Vec, y: Vec) -> (Vec, Vec) {(x, y)} - fn u32_then_three_vectors_u64(x: u32, y: Vec, z: Vec, q: Vec) -> (u32, Vec, Vec, Vec) {(x, y, z, q)} - - fn test_function() -> bool { true } @@ -279,6 +247,13 @@ impl MyContract for Contract { arg } + fn bytes(arg: Bytes) -> Bytes { + arg + } + fn raw_slice(arg: raw_slice) -> raw_slice { + arg + } + fn two_u8_vectors(x: Vec, y: Vec) -> (Vec, Vec) { (x, y) } From 1ce3a79cb3e1adb8c0dfad78c895c48a31e25b8e Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 23:08:22 -0700 Subject: [PATCH 43/55] convert errors --- packages/abi-coder/src/coders/byte.ts | 3 ++- packages/abi-coder/src/coders/raw-slice.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/abi-coder/src/coders/byte.ts b/packages/abi-coder/src/coders/byte.ts index a53dd1c40ea..e297c22d1eb 100644 --- a/packages/abi-coder/src/coders/byte.ts +++ b/packages/abi-coder/src/coders/byte.ts @@ -1,4 +1,5 @@ import { arrayify, concat } from '@ethersproject/bytes'; +import { ErrorCode } from '@fuel-ts/errors'; import { bn } from '@fuel-ts/math'; import { WORD_SIZE } from '../constants'; @@ -16,7 +17,7 @@ export class ByteCoder extends Coder { encode(value: number[]): Uint8Array { if (!Array.isArray(value)) { - this.throwError('expected array value', value); + this.throwError(ErrorCode.ENCODE_ERROR, `Expected array value.`); } const parts: Uint8Array[] = []; diff --git a/packages/abi-coder/src/coders/raw-slice.ts b/packages/abi-coder/src/coders/raw-slice.ts index 4e915aae8de..843c41ad370 100644 --- a/packages/abi-coder/src/coders/raw-slice.ts +++ b/packages/abi-coder/src/coders/raw-slice.ts @@ -1,3 +1,4 @@ +import { ErrorCode } from '@fuel-ts/errors'; import type { BN } from '@fuel-ts/math'; import { WORD_SIZE } from '../constants'; @@ -15,7 +16,7 @@ export class RawSliceCoder extends Coder { encode(value: number[]): Uint8Array { if (!Array.isArray(value)) { - this.throwError('expected array value', value); + this.throwError(ErrorCode.ENCODE_ERROR, `Expected array value.`); } const parts: Uint8Array[] = []; From ffdb9e96ad7acf0e1187608db644b86f446e1908 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Thu, 21 Sep 2023 23:18:07 -0700 Subject: [PATCH 44/55] add struct string --- .../test/fixtures/exhaustive-examples-abi.ts | 294 ++++++++++-------- 1 file changed, 161 insertions(+), 133 deletions(-) diff --git a/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts b/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts index af6262a6344..16a6bac22bf 100644 --- a/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts +++ b/packages/abi-coder/test/fixtures/exhaustive-examples-abi.ts @@ -17,11 +17,11 @@ export const exhaustiveExamplesAbi = { }, { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -74,7 +74,7 @@ export const exhaustiveExamplesAbi = { }, { name: '__tuple_element', - type: 61, + type: 62, typeArguments: null, }, ], @@ -86,20 +86,20 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 62, + type: 63, typeArguments: null, }, { name: '__tuple_element', - type: 53, + type: 54, typeArguments: [ { name: '', - type: 54, + type: 55, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], @@ -137,22 +137,22 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -166,11 +166,11 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -189,38 +189,38 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 60, + type: 61, typeArguments: null, }, { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], }, { name: '__tuple_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], @@ -234,7 +234,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__tuple_element', - type: 62, + type: 63, typeArguments: null, }, { @@ -254,11 +254,11 @@ export const exhaustiveExamplesAbi = { }, { name: '__tuple_element', - type: 53, + type: 54, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, { @@ -277,11 +277,11 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 60, + type: 61, typeArguments: null, }, ], @@ -352,7 +352,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -378,7 +378,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 60, + type: 61, typeArguments: null, }, ], @@ -414,7 +414,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: '__array_element', - type: 62, + type: 63, typeArguments: null, }, ], @@ -430,7 +430,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, { @@ -498,7 +498,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'b', - type: 61, + type: 62, typeArguments: null, }, ], @@ -515,7 +515,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'VariantTwo', - type: 61, + type: 62, typeArguments: null, }, ], @@ -537,11 +537,11 @@ export const exhaustiveExamplesAbi = { }, { name: 'c', - type: 53, + type: 54, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, { @@ -560,16 +560,16 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'num', - type: 62, + type: 63, typeArguments: null, }, { name: 'vec', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -583,7 +583,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'Foo', - type: 61, + type: 62, typeArguments: null, }, { @@ -605,7 +605,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'Foo', - type: 61, + type: 62, typeArguments: null, }, { @@ -733,7 +733,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'len', - type: 61, + type: 62, typeArguments: null, }, ], @@ -754,7 +754,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], @@ -768,7 +768,7 @@ export const exhaustiveExamplesAbi = { components: [ { name: 'bom', - type: 61, + type: 62, typeArguments: null, }, ], @@ -785,7 +785,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'dummy_b', - type: 61, + type: 62, typeArguments: null, }, ], @@ -819,7 +819,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'bam', - type: 54, + type: 55, typeArguments: [ { name: '', @@ -830,7 +830,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'bom', - type: 53, + type: 54, typeArguments: [ { name: '', @@ -858,7 +858,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'cap', - type: 61, + type: 62, typeArguments: null, }, ], @@ -875,7 +875,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'cap', - type: 61, + type: 62, typeArguments: null, }, ], @@ -892,7 +892,7 @@ export const exhaustiveExamplesAbi = { }, { name: 'b', - type: 60, + type: 61, typeArguments: null, }, ], @@ -900,6 +900,18 @@ export const exhaustiveExamplesAbi = { }, { typeId: 53, + type: 'struct String', + components: [ + { + name: 'bytes', + type: 44, + typeArguments: null, + }, + ], + typeParameters: null, + }, + { + typeId: 54, type: 'struct StructA', components: [ { @@ -916,7 +928,7 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 54, + typeId: 55, type: 'struct StructB', components: [ { @@ -928,7 +940,7 @@ export const exhaustiveExamplesAbi = { typeParameters: [34], }, { - typeId: 55, + typeId: 56, type: 'struct StructWithImplicitGenerics', components: [ { @@ -945,21 +957,21 @@ export const exhaustiveExamplesAbi = { typeParameters: [34, 35], }, { - typeId: 56, + typeId: 57, type: 'struct StructWithVector', components: [ { name: 'num', - type: 62, + type: 63, typeArguments: null, }, { name: 'vec', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -968,24 +980,24 @@ export const exhaustiveExamplesAbi = { typeParameters: null, }, { - typeId: 57, + typeId: 58, type: 'struct Test', components: [ { name: 'foo', - type: 61, + type: 62, typeArguments: null, }, { name: 'bar', - type: 61, + type: 62, typeArguments: null, }, ], typeParameters: null, }, { - typeId: 58, + typeId: 59, type: 'struct Vec', components: [ { @@ -1001,32 +1013,32 @@ export const exhaustiveExamplesAbi = { }, { name: 'len', - type: 61, + type: 62, typeArguments: null, }, ], typeParameters: [34], }, { - typeId: 59, + typeId: 60, type: 'u16', components: null, typeParameters: null, }, { - typeId: 60, + typeId: 61, type: 'u32', components: null, typeParameters: null, }, { - typeId: 61, + typeId: 62, type: 'u64', components: null, typeParameters: null, }, { - typeId: 62, + typeId: 63, type: 'u8', components: null, typeParameters: null, @@ -1042,11 +1054,11 @@ export const exhaustiveExamplesAbi = { }, { name: 'x', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1213,7 +1225,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1246,14 +1258,30 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 61, + type: 53, + typeArguments: null, + }, + ], + name: 'dynamic_string', + output: { + name: '', + type: 53, + typeArguments: null, + }, + attributes: null, + }, + { + inputs: [ + { + name: 'arg', + type: 62, typeArguments: null, }, ], name: 'entry_one', output: { name: '', - type: 61, + type: 62, typeArguments: null, }, attributes: null, @@ -1310,7 +1338,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'my_u64', - type: 61, + type: 62, typeArguments: null, }, { @@ -1322,7 +1350,7 @@ export const exhaustiveExamplesAbi = { name: 'my_struct', output: { name: '', - type: 61, + type: 62, typeArguments: null, }, attributes: null, @@ -1335,7 +1363,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1348,7 +1376,7 @@ export const exhaustiveExamplesAbi = { typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1385,11 +1413,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1398,11 +1426,11 @@ export const exhaustiveExamplesAbi = { name: 'simple_vector', output: { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1429,11 +1457,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 54, + type: 55, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1442,11 +1470,11 @@ export const exhaustiveExamplesAbi = { name: 'struct_generic_simple', output: { name: '', - type: 54, + type: 55, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1473,7 +1501,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 55, + type: 56, typeArguments: [ { name: '', @@ -1482,7 +1510,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1491,7 +1519,7 @@ export const exhaustiveExamplesAbi = { name: 'struct_with_implicitGenerics', output: { name: '', - type: 55, + type: 56, typeArguments: [ { name: '', @@ -1500,7 +1528,7 @@ export const exhaustiveExamplesAbi = { }, { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1511,7 +1539,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 54, + type: 55, typeArguments: [ { name: '', @@ -1524,7 +1552,7 @@ export const exhaustiveExamplesAbi = { name: 'struct_with_tuple', output: { name: '', - type: 54, + type: 55, typeArguments: [ { name: '', @@ -1539,19 +1567,19 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'a', - type: 61, + type: 62, typeArguments: null, }, { name: 'b', - type: 61, + type: 62, typeArguments: null, }, ], name: 'sum', output: { name: '', - type: 61, + type: 62, typeArguments: null, }, attributes: null, @@ -1560,14 +1588,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'test', - type: 57, + type: 58, typeArguments: null, }, ], name: 'sum_test', output: { name: '', - type: 61, + type: 62, typeArguments: null, }, attributes: null, @@ -1655,22 +1683,22 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], }, { name: 'y', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1688,38 +1716,38 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 60, + type: 61, typeArguments: null, }, { name: 'y', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], }, { name: 'z', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], }, { name: 'q', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 61, + type: 62, typeArguments: null, }, ], @@ -1737,14 +1765,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 59, + type: 60, typeArguments: null, }, ], name: 'u_16', output: { name: '', - type: 59, + type: 60, typeArguments: null, }, attributes: null, @@ -1753,14 +1781,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 60, + type: 61, typeArguments: null, }, ], name: 'u_32', output: { name: '', - type: 60, + type: 61, typeArguments: null, }, attributes: null, @@ -1769,14 +1797,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 61, + type: 62, typeArguments: null, }, ], name: 'u_64', output: { name: '', - type: 61, + type: 62, typeArguments: null, }, attributes: null, @@ -1785,14 +1813,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 62, + type: 63, typeArguments: null, }, ], name: 'u_8', output: { name: '', - type: 62, + type: 63, typeArguments: null, }, attributes: null, @@ -1801,7 +1829,7 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 58, + type: 59, typeArguments: [ { name: '', @@ -1814,7 +1842,7 @@ export const exhaustiveExamplesAbi = { name: 'vector_boolean', output: { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', @@ -1861,14 +1889,14 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 56, + type: 57, typeArguments: null, }, ], name: 'vector_inside_struct', output: { name: '', - type: 56, + type: 57, typeArguments: null, }, attributes: null, @@ -1877,15 +1905,15 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'arg', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 60, + type: 61, typeArguments: null, }, ], @@ -1896,15 +1924,15 @@ export const exhaustiveExamplesAbi = { name: 'vector_inside_vector', output: { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 60, + type: 61, typeArguments: null, }, ], @@ -1917,11 +1945,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1930,11 +1958,11 @@ export const exhaustiveExamplesAbi = { name: 'vector_u8', output: { name: '', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1945,11 +1973,11 @@ export const exhaustiveExamplesAbi = { inputs: [ { name: 'x', - type: 58, + type: 59, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, ], @@ -1976,10 +2004,10 @@ export const exhaustiveExamplesAbi = { name: 'U8', configurableType: { name: '', - type: 62, + type: 63, typeArguments: null, }, - offset: 1488, + offset: 1808, }, { name: 'BOOL', @@ -1988,7 +2016,7 @@ export const exhaustiveExamplesAbi = { type: 24, typeArguments: null, }, - offset: 1496, + offset: 1816, }, { name: 'ARRAY', @@ -1997,7 +2025,7 @@ export const exhaustiveExamplesAbi = { type: 18, typeArguments: null, }, - offset: 1504, + offset: 1824, }, { name: 'STR_4', @@ -2006,17 +2034,17 @@ export const exhaustiveExamplesAbi = { type: 40, typeArguments: null, }, - offset: 1528, + offset: 1848, }, { name: 'STRUCT', configurableType: { name: '', - type: 53, + type: 54, typeArguments: [ { name: '', - type: 62, + type: 63, typeArguments: null, }, { @@ -2026,7 +2054,7 @@ export const exhaustiveExamplesAbi = { }, ], }, - offset: 1536, + offset: 1856, }, ], } as const; From 3a767a429e7308cd83b1dc20ccbda8f2bd87e48c Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 08:45:11 -0700 Subject: [PATCH 45/55] cs --- .changeset/thirty-dogs-sleep.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changeset/thirty-dogs-sleep.md diff --git a/.changeset/thirty-dogs-sleep.md b/.changeset/thirty-dogs-sleep.md new file mode 100644 index 00000000000..1a51368148c --- /dev/null +++ b/.changeset/thirty-dogs-sleep.md @@ -0,0 +1,4 @@ +--- +--- + +Add tests for Bytes and RawSlice From 61ce5d07ce92b8492306c0892bb58a1c61c0502f Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 08:47:49 -0700 Subject: [PATCH 46/55] cs --- .changeset/grey-eagles-fly.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changeset/grey-eagles-fly.md diff --git a/.changeset/grey-eagles-fly.md b/.changeset/grey-eagles-fly.md new file mode 100644 index 00000000000..1a51368148c --- /dev/null +++ b/.changeset/grey-eagles-fly.md @@ -0,0 +1,4 @@ +--- +--- + +Add tests for Bytes and RawSlice From de981f0e1ed60148827b32a41119eedc187a6926 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 08:57:53 -0700 Subject: [PATCH 47/55] pretty --- packages/fuel-gauge/src/bytes.test.ts | 1 - packages/fuel-gauge/src/raw-slice.test.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 79d7de1c05b..9a4eb695b9d 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -13,7 +13,6 @@ import { import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; - import { getSetupContract } from './utils'; const setupContract = getSetupContract('bytes'); diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index bfe7aa3f98c..5dd90573654 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -1,4 +1,3 @@ - import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; import type { BN } from 'fuels'; import { From 8d1c0b4231b6423f7538d9922749cce8d03078af Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 19:29:25 -0700 Subject: [PATCH 48/55] fix prettier and lint post merge --- packages/fuel-gauge/src/bytes.test.ts | 3 --- packages/fuel-gauge/src/raw-slice.test.ts | 13 ------------- 2 files changed, 16 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index c006ff308af..fcb6fb8d842 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -13,9 +13,6 @@ import { import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; -import predicateBytes from '../fixtures/forc-projects/predicate-bytes'; -import predicateBytesAbi from '../fixtures/forc-projects/predicate-bytes/out/debug/predicate-bytes-abi.json'; - import { getScript, getSetupContract } from './utils'; const setupContract = getSetupContract('bytes'); diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index 22b3b88394b..05ea882cb41 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -14,9 +14,6 @@ import { import predicateRawSlice from '../fixtures/forc-projects/predicate-raw-slice'; import predicateRawSliceAbi from '../fixtures/forc-projects/predicate-raw-slice/out/debug/predicate-raw-slice-abi.json'; -import predicateRawSlice from '../fixtures/forc-projects/predicate-raw-slice'; -import predicateRawSliceAbi from '../fixtures/forc-projects/predicate-raw-slice/out/debug/predicate-raw-slice-abi.json'; - import { getScript, getSetupContract } from './utils'; type SomeEnum = { @@ -38,16 +35,6 @@ const setup = async (balance = 5_000) => { return wallet; }; -type SomeEnum = { - First?: boolean; - Second?: number[]; -}; - -type Wrapper = { - inner: number[][]; - inner_enum: SomeEnum; -}; - const setupContract = getSetupContract('raw-slice'); let contractInstance: Contract; beforeAll(async () => { From 4edc0bd16c3bbf2d05d133340fa00900795c92bd Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 19:51:04 -0700 Subject: [PATCH 49/55] fix assertions --- packages/fuel-gauge/src/bytes.test.ts | 15 +++++++-------- packages/fuel-gauge/src/raw-slice.test.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index fcb6fb8d842..67fb977b481 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -60,9 +60,9 @@ describe('Bytes Tests', () => { it('should test bytes input', async () => { const INPUT = [40, 41, 42]; - await contractInstance.functions.accept_bytes(INPUT).call(); - - expect(true).toBeTruthy(); + await expect(() => + contractInstance.functions.accept_bytes(INPUT).call() + ).not.toThrow(); }); it('should test bytes input [nested]', async () => { @@ -73,9 +73,9 @@ describe('Bytes Tests', () => { inner_enum: { Second: bytes }, }; - await contractInstance.functions.accept_nested_bytes(INPUT).call(); - - expect(true).toBeTruthy(); + await expect( + () => contractInstance.functions.accept_nested_bytes(INPUT).call + ).not.toThrow(); }); it('should test bytes input [predicate-bytes]', async () => { @@ -121,8 +121,7 @@ describe('Bytes Tests', () => { inner: [bytes, bytes], inner_enum: { Second: bytes }, }; - await scriptInstance.functions.main(1, INPUT).call(); - expect(true).toBe(true); + await expect(() => scriptInstance.functions.main(1, INPUT).call).not.toThrow(); }); }); diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index 05ea882cb41..79d859b1d84 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -53,9 +53,9 @@ describe('Raw Slice Tests', () => { it('should test raw slice input', async () => { const INPUT = [40, 41, 42]; - await contractInstance.functions.accept_raw_slice(INPUT).call(); - - expect(true).toBeTruthy(); + await expect(() => + contractInstance.functions.accept_raw_slice(INPUT).call() + ).not.toThrow(); }); it('should test raw slice input [nested]', async () => { @@ -65,9 +65,9 @@ describe('Raw Slice Tests', () => { inner_enum: { Second: slice }, }; - await contractInstance.functions.accept_nested_raw_slice(INPUT).call(); - - expect(true).toBeTruthy(); + await expect(() => + contractInstance.functions.accept_nested_raw_slice(INPUT).call() + ).not.toThrow(); }); it('should test raw slice input [predicate-raw-slice]', async () => { @@ -117,8 +117,7 @@ describe('Raw Slice Tests', () => { inner: [bytes, bytes], inner_enum: { Second: bytes }, }; - await scriptInstance.functions.main(1, INPUT).call(); - expect(true).toBe(true); + await expect(() => scriptInstance.functions.main(1, INPUT).call()).not.toThrow(); }); }); From d8a3d87912768def242441c5732453f04cc4792b Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 25 Sep 2023 21:14:54 -0700 Subject: [PATCH 50/55] revise --- packages/fuel-gauge/src/bytes.test.ts | 14 +++++++------- packages/fuel-gauge/src/raw-slice.test.ts | 17 ++++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/fuel-gauge/src/bytes.test.ts b/packages/fuel-gauge/src/bytes.test.ts index 67fb977b481..6b683db8e20 100644 --- a/packages/fuel-gauge/src/bytes.test.ts +++ b/packages/fuel-gauge/src/bytes.test.ts @@ -1,4 +1,5 @@ import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; +import type { BN } from 'fuels'; import { type Contract, bn, @@ -60,9 +61,8 @@ describe('Bytes Tests', () => { it('should test bytes input', async () => { const INPUT = [40, 41, 42]; - await expect(() => - contractInstance.functions.accept_bytes(INPUT).call() - ).not.toThrow(); + const { value } = await contractInstance.functions.accept_bytes(INPUT).call(); + expect(value).toBeUndefined(); }); it('should test bytes input [nested]', async () => { @@ -73,9 +73,8 @@ describe('Bytes Tests', () => { inner_enum: { Second: bytes }, }; - await expect( - () => contractInstance.functions.accept_nested_bytes(INPUT).call - ).not.toThrow(); + const { value } = await contractInstance.functions.accept_nested_bytes(INPUT).call(); + expect(value).toBeUndefined(); }); it('should test bytes input [predicate-bytes]', async () => { @@ -122,6 +121,7 @@ describe('Bytes Tests', () => { inner_enum: { Second: bytes }, }; - await expect(() => scriptInstance.functions.main(1, INPUT).call).not.toThrow(); + const { value } = await scriptInstance.functions.main(1, INPUT).call(); + expect(value.toNumber()).toStrictEqual(0); }); }); diff --git a/packages/fuel-gauge/src/raw-slice.test.ts b/packages/fuel-gauge/src/raw-slice.test.ts index 79d859b1d84..10bff63302e 100644 --- a/packages/fuel-gauge/src/raw-slice.test.ts +++ b/packages/fuel-gauge/src/raw-slice.test.ts @@ -53,9 +53,9 @@ describe('Raw Slice Tests', () => { it('should test raw slice input', async () => { const INPUT = [40, 41, 42]; - await expect(() => - contractInstance.functions.accept_raw_slice(INPUT).call() - ).not.toThrow(); + const { value } = await contractInstance.functions.accept_raw_slice(INPUT).call(); + + expect(value).toBeUndefined(); }); it('should test raw slice input [nested]', async () => { @@ -65,9 +65,11 @@ describe('Raw Slice Tests', () => { inner_enum: { Second: slice }, }; - await expect(() => - contractInstance.functions.accept_nested_raw_slice(INPUT).call() - ).not.toThrow(); + const { value } = await contractInstance.functions + .accept_nested_raw_slice(INPUT) + .call(); + + expect(value).toBeUndefined(); }); it('should test raw slice input [predicate-raw-slice]', async () => { @@ -118,6 +120,7 @@ describe('Raw Slice Tests', () => { inner_enum: { Second: bytes }, }; - await expect(() => scriptInstance.functions.main(1, INPUT).call()).not.toThrow(); + const { value } = await scriptInstance.functions.main(1, INPUT).call(); + expect(value.map((v: BN) => v.toNumber())).toStrictEqual([1, 2, 3]); }); }); From f5c079a7e542f0841d4b4ec30361e1fce2ceff30 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Wed, 27 Sep 2023 08:42:38 -0700 Subject: [PATCH 51/55] add additional coverage on input validation --- packages/abi-coder/src/coders/byte.test.ts | 12 ++++++++++++ packages/abi-coder/src/coders/raw-slice.test.ts | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/abi-coder/src/coders/byte.test.ts b/packages/abi-coder/src/coders/byte.test.ts index 17c53bbc318..7891d84792a 100644 --- a/packages/abi-coder/src/coders/byte.test.ts +++ b/packages/abi-coder/src/coders/byte.test.ts @@ -1,3 +1,6 @@ +import { FuelError, ErrorCode } from '@fuel-ts/errors'; +import { expectToThrowFuelError } from '@fuel-ts/errors/test-utils'; + import type { Uint8ArrayWithDynamicData } from '../utilities'; import { ByteCoder } from './byte'; @@ -31,6 +34,15 @@ describe('ByteCoder', () => { expect(actual).toStrictEqual(expected); }); + it('should throw when value to encode is not array', async () => { + 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([ diff --git a/packages/abi-coder/src/coders/raw-slice.test.ts b/packages/abi-coder/src/coders/raw-slice.test.ts index adf81641101..a30d821fed3 100644 --- a/packages/abi-coder/src/coders/raw-slice.test.ts +++ b/packages/abi-coder/src/coders/raw-slice.test.ts @@ -1,3 +1,5 @@ +import { FuelError, ErrorCode } from '@fuel-ts/errors'; +import { expectToThrowFuelError } from '@fuel-ts/errors/test-utils'; import type { BN } from '@fuel-ts/math'; import type { Uint8ArrayWithDynamicData } from '../utilities'; @@ -19,6 +21,15 @@ describe('RawSliceCoder', () => { expect(actual).toStrictEqual(expected); }); + it('should throw when value to encode is not array', async () => { + const coder = new RawSliceCoder(); + const nonArrayInput = { ...[1] }; + await expectToThrowFuelError( + () => coder.encode(nonArrayInput), + new FuelError(ErrorCode.ENCODE_ERROR, 'Expected array value.') + ); + }); + it('should decode a raw-slice', () => { const coder = new RawSliceCoder(); const input = new Uint8Array([ From 912c9e2faa736377d4e8db4bd43a551f84650fcc Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sat, 30 Sep 2023 16:24:00 -0700 Subject: [PATCH 52/55] Update packages/fuel-gauge/src/std-lib-string.test.ts Co-authored-by: Dhaiwat --- packages/fuel-gauge/src/std-lib-string.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts index aa19c592b1b..dc14a0fc5dc 100644 --- a/packages/fuel-gauge/src/std-lib-string.test.ts +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -44,7 +44,7 @@ describe('std-lib-string Tests', () => { expect(true).toBe(true); }); - it('should test bytes input [predicate-std-lib-string]', async () => { + it('should test String input [predicate-std-lib-string]', async () => { const wallet = await setup(); const receiver = Wallet.fromAddress(Address.fromRandom(), wallet.provider); const amountToPredicate = 100; From 5c8d56183f260746dcefa7907058ae2bab1a14f1 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Sat, 30 Sep 2023 16:24:17 -0700 Subject: [PATCH 53/55] Update packages/fuel-gauge/src/std-lib-string.test.ts Co-authored-by: Dhaiwat --- packages/fuel-gauge/src/std-lib-string.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts index dc14a0fc5dc..13353fa1495 100644 --- a/packages/fuel-gauge/src/std-lib-string.test.ts +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -78,7 +78,7 @@ describe('std-lib-string Tests', () => { expect(finalPredicateBalance.lte(initialPredicateBalance)).toBeTruthy(); }); - it('should test bytes input [script-std-lib-string]', async () => { + it('should test String input [script-std-lib-string]', async () => { const wallet = await setup(); type MainArgs = [string]; const scriptInstance = getScript('script-std-lib-string', wallet); From c6df9c86136bbea913425bb81d2044a9898f5d72 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 2 Oct 2023 21:38:34 -0700 Subject: [PATCH 54/55] rename --- packages/abi-coder/src/abi-coder.ts | 4 ++-- packages/abi-coder/src/constants.ts | 2 +- packages/abi-coder/src/utilities.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/abi-coder/src/abi-coder.ts b/packages/abi-coder/src/abi-coder.ts index b9f075821ce..397687b2711 100644 --- a/packages/abi-coder/src/abi-coder.ts +++ b/packages/abi-coder/src/abi-coder.ts @@ -26,7 +26,7 @@ import { OPTION_CODER_TYPE, VEC_CODER_TYPE, BYTES_CODER_TYPE, - STRING_CODER_TYPE, + STD_STRING_CODER_TYPE, } from './constants'; import type { JsonAbi, JsonAbiArgument } from './json-abi'; import { ResolvedAbiType } from './resolved-abi-type'; @@ -71,7 +71,7 @@ export abstract class AbiCoder { return new B512Coder(); case BYTES_CODER_TYPE: return new ByteCoder(); - case STRING_CODER_TYPE: + case STD_STRING_CODER_TYPE: return new StdStringCoder(); default: break; diff --git a/packages/abi-coder/src/constants.ts b/packages/abi-coder/src/constants.ts index e46233c610c..b6c3ac599c8 100644 --- a/packages/abi-coder/src/constants.ts +++ b/packages/abi-coder/src/constants.ts @@ -1,7 +1,7 @@ export const OPTION_CODER_TYPE = 'enum Option'; export const VEC_CODER_TYPE = 'struct Vec'; export const BYTES_CODER_TYPE = 'struct Bytes'; -export const STRING_CODER_TYPE = 'struct String'; +export const STD_STRING_CODER_TYPE = 'struct String'; export const stringRegEx = /str\[(?[0-9]+)\]/; export const arrayRegEx = /\[(?[\w\s\\[\]]+);\s*(?[0-9]+)\]/; export const structRegEx = /^struct (?\w+)$/; diff --git a/packages/abi-coder/src/utilities.ts b/packages/abi-coder/src/utilities.ts index ddc06d91963..9d5d3b6023b 100644 --- a/packages/abi-coder/src/utilities.ts +++ b/packages/abi-coder/src/utilities.ts @@ -3,7 +3,7 @@ import { concat, arrayify } from '@ethersproject/bytes'; import { ErrorCode, FuelError } from '@fuel-ts/errors'; import { U64Coder } from './coders/u64'; -import { BYTES_CODER_TYPE, VEC_CODER_TYPE, STRING_CODER_TYPE, WORD_SIZE } from './constants'; +import { BYTES_CODER_TYPE, VEC_CODER_TYPE, STD_STRING_CODER_TYPE, WORD_SIZE } from './constants'; export type DynamicData = { [pointerIndex: number]: Uint8ArrayWithDynamicData; @@ -144,7 +144,7 @@ export const isPointerType = (type: string) => { }; export const isHeapType = (type: string) => - type === VEC_CODER_TYPE || type === BYTES_CODER_TYPE || type === STRING_CODER_TYPE; + type === VEC_CODER_TYPE || type === BYTES_CODER_TYPE || type === STD_STRING_CODER_TYPE; export function findOrThrow( arr: readonly T[], From b09c799b0032822dfd99c27e083bb91c7866bcb9 Mon Sep 17 00:00:00 2001 From: Cameron Manavian Date: Mon, 2 Oct 2023 21:48:49 -0700 Subject: [PATCH 55/55] improve assertions --- packages/fuel-gauge/src/std-lib-string.test.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/fuel-gauge/src/std-lib-string.test.ts b/packages/fuel-gauge/src/std-lib-string.test.ts index 13353fa1495..36d77440def 100644 --- a/packages/fuel-gauge/src/std-lib-string.test.ts +++ b/packages/fuel-gauge/src/std-lib-string.test.ts @@ -1,4 +1,5 @@ import { generateTestWallet } from '@fuel-ts/wallet/test-utils'; +import type { BN } from 'fuels'; import { type Contract, bn, @@ -39,9 +40,9 @@ describe('std-lib-string Tests', () => { it('should test std-lib-string input', async () => { const INPUT = 'Hello World'; - await contractInstance.functions.accepts_dynamic_string(INPUT).call(); + const { value } = await contractInstance.functions.accepts_dynamic_string(INPUT).call(); - expect(true).toBe(true); + expect(value).toBeUndefined(); }); it('should test String input [predicate-std-lib-string]', async () => { @@ -82,10 +83,10 @@ describe('std-lib-string Tests', () => { const wallet = await setup(); type MainArgs = [string]; const scriptInstance = getScript('script-std-lib-string', wallet); - const INPUT = 'Hello World'; - await scriptInstance.functions.main(INPUT).call(); - expect(true).toBe(true); + const { value } = await scriptInstance.functions.main(INPUT).call(); + + expect(value.toNumber()).toStrictEqual(0); }); });