diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a1df29049..4e36eec4b 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -126,40 +126,6 @@ BOOST_AUTO_TEST_CASE(recursive_calls) ) } -BOOST_AUTO_TEST_CASE(multiple_functions) -{ - char const* sourceCode = R"( - contract test { - function a() public returns(uint n) { return 0; } - function b() public returns(uint n) { return 1; } - function c() public returns(uint n) { return 2; } - function f() public returns(uint n) { return 3; } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("a()", bytes()), toBigEndian(u256(0))); - ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(1))); - ABI_CHECK(callContractFunction("c()", bytes()), toBigEndian(u256(2))); - ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(3))); - ABI_CHECK(callContractFunction("i_am_not_there()", bytes()), bytes()); - ) -} - -BOOST_AUTO_TEST_CASE(disorder_named_args) -{ - char const* sourceCode = R"( - contract test { - function a(uint a, uint b, uint c) public returns (uint r) { r = a * 100 + b * 10 + c * 1; } - function b() public returns (uint r) { r = a({c: 3, a: 1, b: 2}); } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("b()", bytes()), toBigEndian(u256(123))); - ) -} - BOOST_AUTO_TEST_CASE(while_loop) { char const* sourceCode = R"( @@ -220,68 +186,6 @@ BOOST_AUTO_TEST_CASE(do_while_loop) ) } -BOOST_AUTO_TEST_CASE(do_while_loop_continue) -{ - char const* sourceCode = R"( - contract test { - function f() public pure returns(uint r) { - uint i = 0; - do - { - if (i > 0) return 0; - i++; - continue; - } while (false); - return 42; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("f()"), encodeArgs(42)); - ) -} - -BOOST_AUTO_TEST_CASE(array_multiple_local_vars) -{ - char const* sourceCode = R"( - contract test { - function f(uint256[] calldata seq) external pure returns (uint256) { - uint i = 0; - uint sum = 0; - while (i < seq.length) - { - uint idx = i; - if (idx >= 10) break; - uint x = seq[idx]; - if (x >= 1000) { - uint n = i + 1; - i = n; - continue; - } - else { - uint y = sum + x; - sum = y; - } - if (sum >= 500) return sum; - i++; - } - return sum; - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(1000), u256(1), u256(2)), encodeArgs(3)); - ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(100), u256(500), u256(300)), encodeArgs(600)); - ABI_CHECK(callContractFunction( - "f(uint256[])", 32, 11, - u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8), u256(9), u256(10), u256(111) - ), encodeArgs(55)); -} - - BOOST_AUTO_TEST_CASE(do_while_loop_multiple_local_vars) { char const* sourceCode = R"( @@ -773,58 +677,6 @@ BOOST_AUTO_TEST_CASE(many_local_variables) ) } -BOOST_AUTO_TEST_CASE(packing_unpacking_types) -{ - char const* sourceCode = R"( - contract test { - function run(bool a, uint32 b, uint64 c) public returns(uint256 y) { - if (a) y = 1; - y = y * 0x100000000 | ~b; - y = y * 0x10000000000000000 | ~c; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK( - callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")), - fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f") - ); -} - -BOOST_AUTO_TEST_CASE(packing_signed_types) -{ - char const* sourceCode = R"( - contract test { - function run() public returns(int8 y) { - uint8 x = 0xfa; - return int8(x); - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK( - callContractFunction("run()"), - fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa") - ); - ) -} - -BOOST_AUTO_TEST_CASE(multiple_return_values) -{ - char const* sourceCode = R"( - contract test { - function run(bool x1, uint x2) public returns(uint y1, bool y2, uint y3) { - y1 = x2; y2 = x1; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd), encodeArgs(0xcd, true, 0)); - ) -} - BOOST_AUTO_TEST_CASE(short_circuiting) { char const* sourceCode = R"( @@ -952,76 +804,6 @@ BOOST_AUTO_TEST_CASE(strings) ) } -BOOST_AUTO_TEST_CASE(inc_dec_operators) -{ - char const* sourceCode = R"( - contract test { - uint8 x; - uint v; - function f() public returns (uint r) { - uint a = 6; - r = a; - r += (a++) * 0x10; - r += (++a) * 0x100; - v = 3; - r += (v++) * 0x1000; - r += (++v) * 0x10000; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs(0x53866)); - ) -} - -BOOST_AUTO_TEST_CASE(bytes_comparison) -{ - char const* sourceCode = R"( - contract test { - function f() public returns (bool) { - bytes2 a = "a"; - bytes2 x = "aa"; - bytes2 b = "b"; - return a < x && x < b; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); - ) -} - -BOOST_AUTO_TEST_CASE(state_smoke_test) -{ - char const* sourceCode = R"( - contract test { - uint256 value1; - uint256 value2; - function get(uint8 which) public returns (uint256 value) { - if (which == 0) return value1; - else return value2; - } - function set(uint8 which, uint256 value) public { - if (which == 0) value1 = value; - else value2 = value; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(0)); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(0)); - ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x00), 0x1234), encodeArgs()); - ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x01), 0x8765), encodeArgs()); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(0x1234)); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x01)), encodeArgs(0x8765)); - ABI_CHECK(callContractFunction("set(uint8,uint256)", uint8_t(0x00), 0x3), encodeArgs()); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(0x00)), encodeArgs(0x3)); - ) -} - BOOST_AUTO_TEST_CASE(compound_assign) { char const* sourceCode = R"( @@ -1247,320 +1029,6 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) ) } -BOOST_AUTO_TEST_CASE(mapping_local_assignment) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8) m1; - mapping(uint8 => uint8) m2; - function f() public returns (uint8, uint8, uint8, uint8) { - mapping(uint8 => uint8) storage m = m1; - m[1] = 42; - - m = m2; - m[2] = 21; - - return (m1[1], m1[2], m2[1], m2[2]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); -} - -BOOST_AUTO_TEST_CASE(mapping_local_tuple_assignment) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8) m1; - mapping(uint8 => uint8) m2; - function f() public returns (uint8, uint8, uint8, uint8) { - mapping(uint8 => uint8) storage m = m1; - m[1] = 42; - - uint8 v; - (m, v) = (m2, 21); - m[2] = v; - - return (m1[1], m1[2], m2[1], m2[2]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); -} - -BOOST_AUTO_TEST_CASE(mapping_local_compound_assignment) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8) m1; - mapping(uint8 => uint8) m2; - function f() public returns (uint8, uint8, uint8, uint8) { - mapping(uint8 => uint8) storage m = m1; - m[1] = 42; - - (m = m2)[2] = 21; - - return (m1[1], m1[2], m2[1], m2[2]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("f()"), encodeArgs(uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(21))); -} - -BOOST_AUTO_TEST_CASE(mapping_internal_argument) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8) a; - mapping(uint8 => uint8) b; - function set_internal(mapping(uint8 => uint8) storage m, uint8 key, uint8 value) internal returns (uint8) { - uint8 oldValue = m[key]; - m[key] = value; - return oldValue; - } - function set(uint8 key, uint8 value_a, uint8 value_b) public returns (uint8 old_a, uint8 old_b) { - old_a = set_internal(a, key, value_a); - old_b = set_internal(b, key, value_b); - } - function get(uint8 key) public returns (uint8, uint8) { - return (a[key], b[key]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", uint8_t(1), uint8_t(21), uint8_t(42)), encodeArgs(uint8_t(0), uint8_t(0))); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(21), uint8_t(42))); - ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", uint8_t(1), uint8_t(10), uint8_t(11)), encodeArgs(uint8_t(21), uint8_t(42))); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(10), uint8_t(11))); -} - -BOOST_AUTO_TEST_CASE(mapping_array_internal_argument) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8)[2] a; - mapping(uint8 => uint8)[2] b; - function set_internal(mapping(uint8 => uint8)[2] storage m, uint8 key, uint8 value1, uint8 value2) internal returns (uint8, uint8) { - uint8 oldValue1 = m[0][key]; - uint8 oldValue2 = m[1][key]; - m[0][key] = value1; - m[1][key] = value2; - return (oldValue1, oldValue2); - } - function set(uint8 key, uint8 value_a1, uint8 value_a2, uint8 value_b1, uint8 value_b2) public returns (uint8 old_a1, uint8 old_a2, uint8 old_b1, uint8 old_b2) { - (old_a1, old_a2) = set_internal(a, key, value_a1, value_a2); - (old_b1, old_b2) = set_internal(b, key, value_b1, value_b2); - } - function get(uint8 key) public returns (uint8, uint8, uint8, uint8) { - return (a[0][key], a[1][key], b[0][key], b[1][key]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", uint8_t(1), uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43)), encodeArgs(uint8_t(0), uint8_t(0), uint8_t(0), uint8_t(0))); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43))); - ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", uint8_t(1), uint8_t(10), uint8_t(30), uint8_t(11), uint8_t(31)), encodeArgs(uint8_t(21), uint8_t(22), uint8_t(42), uint8_t(43))); - ABI_CHECK(callContractFunction("get(uint8)", uint8_t(1)), encodeArgs(uint8_t(10), uint8_t(30), uint8_t(11), uint8_t(31))); -} - -BOOST_AUTO_TEST_CASE(mapping_internal_return) -{ - char const* sourceCode = R"( - contract test { - mapping(uint8 => uint8) a; - mapping(uint8 => uint8) b; - function f() internal returns (mapping(uint8 => uint8) storage r) { - r = a; - r[1] = 42; - r = b; - r[1] = 84; - } - function g() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { - f()[2] = 21; - return (a[0], a[1], a[2], b[0], b[1], b[2]); - } - function h() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { - mapping(uint8 => uint8) storage m = f(); - m[2] = 17; - return (a[0], a[1], a[2], b[0], b[1], b[2]); - } - } - )"; - compileAndRun(sourceCode); - - ABI_CHECK(callContractFunction("g()"), encodeArgs(uint8_t(0), uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(84), uint8_t (21))); - ABI_CHECK(callContractFunction("h()"), encodeArgs(uint8_t(0), uint8_t(42), uint8_t(0), uint8_t(0), uint8_t(84), uint8_t (17))); -} - -BOOST_AUTO_TEST_CASE(structs) -{ - char const* sourceCode = R"( - contract test { - struct s1 { - uint8 x; - bool y; - } - struct s2 { - uint32 z; - s1 s1data; - mapping(uint8 => s2) recursive; - } - s2 data; - function check() public returns (bool ok) { - return data.z == 1 && data.s1data.x == 2 && - data.s1data.y == true && - data.recursive[3].recursive[4].z == 5 && - data.recursive[4].recursive[3].z == 6 && - data.recursive[0].s1data.y == false && - data.recursive[4].z == 9; - } - function set() public { - data.z = 1; - data.s1data.x = 2; - data.s1data.y = true; - data.recursive[3].recursive[4].z = 5; - data.recursive[4].recursive[3].z = 6; - data.recursive[0].s1data.y = false; - data.recursive[4].z = 9; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); - ABI_CHECK(callContractFunction("set()"), bytes()); - ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); -} - -BOOST_AUTO_TEST_CASE(struct_reference) -{ - char const* sourceCode = R"( - contract test { - struct s2 { - uint32 z; - mapping(uint8 => s2) recursive; - } - s2 data; - function check() public returns (bool ok) { - return data.z == 2 && - data.recursive[0].z == 3 && - data.recursive[0].recursive[1].z == 0 && - data.recursive[0].recursive[0].z == 1; - } - function set() public { - data.z = 2; - mapping(uint8 => s2) storage map = data.recursive; - s2 storage inner = map[0]; - inner.z = 3; - inner.recursive[0].z = inner.recursive[1].z + 1; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("check()"), encodeArgs(false)); - ABI_CHECK(callContractFunction("set()"), bytes()); - ABI_CHECK(callContractFunction("check()"), encodeArgs(true)); -} - -BOOST_AUTO_TEST_CASE(deleteStruct) -{ - char const* sourceCode = R"( - contract test { - struct topStruct { - nestedStruct nstr; - uint topValue; - mapping (uint => uint) topMapping; - } - uint toDelete; - topStruct str; - struct nestedStruct { - uint nestedValue; - mapping (uint => bool) nestedMapping; - } - constructor() public { - toDelete = 5; - str.topValue = 1; - str.topMapping[0] = 1; - str.topMapping[1] = 2; - - str.nstr.nestedValue = 2; - str.nstr.nestedMapping[0] = true; - str.nstr.nestedMapping[1] = false; - delete str; - delete toDelete; - } - function getToDelete() public returns (uint res){ - res = toDelete; - } - function getTopValue() public returns(uint topValue){ - topValue = str.topValue; - } - function getNestedValue() public returns(uint nestedValue){ - nestedValue = str.nstr.nestedValue; - } - function getTopMapping(uint index) public returns(uint ret) { - ret = str.topMapping[index]; - } - function getNestedMapping(uint index) public returns(bool ret) { - return str.nstr.nestedMapping[index]; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("getToDelete()"), encodeArgs(0)); - ABI_CHECK(callContractFunction("getTopValue()"), encodeArgs(0)); - ABI_CHECK(callContractFunction("getNestedValue()"), encodeArgs(0)); - // mapping values should be the same - ABI_CHECK(callContractFunction("getTopMapping(uint256)", 0), encodeArgs(1)); - ABI_CHECK(callContractFunction("getTopMapping(uint256)", 1), encodeArgs(2)); - ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 0), encodeArgs(true)); - ABI_CHECK(callContractFunction("getNestedMapping(uint256)", 1), encodeArgs(false)); -} - -BOOST_AUTO_TEST_CASE(deleteLocal) -{ - char const* sourceCode = R"( - contract test { - function delLocal() public returns (uint res){ - uint v = 5; - delete v; - res = v; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(0)); - ) -} - -BOOST_AUTO_TEST_CASE(deleteLocals) -{ - char const* sourceCode = R"( - contract test { - function delLocal() public returns (uint res1, uint res2){ - uint v = 5; - uint w = 6; - uint x = 7; - delete v; - res1 = w; - res2 = x; - } - } - )"; - ALSO_VIA_YUL( - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("delLocal()"), encodeArgs(6, 7)); - ) -} - BOOST_AUTO_TEST_CASE(deleteLength) { char const* sourceCode = R"( @@ -1609,74 +1077,6 @@ BOOST_AUTO_TEST_CASE(constructor) ) } -BOOST_AUTO_TEST_CASE(simple_accessor) -{ - char const* sourceCode = R"( - contract test { - uint256 public data; - constructor() public { - data = 8; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("data()"), encodeArgs(8)); -} - -BOOST_AUTO_TEST_CASE(array_accessor) -{ - char const* sourceCode = R"( - contract test { - uint[8] public data; - uint[] public dynamicData; - uint24[] public smallTypeData; - struct st { uint a; uint[] finalArray; } - mapping(uint256 => mapping(uint256 => st[5])) public multiple_map; - - constructor() public { - data[0] = 8; - dynamicData.length = 3; - dynamicData[2] = 8; - smallTypeData.length = 128; - smallTypeData[1] = 22; - smallTypeData[127] = 2; - multiple_map[2][1][2].a = 3; - multiple_map[2][1][2].finalArray.length = 4; - multiple_map[2][1][2].finalArray[3] = 5; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("data(uint256)", 0), encodeArgs(8)); - ABI_CHECK(callContractFunction("data(uint256)", 8), encodeArgs()); - ABI_CHECK(callContractFunction("dynamicData(uint256)", 2), encodeArgs(8)); - ABI_CHECK(callContractFunction("dynamicData(uint256)", 8), encodeArgs()); - ABI_CHECK(callContractFunction("smallTypeData(uint256)", 1), encodeArgs(22)); - ABI_CHECK(callContractFunction("smallTypeData(uint256)", 127), encodeArgs(2)); - ABI_CHECK(callContractFunction("smallTypeData(uint256)", 128), encodeArgs()); - ABI_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2), encodeArgs(3)); -} - -BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) -{ - char const* sourceCode = R"( - contract test { - mapping(uint => uint[8]) public data; - mapping(uint => uint[]) public dynamicData; - constructor() public { - data[2][2] = 8; - dynamicData[2].length = 3; - dynamicData[2][2] = 8; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("data(uint256,uint256)", 2, 2), encodeArgs(8)); - ABI_CHECK(callContractFunction("data(uint256, 256)", 2, 8), encodeArgs()); - ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2), encodeArgs(8)); - ABI_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8), encodeArgs()); -} - BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { char const* sourceCode = R"( @@ -1703,47 +1103,6 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) ABI_CHECK(callContractFunction("super_secret_data()"), bytes()); } -BOOST_AUTO_TEST_CASE(complex_accessors) -{ - char const* sourceCode = R"( - contract test { - mapping(uint256 => bytes4) public to_string_map; - mapping(uint256 => bool) public to_bool_map; - mapping(uint256 => uint256) public to_uint_map; - mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map; - constructor() public { - to_string_map[42] = "24"; - to_bool_map[42] = false; - to_uint_map[42] = 12; - to_multiple_map[42][23] = 31; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("to_string_map(uint256)", 42), encodeArgs("24")); - ABI_CHECK(callContractFunction("to_bool_map(uint256)", 42), encodeArgs(false)); - ABI_CHECK(callContractFunction("to_uint_map(uint256)", 42), encodeArgs(12)); - ABI_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23), encodeArgs(31)); -} - -BOOST_AUTO_TEST_CASE(struct_accessor) -{ - char const* sourceCode = R"( - contract test { - struct Data { uint a; uint8 b; mapping(uint => uint) c; bool d; } - mapping(uint => Data) public data; - constructor() public { - data[7].a = 1; - data[7].b = 2; - data[7].c[0] = 3; - data[7].d = true; - } - } - )"; - compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("data(uint256)", 7), encodeArgs(1, 2, true)); -} - BOOST_AUTO_TEST_CASE(balance) { char const* sourceCode = R"( diff --git a/test/libsolidity/semanticTests/expressions/bytes_comparison.sol b/test/libsolidity/semanticTests/expressions/bytes_comparison.sol new file mode 100644 index 000000000..a9a0d3a75 --- /dev/null +++ b/test/libsolidity/semanticTests/expressions/bytes_comparison.sol @@ -0,0 +1,12 @@ +contract test { + function f() public returns (bool) { + bytes2 a = "a"; + bytes2 x = "aa"; + bytes2 b = "b"; + return a < x && x < b; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> true diff --git a/test/libsolidity/semanticTests/expressions/inc_dec_operators.sol b/test/libsolidity/semanticTests/expressions/inc_dec_operators.sol new file mode 100644 index 000000000..3750ee9bb --- /dev/null +++ b/test/libsolidity/semanticTests/expressions/inc_dec_operators.sol @@ -0,0 +1,17 @@ +contract test { + uint8 x; + uint v; + function f() public returns (uint r) { + uint a = 6; + r = a; + r += (a++) * 0x10; + r += (++a) * 0x100; + v = 3; + r += (v++) * 0x1000; + r += (++v) * 0x10000; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x053866 diff --git a/test/libsolidity/semanticTests/functionCall/array_multiple_local_vars.sol b/test/libsolidity/semanticTests/functionCall/array_multiple_local_vars.sol new file mode 100644 index 000000000..4dbfe91f1 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/array_multiple_local_vars.sol @@ -0,0 +1,28 @@ +contract test { + function f(uint256[] calldata seq) external pure returns (uint256) { + uint i = 0; + uint sum = 0; + while (i < seq.length) + { + uint idx = i; + if (idx >= 10) break; + uint x = seq[idx]; + if (x >= 1000) { + uint n = i + 1; + i = n; + continue; + } + else { + uint y = sum + x; + sum = y; + } + if (sum >= 500) return sum; + i++; + } + return sum; + } +} +// ---- +// f(uint256[]): 32, 3, 1000, 1, 2 -> 3 +// f(uint256[]): 32, 3, 100, 500, 300 -> 600 +// f(uint256[]): 32, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 111 -> 55 diff --git a/test/libsolidity/semanticTests/functionCall/disordered_named_args.sol b/test/libsolidity/semanticTests/functionCall/disordered_named_args.sol new file mode 100644 index 000000000..2d16f515d --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/disordered_named_args.sol @@ -0,0 +1,8 @@ +contract test { + function a(uint a, uint b, uint c) public returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() public returns (uint r) { r = a({c: 3, a: 1, b: 2}); } +} +// ==== +// compileViaYul: also +// ---- +// b() -> 123 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol new file mode 100644 index 000000000..54baa4572 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/mapping_array_internal_argument.sol @@ -0,0 +1,23 @@ +contract test { + mapping(uint8 => uint8)[2] a; + mapping(uint8 => uint8)[2] b; + function set_internal(mapping(uint8 => uint8)[2] storage m, uint8 key, uint8 value1, uint8 value2) internal returns (uint8, uint8) { + uint8 oldValue1 = m[0][key]; + uint8 oldValue2 = m[1][key]; + m[0][key] = value1; + m[1][key] = value2; + return (oldValue1, oldValue2); + } + function set(uint8 key, uint8 value_a1, uint8 value_a2, uint8 value_b1, uint8 value_b2) public returns (uint8 old_a1, uint8 old_a2, uint8 old_b1, uint8 old_b2) { + (old_a1, old_a2) = set_internal(a, key, value_a1, value_a2); + (old_b1, old_b2) = set_internal(b, key, value_b1, value_b2); + } + function get(uint8 key) public returns (uint8, uint8, uint8, uint8) { + return (a[0][key], a[1][key], b[0][key], b[1][key]); + } +} +// ---- +// set(uint8,uint8,uint8,uint8,uint8): 1, 21, 22, 42, 43 -> 0, 0, 0, 0 +// get(uint8): 1 -> 21, 22, 42, 43 +// set(uint8,uint8,uint8,uint8,uint8): 1, 10, 30, 11, 31 -> 21, 22, 42, 43 +// get(uint8): 1 -> 10, 30, 11, 31 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_internal_argument.sol b/test/libsolidity/semanticTests/functionCall/mapping_internal_argument.sol new file mode 100644 index 000000000..728be2c09 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/mapping_internal_argument.sol @@ -0,0 +1,21 @@ +contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function set_internal(mapping(uint8 => uint8) storage m, uint8 key, uint8 value) internal returns (uint8) { + uint8 oldValue = m[key]; + m[key] = value; + return oldValue; + } + function set(uint8 key, uint8 value_a, uint8 value_b) public returns (uint8 old_a, uint8 old_b) { + old_a = set_internal(a, key, value_a); + old_b = set_internal(b, key, value_b); + } + function get(uint8 key) public returns (uint8, uint8) { + return (a[key], b[key]); + } +} +// ---- +// set(uint8,uint8,uint8): 1, 21, 42 -> 0, 0 +// get(uint8): 1 -> 21, 42 +// set(uint8,uint8,uint8): 1, 10, 11 -> 21, 42 +// get(uint8): 1 -> 10, 11 diff --git a/test/libsolidity/semanticTests/functionCall/mapping_internal_return.sol b/test/libsolidity/semanticTests/functionCall/mapping_internal_return.sol new file mode 100644 index 000000000..7756a92b1 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/mapping_internal_return.sol @@ -0,0 +1,22 @@ +contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function f() internal returns (mapping(uint8 => uint8) storage r) { + r = a; + r[1] = 42; + r = b; + r[1] = 84; + } + function g() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + f()[2] = 21; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function h() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = f(); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } +} +// ---- +// g() -> 0, 42, 0, 0, 84, 21 +// h() -> 0, 42, 0, 0, 84, 17 diff --git a/test/libsolidity/semanticTests/functionCall/multiple_return_values.sol b/test/libsolidity/semanticTests/functionCall/multiple_return_values.sol new file mode 100644 index 000000000..d3cab0dac --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/multiple_return_values.sol @@ -0,0 +1,9 @@ +contract test { + function run(bool x1, uint x2) public returns(uint y1, bool y2, uint y3) { + y1 = x2; y2 = x1; + } +} +// ==== +// compileViaYul: also +// ---- +// run(bool,uint256): true, 0xcd -> 0xcd, true, 0 diff --git a/test/libsolidity/semanticTests/statements/do_while_loop_continue.sol b/test/libsolidity/semanticTests/statements/do_while_loop_continue.sol new file mode 100644 index 000000000..19b4f3827 --- /dev/null +++ b/test/libsolidity/semanticTests/statements/do_while_loop_continue.sol @@ -0,0 +1,16 @@ +contract test { + function f() public pure returns(uint r) { + uint i = 0; + do + { + if (i > 0) return 0; + i++; + continue; + } while (false); + return 42; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 42 diff --git a/test/libsolidity/semanticTests/storage/accessors_mapping_for_array.sol b/test/libsolidity/semanticTests/storage/accessors_mapping_for_array.sol new file mode 100644 index 000000000..81f6c2014 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/accessors_mapping_for_array.sol @@ -0,0 +1,14 @@ +contract test { + mapping(uint => uint[8]) public data; + mapping(uint => uint[]) public dynamicData; + constructor() public { + data[2][2] = 8; + dynamicData[2].length = 3; + dynamicData[2][2] = 8; + } +} +// ---- +// data(uint256,uint256): 2, 2 -> 8 +// data(uint256,uint256): 2, 8 -> FAILURE # NB: the original code contained a bug here # +// dynamicData(uint256,uint256): 2, 2 -> 8 +// dynamicData(uint256,uint256): 2, 8 -> FAILURE diff --git a/test/libsolidity/semanticTests/storage/array_accessor.sol b/test/libsolidity/semanticTests/storage/array_accessor.sol new file mode 100644 index 000000000..b02962472 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/array_accessor.sol @@ -0,0 +1,28 @@ +contract test { + uint[8] public data; + uint[] public dynamicData; + uint24[] public smallTypeData; + struct st { uint a; uint[] finalArray; } + mapping(uint256 => mapping(uint256 => st[5])) public multiple_map; + + constructor() public { + data[0] = 8; + dynamicData.length = 3; + dynamicData[2] = 8; + smallTypeData.length = 128; + smallTypeData[1] = 22; + smallTypeData[127] = 2; + multiple_map[2][1][2].a = 3; + multiple_map[2][1][2].finalArray.length = 4; + multiple_map[2][1][2].finalArray[3] = 5; + } +} +// ---- +// data(uint256): 0 -> 8 +// data(uint256): 8 -> FAILURE +// dynamicData(uint256): 2 -> 8 +// dynamicData(uint256): 8 -> FAILURE +// smallTypeData(uint256): 1 -> 22 +// smallTypeData(uint256): 127 -> 2 +// smallTypeData(uint256): 128 -> FAILURE +// multiple_map(uint256,uint256,uint256): 2, 1, 2 -> 3 diff --git a/test/libsolidity/semanticTests/storage/complex_accessors.sol b/test/libsolidity/semanticTests/storage/complex_accessors.sol new file mode 100644 index 000000000..1169e4ea5 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/complex_accessors.sol @@ -0,0 +1,17 @@ +contract test { + mapping(uint256 => bytes4) public to_string_map; + mapping(uint256 => bool) public to_bool_map; + mapping(uint256 => uint256) public to_uint_map; + mapping(uint256 => mapping(uint256 => uint256)) public to_multiple_map; + constructor() public { + to_string_map[42] = "24"; + to_bool_map[42] = false; + to_uint_map[42] = 12; + to_multiple_map[42][23] = 31; + } +} +// ---- +// to_string_map(uint256): 42 -> "24" +// to_bool_map(uint256): 42 -> false +// to_uint_map(uint256): 42 -> 12 +// to_multiple_map(uint256,uint256): 42, 23 -> 31 diff --git a/test/libsolidity/semanticTests/storage/simple_accessor.sol b/test/libsolidity/semanticTests/storage/simple_accessor.sol new file mode 100644 index 000000000..23bcfbfac --- /dev/null +++ b/test/libsolidity/semanticTests/storage/simple_accessor.sol @@ -0,0 +1,8 @@ +contract test { + uint256 public data; + constructor() public { + data = 8; + } +} +// ---- +// data() -> 8 diff --git a/test/libsolidity/semanticTests/storage/state_smoke_test.sol b/test/libsolidity/semanticTests/storage/state_smoke_test.sol new file mode 100644 index 000000000..dc82e9129 --- /dev/null +++ b/test/libsolidity/semanticTests/storage/state_smoke_test.sol @@ -0,0 +1,23 @@ +contract test { + uint256 value1; + uint256 value2; + function get(uint8 which) public returns (uint256 value) { + if (which == 0) return value1; + else return value2; + } + function set(uint8 which, uint256 value) public { + if (which == 0) value1 = value; + else value2 = value; + } +} +// ==== +// compileViaYul: also +// ---- +// get(uint8): 0x00 -> 0 +// get(uint8): 0x01 -> 0 +// set(uint8,uint256): 0x00, 0x1234 -> +// set(uint8,uint256): 0x01, 0x8765 -> +// get(uint8): 0x00 -> 0x1234 +// get(uint8): 0x01 -> 0x8765 +// set(uint8,uint256): 0x00, 0x03 -> +// get(uint8): 0x00 -> 0x03 diff --git a/test/libsolidity/semanticTests/storage/struct_accessor.sol b/test/libsolidity/semanticTests/storage/struct_accessor.sol new file mode 100644 index 000000000..398cf750b --- /dev/null +++ b/test/libsolidity/semanticTests/storage/struct_accessor.sol @@ -0,0 +1,12 @@ +contract test { + struct Data { uint a; uint8 b; mapping(uint => uint) c; bool d; } + mapping(uint => Data) public data; + constructor() public { + data[7].a = 1; + data[7].b = 2; + data[7].c[0] = 3; + data[7].d = true; + } +} +// ---- +// data(uint256): 7 -> 1, 2, true diff --git a/test/libsolidity/semanticTests/structs/delete_struct.sol b/test/libsolidity/semanticTests/structs/delete_struct.sol new file mode 100644 index 000000000..7f57ce63a --- /dev/null +++ b/test/libsolidity/semanticTests/structs/delete_struct.sol @@ -0,0 +1,49 @@ +contract test { + struct topStruct { + nestedStruct nstr; + uint topValue; + mapping (uint => uint) topMapping; + } + uint toDelete; + topStruct str; + struct nestedStruct { + uint nestedValue; + mapping (uint => bool) nestedMapping; + } + constructor() public { + toDelete = 5; + str.topValue = 1; + str.topMapping[0] = 1; + str.topMapping[1] = 2; + + str.nstr.nestedValue = 2; + str.nstr.nestedMapping[0] = true; + str.nstr.nestedMapping[1] = false; + delete str; + delete toDelete; + } + function getToDelete() public returns (uint res){ + res = toDelete; + } + function getTopValue() public returns(uint topValue){ + topValue = str.topValue; + } + function getNestedValue() public returns(uint nestedValue){ + nestedValue = str.nstr.nestedValue; + } + function getTopMapping(uint index) public returns(uint ret) { + ret = str.topMapping[index]; + } + function getNestedMapping(uint index) public returns(bool ret) { + return str.nstr.nestedMapping[index]; + } +} +// ---- +// getToDelete() -> 0 +// getTopValue() -> 0 +// getNestedValue() -> 0 +// #mapping values should be the same# +// getTopMapping(uint256): 0 -> 1 +// getTopMapping(uint256): 1 -> 2 +// getNestedMapping(uint256): 0 -> true +// getNestedMapping(uint256): 1 -> false diff --git a/test/libsolidity/semanticTests/structs/struct_reference.sol b/test/libsolidity/semanticTests/structs/struct_reference.sol new file mode 100644 index 000000000..79eeccbe7 --- /dev/null +++ b/test/libsolidity/semanticTests/structs/struct_reference.sol @@ -0,0 +1,24 @@ +contract test { + struct s2 { + uint32 z; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() public returns (bool ok) { + return data.z == 2 && + data.recursive[0].z == 3 && + data.recursive[0].recursive[1].z == 0 && + data.recursive[0].recursive[0].z == 1; + } + function set() public { + data.z = 2; + mapping(uint8 => s2) storage map = data.recursive; + s2 storage inner = map[0]; + inner.z = 3; + inner.recursive[0].z = inner.recursive[1].z + 1; + } +} +// ---- +// check() -> false +// set() -> +// check() -> true diff --git a/test/libsolidity/semanticTests/structs/structs.sol b/test/libsolidity/semanticTests/structs/structs.sol new file mode 100644 index 000000000..4491f625d --- /dev/null +++ b/test/libsolidity/semanticTests/structs/structs.sol @@ -0,0 +1,33 @@ +contract test { + struct s1 { + uint8 x; + bool y; + } + struct s2 { + uint32 z; + s1 s1data; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() public returns (bool ok) { + return data.z == 1 && data.s1data.x == 2 && + data.s1data.y == true && + data.recursive[3].recursive[4].z == 5 && + data.recursive[4].recursive[3].z == 6 && + data.recursive[0].s1data.y == false && + data.recursive[4].z == 9; + } + function set() public { + data.z = 1; + data.s1data.x = 2; + data.s1data.y = true; + data.recursive[3].recursive[4].z = 5; + data.recursive[4].recursive[3].z = 6; + data.recursive[0].s1data.y = false; + data.recursive[4].z = 9; + } +} +// ---- +// check() -> false +// set() -> +// check() -> true diff --git a/test/libsolidity/semanticTests/types/packing_signed_types.sol b/test/libsolidity/semanticTests/types/packing_signed_types.sol new file mode 100644 index 000000000..2d2e0e16e --- /dev/null +++ b/test/libsolidity/semanticTests/types/packing_signed_types.sol @@ -0,0 +1,8 @@ +contract test { + function run() public returns(int8 y) { + uint8 x = 0xfa; + return int8(x); + } +} +// ---- +// run() -> 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa diff --git a/test/libsolidity/semanticTests/types/packing_unpacking_types.sol b/test/libsolidity/semanticTests/types/packing_unpacking_types.sol new file mode 100644 index 000000000..8b500cca1 --- /dev/null +++ b/test/libsolidity/semanticTests/types/packing_unpacking_types.sol @@ -0,0 +1,10 @@ +contract test { + function run(bool a, uint32 b, uint64 c) public returns(uint256 y) { + if (a) y = 1; + y = y * 0x100000000 | ~b; + y = y * 0x10000000000000000 | ~c; + } +} +// ---- +// run(bool,uint32,uint64): true, 0x0f0f0f0f, 0xf0f0f0f0f0f0f0f0 +// -> 0x0000000000000000000000000000000000000001f0f0f0f00f0f0f0f0f0f0f0f diff --git a/test/libsolidity/semanticTests/variables/delete_local.sol b/test/libsolidity/semanticTests/variables/delete_local.sol new file mode 100644 index 000000000..e29d6a942 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/delete_local.sol @@ -0,0 +1,11 @@ +contract test { + function delLocal() public returns (uint res){ + uint v = 5; + delete v; + res = v; + } +} +// ==== +// compileViaYul: also +// ---- +// delLocal() -> 0 diff --git a/test/libsolidity/semanticTests/variables/delete_locals.sol b/test/libsolidity/semanticTests/variables/delete_locals.sol new file mode 100644 index 000000000..8486f4999 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/delete_locals.sol @@ -0,0 +1,14 @@ +contract test { + function delLocal() public returns (uint res1, uint res2){ + uint v = 5; + uint w = 6; + uint x = 7; + delete v; + res1 = w; + res2 = x; + } +} +// ==== +// compileViaYul: also +// ---- +// delLocal() -> 6, 7 diff --git a/test/libsolidity/semanticTests/variables/mapping_local_assignment.sol b/test/libsolidity/semanticTests/variables/mapping_local_assignment.sol new file mode 100644 index 000000000..b99385823 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/mapping_local_assignment.sol @@ -0,0 +1,15 @@ +contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + m = m2; + m[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } +} +// ---- +// f() -> 42, 0, 0, 21 diff --git a/test/libsolidity/semanticTests/variables/mapping_local_compound_assignment.sol b/test/libsolidity/semanticTests/variables/mapping_local_compound_assignment.sol new file mode 100644 index 000000000..df3ee2f54 --- /dev/null +++ b/test/libsolidity/semanticTests/variables/mapping_local_compound_assignment.sol @@ -0,0 +1,14 @@ +contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + (m = m2)[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } +} +// ---- +// f() -> 42, 0, 0, 21 diff --git a/test/libsolidity/semanticTests/variables/mapping_local_tuple_assignment.sol b/test/libsolidity/semanticTests/variables/mapping_local_tuple_assignment.sol new file mode 100644 index 000000000..39dd04abb --- /dev/null +++ b/test/libsolidity/semanticTests/variables/mapping_local_tuple_assignment.sol @@ -0,0 +1,16 @@ +contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + uint8 v; + (m, v) = (m2, 21); + m[2] = v; + + return (m1[1], m1[2], m2[1], m2[2]); + } +} +// ---- +// f() -> 42, 0, 0, 21