Skip to content

Commit

Permalink
#252 Add capability to byte slice to be optional (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
nevendyulgerov authored Oct 30, 2024
1 parent fc4aa62 commit 573c3f1
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 2 deletions.
25 changes: 23 additions & 2 deletions apps/web/src/components/specification/decoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
decodeFunctionData,
parseAbiParameters,
slice,
SliceOffsetOutOfBoundsError,
} from "viem";
import SpecificationModeNotSupportedError from "./errors/SpecificationModeNotSupported";
import { ABI_PARAMS, JSON_ABI, Specification, specModes } from "./types";
Expand Down Expand Up @@ -70,8 +71,28 @@ const addPiecesToEnvelope = (e: Envelope): Envelope => {
try {
if (e.spec.sliceInstructions?.length) {
e.spec.sliceInstructions.forEach((instruction, index) => {
const { from, to, name, type } = instruction;
const part = slice(e.input, from, to);
const {
from,
to,
name,
type,
optional = false,
} = instruction;
let part;

try {
part = slice(e.input, from, to);
} catch (err: any) {
if (
err instanceof SliceOffsetOutOfBoundsError &&
optional
) {
part = "0x" as Hex;
} else {
throw err;
}
}

const decodedPart =
!isNil(type) && !isEmpty(type)
? head(decodeAbiParameters([{ type, name }], part))
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/components/specification/systemSpecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const ERC20PortalSpec: Specification = {
{ from: 1, to: 21, name: "tokenAddress" },
{ from: 21, to: 41, name: "from" },
{ from: 41, to: 73, name: "amount", type: "uint" },
{ from: 73, name: "execLayerData", optional: true },
],
abiParams: [],
conditionals: [
Expand Down Expand Up @@ -135,6 +136,7 @@ const EtherPortalSpec: Specification = {
sliceInstructions: [
{ from: 0, to: 20, name: "sender" },
{ from: 20, to: 52, name: "amount", type: "uint256" },
{ from: 52, name: "execLayerData", optional: true },
],
abiParams: [],
conditionals: [
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/components/specification/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export interface SliceInstruction {
name?: string;
/** The type to decode e.g. uint. Leaving empty will default to the raw sliced return; useful for Address for example.*/
type?: AbiType;
/** A flag to signal to the decoder not to throw an exception caused by slicing the defined byte range.*/
optional?: boolean;
}

type Commons = {
Expand Down
36 changes: 36 additions & 0 deletions apps/web/test/components/specification/decoder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,44 @@ Slice name: "from" (Is it the right one?)`,
expect(envelope.result).toEqual({
amount: 10000000000000000n,
sender: "0x0c70e9a737aa92055c8c1217bf887a65cb2292f4",
execLayerData: "0x",
});
});

it("should decode ether-portal data with the exec-layer information", () => {
const envelope = decodePayload(
systemSpecification.EtherPortalSpec,
encodedDataSamples.etherPortalSampleWithExecLayer,
);

expect(envelope.result).toEqual({
amount: 300n,
execLayerData:
"0x33303020657468206465706f736974656420746f20307833613134363931353532376264313532383032366235633134333335303938646666323730306361",
sender: "0x3a146915527bd1528026b5c14335098dff2700ca",
});
});

it("should fail to decode ether-portal data with required but missing exec-layer information", () => {
const envelope = decodePayload(
{
...systemSpecification.EtherPortalSpec,
sliceInstructions:
systemSpecification.EtherPortalSpec.sliceInstructions?.map(
(instruction) =>
instruction.name === "execLayerData"
? {
...instruction,
optional: false,
}
: instruction,
),
},
encodedDataSamples.etherPortalSampleWithoutExecLayer,
);

expect(envelope.result).toEqual({});
});
});

describe("Struct definition example cases", () => {
Expand Down

0 comments on commit 573c3f1

Please sign in to comment.