Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2020-11-17 18:51:57 +01:00
141 changed files with 2354 additions and 1203 deletions
+32
View File
@@ -282,6 +282,38 @@ BOOST_AUTO_TEST_CASE(metadata_useLiteralContent)
check(sourceCode, false);
}
BOOST_AUTO_TEST_CASE(metadata_viair)
{
char const* sourceCode = R"(
pragma solidity >=0.0;
contract test {
}
)";
auto check = [](char const* _src, bool _viair)
{
CompilerStack compilerStack;
compilerStack.setSources({{"", std::string(_src)}});
compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion());
compilerStack.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
compilerStack.setViaIR(_viair);
BOOST_REQUIRE_MESSAGE(compilerStack.compile(), "Compiling contract failed");
string metadata_str = compilerStack.metadata("test");
Json::Value metadata;
util::jsonParseStrict(metadata_str, metadata);
BOOST_CHECK(solidity::test::isValidMetadata(metadata_str));
BOOST_CHECK(metadata.isMember("settings"));
if (_viair)
{
BOOST_CHECK(metadata["settings"].isMember("viaIR"));
BOOST_CHECK(metadata["settings"]["viaIR"].asBool());
}
};
check(sourceCode, true);
check(sourceCode, false);
}
BOOST_AUTO_TEST_CASE(metadata_revert_strings)
{
CompilerStack compilerStack;
-925
View File
@@ -2500,25 +2500,6 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign)
ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80));
}
BOOST_AUTO_TEST_CASE(delete_removes_bytes_data)
{
char const* sourceCode = R"(
contract c {
fallback() external { data = msg.data; }
function del() public returns (bool) { delete data; return true; }
bytes data;
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("---", 7), bytes());
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("del()", 7), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)
{
char const* sourceCode = R"(
@@ -2540,83 +2521,6 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)
);
}
BOOST_AUTO_TEST_CASE(copy_removes_bytes_data)
{
char const* sourceCode = R"(
contract c {
function set() public returns (bool) { data1 = msg.data; return true; }
function reset() public returns (bool) { data1 = data2; return true; }
bytes data1;
bytes data2;
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("set()", 1, 2, 3, 4, 5), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("reset()"), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(bytes_inside_mappings)
{
char const* sourceCode = R"(
contract c {
function set(uint key) public returns (bool) { data[key] = msg.data; return true; }
function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; }
mapping(uint => bytes) data;
}
)";
compileAndRun(sourceCode);
// store a short byte array at 1 and a longer one at 2
ABI_CHECK(callContractFunction("set(uint256)", 1, 2), encodeArgs(true));
ABI_CHECK(callContractFunction("set(uint256)", 2, 2, 3, 4, 5), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
// copy shorter to longer
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 1, 2), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
// copy empty to both
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 1), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("copy(uint256,uint256)", 99, 2), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete)
{
char const* sourceCode = R"(
contract c {
struct Struct { uint a; bytes data; uint b; }
Struct data1;
Struct data2;
function set(uint _a, bytes calldata _data, uint _b) external returns (bool) {
data1.a = _a;
data1.b = _b;
data1.data = _data;
return true;
}
function copy() public returns (bool) {
data1 = data2;
return true;
}
function del() public returns (bool) {
delete data1;
return true;
}
}
)";
compileAndRun(sourceCode);
string data = "123456789012345678901234567890123";
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("copy()"), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, 0x60, 13, u256(data.length()), data), encodeArgs(true));
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("del()"), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(storing_invalid_boolean)
{
char const* sourceCode = R"(
@@ -2801,197 +2705,6 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments)
);
}
BOOST_AUTO_TEST_CASE(fixed_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint spacer1;
uint spacer2;
uint[20] data;
function fill() public {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() public { delete data; }
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("fill()"), bytes());
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("clear()"), bytes());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(short_fixed_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint spacer1;
uint spacer2;
uint[3] data;
function fill() public {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() public { delete data; }
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("fill()"), bytes());
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("clear()"), bytes());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(dynamic_array_cleanup)
{
char const* sourceCode = R"(
contract c {
uint[20] spacer;
uint[] dynamic;
function fill() public {
for (uint i = 0; i < 21; ++i)
dynamic.push(i + 1);
}
function halfClear() public {
while (dynamic.length > 5)
dynamic.pop();
}
function fullClear() public { delete dynamic; }
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("fill()"), bytes());
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("halfClear()"), bytes());
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("fullClear()"), bytes());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(dynamic_multi_array_cleanup)
{
char const* sourceCode = R"(
contract c {
struct s { uint[][] d; }
s[] data;
function fill() public returns (uint) {
while (data.length < 3)
data.push();
while (data[2].d.length < 4)
data[2].d.push();
while (data[2].d[3].length < 5)
data[2].d[3].push();
data[2].d[3][4] = 8;
return data[2].d[3][4];
}
function clear() public { delete data; }
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("fill()"), encodeArgs(8));
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("clear()"), bytes());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_dyn_dyn)
{
char const* sourceCode = R"(
contract c {
uint[] data1;
uint[] data2;
function setData1(uint length, uint index, uint value) public {
data1 = new uint[](length);
if (index < length)
data1[index] = value;
}
function copyStorageStorage() public { data2 = data1; }
function getData2(uint index) public returns (uint len, uint val) {
len = data2.length; if (index < len) val = data2[index];
}
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 10, 5, 4), bytes());
ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes());
ABI_CHECK(callContractFunction("getData2(uint256)", 5), encodeArgs(10, 4));
ABI_CHECK(callContractFunction("setData1(uint256,uint256,uint256)", 0, 0, 0), bytes());
ABI_CHECK(callContractFunction("copyStorageStorage()"), bytes());
ABI_CHECK(callContractFunction("getData2(uint256)", 0), encodeArgs(0, 0));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(array_copy_target_leftover)
{
// test that leftover elements in the last slot of target are correctly cleared during assignment
char const* sourceCode = R"(
contract c {
byte[10] data1;
bytes2[32] data2;
function test() public returns (uint check, uint res1, uint res2) {
uint i;
for (i = 0; i < data2.length; ++i)
data2[i] = 0xffff;
check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14]));
for (i = 0; i < data1.length; ++i)
data1[i] = byte(uint8(1 + i));
data2 = data1;
for (i = 0; i < 16; ++i)
res1 |= uint(uint16(data2[i])) * 0x10000**i;
for (i = 0; i < 16; ++i)
res2 |= uint(uint16(data2[16 + i])) * 0x10000**i;
}
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(u256("0xffffffff"), asString(fromHex("0000000000000000000000000a00090008000700060005000400030002000100")), asString(fromHex("0000000000000000000000000000000000000000000000000000000000000000"))));
}
BOOST_AUTO_TEST_CASE(array_copy_storage_storage_struct)
{
char const* sourceCode = R"(
contract c {
struct Data { uint x; uint y; }
Data[] data1;
Data[] data2;
function test() public returns (uint x, uint y) {
while (data1.length < 9)
data1.push();
data1[8].x = 4;
data1[8].y = 5;
data2 = data1;
x = data2[8].x;
y = data2[8].y;
while (data1.length > 0)
data1.pop();
data2 = data1;
}
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(4, 5));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(array_copy_storage_abi)
{
// NOTE: This does not really test copying from storage to ABI directly,
@@ -3048,331 +2761,6 @@ BOOST_AUTO_TEST_CASE(array_copy_storage_abi)
);
}
BOOST_AUTO_TEST_CASE(array_pop_uint16_transition)
{
char const* sourceCode = R"(
contract c {
uint16[] data;
function test() public returns (uint16 x, uint16 y, uint16 z) {
for (uint i = 1; i <= 48; i++)
data.push(uint16(i));
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1];
for (uint l = 1; l <= 10; l++)
data.pop();
z = data[data.length - 1];
for (uint m = 1; m <= 18; m++)
data.pop();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(38, 28, 18));
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(array_pop_uint24_transition)
{
char const* sourceCode = R"(
contract c {
uint256 a;
uint256 b;
uint256 c;
uint24[] data;
function test() public returns (uint24 x, uint24 y) {
for (uint i = 1; i <= 30; i++)
data.push(uint24(i));
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1];
for (uint l = 1; l <= 10; l++)
data.pop();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(20, 10));
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(array_pop_array_transition)
{
char const* sourceCode = R"(
contract c {
uint256 a;
uint256 b;
uint256 c;
uint16[] inner = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
uint16[][] data;
function test() public returns (uint x, uint y, uint z) {
for (uint i = 1; i <= 48; i++)
data.push(inner);
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1][0];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1][1];
for (uint l = 1; l <= 10; l++)
data.pop();
z = data[data.length - 1][2];
for (uint m = 1; m <= 18; m++)
data.pop();
delete inner;
}
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 2, 3));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
BOOST_AUTO_TEST_CASE(array_pop_storage_empty)
{
char const* sourceCode = R"(
contract c {
uint[] data;
function test() public {
data.push(7);
data.pop();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(byte_array_pop_storage_empty)
{
char const* sourceCode = R"(
contract c {
bytes data;
function test() public {
data.push(0x07);
data.push(0x05);
data.push(0x03);
data.pop();
data.pop();
data.pop();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs());
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty)
{
char const* sourceCode = R"(
contract c {
uint256 a;
uint256 b;
uint256 c;
bytes data;
function test() public returns (bool) {
for (uint8 i = 0; i <= 40; i++)
data.push(byte(i+1));
for (int8 j = 40; j >= 0; j--) {
require(data[uint8(j)] == byte(j+1));
require(data.length == uint8(j+1));
data.pop();
}
return true;
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(true));
BOOST_CHECK(storageEmpty(m_contractAddress));
);
}
BOOST_AUTO_TEST_CASE(byte_array_pop_long_storage_empty_garbage_ref)
{
char const* sourceCode = R"(
contract c {
uint256 a;
uint256 b;
bytes data;
function test() public {
for (uint8 i = 0; i <= 40; i++)
data.push(0x03);
for (uint8 j = 0; j <= 40; j++) {
assembly {
mstore(0, "garbage")
}
data.pop();
}
}
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs());
BOOST_CHECK(storageEmpty(m_contractAddress));
}
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"(
@@ -3684,159 +3072,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<u256> 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<u256> 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"(
@@ -3859,35 +3094,6 @@ BOOST_AUTO_TEST_CASE(memory_types_initialisation)
ABI_CHECK(callContractFunction("nestedStat()"), encodeArgs(vector<u256>(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<u256> 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"(
@@ -3936,84 +3142,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)),
panicData(PanicCode::ArrayOutOfBounds)
);
}
BOOST_AUTO_TEST_CASE(calldata_array_two_dimensional)
{
vector<vector<u256>> 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<u256> 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]));
}
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256,uint256)", 0x60, i, data[i].size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
}
ABI_CHECK(callContractFunction("test(" + arrayType + ",uint256)", 0x40, data.size(), encoding), panicData(PanicCode::ArrayOutOfBounds));
}
}
BOOST_AUTO_TEST_CASE(calldata_array_dynamic_three_dimensional)
{
vector<vector<vector<u256>>> data {
@@ -6591,59 +5719,6 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser)
);
}
BOOST_AUTO_TEST_CASE(try_catch_library_call)
{
char const* sourceCode = R"(
library L {
struct S { uint x; }
function integer(uint t, bool b) public view returns (uint) {
if (b) {
return t;
} else {
revert("failure");
}
}
function stru(S storage t, bool b) public view returns (uint) {
if (b) {
return t.x;
} else {
revert("failure");
}
}
}
contract C {
using L for L.S;
L.S t;
function f(bool b) public returns (uint, string memory) {
uint x = 8;
try L.integer(x, b) returns (uint _x) {
return (_x, "");
} catch Error(string memory message) {
return (18, message);
}
}
function g(bool b) public returns (uint, string memory) {
t.x = 9;
try t.stru(b) returns (uint x) {
return (x, "");
} catch Error(string memory message) {
return (19, message);
}
}
}
)";
if (solidity::test::CommonOptions::get().evmVersion().supportsReturndata())
{
compileAndRun(sourceCode, 0, "L", bytes());
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(8, 0x40, 0));
ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(18, 0x40, 7, "failure"));
ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(9, 0x40, 0));
ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs(19, 0x40, 7, "failure"));
}
}
BOOST_AUTO_TEST_CASE(strip_reason_strings)
{
char const* sourceCode = R"(
+225
View File
@@ -1748,6 +1748,7 @@ BOOST_AUTO_TEST_CASE(user_explicit_inherit_partial2)
checkNatspec(sourceCode, "ERC20", natspec, true);
checkNatspec(sourceCode, "Token", natspec2, true);
}
BOOST_AUTO_TEST_CASE(dev_explicit_inherit_partial)
{
char const *sourceCode = R"(
@@ -2022,6 +2023,230 @@ BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex)
);
}
BOOST_AUTO_TEST_CASE(dev_different_return_name)
{
char const *sourceCode = R"(
contract A {
/// @return y value
function g(int x) public pure virtual returns (int y) { return x; }
}
contract B is A {
function g(int x) public pure override returns (int z) { return x; }
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"y": "value"
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"z": "value"
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "A", natspec, false);
checkNatspec(sourceCode, "B", natspec2, false);
}
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple)
{
char const *sourceCode = R"(
contract A {
/// @return a value A
/// @return b value B
function g(int x) public pure virtual returns (int a, int b) { return (1, 2); }
}
contract B is A {
function g(int x) public pure override returns (int z, int y) { return (1, 2); }
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"a": "value A",
"b": "value B"
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"z": "value A",
"y": "value B"
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "A", natspec, false);
checkNatspec(sourceCode, "B", natspec2, false);
}
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple_partly_unnamed)
{
char const *sourceCode = R"(
contract A {
/// @return value A
/// @return b value B
function g(int x) public pure virtual returns (int, int b) { return (1, 2); }
}
contract B is A {
function g(int x) public pure override returns (int z, int) { return (1, 2); }
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"_0": "value A",
"b": "value B"
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"z": "value A",
"_1": "value B"
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "A", natspec, false);
checkNatspec(sourceCode, "B", natspec2, false);
}
BOOST_AUTO_TEST_CASE(dev_different_return_name_multiple_unnamed)
{
char const *sourceCode = R"(
contract A {
/// @return value A
/// @return value B
function g(int x) public pure virtual returns (int, int) { return (1, 2); }
}
contract B is A {
function g(int x) public pure override returns (int z, int y) { return (1, 2); }
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"_0": "value A",
"_1": "value B"
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"z": "value A",
"y": "value B"
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "A", natspec, false);
checkNatspec(sourceCode, "B", natspec2, false);
}
BOOST_AUTO_TEST_CASE(dev_return_name_no_description)
{
char const *sourceCode = R"(
contract A {
/// @return a
function g(int x) public pure virtual returns (int a) { return 2; }
}
contract B is A {
function g(int x) public pure override returns (int b) { return 2; }
}
)";
char const *natspec = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"a": "a",
}
}
}
})ABCDEF";
char const *natspec2 = R"ABCDEF({
"methods":
{
"g(int256)":
{
"returns":
{
"b": "a",
}
}
}
})ABCDEF";
checkNatspec(sourceCode, "A", natspec, false);
checkNatspec(sourceCode, "B", natspec2, false);
}
}
BOOST_AUTO_TEST_SUITE_END()
+174 -14
View File
@@ -86,6 +86,48 @@ Json::Value getContractResult(Json::Value const& _compilerResult, string const&
return _compilerResult["contracts"][_file][_name];
}
void checkLinkReferencesSchema(Json::Value const& _contractResult)
{
BOOST_TEST_REQUIRE(_contractResult.isObject());
BOOST_TEST_REQUIRE(_contractResult["evm"]["bytecode"].isObject());
Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"];
BOOST_TEST_REQUIRE(linkReferenceResult.isObject());
for (string const& fileName: linkReferenceResult.getMemberNames())
{
BOOST_TEST_REQUIRE(linkReferenceResult[fileName].isObject());
for (string const& libraryName: linkReferenceResult[fileName].getMemberNames())
{
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName].isArray());
BOOST_TEST_REQUIRE(!linkReferenceResult[fileName][libraryName].empty());
for (int i = 0; i < static_cast<int>(linkReferenceResult.size()); ++i)
{
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].isObject());
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i].size() == 2);
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["length"].isUInt());
BOOST_TEST_REQUIRE(linkReferenceResult[fileName][libraryName][i]["start"].isUInt());
}
}
}
}
void expectLinkReferences(Json::Value const& _contractResult, map<string, set<string>> const& _expectedLinkReferences)
{
checkLinkReferencesSchema(_contractResult);
Json::Value const& linkReferenceResult = _contractResult["evm"]["bytecode"]["linkReferences"];
BOOST_TEST(linkReferenceResult.size() == _expectedLinkReferences.size());
for (auto const& [fileName, libraries]: _expectedLinkReferences)
{
BOOST_TEST(linkReferenceResult.isMember(fileName));
BOOST_TEST(linkReferenceResult[fileName].size() == libraries.size());
for (string const& libraryName: libraries)
BOOST_TEST(linkReferenceResult[fileName].isMember(libraryName));
}
}
Json::Value compile(string _input)
{
StandardCompiler compiler;
@@ -710,11 +752,7 @@ BOOST_AUTO_TEST_CASE(library_filename_with_colon)
BOOST_CHECK(containsAtMostWarnings(result));
Json::Value contract = getContractResult(result, "fileA", "A");
BOOST_CHECK(contract.isObject());
BOOST_CHECK(contract["evm"]["bytecode"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"]["L"].isArray());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["git:library.sol"]["L"][0].isObject());
expectLinkReferences(contract, {{"git:library.sol", {"L"}}});
}
BOOST_AUTO_TEST_CASE(libraries_invalid_top_level)
@@ -860,15 +898,137 @@ BOOST_AUTO_TEST_CASE(library_linking)
}
)";
Json::Value result = compile(input);
BOOST_CHECK(containsAtMostWarnings(result));
Json::Value contract = getContractResult(result, "fileA", "A");
BOOST_CHECK(contract.isObject());
BOOST_CHECK(contract["evm"]["bytecode"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"].isObject());
BOOST_CHECK(!contract["evm"]["bytecode"]["linkReferences"]["library.sol"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"].isArray());
BOOST_CHECK(contract["evm"]["bytecode"]["linkReferences"]["library2.sol"]["L2"][0].isObject());
BOOST_TEST(containsAtMostWarnings(result));
Json::Value contractResult = getContractResult(result, "fileA", "A");
expectLinkReferences(contractResult, {{"library2.sol", {"L2"}}});
}
BOOST_AUTO_TEST_CASE(linking_yul)
{
char const* input = R"(
{
"language": "Yul",
"settings": {
"libraries": {
"fileB": {
"L": "0x4200000000000000000000000000000000000001"
}
},
"outputSelection": {
"fileA": {
"*": [
"evm.bytecode.linkReferences"
]
}
}
},
"sources": {
"fileA": {
"content": "object \"a\" { code { let addr := linkersymbol(\"fileB:L\") } }"
}
}
}
)";
Json::Value result = compile(input);
BOOST_TEST(containsAtMostWarnings(result));
Json::Value contractResult = getContractResult(result, "fileA", "a");
expectLinkReferences(contractResult, {});
}
BOOST_AUTO_TEST_CASE(linking_yul_empty_link_reference)
{
char const* input = R"(
{
"language": "Yul",
"settings": {
"libraries": {
"": {
"": "0x4200000000000000000000000000000000000001"
}
},
"outputSelection": {
"fileA": {
"*": [
"evm.bytecode.linkReferences"
]
}
}
},
"sources": {
"fileA": {
"content": "object \"a\" { code { let addr := linkersymbol(\"\") } }"
}
}
}
)";
Json::Value result = compile(input);
BOOST_TEST(containsAtMostWarnings(result));
Json::Value contractResult = getContractResult(result, "fileA", "a");
expectLinkReferences(contractResult, {{"", {""}}});
}
BOOST_AUTO_TEST_CASE(linking_yul_no_filename_in_link_reference)
{
char const* input = R"(
{
"language": "Yul",
"settings": {
"libraries": {
"": {
"L": "0x4200000000000000000000000000000000000001"
}
},
"outputSelection": {
"fileA": {
"*": [
"evm.bytecode.linkReferences"
]
}
}
},
"sources": {
"fileA": {
"content": "object \"a\" { code { let addr := linkersymbol(\"L\") } }"
}
}
}
)";
Json::Value result = compile(input);
BOOST_TEST(containsAtMostWarnings(result));
Json::Value contractResult = getContractResult(result, "fileA", "a");
expectLinkReferences(contractResult, {{"", {"L"}}});
}
BOOST_AUTO_TEST_CASE(linking_yul_same_library_name_different_files)
{
char const* input = R"(
{
"language": "Yul",
"settings": {
"libraries": {
"fileB": {
"L": "0x4200000000000000000000000000000000000001"
}
},
"outputSelection": {
"fileA": {
"*": [
"evm.bytecode.linkReferences"
]
}
}
},
"sources": {
"fileA": {
"content": "object \"a\" { code { let addr := linkersymbol(\"fileC:L\") } }"
}
}
}
)";
Json::Value result = compile(input);
BOOST_TEST(containsAtMostWarnings(result));
Json::Value contractResult = getContractResult(result, "fileA", "a");
expectLinkReferences(contractResult, {{"fileC", {"L"}}});
}
BOOST_AUTO_TEST_CASE(evm_version)
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,42 @@
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);
}
}
// ====
// compileViaYul: also
// ----
// test() -> 0x02000202
// storage: empty
// clear() -> 0, 0
// storage: empty
@@ -11,5 +11,7 @@ contract c {
}
}
// ====
// compileViaYul: also
// ----
// test(uint256[2][]): 32, 3, 7, 8, 9, 10, 11, 12 -> 10
@@ -0,0 +1,24 @@
contract c {
uint[] data1;
uint[] data2;
function setData1(uint length, uint index, uint value) public {
data1 = new uint[](length);
if (index < length)
data1[index] = value;
}
function copyStorageStorage() public { data2 = data1; }
function getData2(uint index) public returns (uint len, uint val) {
len = data2.length; if (index < len) val = data2[index];
}
}
// ====
// compileViaYul: also
// ----
// setData1(uint256,uint256,uint256): 10, 5, 4 ->
// copyStorageStorage() ->
// getData2(uint256): 5 -> 10, 4
// setData1(uint256,uint256,uint256): 0, 0, 0 ->
// copyStorageStorage() ->
// getData2(uint256): 0 -> 0, 0
// storage: empty
@@ -10,5 +10,7 @@ contract c {
}
}
// ====
// compileViaYul: also
// ----
// test() -> 9, 4
@@ -0,0 +1,22 @@
contract c {
struct Data { uint x; uint y; }
Data[] data1;
Data[] data2;
function test() public returns (uint x, uint y) {
while (data1.length < 9)
data1.push();
data1[8].x = 4;
data1[8].y = 5;
data2 = data1;
x = data2[8].x;
y = data2[8].y;
while (data1.length > 0)
data1.pop();
data2 = data1;
}
}
// ====
// compileViaYul: also
// ----
// test() -> 4, 5
// storage: empty
@@ -0,0 +1,19 @@
contract c {
byte[10] data1;
bytes2[32] data2;
function test() public returns (uint check, uint res1, uint res2) {
uint i;
for (i = 0; i < data2.length; ++i)
data2[i] = 0xffff;
check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14]));
for (i = 0; i < data1.length; ++i)
data1[i] = byte(uint8(1 + i));
data2 = data1;
for (i = 0; i < 16; ++i)
res1 |= uint(uint16(data2[i])) * 0x10000**i;
for (i = 0; i < 16; ++i)
res2 |= uint(uint16(data2[16 + i])) * 0x10000**i;
}
}
// ----
// test() -> 0xffffffff, 0x0000000000000000000000000a00090008000700060005000400030002000100, 0x0000000000000000000000000000000000000000000000000000000000000000
@@ -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
@@ -0,0 +1,17 @@
contract c {
function set(uint key) public returns (bool) { data[key] = msg.data; return true; }
function copy(uint from, uint to) public returns (bool) { data[to] = data[from]; return true; }
mapping(uint => bytes) data;
}
// ====
// compileViaYul: also
// ----
// set(uint256): 1, 2 -> true
// set(uint256): 2, 2, 3, 4, 5 -> true
// storage: nonempty
// copy(uint256,uint256): 1, 2 -> true
// storage: nonempty
// copy(uint256,uint256): 99, 1 -> true
// storage: nonempty
// copy(uint256,uint256): 99, 2 -> true
// storage: empty
@@ -14,5 +14,7 @@ contract C {
}
}
// ====
// compileViaYul: also
// ----
// test() -> 7
@@ -0,0 +1,14 @@
contract c {
function set() public returns (bool) { data1 = msg.data; return true; }
function reset() public returns (bool) { data1 = data2; return true; }
bytes data1;
bytes data2;
}
// ====
// compileViaYul: also
// ----
// set(): 1, 2, 3, 4, 5 -> true
// storage: nonempty
// reset() -> true
// storage: empty
@@ -0,0 +1,12 @@
contract c {
fallback() external { data = msg.data; }
function del() public returns (bool) { delete data; return true; }
bytes data;
}
// ====
// compileViaYul: also
// ----
// (): 7 ->
// storage: nonempty
// del(): 7 -> true
// storage: empty
@@ -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
@@ -0,0 +1,23 @@
contract c {
uint[20] spacer;
uint[] dynamic;
function fill() public {
for (uint i = 0; i < 21; ++i)
dynamic.push(i + 1);
}
function halfClear() public {
while (dynamic.length > 5)
dynamic.pop();
}
function fullClear() public { delete dynamic; }
}
// ====
// compileViaYul: also
// ----
// storage: empty
// fill() ->
// storage: nonempty
// halfClear() ->
// storage: nonempty
// fullClear() ->
// storage: empty
@@ -0,0 +1,23 @@
contract c {
struct s { uint[][] d; }
s[] data;
function fill() public returns (uint) {
while (data.length < 3)
data.push();
while (data[2].d.length < 4)
data[2].d.push();
while (data[2].d[3].length < 5)
data[2].d[3].push();
data[2].d[3][4] = 8;
return data[2].d[3][4];
}
function clear() public { delete data; }
}
// ====
// compileViaYul: also
// ----
// storage: empty
// fill() -> 8
// storage: nonempty
// clear() ->
// storage: empty
@@ -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
@@ -0,0 +1,17 @@
contract c {
uint spacer1;
uint spacer2;
uint[20] data;
function fill() public {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() public { delete data; }
}
// ====
// compileViaYul: also
// ----
// storage: empty
// fill() ->
// storage: nonempty
// clear() ->
// storage: empty
@@ -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
@@ -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"
@@ -0,0 +1,28 @@
contract c {
uint256 a;
uint256 b;
uint256 c;
uint16[] inner = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
uint16[][] data;
function test() public returns (uint x, uint y, uint z) {
for (uint i = 1; i <= 48; i++)
data.push(inner);
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1][0];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1][1];
for (uint l = 1; l <= 10; l++)
data.pop();
z = data[data.length - 1][2];
for (uint m = 1; m <= 18; m++)
data.pop();
delete inner;
}
}
// ====
// compileViaYul: also
// ----
// test() -> 1, 2, 3
// storage: empty
@@ -0,0 +1,12 @@
contract c {
uint[] data;
function test() public {
data.push(7);
data.pop();
}
}
// ====
// compileViaYul: also
// ----
// test() ->
// storage: empty
@@ -0,0 +1,23 @@
contract c {
uint16[] data;
function test() public returns (uint16 x, uint16 y, uint16 z) {
for (uint i = 1; i <= 48; i++)
data.push(uint16(i));
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1];
for (uint l = 1; l <= 10; l++)
data.pop();
z = data[data.length - 1];
for (uint m = 1; m <= 18; m++)
data.pop();
}
}
// ====
// compileViaYul: also
// ----
// test() -> 38, 28, 18
// storage: empty
@@ -0,0 +1,23 @@
contract c {
uint256 a;
uint256 b;
uint256 c;
uint24[] data;
function test() public returns (uint24 x, uint24 y) {
for (uint i = 1; i <= 30; i++)
data.push(uint24(i));
for (uint j = 1; j <= 10; j++)
data.pop();
x = data[data.length - 1];
for (uint k = 1; k <= 10; k++)
data.pop();
y = data[data.length - 1];
for (uint l = 1; l <= 10; l++)
data.pop();
}
}
// ====
// compileViaYul: also
// ----
// test() -> 20, 10
// storage: empty
@@ -0,0 +1,21 @@
contract c {
uint256 a;
uint256 b;
uint256 c;
bytes data;
function test() public returns (bool) {
for (uint8 i = 0; i <= 40; i++)
data.push(byte(i+1));
for (int8 j = 40; j >= 0; j--) {
require(data[uint8(j)] == byte(j+1));
require(data.length == uint8(j+1));
data.pop();
}
return true;
}
}
// ====
// compileViaYul: also
// ----
// test() -> true
// storage: empty
@@ -0,0 +1,20 @@
contract c {
uint256 a;
uint256 b;
bytes data;
function test() public {
for (uint8 i = 0; i <= 40; i++)
data.push(0x03);
for (uint8 j = 0; j <= 40; j++) {
assembly {
mstore(0, "garbage")
}
data.pop();
}
}
}
// ====
// compileViaYul: also
// ----
// test() ->
// storage: empty
@@ -0,0 +1,16 @@
contract c {
bytes data;
function test() public {
data.push(0x07);
data.push(0x05);
data.push(0x03);
data.pop();
data.pop();
data.pop();
}
}
// ====
// compileViaYul: also
// ----
// test() ->
// storage: empty
@@ -0,0 +1,17 @@
contract c {
uint spacer1;
uint spacer2;
uint[3] data;
function fill() public {
for (uint i = 0; i < data.length; ++i) data[i] = i+1;
}
function clear() public { delete data; }
}
// ====
// compileViaYul: also
// ----
// storage: empty
// fill() ->
// storage: nonempty
// clear() ->
// storage: empty
@@ -12,6 +12,8 @@ contract Test {
return bytes(s).length;
}
}
// ====
// compileViaYul: also
// ----
// f(string,uint256): 0x40, 0x02, 0x06, "abcdef" -> "c"
// l() -> 0x06
@@ -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
@@ -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"
@@ -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"
@@ -32,5 +32,7 @@ contract test {
}
}
// ====
// compileViaYul: also
// ----
// assign() -> 2, 2, 3, 3
@@ -0,0 +1,35 @@
contract c {
struct Struct { uint a; bytes data; uint b; }
Struct data1;
Struct data2;
function set(uint _a, bytes calldata _data, uint _b) external returns (bool) {
data1.a = _a;
data1.b = _b;
data1.data = _data;
return true;
}
function copy() public returns (bool) {
data1 = data2;
return true;
}
function del() public returns (bool) {
delete data1;
return true;
}
function test(uint256 i) public returns (byte) {
return data1.data[i];
}
}
// ====
// compileViaYul: also
// ----
// storage: empty
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
// test(uint256): 32 -> "3"
// storage: nonempty
// copy() -> true
// storage: empty
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
// storage: nonempty
// del() -> true
// storage: empty
@@ -34,6 +34,8 @@ contract c {
}
}
// ====
// compileViaYul: also
// ----
// set(uint256): 7 -> true
// retrieve(uint256): 7 -> 1, 3, 4, 2
@@ -0,0 +1,45 @@
library L {
struct S { uint x; }
function integer(uint t, bool b) public view returns (uint) {
if (b) {
return t;
} else {
revert("failure");
}
}
function stru(S storage t, bool b) public view returns (uint) {
if (b) {
return t.x;
} else {
revert("failure");
}
}
}
contract C {
using L for L.S;
L.S t;
function f(bool b) public returns (uint, string memory) {
uint x = 8;
try L.integer(x, b) returns (uint _x) {
return (_x, "");
} catch Error(string memory message) {
return (18, message);
}
}
function g(bool b) public returns (uint, string memory) {
t.x = 9;
try t.stru(b) returns (uint x) {
return (x, "");
} catch Error(string memory message) {
return (19, message);
}
}
}
// ====
// EVMVersion: >=byzantium
// ----
// library: L
// f(bool): true -> 8, 0x40, 0
// f(bool): false -> 18, 0x40, 7, "failure"
// g(bool): true -> 9, 0x40, 0
// g(bool): false -> 19, 0x40, 7, "failure"
@@ -23,6 +23,8 @@ contract c {
}
}
// ====
// compileViaYul: also
// ----
// x() -> 0, 0
// y() -> 0, 0
@@ -0,0 +1,21 @@
pragma experimental SMTChecker;
contract C {
uint x = initX();
function initX() internal pure returns (uint) {
return 42;
}
}
contract D is C {
uint y;
constructor() {
assert(x == 42);
y = x;
}
}
// ====
// SMTEngine: bmc
// ----
@@ -0,0 +1,19 @@
pragma experimental SMTChecker;
contract C {
uint x = initX();
uint y = initY();
function initX() internal pure returns (uint) {
return 42;
}
function initY() internal view returns (uint) {
assert(x == 42);
return x;
}
}
// ====
// SMTEngine: bmc
// ----
// Warning 4661: (205-220): BMC: Assertion violation happens here.
@@ -22,4 +22,4 @@ contract C {
// Warning 4144: (217-222): BMC: Underflow (resulting value less than 0) happens here.
// Warning 2661: (293-298): BMC: Overflow (resulting value larger than 2**256 - 1) happens here.
// Warning 3046: (369-374): BMC: Division by zero happens here.
// Warning 6084: (68-73): BMC: Underflow (resulting value less than 0) happens here.
// Warning 4144: (68-73): BMC: Underflow (resulting value less than 0) happens here.
@@ -9,9 +9,7 @@ contract C
function g(uint y) public {
require(y < 1000);
this.f(y);
// Fails as false positive because CHC does not support `this`.
assert(x < 1000);
}
}
// ----
// Warning 6328: (227-243): CHC: Assertion violation happens here.
@@ -0,0 +1,16 @@
pragma experimental SMTChecker;
contract C {
uint a;
function f(uint x) public {
this.g(x);
assert(a == x);
assert(a != 42);
}
function g(uint x) public {
a = x;
}
}
// ----
// Warning 6328: (141-156): CHC: Assertion violation happens here.
@@ -10,9 +10,7 @@ contract C
function g(uint y) public {
require(y < 1000);
uint z = this.f(y);
// Fails as false positive because CHC does not support `this`.
assert(z < 1000);
}
}
// ----
// Warning 6328: (263-279): CHC: Assertion violation happens here.
@@ -0,0 +1,28 @@
pragma experimental SMTChecker;
contract C {
address lastCaller;
constructor() {
lastCaller = msg.sender;
}
modifier log {
lastCaller = msg.sender;
_;
}
function test() log public {
assert(lastCaller == msg.sender);
this.g();
assert(lastCaller == address(this));
assert(lastCaller == msg.sender);
assert(lastCaller == address(0));
}
function g() log public {
}
}
// ----
// Warning 6328: (347-379): CHC: Assertion violation happens here.
// Warning 6328: (389-421): CHC: Assertion violation happens here.
@@ -0,0 +1,14 @@
pragma experimental SMTChecker;
contract C {
function test() view public {
require(address(this) != tx.origin);
assert(!this.g());
}
function g() view public returns (bool) {
return msg.sender == tx.origin;
}
}
// ----
@@ -0,0 +1,12 @@
pragma experimental SMTChecker;
contract C {
uint public x;
function f() public view {
uint y = this.x();
assert(y == x); // This fails as false positive because of lack of support for external getters.
}
}
// ----
// Warning 6328: (114-128): CHC: Assertion violation happens here.
@@ -0,0 +1,12 @@
pragma experimental SMTChecker;
contract C {
mapping (uint => uint) public map;
function f() public view {
uint y = this.map(2);
assert(y == map[2]); // This fails as false positive because of lack of support for external getters.
}
}
// ----
// Warning 6328: (137-156): CHC: Assertion violation happens here.
@@ -0,0 +1,12 @@
pragma experimental SMTChecker;
contract C {
mapping (uint => mapping (uint => uint)) public map;
function f() public view {
uint y = this.map(2, 3);
assert(y == map[2][3]); // This fails as false positive because of lack of support for external getters.
}
}
// ----
// Warning 6328: (158-180): CHC: Assertion violation happens here.
@@ -6,7 +6,6 @@ contract C
function g() public {
x = 0;
this.h();
// Fails as false positive because CHC does not support `this`.
assert(x == 2);
}
function h() public {
@@ -14,4 +13,3 @@ contract C
}
}
// ----
// Warning 6328: (186-200): CHC: Assertion violation happens here.
@@ -8,7 +8,7 @@ contract C {
assert(bytes(b[10:]).length == 20);
assert(bytes(b[10:])[0] == 0xff);
//assert(bytes(b[10:])[5] == 0xff); // Removed because of Spacer's nondeterminism
assert(bytes(b[10:])[19] == 0xaa);
//assert(bytes(b[10:])[19] == 0xaa); // Removed because of Spacer nondeterminism
}
}
// ----