Merge pull request #13464 from ethereum/copying_reference_types

Add tests for copying reference types between data locations
This commit is contained in:
Daniel Kirchner 2022-09-15 15:44:38 +02:00 committed by GitHub
commit 1fbee8259a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1223 additions and 0 deletions

View File

@ -0,0 +1,61 @@
pragma abicoder v2;
contract C {
mapping (uint => uint8[][]) m;
uint8[][] s;
constructor() {
s = new uint8[][](2);
s[0] = new uint8[](2);
s[0][0] = 10;
s[0][1] = 11;
s[1] = new uint8[](3);
s[1][0] = 12;
s[1][1] = 13;
s[1][2] = 14;
}
function from_storage() public returns (uint8[][] memory) {
m[0] = new uint8[][](2);
m[0][0] = s[0];
m[0][1] = s[1];
return m[0];
}
function from_storage_ptr() public returns (uint8[][] memory) {
uint8[][] storage sPtr = s;
m[0] = new uint8[][](2);
m[0][0] = sPtr[0];
m[0][1] = sPtr[1];
return m[0];
}
function from_memory() public returns (uint8[][] memory) {
uint8[][] memory a = s;
m[0] = new uint8[][](2);
m[0][0] = a[0];
m[0][1] = a[1];
return m[0];
}
function from_calldata(uint8[][] calldata _a) public returns (uint8[][] memory) {
m[0] = new uint8[][](2);
m[0][0] = _a[0];
m[0][1] = _a[1];
return m[0];
}
}
// ----
// from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// gas irOptimized: 150098
// gas legacy: 150830
// gas legacyOptimized: 148728
// from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14

View File

@ -0,0 +1,45 @@
pragma abicoder v2;
contract C {
uint256[][] a1;
uint256[][2] a2;
uint256[2][] a3;
uint256[2][2] a4;
constructor() {
a1 = new uint256[][](2);
a1[0] = [1, 2];
a1[1] = [3, 4, 5];
a2[0] = [6, 7, 8];
a2[1] = [9];
a3.push([1, 2]);
a3.push([3, 4]);
a3.push([5, 6]);
a4 = [[10, 11], [12, 13]];
}
function test1() external returns (uint256[][] memory) {
return a1;
}
function test2() external returns (uint256[][2] memory) {
return a2;
}
function test3() external returns (uint256[2][] memory) {
return a3;
}
function test4() external returns (uint256[2][2] memory) {
return a4;
}
}
// ----
// test1() -> 0x20, 2, 0x40, 0xa0, 2, 1, 2, 3, 3, 4, 5
// test2() -> 0x20, 0x40, 0xc0, 3, 6, 7, 8, 1, 9
// test3() -> 0x20, 3, 1, 2, 3, 4, 5, 6
// test4() -> 10, 11, 12, 13

View File

@ -0,0 +1,45 @@
pragma abicoder v2;
contract C {
mapping (uint => uint8[][]) m;
uint8[][] s;
constructor() {
s = new uint8[][](2);
s[0] = new uint8[](2);
s[0][0] = 10;
s[0][1] = 11;
s[1] = new uint8[](3);
s[1][0] = 12;
s[1][1] = 13;
s[1][2] = 14;
}
function from_storage() public returns (uint8[][] memory) {
m[0] = s;
return m[0];
}
function from_storage_ptr() public returns (uint8[][] memory) {
uint8[][] storage sPtr = s;
m[0] = sPtr;
return m[0];
}
function from_memory() public returns (uint8[][] memory) {
uint8[][] memory a = s;
m[0] = a;
return m[0];
}
}
// ----
// from_storage() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// gas irOptimized: 147913
// gas legacy: 148965
// gas legacyOptimized: 146935
// from_storage_ptr() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// from_memory() -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14

View File

@ -0,0 +1,18 @@
pragma abicoder v2;
contract C {
mapping (uint => uint8[][]) m;
uint8[][] s;
function from_calldata(uint8[][] calldata _a) public returns (uint8[][] memory) {
m[0] = _a;
return m[0];
}
}
// ====
// compileViaYul: true
// ----
// from_calldata(uint8[][]): 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14 -> 0x20, 2, 0x40, 0xa0, 2, 10, 11, 3, 12, 13, 14
// gas irOptimized: 139927

View File

@ -0,0 +1,40 @@
pragma abicoder v2;
contract C {
struct S {
uint8[] a;
uint8[2] b;
}
S[][][] s1;
S[][1][] s2;
S[1][][1] s3;
function test1(S[][][] calldata _a) public returns (S[][] memory){
s1.push();
s1[0] = _a[0];
return s1[0];
}
function test2(S[][1][] calldata _a) public returns (S[][1] memory) {
s2.push();
s2[0] = _a[0];
return s2[0];
}
function test3(S[1][][2] calldata _a) public returns (S[1][] memory) {
s3[0] = _a[1];
return s3[0];
}
}
// ====
// compileViaYul: true
// ----
// test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29
// gas irOptimized: 327878
// test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 140894
// test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 188509

View File

@ -0,0 +1,40 @@
pragma abicoder v2;
contract C {
struct S {
uint8[] a;
uint8[2] b;
}
S[][][] s1;
S[][1][] s2;
S[1][][1] s3;
function test1(S[][][] memory _a) public returns (S[][] memory){
s1.push();
s1[0] = _a[0];
return s1[0];
}
function test2(S[][1][] memory _a) public returns (S[][1] memory) {
s2.push();
s2[0] = _a[0];
return s2[0];
}
function test3(S[1][][2] memory _a) public returns (S[1][] memory) {
s3[0] = _a[1];
return s3[0];
}
}
// ====
// compileViaYul: true
// ----
// test1((uint8[],uint8[2])[][][]): 0x20, 1, 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29
// gas irOptimized: 332334
// test2((uint8[],uint8[2])[][1][]): 0x20, 2, 0x40, 0x0160, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13, 0x20, 1, 0x20, 0x60, 31, 37, 2, 23, 29 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 145029
// test3((uint8[],uint8[2])[1][][2]): 0x20, 0x40, 0x60, 0, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 288, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 192344

View File

@ -0,0 +1,41 @@
pragma abicoder v2;
contract C {
function test1(uint8[][][] calldata _a) public returns (uint8[][] memory) {
return _a[1];
}
function test2(uint8[][1][] calldata _a) public returns (uint8[][1] memory) {
return _a[0];
}
function test3(uint8[2][][2] calldata _a) public returns (uint8[2][] memory) {
return _a[0];
}
function test4(uint16[][] calldata _a) public returns (uint16[][] memory) {
uint16[][][] memory tmp = new uint16[][][](2);
tmp[1] = _a;
return tmp[1];
}
function test5(uint32[][2] calldata _a) public returns (uint32[][2] memory) {
uint32[][2][] memory tmp = new uint32[][2][](1);
tmp[0] = _a;
return tmp[0];
}
function test6(uint32[2][] calldata _a) public returns (uint32[2][] memory) {
uint32[2][][] memory tmp = new uint32[2][][](1);
tmp[0] = _a;
return tmp[0];
}
}
// ----
// test1(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// test2(uint8[][1][]): 0x20, 2, 0x40, 0xe0, 0x20, 3, 12, 13, 14, 0x20, 3, 15, 16, 17 -> 0x20, 0x20, 3, 12, 13, 14
// test3(uint8[2][][2]): 0x20, 0x40, 0xa0, 1, 7, 7, 2, 8, 8, 0x09, 9 -> 0x20, 1, 7, 7
// test4(uint16[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// test5(uint32[][2]): 0x20, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 0x40, 0x80, 1, 7, 2, 8, 9
// test6(uint32[2][]): 0x20, 2, 5, 6, 7, 8 -> 0x20, 2, 5, 6, 7, 8

View File

@ -0,0 +1,30 @@
contract C {
uint8[2][2] a;
uint8[2][2][2] a2;
function test(uint8[2][2][2] calldata _a) public {
a = _a[0];
require(a[0][0] == 1);
require(a[0][1] == 2);
require(a[1][0] == 3);
require(a[1][1] == 4);
}
function test2(uint8[2][2] calldata _a) public {
a2[0] = _a;
require(a2[0][0][0] == 1);
require(a2[0][0][1] == 2);
require(a2[0][1][0] == 3);
require(a2[0][1][1] == 4);
require(a2[1][0][0] == 0);
require(a2[1][0][1] == 0);
require(a2[1][1][0] == 0);
require(a2[1][1][1] == 0);
}
}
// ----
// test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8
// test2(uint8[2][2]): 1, 2, 3, 4
// gas irOptimized: 119939
// gas legacyOptimized: 120228

View File

@ -0,0 +1,41 @@
pragma abicoder v2;
contract C {
function test1(uint8[][][] memory _a) public returns (uint8[][] memory) {
return _a[1];
}
function test2(uint8[][1][] memory _a) public returns (uint8[][1] memory) {
return _a[0];
}
function test3(uint8[2][][2] memory _a) public returns (uint8[2][] memory) {
return _a[0];
}
function test4(uint16[][] memory _a) public returns (uint16[][] memory) {
uint16[][][] memory tmp = new uint16[][][](2);
tmp[1] = _a;
return tmp[1];
}
function test5(uint32[][2] memory _a) public returns (uint32[][2] memory) {
uint32[][2][] memory tmp = new uint32[][2][](1);
tmp[0] = _a;
return tmp[0];
}
function test6(uint32[2][] memory _a) public returns (uint32[2][] memory) {
uint32[2][][] memory tmp = new uint32[2][][](1);
tmp[0] = _a;
return tmp[0];
}
}
// ----
// test1(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// test2(uint8[][1][]): 0x20, 2, 0x40, 0xe0, 0x20, 3, 12, 13, 14, 0x20, 3, 15, 16, 17 -> 0x20, 0x20, 3, 12, 13, 14
// test3(uint8[2][][2]): 0x20, 0x40, 0xa0, 1, 7, 7, 2, 8, 8, 0x09, 9 -> 0x20, 1, 7, 7
// test4(uint16[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// test5(uint32[][2]): 0x20, 0x40, 0x80, 1, 7, 2, 8, 9 -> 0x20, 0x40, 0x80, 1, 7, 2, 8, 9
// test6(uint32[2][]): 0x20, 2, 5, 6, 7, 8 -> 0x20, 2, 5, 6, 7, 8

View File

@ -0,0 +1,30 @@
contract C {
uint8[2][2] a1;
uint8[2][2][2] a2;
function test(uint8[2][2][2] memory _a) public {
a1 = _a[0];
require(a1[0][0] == 1);
require(a1[0][1] == 2);
require(a1[1][0] == 3);
require(a1[1][1] == 4);
}
function test2(uint8[2][2] memory _a) public {
a2[0] = _a;
require(a2[0][0][0] == 1);
require(a2[0][0][1] == 2);
require(a2[0][1][0] == 3);
require(a2[0][1][1] == 4);
require(a2[1][0][0] == 0);
require(a2[1][0][1] == 0);
require(a2[1][1][0] == 0);
require(a2[1][1][1] == 0);
}
}
// ----
// test(uint8[2][2][2]): 1, 2, 3, 4, 5, 6, 7, 8
// test2(uint8[2][2]): 1, 2, 3, 4
// gas irOptimized: 119939
// gas legacyOptimized: 120228

View File

@ -0,0 +1,71 @@
pragma abicoder v2;
contract C {
uint8[][][] a1 = new uint8[][][](2);
uint8[][][2] a2;
uint8[][2][] a3 = new uint8[][2][](1);
uint8[2][][] a4 = new uint8[2][][](2);
constructor() {
a1[1] = new uint8[][](2);
a1[1][0] = [3, 4];
a1[1][1] = [5, 6];
a2[0] = new uint8[][](2);
a2[0][0] = [6, 7];
a2[0][1] = [8, 9];
a2[1] = new uint8[][](2);
a2[1][0] = [10, 11];
a3[0][0] = [3, 4];
a3[0][1] = [5, 6];
a4[0] = new uint8[2][](1);
a4[0][0] = [17, 23];
a4[1] = new uint8[2][](1);
a4[1][0] = [19, 31];
}
function test1() public returns (uint8[][] memory) {
return a1[1];
}
function test2() public returns (uint8[][] memory) {
return a2[0];
}
function test3() public returns (uint8[][2] memory) {
return a3[0];
}
function test4() public returns (uint8[2][] memory) {
return a4[1];
}
function test5() public returns (uint8[][][] memory) {
uint8[][][] memory tmp = new uint8[][][](3);
tmp[1] = a1[1];
return tmp;
}
function test6() public returns (uint8[][2][] memory) {
uint8[][2][] memory tmp = new uint8[][2][](2);
tmp[0] = a3[0];
return tmp;
}
function test7() public returns (uint8[2][][] memory) {
uint8[2][][] memory tmp = new uint8[2][][](1);
tmp[0] = a4[0];
return tmp;
}
}
// ----
// test1() -> 0x20, 2, 0x40, 0xa0, 2, 3, 4, 2, 5, 6
// test2() -> 0x20, 2, 0x40, 0xa0, 2, 6, 7, 2, 8, 9
// test3() -> 0x20, 0x40, 0xa0, 2, 3, 4, 2, 5, 6
// test4() -> 0x20, 1, 19, 31
// test5() -> 0x20, 3, 0x60, 0x80, 0x01a0, 0, 2, 0x40, 0xa0, 2, 3, 4, 2, 5, 6, 0
// test6() -> 0x20, 2, 0x40, 0x0140, 0x40, 0xa0, 2, 3, 4, 2, 5, 6, 0x40, 0x60, 0, 0
// test7() -> 0x20, 1, 0x20, 1, 17, 23

View File

@ -0,0 +1,85 @@
pragma abicoder v2;
contract C {
uint8[][][] src1 = new uint8[][][](2);
uint8[][][2] src2;
uint8[][2][] src3 = new uint8[][2][](1);
uint8[2][][] src4 = new uint8[2][][](2);
uint8[][] dst1;
uint8[][] dst2;
uint8[][2] dst3;
uint8[][] dst4;
constructor() {
src1[1] = new uint8[][](2);
src1[1][0] = [3, 4];
src1[1][1] = [5, 6];
src2[0] = new uint8[][](2);
src2[0][0] = [6, 7];
src2[0][1] = [8, 9];
src2[1] = new uint8[][](2);
src2[1][0] = [10, 11];
src3[0][0] = [3, 4];
src3[0][1] = [5, 6];
src4[0] = new uint8[2][](1);
src4[0][0] = [17, 23];
src4[1] = new uint8[2][](1);
src4[1][0] = [19, 31];
}
function test1() public {
dst1 = src1[1];
require(dst1.length == 2);
require(dst1[0][0] == src1[1][0][0]);
require(dst1[0][1] == src1[1][0][1]);
require(dst1[1][0] == src1[1][1][0]);
require(dst1[1][1] == src1[1][1][1]);
}
function test2() public {
dst2 = src2[0];
require(dst2.length == 2);
require(dst2[0][0] == src2[1][0][0]);
require(dst2[0][1] == src2[1][0][1]);
require(dst2[1][0] == src2[1][1][0]);
require(dst2[1][1] == src2[1][1][1]);
}
function test3() public {
dst3 = src3[0];
require(dst3[0][0] == src3[0][0][0]);
require(dst3[0][1] == src3[0][0][1]);
require(dst3[1][0] == src3[0][1][0]);
require(dst3[1][1] == src3[0][1][1]);
}
function test4() public {
dst4 = src4[1];
require(dst4.length == 2);
require(dst4[0][0] == src4[0][0][0]);
require(dst4[0][1] == src4[0][0][1]);
require(dst4[1][0] == src4[0][1][0]);
require(dst4[1][1] == src4[0][1][1]);
}
}
// ----
// test1() ->
// gas irOptimized: 150570
// gas legacy: 151017
// gas legacyOptimized: 150970
// test2() -> FAILURE
// gas irOptimized: 150408
// gas legacy: 150700
// gas legacyOptimized: 150601
// test3() ->
// gas irOptimized: 123810
// gas legacy: 125381
// gas legacyOptimized: 125160
// test4() -> FAILURE

View File

@ -0,0 +1,25 @@
pragma abicoder v2;
contract C {
struct S {
uint8 x;
uint8 y;
}
function test1(S[1][2] calldata a) public returns (S[1][2] memory) {
return a;
}
function test2(S[1][] calldata a) public returns (S[1][] memory) {
return a;
}
function test3(S[][2] calldata a) public returns (S[][2] memory) {
return a;
}
}
// ----
// test1((uint8,uint8)[1][2]): 1, 2, 3, 4 -> 1, 2, 3, 4
// test2((uint8,uint8)[1][]): 0x20, 3, 7, 11, 13, 17, 19, 23 -> 0x20, 3, 7, 11, 13, 17, 19, 23
// test3((uint8,uint8)[][2]): 0x20, 0x40, 0xa0, 1, 3, 7, 2, 11, 13, 17, 19 -> 0x20, 0x40, 0xa0, 1, 3, 7, 2, 11, 13, 17, 19

View File

@ -0,0 +1,38 @@
pragma abicoder v2;
contract C {
struct S {
uint8[] a;
uint8[2] b;
}
S[][] s1;
S[][1] s2;
S[1][] s3;
function test1(S[][] calldata _a) public returns (S[][] memory){
s1 = _a;
return s1;
}
function test2(S[][1] calldata _a) public returns (S[][1] memory) {
s2 = _a;
return s2;
}
function test3(S[1][] calldata _a) public returns (S[1][] memory) {
s3 = _a;
return s3;
}
}
// ====
// compileViaYul: true
// ----
// test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29
// gas irOptimized: 304768
// test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 116476
// test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 187998

View File

@ -0,0 +1,25 @@
pragma abicoder v2;
contract C {
struct S {
uint8 x;
uint8 y;
}
function test1(S[1][2] memory a) public returns (S[1][2] memory r) {
r = a;
}
function test2(S[1][] memory a) public returns (S[1][] memory r) {
r = a;
}
function test3(S[][2] memory a) public returns (S[][2] memory r) {
r = a;
}
}
// ----
// test1((uint8,uint8)[1][2]): 1, 2, 3, 4 -> 1, 2, 3, 4
// test2((uint8,uint8)[1][]): 0x20, 3, 7, 11, 13, 17, 19, 23 -> 0x20, 3, 7, 11, 13, 17, 19, 23
// test3((uint8,uint8)[][2]): 0x20, 0x40, 0xa0, 1, 3, 7, 2, 11, 13, 17, 19 -> 0x20, 0x40, 0xa0, 1, 3, 7, 2, 11, 13, 17, 19

View File

@ -0,0 +1,38 @@
pragma abicoder v2;
contract C {
struct S {
uint8[] a;
uint8[2] b;
}
S[][] s1;
S[][1] s2;
S[1][] s3;
function test1(S[][] memory _a) public returns (S[][] memory){
s1 = _a;
return s1;
}
function test2(S[][1] memory _a) public returns (S[][1] memory) {
s2 = _a;
return s2;
}
function test3(S[1][] memory _a) public returns (S[1][] memory) {
s3 = _a;
return s3;
}
}
// ====
// compileViaYul: true
// ----
// test1((uint8[],uint8[2])[][]): 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29 -> 0x20, 2, 0x40, 0x0140, 1, 0x20, 0x60, 3, 7, 2, 1, 2, 2, 0x40, 0x0100, 0x60, 17, 19, 2, 11, 13, 0x60, 31, 37, 2, 23, 29
// gas irOptimized: 308790
// test2((uint8[],uint8[2])[][1]): 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 0x20, 1, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 118077
// test3((uint8[],uint8[2])[1][]): 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13 -> 0x20, 2, 0x40, 0x0120, 0x20, 0x60, 3, 7, 2, 1, 2, 0x20, 0x60, 17, 19, 2, 11, 13
// gas irOptimized: 190775

View File

@ -0,0 +1,70 @@
pragma abicoder v2;
contract C {
struct S {
uint8 x;
uint8 y;
}
S[][] src1;
S[][1] src2;
S[1][] src3;
S[][] dst1;
S[][1] dst2;
S[1][] dst3;
constructor() {
src1 = new S[][](1);
src1[0].push(S({x: 3, y: 7}));
src1[0].push(S({x: 11, y: 13}));
src2[0].push(S({x: 3, y: 7}));
src2[0].push(S({x: 11, y: 13}));
src2[0].push(S({x: 17, y: 19}));
src3.push([S({x: 3, y: 7})]);
src3.push([S({x: 11, y: 13})]);
}
function test1() public {
dst1 = src1;
require(dst1.length == 1);
require(dst1[0][0].x == src1[0][0].x);
require(dst1[0][0].y == src1[0][0].y);
require(dst1[0][1].x == src1[0][1].x);
require(dst1[0][1].y == src1[0][1].y);
}
function test2() public {
dst2 = src2;
require(dst2[0].length == 3);
require(dst2[0][0].x == src2[0][0].x);
require(dst2[0][0].y == src2[0][0].y);
require(dst2[0][1].x == src2[0][1].x);
require(dst2[0][1].y == src2[0][1].y);
require(dst2[0][2].x == src2[0][2].x);
require(dst2[0][2].y == src2[0][2].y);
}
function test3() public {
dst3 = src3;
require(dst3.length == 2);
require(dst3[0][0].x == src3[0][0].x);
require(dst3[0][0].y == src3[0][0].y);
require(dst3[1][0].x == src3[1][0].x);
require(dst3[1][0].y == src3[1][0].y);
}
}
// ====
// compileViaYul: true
// ----
// test1()
// gas irOptimized: 123279
// test2()
// gas irOptimized: 123073
// test3()

View File

@ -0,0 +1,45 @@
pragma abicoder v2;
contract C {
struct S {
uint8[] a;
uint8[2] b;
}
uint8[] a1;
uint8[] a2;
uint8[] a3;
S[][] s1;
S[1][1] s2;
constructor() {
a1.push(23);
a1.push(29);
a2.push(31);
s1 = new S[][](2);
s1[0] = new S[](2);
s1[0][0] = S({a: a1, b: [7, 11]});
s1[0][1] = S({a: a2, b: [17, 19]});
s1[1] = new S[](1);
s1[1][0] = S({a: a3, b: [37, 41]});
s2[0][0] = S({a: a3, b: [43, 47]});
}
function test1() public returns (S[] memory) {
return s1[0];
}
function test2() public returns (S[1] memory) {
return s2[0];
}
}
// ====
// compileViaYul: true
// ----
// test1() -> 0x20, 2, 0x40, 0x0100, 0x60, 7, 11, 2, 23, 29, 0x60, 17, 19, 1, 31
// test2() -> 0x20, 0x20, 0x60, 43, 47, 0

View File

@ -0,0 +1,37 @@
pragma abicoder v2;
contract C {
uint8[][] a;
uint8[][][] a2;
function test(uint8[][][] calldata _a) public {
a = _a[1];
require(a.length == 2);
require(a[0].length == 1);
require(a[0][0] == 7);
require(a[1].length == 2);
require(a[1][0] == 8);
require(a[1][1] == 9);
}
function test2(uint8[][] calldata _a) public {
a2 = new uint8[][][](2);
a2[0] = _a;
require(a2[0].length == 2);
require(a2[0][0].length == 1);
require(a2[0][0][0] == 7);
require(a2[0][1].length == 2);
require(a2[0][1][0] == 8);
require(a2[0][1][1] == 9);
require(a2[1].length == 0);
}
}
// ====
// compileViaYul: true
// ----
// test(uint8[][][]): 0x20, 2, 0x40, 0x60, 0, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// gas irOptimized: 138083
// test2(uint8[][]): 0x20, 2, 0x40, 0x80, 1, 7, 2, 8, 9
// gas irOptimized: 164290
// gas legacyOptimized: 120228

View File

@ -0,0 +1,44 @@
pragma abicoder v2;
contract C {
struct S {
bytes b;
uint16[] a;
uint16 u;
}
constructor() {
uint16[] memory a = new uint16[](2);
a[0] = 13;
a[1] = 14;
m[7] = S({b: "foo", a: a, u: 7});
}
mapping (uint => S) m;
S s;
function to_state() public returns (S memory) {
s = m[7];
return s;
}
function to_storage() public returns (S memory) {
S storage sLocal = s;
sLocal = m[7];
return sLocal;
}
function to_memory() public returns (S memory) {
return m[7];
}
}
// ----
// to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 121513
// gas legacy: 123120
// gas legacyOptimized: 121776
// to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14

View File

@ -0,0 +1,16 @@
pragma abicoder v2;
contract C {
struct S {
uint8[1] x;
uint8[] y;
}
function test(S calldata s) public returns (S memory) {
return s;
}
}
// ----
// test((uint8[1],uint8[])): 0x20, 3, 0x40, 2, 7, 11 -> 0x20, 3, 0x40, 2, 7, 11
// test((uint8[1],uint8[])): 0x20, 3, 0x40, 3, 17, 19, 23 -> 0x20, 3, 0x40, 3, 17, 19, 23

View File

@ -0,0 +1,22 @@
pragma abicoder v2;
contract C {
struct S {
uint8[1] x;
uint8[] y;
}
S s;
function test(S calldata src) public {
s = src;
require(s.x[0] == 3);
require(s.y.length == 2);
require(s.y[0] == 7);
require(s.y[1] == 11);
}
}
// ----
// test((uint8[1],uint8[])): 0x20, 3, 0x40, 2, 7, 11

View File

@ -0,0 +1,16 @@
pragma abicoder v2;
contract C {
struct S {
uint8[1] x;
uint8[] y;
}
function test(S memory s) public returns (S memory r) {
return r;
}
}
// ----
// test((uint8[1],uint8[])): 0x20, 3, 0x40, 2, 7, 11 -> 0x20, 0, 0x40, 0
// test((uint8[1],uint8[])): 0x20, 3, 0x40, 3, 17, 19, 23 -> 0x20, 0, 0x40, 0

View File

@ -0,0 +1,27 @@
contract C {
struct S {
uint8[1] x;
uint8[] y;
}
S src;
S dst;
constructor() {
src.x = [3];
src.y.push(7);
src.y.push(11);
}
function test() public {
dst = src;
require(dst.x[0] == 3);
require(dst.y.length == 2);
require(dst.y[0] == 7);
require(dst.y[1] == 11);
}
}
// ----
// test()

View File

@ -0,0 +1,52 @@
pragma abicoder v2;
contract C {
struct S {
bytes b;
uint16[] a;
uint16 u;
}
constructor() {
uint16[] memory a = new uint16[](2);
a[0] = 13;
a[1] = 14;
m[7] = S({b: "foo", a: a, u: 7});
}
mapping (uint => S) m;
S s;
function to_state() public returns (S memory) {
s.b = m[7].b;
s.a = m[7].a;
s.u = m[7].u;
return s;
}
function to_storage() public returns (S memory) {
S storage sLocal = s;
sLocal.b = m[7].b;
sLocal.a = m[7].a;
sLocal.u = m[7].u;
return sLocal;
}
function to_memory() public returns (S memory) {
S memory sLocal;
sLocal.b = m[7].b;
sLocal.a = m[7].a;
sLocal.u = m[7].u;
return sLocal;
}
}
// ----
// to_state() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 121616
// gas legacy: 123263
// gas legacyOptimized: 121785
// to_storage() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// to_memory() -> 0x20, 0x60, 0xa0, 7, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14

View File

@ -0,0 +1,66 @@
pragma abicoder v2;
contract C {
struct S {
bytes b;
uint16[] a;
uint16 u;
}
S s;
constructor() {
uint16[] memory a = new uint16[](2);
a[0] = 13;
a[1] = 14;
s.b = "foo";
s.a = a;
s.u = 21;
}
mapping (uint => S) m;
function from_memory() public returns (S memory) {
S memory sMemory = s;
m[0].b = sMemory.b;
m[0].a = sMemory.a;
m[0].u = sMemory.u;
return m[0];
}
function from_state() public returns (S memory) {
m[1].b = s.b;
m[1].a = s.a;
m[1].u = s.u;
return m[1];
}
function from_storage() public returns (S memory) {
S storage sLocal = s;
m[1].b = sLocal.b;
m[1].a = sLocal.a;
m[1].u = sLocal.u;
return m[1];
}
function from_calldata(S calldata sCalldata) public returns (S memory) {
m[2].b = sCalldata.b;
m[2].a = sCalldata.a;
m[2].u = sCalldata.u;
return m[2];
}
}
// ----
// from_memory() -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 123062
// gas legacy: 130289
// gas legacyOptimized: 128785
// from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 121776
// gas legacy: 123341
// gas legacyOptimized: 121892
// from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 0x15, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 115169
// gas legacy: 122579
// gas legacyOptimized: 120829

View File

@ -0,0 +1,63 @@
pragma abicoder v2;
contract C {
struct S {
bytes b;
uint16[] a;
uint16 u;
}
S s;
constructor() {
uint16[] memory a = new uint16[](2);
a[0] = 13;
a[1] = 14;
s.b = "foo";
s.a = a;
s.u = 21;
}
mapping (uint => S) m;
function from_state() public returns (S memory) {
m[0] = s;
return m[0];
}
function from_storage() public returns (S memory) {
S storage sLocal = s;
m[1] = sLocal;
return m[1];
}
function from_memory() public returns (S memory) {
S memory sMemory = s;
m[2] = sMemory;
return m[2];
}
function from_calldata(S calldata sCalldata) public returns (S memory) {
m[3] = sCalldata;
return m[3];
}
}
// ----
// from_state() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 121709
// gas legacy: 123198
// gas legacyOptimized: 121830
// from_storage() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 121753
// gas legacy: 123247
// gas legacyOptimized: 121882
// from_memory() -> 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 122954
// gas legacy: 130146
// gas legacyOptimized: 128779
// from_calldata((bytes,uint16[],uint16)): 0x20, 0x60, 0xa0, 21, 3, 0x666F6F0000000000000000000000000000000000000000000000000000000000, 2, 13, 14 -> 0x20, 0x60, 0xa0, 21, 3, 0x666f6f0000000000000000000000000000000000000000000000000000000000, 2, 13, 14
// gas irOptimized: 115067
// gas legacy: 118383
// gas legacyOptimized: 115458

View File

@ -0,0 +1,35 @@
pragma abicoder v2;
contract C {
struct S {
uint8[3] x;
uint8[][] y;
uint16 z;
}
mapping (uint8 => S) src;
mapping (uint8 => S) dst;
constructor() {
uint8[] memory d = new uint8[](2);
d[0] = 3;
d[1] = 4;
uint8[][] memory y = new uint8[][](2);
y[0] = d;
y[1] = d;
src[0] = S({x: [7, 8, 9], y: y, z: 13});
}
function f() public returns (S memory) {
dst[0] = src[0];
return dst[0];
}
}
// ----
// f() -> 0x20, 7, 8, 9, 0xa0, 13, 2, 0x40, 0xa0, 2, 3, 4, 2, 3, 4
// gas irOptimized: 197113
// gas legacy: 199986
// gas legacyOptimized: 196847

View File

@ -0,0 +1,57 @@
pragma abicoder v2;
contract C {
struct S {
uint8 x;
}
constructor() {
s = S({x: 7});
m2[0].push();
}
S s;
mapping (uint8 => S[2]) m1;
mapping (uint8 => S[]) m2;
function from_storage_to_static_array() public returns (S[2] memory) {
m1[0][1] = s;
return m1[0];
}
function from_storage_to_dynamic_array() public returns (S[] memory) {
m2[0][0] = s;
return m2[0];
}
function from_memory_to_static_array() public returns (S[2] memory) {
S memory sLocal = s;
m1[0][1] = sLocal;
return m1[0];
}
function from_memory_to_dynamic_array() public returns (S[] memory) {
S memory sLocal = s;
m2[0][0] = sLocal;
return m2[0];
}
function from_calldata_to_static_array(S calldata sCalldata) public returns (S[2] memory) {
m1[0][1] = sCalldata;
return m1[0];
}
function from_calldata_to_dynamic_array(S calldata sCalldata) public returns (S[] memory) {
m2[0][0] = sCalldata;
return m2[0];
}
}
// ----
// from_storage_to_static_array() -> 0, 7
// from_storage_to_dynamic_array() -> 0x20, 1, 7
// from_memory_to_static_array() -> 0, 7
// from_memory_to_dynamic_array() -> 0x20, 1, 7
// from_calldata_to_static_array((uint8)): 8 -> 0, 8
// from_calldata_to_dynamic_array((uint8)): 8 -> 0x20, 1, 8