Implement ABI encoding of calldata arrays and structs.

This commit is contained in:
Daniel Kirchner
2019-04-04 13:05:32 +02:00
parent d82157d46a
commit 91a2a9a9c3
19 changed files with 531 additions and 25 deletions
@@ -0,0 +1,22 @@
pragma experimental ABIEncoderV2;
contract C {
function g(uint256[] calldata) external pure returns (bytes memory) {
return msg.data;
}
function f(uint256[][1] calldata s) external view returns (bool) {
bytes memory a = this.g(s[0]);
uint256[] memory m = s[0];
bytes memory b = this.g(m);
assert(a.length == b.length);
for (uint i = 0; i < a.length; i++)
assert(a[i] == b[i]);
return true;
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[][1]): 32, 32, 0 -> true
// f(uint256[][1]): 32, 32, 1, 42 -> true
// f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true
@@ -0,0 +1,33 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(uint256[] calldata s) external view returns (bytes memory) {
return this.f(s);
}
function h(uint8[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function i(uint8[] calldata s) external view returns (bytes memory) {
return this.h(s);
}
function j(bytes calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function k(bytes calldata s) external view returns (bytes memory) {
return this.j(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[]): 32, 3, 23, 42, 87 -> 32, 160, 32, 3, 23, 42, 87
// g(uint256[]): 32, 3, 23, 42, 87 -> 32, 160, 32, 3, 23, 42, 87
// h(uint8[]): 32, 3, 23, 42, 87 -> 32, 160, 32, 3, 23, 42, 87
// i(uint8[]): 32, 3, 23, 42, 87 -> 32, 160, 32, 3, 23, 42, 87
// h(uint8[]): 32, 3, 0xFF23, 0x1242, 0xAB87 -> FAILURE
// i(uint8[]): 32, 3, 0xAB23, 0x1242, 0xFF87 -> FAILURE
// j(bytes): 32, 3, hex"123456" -> 32, 96, 32, 3, left(0x123456)
// k(bytes): 32, 3, hex"AB33FF" -> 32, 96, 32, 3, left(0xAB33FF)
@@ -0,0 +1,34 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(uint256[][2] calldata s, uint256 which) external view returns (bytes memory) {
return this.f(s[which]);
}
function h(uint8[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function i(uint8[][2] calldata s, uint256 which) external view returns (bytes memory) {
return this.h(s[which]);
}
function j(bytes calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function k(bytes[2] calldata s, uint256 which) external view returns (bytes memory) {
return this.j(s[which]);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[]): 32, 3, 42, 23, 87 -> 32, 160, 32, 3, 42, 23, 87
// g(uint256[][2],uint256): 0x40, 0, 0x40, 0xC0, 3, 42, 23, 87, 4, 11, 13, 17 -> 32, 160, 32, 3, 42, 23, 87
// g(uint256[][2],uint256): 0x40, 1, 0x40, 0xC0, 3, 42, 23, 87, 4, 11, 13, 17, 27 -> 32, 192, 32, 4, 11, 13, 17, 27
// h(uint8[]): 32, 3, 42, 23, 87 -> 32, 160, 32, 3, 42, 23, 87
// i(uint8[][2],uint256): 0x40, 0, 0x40, 0xC0, 3, 42, 23, 87, 4, 11, 13, 17 -> 32, 160, 32, 3, 42, 23, 87
// i(uint8[][2],uint256): 0x40, 1, 0x40, 0xC0, 3, 42, 23, 87, 4, 11, 13, 17, 27 -> 32, 192, 32, 4, 11, 13, 17, 27
// j(bytes): 32, 3, hex"AB11FF" -> 32, 96, 32, 3, left(0xAB11FF)
// k(bytes[2],uint256): 0x40, 0, 0x40, 0x63, 3, hex"AB11FF", 4, hex"FF791432" -> 32, 96, 32, 3, left(0xAB11FF)
// k(bytes[2],uint256): 0x40, 1, 0x40, 0x63, 3, hex"AB11FF", 4, hex"FF791432" -> 32, 96, 32, 4, left(0xFF791432)
@@ -0,0 +1,49 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint8[][1][] calldata s) external pure returns (bytes memory) {
return msg.data;
}
function f2(uint256[][2][] calldata s) external pure returns (bytes memory) {
return msg.data;
}
function reenc_f(uint8[][1][] calldata s) external view returns (bytes memory) {
return this.f(s);
}
function reenc_f2(uint256[][2][] calldata s) external view returns (bytes memory) {
return this.f2(s);
}
function g() external returns (bytes memory) {
uint8[][1][] memory m = new uint8[][1][](1);
m[0][0] = new uint8[](1);
m[0][0][0] = 42;
return this.f(m);
}
function h() external returns (bytes memory) {
uint8[][1][] memory m = new uint8[][1][](1);
m[0][0] = new uint8[](1);
m[0][0][0] = 42;
return this.reenc_f(m);
}
function i() external returns (bytes memory) {
uint256[][2][] memory m = new uint256[][2][](1);
m[0][0] = new uint256[](1);
m[0][1] = new uint256[](1);
m[0][0][0] = 42;
m[0][1][0] = 42;
return this.f2(m);
}
function j() external returns (bytes memory) {
uint256[][2][] memory m = new uint256[][2][](1);
m[0][0] = new uint256[](1);
m[0][1] = new uint256[](1);
m[0][0][0] = 42;
m[0][1][0] = 42;
return this.reenc_f2(m);
}
}
// ====
// EVMVersion: >homestead
// ----
// g() -> 32, 196, hex"eccb829a", 32, 1, 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000"
// h() -> 32, 196, hex"eccb829a", 32, 1, 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000"
@@ -0,0 +1,30 @@
pragma experimental ABIEncoderV2;
contract C {
function f(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) {
assert(s.length == 3);
return (s[0](), s[1](), s[2]());
}
function f_reenc(function() external returns (uint)[] calldata s) external returns (uint, uint, uint) {
return this.f(s);
}
function getter1() external returns (uint) {
return 23;
}
function getter2() external returns (uint) {
return 37;
}
function getter3() external returns (uint) {
return 71;
}
function g(bool reenc) external returns (uint, uint, uint) {
function() external returns (uint)[] memory a = new function() external returns (uint)[](3);
a[0] = this.getter1;
a[1] = this.getter2;
a[2] = this.getter3;
return reenc ? this.f_reenc(a) : this.f(a);
}
}
// ----
// g(bool): false -> 23, 37, 71
// g(bool): true -> 23, 37, 71
@@ -0,0 +1,31 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[][] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(uint256[][] calldata s) external view returns (bytes memory) {
return this.f(s);
}
function h(uint8[][] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function i(uint8[][] calldata s) external view returns (bytes memory) {
return this.h(s);
}
function j(bytes[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function k(bytes[] calldata s) external view returns (bytes memory) {
return this.j(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 13, 17, 23, 4, 27, 31, 37, 41 -> 32, 416, 32, 2, 64, 192, 3, 13, 17, 23, 4, 27, 31, 37, 41
// g(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 13, 17, 23, 4, 27, 31, 37, 41 -> 32, 416, 32, 2, 64, 192, 3, 13, 17, 23, 4, 27, 31, 37, 41
// h(uint8[][]): 0x20, 2, 0x40, 0xC0, 3, 13, 17, 23, 4, 27, 31, 37, 41 -> 32, 416, 32, 2, 64, 192, 3, 13, 17, 23, 4, 27, 31, 37, 41
// i(uint8[][]): 0x20, 2, 0x40, 0xC0, 3, 13, 17, 23, 4, 27, 31, 37, 41 -> 32, 416, 32, 2, 64, 192, 3, 13, 17, 23, 4, 27, 31, 37, 41
// j(bytes[]): 0x20, 2, 0x40, 0x63, 3, hex"131723", 4, hex"27313741" -> 32, 256, 32, 2, 64, 128, 3, left(0x131723), 4, left(0x27313741)
// k(bytes[]): 0x20, 2, 0x40, 0x63, 3, hex"131723", 4, hex"27313741" -> 32, 256, 32, 2, 64, 128, 3, left(0x131723), 4, left(0x27313741)
@@ -0,0 +1,25 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[3] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(uint256[3] calldata s) external view returns (bytes memory) {
return this.f(s);
}
function h(uint8[3] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function i(uint8[3] calldata s) external view returns (bytes memory) {
return this.h(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// g(uint256[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// h(uint8[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// i(uint8[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// h(uint8[3]): 0xFF23, 0x1242, 0xAB87 -> FAILURE
// i(uint8[3]): 0xAB23, 0x1242, 0xFF87 -> FAILURE
@@ -0,0 +1,49 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint8[1][][1] calldata s) external pure returns (bytes memory) {
return msg.data;
}
function f2(uint256[2][][2] calldata s) external pure returns (bytes memory) {
return msg.data;
}
function reenc_f(uint8[1][][1] calldata s) external view returns (bytes memory) {
return this.f(s);
}
function reenc_f2(uint256[2][][2] calldata s) external view returns (bytes memory) {
return this.f2(s);
}
function g() external returns (bytes memory) {
uint8[1][][1] memory m = [new uint8[1][](1)];
m[0][0][0] = 42;
return this.f(m);
}
function h() external returns (bytes memory) {
uint8[1][][1] memory m = [new uint8[1][](1)];
m[0][0][0] = 42;
return this.reenc_f(m);
}
function i() external returns (bytes memory) {
uint256[2][][2] memory m = [new uint256[2][](1),new uint256[2][](1)];
m[0][0][0] = 0x00042;
m[0][0][1] = 0x00142;
m[1][0][0] = 0x10042;
m[1][0][1] = 0x10142;
return this.f2(m);
}
function j() external returns (bytes memory) {
uint256[2][][2] memory m = [new uint256[2][](1),new uint256[2][](1)];
m[0][0][0] = 0x00042;
m[0][0][1] = 0x00142;
m[1][0][0] = 0x10042;
m[1][0][1] = 0x10142;
return this.reenc_f2(m);
}
}
// ====
// EVMVersion: >homestead
// ----
// g() -> 32, 132, hex"15cfcc01", 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000"
// h() -> 32, 132, hex"15cfcc01", 32, 32, 1, 42, hex"00000000000000000000000000000000000000000000000000000000"
// i() -> 32, 292, hex"dc0ee233", 32, 64, 160, 1, 0x42, 0x000142, 1, 0x010042, 0x010142, hex"00000000000000000000000000000000000000000000000000000000"
// j() -> 32, 292, hex"dc0ee233", 32, 64, 160, 1, 0x42, 0x000142, 1, 0x010042, 0x010142, hex"00000000000000000000000000000000000000000000000000000000"
@@ -0,0 +1,25 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[3] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(uint256[3][2] calldata s, uint256 which) external view returns (bytes memory) {
return this.f(s[which]);
}
function h(uint8[3] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function i(uint8[3][2] calldata s, uint256 which) external view returns (bytes memory) {
return this.h(s[which]);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// g(uint256[3][2],uint256): 23, 42, 87, 123, 142, 187, 0 -> 32, 96, 23, 42, 87
// g(uint256[3][2],uint256): 23, 42, 87, 123, 142, 187, 1 -> 32, 96, 123, 142, 187
// h(uint8[3]): 23, 42, 87 -> 32, 96, 23, 42, 87
// i(uint8[3][2],uint256): 23, 42, 87, 123, 142, 187, 0 -> 32, 96, 23, 42, 87
// i(uint8[3][2],uint256): 23, 42, 87, 123, 142, 187, 1 -> 32, 96, 123, 142, 187
@@ -0,0 +1,16 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint256[] a; }
function f(S[] calldata s) external pure returns (bytes memory) {
return abi.encode(s);
}
function g(S[] calldata s) external view returns (bytes memory) {
return this.f(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f((uint256[])[]): 32, 1, 32, 32, 3, 17, 42, 23 -> 32, 256, 32, 1, 32, 32, 3, 17, 42, 23
// g((uint256[])[]): 32, 1, 32, 32, 3, 17, 42, 23 -> 32, 256, 32, 1, 32, 32, 3, 17, 42, 23
@@ -0,0 +1,20 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[] calldata s1, uint256[] calldata s2, bool which) external pure returns (bytes memory) {
if (which)
return abi.encode(s1);
else
return abi.encode(s2);
}
function g(uint256[] calldata s1, uint256[] calldata s2, bool which) external view returns (bytes memory) {
return this.f(s1, s2, which);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[],uint256[],bool): 0x60, 0xE0, true, 3, 23, 42, 87, 2, 51, 72 -> 32, 160, 0x20, 3, 23, 42, 87
// f(uint256[],uint256[],bool): 0x60, 0xE0, false, 3, 23, 42, 87, 2, 51, 72 -> 32, 128, 0x20, 2, 51, 72
// g(uint256[],uint256[],bool): 0x60, 0xE0, true, 3, 23, 42, 87, 2, 51, 72 -> 32, 160, 0x20, 3, 23, 42, 87
// g(uint256[],uint256[],bool): 0x60, 0xE0, false, 3, 23, 42, 87, 2, 51, 72 -> 32, 128, 0x20, 2, 51, 72
@@ -0,0 +1,20 @@
pragma experimental ABIEncoderV2;
contract C {
function f(uint256[3] calldata s1, uint256[2] calldata s2, bool which) external pure returns (bytes memory) {
if (which)
return abi.encode(s1);
else
return abi.encode(s2);
}
function g(uint256[3] calldata s1, uint256[2] calldata s2, bool which) external view returns (bytes memory) {
return this.f(s1, s2, which);
}
}
// ====
// EVMVersion: >homestead
// ----
// f(uint256[3],uint256[2],bool): 23, 42, 87, 51, 72, true -> 32, 96, 23, 42, 87
// f(uint256[3],uint256[2],bool): 23, 42, 87, 51, 72, false -> 32, 64, 51, 72
// g(uint256[3],uint256[2],bool): 23, 42, 87, 51, 72, true -> 32, 96, 23, 42, 87
// g(uint256[3],uint256[2],bool): 23, 42, 87, 51, 72, false -> 32, 64, 51, 72
@@ -0,0 +1,18 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint256[] a; }
function f(S calldata s) external returns (bytes memory) {
return abi.encode(s);
}
function g(S calldata s) external returns (bytes memory) {
return this.f(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f((uint256[])): 0x20, 0x20, 3, 42, 23, 17 -> 32, 192, 0x20, 0x20, 3, 42, 23, 17
// g((uint256[])): 0x20, 0x20, 3, 42, 23, 17 -> 32, 192, 0x20, 0x20, 3, 42, 23, 17
@@ -0,0 +1,18 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint256 a; }
function f(S calldata s) external returns (bytes memory) {
return abi.encode(s);
}
function g(S calldata s) external returns (bytes memory) {
return this.f(s);
}
}
// ====
// EVMVersion: >homestead
// ----
// f((uint256)): 3 -> 32, 32, 3
// g((uint256)): 3 -> 32, 32, 3