diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e610f239f..b650db5b5 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2854,145 +2854,6 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi) ); } -BOOST_AUTO_TEST_CASE(external_array_args) -{ - char const* sourceCode = R"( - contract c { - function test(uint[8] calldata a, uint[] calldata b, uint[5] calldata c, uint a_index, uint b_index, uint c_index) - external returns (uint av, uint bv, uint cv) { - av = a[a_index]; - bv = b[b_index]; - cv = c[c_index]; - } - } - )"; - compileAndRun(sourceCode); - bytes params = encodeArgs( - 1, 2, 3, 4, 5, 6, 7, 8, // a - 32 * (8 + 1 + 5 + 1 + 1 + 1), // offset to b - 21, 22, 23, 24, 25, // c - 0, 1, 2, // (a,b,c)_index - 3, // b.length - 11, 12, 13 // b - ); - ABI_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params), encodeArgs(1, 12, 23)); -} - -BOOST_AUTO_TEST_CASE(bytes_index_access) -{ - char const* sourceCode = R"( - contract c { - bytes data; - function direct(bytes calldata arg, uint index) external returns (uint) { - return uint(uint8(arg[index])); - } - function storageCopyRead(bytes calldata arg, uint index) external returns (uint) { - data = arg; - return uint(uint8(data[index])); - } - function storageWrite() external returns (uint) { - data = new bytes(35); - data[31] = 0x77; - data[32] = 0x14; - - data[31] = 0x01; - data[31] |= 0x08; - data[30] = 0x01; - data[32] = 0x03; - return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32])); - } - } - )"; - string array{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33}; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); - ABI_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array), encodeArgs(33)); - ABI_CHECK(callContractFunction("storageWrite()"), encodeArgs(0x193)); - ); -} - -BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) -{ - char const* sourceCode = R"( - contract c { - uint[9] m_data; - uint[] m_data_dyn; - uint8[][] m_byte_data; - function store(uint[9] calldata a, uint8[3][] calldata b) external returns (uint8) { - m_data = a; - m_data_dyn = a; - m_byte_data = b; - return b[3][1]; // note that access and declaration are reversed to each other - } - function retrieve() public returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) { - a = m_data.length; - b = m_data[7]; - c = m_data_dyn.length; - d = m_data_dyn[7]; - e = m_byte_data.length; - f = m_byte_data[3].length; - g = m_byte_data[3][1]; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs(21, 22, 23, 24, 25, 26, 27, 28, 29, u256(32 * (9 + 1)), 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 )), encodeArgs(32)); - ABI_CHECK(callContractFunction("retrieve()"), encodeArgs(9, 28, 9, 28, 4, 3, 32)); -} - -BOOST_AUTO_TEST_CASE(array_copy_including_array) -{ - char const* sourceCode = R"( - contract c { - uint[3][90][] large; - uint[3][3][] small; - function test() public returns (uint r) { - for (uint i = 0; i < 7; i++) { - large.push(); - small.push(); - } - large[3][2][0] = 2; - large[1] = large[3]; - small[3][2][0] = 2; - small[1] = small[2]; - r = (( - small[3][2][0] * 0x100 | - small[1][2][0]) * 0x100 | - large[3][2][0]) * 0x100 | - large[1][2][0]; - delete small; - delete large; - - } - function clear() public returns (uint, uint) { - for (uint i = 0; i < 7; i++) { - large.push(); - small.push(); - } - small[3][2][0] = 0; - large[3][2][0] = 0; - while (small.length > 0) - small.pop(); - while (large.length > 0) - large.pop(); - return (small.length, large.length); - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000202)); - BOOST_CHECK(storageEmpty(m_contractAddress)); - ABI_CHECK(callContractFunction("clear()"), encodeArgs(0, 0)); - BOOST_CHECK(storageEmpty(m_contractAddress)); -} - //BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars) //{ // char const* sourceCode = R"( @@ -3305,159 +3166,6 @@ BOOST_AUTO_TEST_CASE(return_bytes_internal) } } -BOOST_AUTO_TEST_CASE(bytes_index_access_memory) -{ - char const* sourceCode = R"( - contract Main { - function f(bytes memory _s1, uint i1, uint i2, uint i3) public returns (byte c1, byte c2, byte c3) { - c1 = _s1[i1]; - c2 = intern(_s1, i2); - c3 = internIndirect(_s1)[i3]; - } - function intern(bytes memory _s1, uint i) public returns (byte c) { - return _s1[i]; - } - function internIndirect(bytes memory _s1) public returns (bytes memory) { - return _s1; - } - } - )"; - compileAndRun(sourceCode, 0, "Main"); - string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); - bytes dyn1 = encodeArgs(u256(s1.length()), s1); - bytes args1 = encodeArgs(u256(0x80), u256(3), u256(4), u256(5)) + dyn1; - BOOST_REQUIRE( - callContractFunction("f(bytes,uint256,uint256,uint256)", asString(args1)) == - encodeArgs(string{s1[3]}, string{s1[4]}, string{s1[5]}) - ); -} - -BOOST_AUTO_TEST_CASE(bytes_in_constructors_unpacker) -{ - char const* sourceCode = R"( - contract Test { - uint public m_x; - bytes public m_s; - constructor(uint x, bytes memory s) { - m_x = x; - m_s = s; - } - } - )"; - string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); - bytes dyn1 = encodeArgs(u256(s1.length()), s1); - u256 x = 7; - bytes args1 = encodeArgs(x, u256(0x40)) + dyn1; - compileAndRun(sourceCode, 0, "Test", args1); - BOOST_REQUIRE(callContractFunction("m_x()") == encodeArgs(x)); - BOOST_REQUIRE(callContractFunction("m_s()") == encodeArgs(u256(0x20)) + dyn1); -} - -BOOST_AUTO_TEST_CASE(bytes_in_constructors_packer) -{ - char const* sourceCode = R"( - contract Base { - uint public m_x; - bytes m_s; - constructor(uint x, bytes memory s) { - m_x = x; - m_s = s; - } - function part(uint i) public returns (byte) { - return m_s[i]; - } - } - contract Main is Base { - constructor(bytes memory s, uint x) Base(x, f(s)) {} - function f(bytes memory s) public returns (bytes memory) { - return s; - } - } - contract Creator { - function f(uint x, bytes memory s) public returns (uint r, byte ch) { - Main c = new Main(s, x); - r = c.m_x(); - ch = c.part(x); - } - } - )"; - compileAndRun(sourceCode, 0, "Creator"); - string s1("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); - bytes dyn1 = encodeArgs(u256(s1.length()), s1); - u256 x = 7; - bytes args1 = encodeArgs(x, u256(0x40)) + dyn1; - BOOST_REQUIRE( - callContractFunction("f(uint256,bytes)", asString(args1)) == - encodeArgs(x, string{s1[unsigned(x)]}) - ); -} - -BOOST_AUTO_TEST_CASE(arrays_in_constructors) -{ - char const* sourceCode = R"( - contract Base { - uint public m_x; - address[] m_s; - constructor(uint x, address[] memory s) { - m_x = x; - m_s = s; - } - function part(uint i) public returns (address) { - return m_s[i]; - } - } - contract Main is Base { - constructor(address[] memory s, uint x) Base(x, f(s)) {} - function f(address[] memory s) public returns (address[] memory) { - return s; - } - } - contract Creator { - function f(uint x, address[] memory s) public returns (uint r, address ch) { - Main c = new Main(s, x); - r = c.m_x(); - ch = c.part(x); - } - } - )"; - compileAndRun(sourceCode, 0, "Creator"); - vector s1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - bytes dyn1 = encodeArgs(u256(s1.size()), s1); - u256 x = 7; - bytes args1 = encodeArgs(x, u256(0x40)) + dyn1; - BOOST_REQUIRE( - callContractFunction("f(uint256,address[])", asString(args1)) == - encodeArgs(x, s1[unsigned(x)]) - ); -} - -BOOST_AUTO_TEST_CASE(arrays_from_and_to_storage) -{ - char const* sourceCode = R"( - contract Test { - uint24[] public data; - function set(uint24[] memory _data) public returns (uint) { - data = _data; - return data.length; - } - function get() public returns (uint24[] memory) { - return data; - } - } - )"; - compileAndRun(sourceCode, 0, "Test"); - - vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; - BOOST_REQUIRE( - callContractFunction("set(uint24[])", u256(0x20), u256(data.size()), data) == - encodeArgs(u256(data.size())) - ); - ABI_CHECK(callContractFunction("data(uint256)", u256(7)), encodeArgs(u256(8))); - ABI_CHECK(callContractFunction("data(uint256)", u256(15)), encodeArgs(u256(16))); - ABI_CHECK(callContractFunction("data(uint256)", u256(18)), encodeArgs()); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0x20), u256(data.size()), data)); -} - BOOST_AUTO_TEST_CASE(memory_types_initialisation) { char const* sourceCode = R"( @@ -3480,35 +3188,6 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation) ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector(3 * 7))); } -BOOST_AUTO_TEST_CASE(memory_arrays_delete) -{ - char const* sourceCode = R"( - contract Test { - function del() public returns (uint24[3][4] memory) { - uint24[3][4] memory x; - for (uint24 i = 0; i < x.length; i ++) - for (uint24 j = 0; j < x[i].length; j ++) - x[i][j] = i * 0x10 + j; - delete x[1]; - delete x[3][2]; - return x; - } - } - )"; - compileAndRun(sourceCode, 0, "Test"); - - vector data(3 * 4); - for (unsigned i = 0; i < 4; i++) - for (unsigned j = 0; j < 3; j++) - { - u256 v = 0; - if (!(i == 1 || (i == 3 && j == 2))) - v = i * 0x10 + j; - data[i * 3 + j] = v; - } - ABI_CHECK(callContractFunction("del()"), encodeArgs(data)); -} - BOOST_AUTO_TEST_CASE(calldata_struct_short) { char const* sourceCode = R"( @@ -3557,86 +3236,6 @@ BOOST_AUTO_TEST_CASE(calldata_struct_function_type) ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23)); } -BOOST_AUTO_TEST_CASE(calldata_bytes_array_bounds) -{ - char const* sourceCode = R"( - pragma experimental ABIEncoderV2; - contract C { - function f(bytes[] calldata a, uint256 i) external returns (uint) { - return uint8(a[0][i]); - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - - ABI_CHECK( - callContractFunction("f(bytes[],uint256)", 0x40, 0, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)), - encodeArgs('a') - ); - ABI_CHECK( - callContractFunction("f(bytes[],uint256)", 0x40, 1, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)), - encodeArgs('b') - ); - ABI_CHECK( - callContractFunction("f(bytes[],uint256)", 0x40, 2, 1, 0x20, 2, bytes{'a', 'b'} + bytes(30, 0)), - encodeArgs() - ); -} - -BOOST_AUTO_TEST_CASE(calldata_array_two_dimensional) -{ - vector> data { - { 0x0A01, 0x0A02, 0x0A03 }, - { 0x0B01, 0x0B02, 0x0B03, 0x0B04 } - }; - - for (bool outerDynamicallySized: { true, false }) - { - string arrayType = outerDynamicallySized ? "uint256[][]" : "uint256[][2]"; - string sourceCode = R"( - pragma experimental ABIEncoderV2; - contract C { - function test()" + arrayType + R"( calldata a) external returns (uint256) { - return a.length; - } - function test()" + arrayType + R"( calldata a, uint256 i) external returns (uint256) { - return a[i].length; - } - function test()" + arrayType + R"( calldata a, uint256 i, uint256 j) external returns (uint256) { - return a[i][j]; - } - function reenc()" + arrayType + R"( calldata a, uint256 i, uint256 j) external returns (uint256) { - return this.test(a, i, j); - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - - bytes encoding = encodeArray( - outerDynamicallySized, - true, - data | boost::adaptors::transformed([&](vector const& _values) { - return encodeArray(true, false, _values); - }) - ); - - ABI_CHECK(callContractFunction("test(" + arrayType + ")", 0x20, encoding), encodeArgs(data.size())); - for (size_t i = 0; i < data.size(); i++) - { - ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, i, encoding), encodeArgs(data[i].size())); - for (size_t j = 0; j < data[i].size(); j++) - { - ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j])); - ABI_CHECK(callContractFunction("reenc(" + arrayType + ",uint256,uint256)", 0x60, i, j, encoding), encodeArgs(data[i][j])); - } - // out of bounds access - ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), encodeArgs()); - } - // out of bounds access - ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), encodeArgs()); - } -} - BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional) { vector>> data { diff --git a/test/libsolidity/semanticTests/array/calldata_array_two_dimensional.sol b/test/libsolidity/semanticTests/array/calldata_array_two_dimensional.sol new file mode 100644 index 000000000..4c20627e7 --- /dev/null +++ b/test/libsolidity/semanticTests/array/calldata_array_two_dimensional.sol @@ -0,0 +1,38 @@ +pragma experimental ABIEncoderV2; +contract C { + function test(uint256[][2] calldata a) external returns (uint256) { + return a.length; + } + function test(uint256[][2] calldata a, uint256 i) external returns (uint256) { + return a[i].length; + } + function test(uint256[][2] calldata a, uint256 i, uint256 j) external returns (uint256) { + return a[i][j]; + } + function reenc(uint256[][2] calldata a, uint256 i, uint256 j) external returns (uint256) { + return this.test(a, i, j); + } +} +// ==== +// compileViaYul: also +// ---- +// test(uint256[][2]): 0x20, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 2 +// test(uint256[][2],uint256): 0x40, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 3 +// test(uint256[][2],uint256): 0x40, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 4 +// test(uint256[][2],uint256,uint256): 0x60, 0, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01 +// reenc(uint256[][2],uint256,uint256): 0x60, 0, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01 +// test(uint256[][2],uint256,uint256): 0x60, 0, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02 +// reenc(uint256[][2],uint256,uint256): 0x60, 0, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02 +// test(uint256[][2],uint256,uint256): 0x60, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03 +// reenc(uint256[][2],uint256,uint256): 0x60, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03 +// test(uint256[][2],uint256,uint256): 0x60, 1, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01 +// reenc(uint256[][2],uint256,uint256): 0x60, 1, 0, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01 +// test(uint256[][2],uint256,uint256): 0x60, 1, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02 +// reenc(uint256[][2],uint256,uint256): 0x60, 1, 1, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02 +// test(uint256[][2],uint256,uint256): 0x60, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03 +// reenc(uint256[][2],uint256,uint256): 0x60, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03 +// test(uint256[][2],uint256,uint256): 0x60, 1, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04 +// reenc(uint256[][2],uint256,uint256): 0x60, 1, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04 +// test(uint256[][2],uint256,uint256): 0x60, 0, 3, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE +// test(uint256[][2],uint256,uint256): 0x60, 1, 4, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE +// test(uint256[][2],uint256): 0x40, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/calldata_array_two_dimensional_1.sol b/test/libsolidity/semanticTests/array/calldata_array_two_dimensional_1.sol new file mode 100644 index 000000000..9d40a356d --- /dev/null +++ b/test/libsolidity/semanticTests/array/calldata_array_two_dimensional_1.sol @@ -0,0 +1,38 @@ +pragma experimental ABIEncoderV2; +contract C { + function test(uint256[][] calldata a) external returns (uint256) { + return a.length; + } + function test(uint256[][] calldata a, uint256 i) external returns (uint256) { + return a[i].length; + } + function test(uint256[][] calldata a, uint256 i, uint256 j) external returns (uint256) { + return a[i][j]; + } + function reenc(uint256[][] calldata a, uint256 i, uint256 j) external returns (uint256) { + return this.test(a, i, j); + } +} +// ==== +// compileViaYul: also +// ---- +// test(uint256[][]): 0x20, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 2 +// test(uint256[][],uint256): 0x40, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 3 +// test(uint256[][],uint256): 0x40, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 4 +// test(uint256[][],uint256,uint256): 0x60, 0, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01 +// reenc(uint256[][],uint256,uint256): 0x60, 0, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A01 +// test(uint256[][],uint256,uint256): 0x60, 0, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02 +// reenc(uint256[][],uint256,uint256): 0x60, 0, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A02 +// test(uint256[][],uint256,uint256): 0x60, 0, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03 +// reenc(uint256[][],uint256,uint256): 0x60, 0, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0A03 +// test(uint256[][],uint256,uint256): 0x60, 1, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01 +// reenc(uint256[][],uint256,uint256): 0x60, 1, 0, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B01 +// test(uint256[][],uint256,uint256): 0x60, 1, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02 +// reenc(uint256[][],uint256,uint256): 0x60, 1, 1, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B02 +// test(uint256[][],uint256,uint256): 0x60, 1, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03 +// reenc(uint256[][],uint256,uint256): 0x60, 1, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B03 +// test(uint256[][],uint256,uint256): 0x60, 1, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04 +// reenc(uint256[][],uint256,uint256): 0x60, 1, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> 0x0B04 +// test(uint256[][],uint256,uint256): 0x60, 0, 3, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE +// test(uint256[][],uint256,uint256): 0x60, 1, 4, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE +// test(uint256[][],uint256): 0x40, 2, 2, 0x40, 0xC0, 3, 0x0A01, 0x0A02, 0x0A03, 4, 0x0B01, 0x0B02, 0x0B03, 0x0B04 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/calldata_bytes_array_bounds.sol b/test/libsolidity/semanticTests/array/calldata_bytes_array_bounds.sol new file mode 100644 index 000000000..ed120d501 --- /dev/null +++ b/test/libsolidity/semanticTests/array/calldata_bytes_array_bounds.sol @@ -0,0 +1,12 @@ +pragma experimental ABIEncoderV2; +contract C { + function f(bytes[] calldata a, uint256 i) external returns (uint) { + return uint8(a[0][i]); + } +} +// ==== +// compileViaYul: also +// ---- +// f(bytes[],uint256): 0x40, 0, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x61 +// f(bytes[],uint256): 0x40, 1, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> 0x62 +// f(bytes[],uint256): 0x40, 2, 1, 0x20, 2, 0x6162000000000000000000000000000000000000000000000000000000000000 -> FAILURE diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol new file mode 100644 index 000000000..20c934bc4 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_copy_calldata_storage.sol @@ -0,0 +1,25 @@ +contract c { + uint[9] m_data; + uint[] m_data_dyn; + uint8[][] m_byte_data; + function store(uint[9] calldata a, uint8[3][] calldata b) external returns (uint8) { + m_data = a; + m_data_dyn = a; + m_byte_data = b; + return b[3][1]; // note that access and declaration are reversed to each other + } + function retrieve() public returns (uint a, uint b, uint c, uint d, uint e, uint f, uint g) { + a = m_data.length; + b = m_data[7]; + c = m_data_dyn.length; + d = m_data_dyn[7]; + e = m_byte_data.length; + f = m_byte_data[3].length; + g = m_byte_data[3][1]; + } +} +// ==== +// compileViaYul: also +// ---- +// store(uint256[9],uint8[3][]): 21, 22, 23, 24, 25, 26, 27, 28, 29, 0x140, 4, 1, 2, 3, 11, 12, 13, 21, 22, 23, 31, 32, 33 -> 32 +// retrieve() -> 9, 28, 9, 28, 4, 3, 32 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol new file mode 100644 index 000000000..04564b748 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_copy_including_array.sol @@ -0,0 +1,40 @@ +contract c { + uint[3][90][] large; + uint[3][3][] small; + function test() public returns (uint r) { + for (uint i = 0; i < 7; i++) { + large.push(); + small.push(); + } + large[3][2][0] = 2; + large[1] = large[3]; + small[3][2][0] = 2; + small[1] = small[2]; + r = (( + small[3][2][0] * 0x100 | + small[1][2][0]) * 0x100 | + large[3][2][0]) * 0x100 | + large[1][2][0]; + delete small; + delete large; + + } + function clear() public returns (uint, uint) { + for (uint i = 0; i < 7; i++) { + large.push(); + small.push(); + } + small[3][2][0] = 0; + large[3][2][0] = 0; + while (small.length > 0) + small.pop(); + while (large.length > 0) + large.pop(); + return (small.length, large.length); + } +} +// ---- +// test() -> 0x02000202 +// storage: empty +// clear() -> 0, 0 +// storage: empty diff --git a/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol new file mode 100644 index 000000000..8b99bf14c --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/arrays_from_and_to_storage.sol @@ -0,0 +1,18 @@ +contract Test { + uint24[] public data; + function set(uint24[] memory _data) public returns (uint) { + data = _data; + return data.length; + } + function get() public returns (uint24[] memory) { + return data; + } +} +// ==== +// compileViaYul: also +// ---- +// set(uint24[]): 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 -> 18 +// data(uint256): 7 -> 8 +// data(uint256): 15 -> 16 +// data(uint256): 18 -> FAILURE +// get() -> 0x20, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 diff --git a/test/libsolidity/semanticTests/array/delete/memory_arrays_delete.sol b/test/libsolidity/semanticTests/array/delete/memory_arrays_delete.sol new file mode 100644 index 000000000..31c86b353 --- /dev/null +++ b/test/libsolidity/semanticTests/array/delete/memory_arrays_delete.sol @@ -0,0 +1,15 @@ +contract Test { + function del() public returns (uint24[3][4] memory) { + uint24[3][4] memory x; + for (uint24 i = 0; i < x.length; i ++) + for (uint24 j = 0; j < x[i].length; j ++) + x[i][j] = i * 0x10 + j; + delete x[1]; + delete x[3][2]; + return x; + } +} +// ==== +// compileViaYul: also +// ---- +// del() -> 0, 1, 2, 0, 0, 0, 0x20, 0x21, 0x22, 0x30, 0x31, 0 diff --git a/test/libsolidity/semanticTests/array/external_array_args.sol b/test/libsolidity/semanticTests/array/external_array_args.sol new file mode 100644 index 000000000..38205ea95 --- /dev/null +++ b/test/libsolidity/semanticTests/array/external_array_args.sol @@ -0,0 +1,12 @@ +contract c { + function test(uint[8] calldata a, uint[] calldata b, uint[5] calldata c, uint a_index, uint b_index, uint c_index) + external returns (uint av, uint bv, uint cv) { + av = a[a_index]; + bv = b[b_index]; + cv = c[c_index]; + } +} +// ==== +// compileViaYul: also +// ---- +// test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256): 1, 2, 3, 4, 5, 6, 7, 8, 0x220, 21, 22, 23, 24, 25, 0, 1, 2, 3, 11, 12, 13 -> 1, 12, 23 diff --git a/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access.sol b/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access.sol new file mode 100644 index 000000000..9a0c85ac7 --- /dev/null +++ b/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access.sol @@ -0,0 +1,27 @@ +contract c { + bytes data; + function direct(bytes calldata arg, uint index) external returns (uint) { + return uint(uint8(arg[index])); + } + function storageCopyRead(bytes calldata arg, uint index) external returns (uint) { + data = arg; + return uint(uint8(data[index])); + } + function storageWrite() external returns (uint) { + data = new bytes(35); + data[31] = 0x77; + data[32] = 0x14; + + data[31] = 0x01; + data[31] |= 0x08; + data[30] = 0x01; + data[32] = 0x03; + return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32])); + } +} +// ==== +// compileViaYul: also +// ---- +// direct(bytes,uint256): 0x40, 33, 34, 0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F, left(0x2021) -> 0x21 +// storageCopyRead(bytes,uint256): 0x40, 33, 34, 0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F, left(0x2021) -> 0x21 +// storageWrite() -> 0x193 diff --git a/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access_memory.sol b/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access_memory.sol new file mode 100644 index 000000000..1c2824d7c --- /dev/null +++ b/test/libsolidity/semanticTests/array/indexAccess/bytes_index_access_memory.sol @@ -0,0 +1,17 @@ +contract Main { + function f(bytes memory _s1, uint i1, uint i2, uint i3) public returns (byte c1, byte c2, byte c3) { + c1 = _s1[i1]; + c2 = intern(_s1, i2); + c3 = internIndirect(_s1)[i3]; + } + function intern(bytes memory _s1, uint i) public returns (byte c) { + return _s1[i]; + } + function internIndirect(bytes memory _s1) public returns (bytes memory) { + return _s1; + } +} +// ==== +// compileViaYul: also +// ---- +// f(bytes,uint256,uint256,uint256): 0x80, 3, 4, 5, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> "d", "e", "f" diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol new file mode 100644 index 000000000..ae380af8e --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -0,0 +1,28 @@ +contract Base { + uint public m_x; + address[] m_s; + constructor(uint x, address[] memory s) { + m_x = x; + m_s = s; + } + function part(uint i) public returns (address) { + return m_s[i]; + } +} +contract Main is Base { + constructor(address[] memory s, uint x) Base(x, f(s)) {} + function f(address[] memory s) public returns (address[] memory) { + return s; + } +} +contract Creator { + function f(uint x, address[] memory s) public returns (uint r, address ch) { + Main c = new Main(s, x); + r = c.m_x(); + ch = c.part(x); + } +} +// ==== +// compileViaYul: also +// ---- +// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol new file mode 100644 index 000000000..35e69bf4e --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -0,0 +1,28 @@ +contract Base { + uint public m_x; + bytes m_s; + constructor(uint x, bytes memory s) { + m_x = x; + m_s = s; + } + function part(uint i) public returns (byte) { + return m_s[i]; + } +} +contract Main is Base { + constructor(bytes memory s, uint x) Base(x, f(s)) {} + function f(bytes memory s) public returns (bytes memory) { + return s; + } +} +contract Creator { + function f(uint x, bytes memory s) public returns (uint r, byte ch) { + Main c = new Main(s, x); + r = c.m_x(); + ch = c.part(x); + } +} +// ==== +// compileViaYul: also +// ---- +// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol new file mode 100644 index 000000000..1d163d82e --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_unpacker.sol @@ -0,0 +1,12 @@ +contract Test { + uint public m_x; + bytes public m_s; + constructor(uint x, bytes memory s) { + m_x = x; + m_s = s; + } +} +// ---- +// constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> +// m_x() -> 7 +// m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz"