Skip to content

Commit

Permalink
Introducing the new AbiEncoded node. Expanding TypeEquivalent to incl…
Browse files Browse the repository at this point in the history
…ude AbiEncoded (in addition to Calldata)
  • Loading branch information
cristovaoth committed Jun 30, 2023
1 parent 5b26f7c commit f7737f5
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 39 deletions.
7 changes: 5 additions & 2 deletions packages/evm/contracts/Decoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ library Decoder {
result
);
result.size += 32;
} else if (paramType == ParameterType.Calldata) {
} else if (
paramType == ParameterType.Calldata ||
paramType == ParameterType.AbiEncoded
) {
__block__(
data,
location + 32 + 4,
location + 32 + (paramType == ParameterType.Calldata ? 4 : 0),
node,
node.children.length,
false,
Expand Down
13 changes: 9 additions & 4 deletions packages/evm/contracts/Integrity.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ library Integrity {
if (
paramType != ParameterType.Tuple &&
paramType != ParameterType.Array &&
paramType != ParameterType.Calldata
paramType != ParameterType.Calldata &&
paramType != ParameterType.AbiEncoded
) {
revert UnsuitableParameterType(index);
}
Expand Down Expand Up @@ -201,7 +202,8 @@ library Integrity {
}
} else if (
condition.paramType == ParameterType.Tuple ||
condition.paramType == ParameterType.Calldata
condition.paramType == ParameterType.Calldata ||
condition.paramType == ParameterType.AbiEncoded
) {
if (childBounds.length == 0) {
revert UnsuitableChildCount(i);
Expand Down Expand Up @@ -286,9 +288,12 @@ library Integrity {
uint256 j,
Topology.Bounds[] memory childrenBounds
) private pure returns (bool) {
ParameterType leftParamType = Topology
.typeTree(conditions, i, childrenBounds)
.paramType;
return
Topology.typeTree(conditions, i, childrenBounds).paramType ==
ParameterType.Calldata &&
(leftParamType == ParameterType.Calldata ||
leftParamType == ParameterType.AbiEncoded) &&
Topology.typeTree(conditions, j, childrenBounds).paramType ==
ParameterType.Dynamic;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/evm/contracts/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ enum ParameterType {
Dynamic,
Tuple,
Array,
Calldata
Calldata,
AbiEncoded
}

enum Operator {
Expand All @@ -33,7 +34,7 @@ enum Operator {
/* 04: */ _Placeholder04,
// ------------------------------------------------------------
// 05-14: COMPLEX EXPRESSIONS
// paramType: Calldata / Tuple / Array,
// paramType: Calldata / AbiEncoded / Tuple / Array,
// ✅ children
// 🚫 compValue
/* 05: */ Matches,
Expand Down
152 changes: 121 additions & 31 deletions packages/evm/test/Integrity.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1568,65 +1568,155 @@ describe("Integrity", async () => {
it("sibling type equivalence - ok", async () => {
const { integrity, enforce } = await loadFixture(setup);

const conditions = [
{
parent: 0,
paramType: ParameterType.None,
operator: Operator.Or,
compValue: "0x",
},
{
parent: 0,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 0,
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Static,
operator: Operator.Pass,
compValue: "0x",
},
];
await expect(enforce(conditions)).to.not.be.reverted;
// A function with a dynamic argument, which is also an embedded Calldata encoded field
await expect(
enforce([
{
parent: 0,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 0,
paramType: ParameterType.None,
operator: Operator.And,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 2,
paramType: ParameterType.Static,
operator: Operator.Pass,
compValue: "0x",
},
])
).to.not.be.reverted;

// Dynamic should not come first for EquvialentSiblingTypeTrees
// A function with a dynamic argument, which is also an embedded AbiEncoded encoded field
await expect(
enforce([
{
parent: 0,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 0,
paramType: ParameterType.None,
operator: Operator.Or,
operator: Operator.And,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.AbiEncoded,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 2,
paramType: ParameterType.Static,
operator: Operator.Pass,
compValue: "0x",
},
])
).to.not.be.reverted;

// Dynamic can't come before the Calldata node that actually defines the type tree and should be the Anchor
await expect(
enforce([
{
parent: 0,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 0,
paramType: ParameterType.None,
operator: Operator.And,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},

{
parent: 3,
paramType: ParameterType.Static,
operator: Operator.Pass,
compValue: "0x",
},
])
)
.to.be.revertedWithCustomError(integrity, "UnsuitableChildTypeTree")
.withArgs(1);

// Dynamic can't come before the AbiEncoded node that actually defines the type tree and should be the Anchor
await expect(
enforce([
{
parent: 0,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 2,
parent: 0,
paramType: ParameterType.None,
operator: Operator.And,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
compValue: "0x",
},
{
parent: 1,
paramType: ParameterType.Calldata,
operator: Operator.Pass,
compValue: "0x",
},

{
parent: 3,
paramType: ParameterType.Static,
operator: Operator.Pass,
compValue: "0x",
},
])
)
.to.be.revertedWithCustomError(integrity, "UnsuitableChildTypeTree")
.withArgs(0);
.withArgs(1);
});
});
});
Expand Down
63 changes: 63 additions & 0 deletions packages/evm/test/decoder/ParameterTypeDynamic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,69 @@ describe("Decoder library", async () => {
await decoder.pluck(data as string, tupleField.location, tupleField.size)
).to.equal(encode(["bytes"], ["0xbadfed"], YesRemoveOffset));
});
it("plucks Dynamic from embedded AbiEncoded", async () => {
const { decoder } = await loadFixture(setup);

const iface = new Interface(["function fn(bytes a)"]);
const embedded = defaultAbiCoder.encode(
["bytes", "bool", "bytes2[]"],
["0xbadfed", true, ["0xccdd", "0x3333"]]
);

const data = iface.encodeFunctionData("fn", [embedded]);

const condition = {
paramType: ParameterType.Calldata,
operator: Operator.Matches,
children: [
{
paramType: ParameterType.AbiEncoded,
operator: Operator.Matches,
children: [
{
paramType: ParameterType.Dynamic,
operator: Operator.Pass,
children: [],
},
{
paramType: ParameterType.Static,
operator: Operator.Pass,
children: [],
},
{
paramType: ParameterType.Array,
operator: Operator.Pass,
children: [
{
paramType: ParameterType.Static,
operator: Operator.Pass,
children: [],
},
],
},
],
},
],
};

const result = await decoder.inspect(data as string, condition);

const field1 = result.children[0].children[0];
expect(
await decoder.pluck(data as string, field1.location, field1.size)
).to.equal(encode(["bytes"], ["0xbadfed"]));

const field2 = result.children[0].children[1];
expect(
await decoder.pluck(data as string, field2.location, field2.size)
).to.equal(encode(["bool"], ["false"], false));

const field3 = result.children[0].children[2];
expect(
await decoder.pluck(data as string, field3.location, field3.size)
).to.equal(encode(["bytes2[]"], [["0xccdd", "0x3333"]]));
});

it("plucks Dynamic from type equivalent branch", async () => {
const { decoder } = await loadFixture(setup);

Expand Down
1 change: 1 addition & 0 deletions packages/evm/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export enum ParameterType {
Tuple,
Array,
Calldata,
AbiEncoded,
}

export enum Operator {
Expand Down

0 comments on commit f7737f5

Please sign in to comment.