trial test cases extracted from SoliidityEndToEndTest.cpp into .sol files.

removed libevmone.so files from the directory

trial test cases extracted from SoliidityEndToEndTest.cpp into .sol files. Corresponding code in the .cpp file has been commented instead of begin removed pending preliminary reviews

removed libevmone files

Added testcase packed_storage_structs_delete

added test case invalid_enum_logged

added test case enum_referencing

added test case memory_types_initialisation

added test case return string

added test case constant_string_literal.sol

removed extractable keyword from solidityEndtoEnd.cpp, moved copying_bytes_multiassigned.sol to array/copying folder, added recv() function to copying_bytes_multiassigned.sol but this test case is failing now

change typo error in the name of test case library_staticcall_delegatecal.sol to library_staticcall_delegatecall.sol

Added compileToEwasm:false to call_forward_bytes.sol test case and moved it to semanticTests/fallback

added compileToEwasm:false line to library_call_in_homestead

added compileToEwasm: false line to copying_bytes_multiassign, copy_from_calldata_removes_bytes, enum_referencing, library_call_in_homestead, struct_referencing

Added test case internal_types_in_library

Added test case mapping_arguments_in_library

Added test case mapping_returns_in_library

Added test case mapping_returns_in_library_named

Added test case using_library_mappings_public

Added test case library_function_external

Added test case library_stray_values

added test case using_library_mappings_return

added test case using_library_structs

Added test case using_for_function_on_struct and corrections to using_library_structs, using_library_mpapings_return, library_stray_values

Added test case using_for_overload

added test case using_for_by_name

added test case bound_function_in_function

added test case bound_function_in_var

added test case bound_function_to_string

added test case payable_function_calls_library

added function call corrections to copying_bytes_multiassign and call_forward_bytes

Made changes to the test cases as per comments on PR #12289

mentioned in Changelog.md : Extraced some test cases from SolEndToEnd.cpp
This commit is contained in:
nishant-sachdeva 2021-11-17 00:17:37 +05:30
parent 6363ff31db
commit 19a74506e3
22 changed files with 584 additions and 519 deletions

View File

@ -1551,26 +1551,6 @@ BOOST_AUTO_TEST_CASE(generic_staticcall)
}
}
BOOST_AUTO_TEST_CASE(library_call_in_homestead)
{
char const* sourceCode = R"(
library Lib { function m() public returns (address) { return msg.sender; } }
contract Test {
address public sender;
function f() public {
sender = Lib.m();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs());
ABI_CHECK(callContractFunction("sender()"), encodeArgs(m_sender));
)
}
BOOST_AUTO_TEST_CASE(library_call_protection)
{
// This tests code that reverts a call if it is a direct call to a library
@ -1626,38 +1606,6 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
);
}
BOOST_AUTO_TEST_CASE(call_forward_bytes)
{
char const* sourceCode = R"(
contract receiver {
uint public received;
function recv(uint x) public { received += x + 1; }
fallback() external { received = 0x80; }
}
contract sender {
constructor() { rec = new receiver(); }
fallback() external { savedData = msg.data; }
function forward() public returns (bool) { address(rec).call(savedData); return true; }
function clear() public returns (bool) { delete savedData; return true; }
function val() public returns (uint) { return rec.received(); }
receiver rec;
bytes savedData;
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN();
compileAndRun(sourceCode, 0, "sender");
ABI_CHECK(callContractFunction("recv(uint256)", 7), bytes());
ABI_CHECK(callContractFunction("val()"), encodeArgs(0));
ABI_CHECK(callContractFunction("forward()"), encodeArgs(true));
ABI_CHECK(callContractFunction("val()"), encodeArgs(8));
ABI_CHECK(callContractFunction("clear()"), encodeArgs(true));
ABI_CHECK(callContractFunction("val()"), encodeArgs(8));
ABI_CHECK(callContractFunction("forward()"), encodeArgs(true));
ABI_CHECK(callContractFunction("val()"), encodeArgs(0x80));
);
}
BOOST_AUTO_TEST_CASE(call_forward_bytes_length)
{
char const* sourceCode = R"(
@ -2576,254 +2524,6 @@ BOOST_AUTO_TEST_CASE(library_function_external)
)
}
BOOST_AUTO_TEST_CASE(library_stray_values)
{
char const* sourceCode = R"(
library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } }
contract Test {
function f(uint x) public returns (uint) {
Lib;
Lib.m;
return x + 9;
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(42)));
)
}
BOOST_AUTO_TEST_CASE(internal_types_in_library)
{
char const* sourceCode = R"(
library Lib {
function find(uint16[] storage _haystack, uint16 _needle) public view returns (uint)
{
for (uint i = 0; i < _haystack.length; ++i)
if (_haystack[i] == _needle)
return i;
return type(uint).max;
}
}
contract Test {
mapping(string => uint16[]) data;
function f() public returns (uint a, uint b)
{
while (data["abc"].length < 20)
data["abc"].push();
data["abc"][4] = 9;
data["abc"][17] = 3;
a = Lib.find(data["abc"], 9);
b = Lib.find(data["abc"], 3);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17)));
)
}
BOOST_AUTO_TEST_CASE(mapping_arguments_in_library)
{
char const* sourceCode = R"(
library Lib {
function set(mapping(uint => uint) storage m, uint key, uint value) internal
{
m[key] = value;
}
function get(mapping(uint => uint) storage m, uint key) internal view returns (uint)
{
return m[key];
}
}
contract Test {
mapping(uint => uint) m;
function set(uint256 key, uint256 value) public returns (uint)
{
uint oldValue = Lib.get(m, key);
Lib.set(m, key, value);
return oldValue;
}
function get(uint256 key) public view returns (uint) {
return Lib.get(m, key);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(42)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(84)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(7)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(84)));
ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(7)));
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(21)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(42)), encodeArgs(u256(84)));
ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(14)), encodeArgs(u256(7)));
ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(21)));
ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(14)));
)
}
BOOST_AUTO_TEST_CASE(mapping_returns_in_library)
{
char const* sourceCode = R"(
library Lib {
function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage)
{
return c ? a : b;
}
}
contract Test {
mapping(uint => uint) a;
mapping(uint => uint) b;
function set(bool choice, uint256 key, uint256 value) public returns (uint)
{
mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice);
uint oldValue = m[key];
m[key] = value;
return oldValue;
}
function get(bool choice, uint256 key) public view returns (uint) {
return Lib.choose_mapping(a, b, choice)[key];
}
function get_a(uint256 key) public view returns (uint) {
return a[key];
}
function get_b(uint256 key) public view returns (uint) {
return b[key];
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(42)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(84)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(7)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(10)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(11)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(12)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(84)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(7)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(84)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(7)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(10)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(11)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(12)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(10)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(11)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(12)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(21)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(42)), encodeArgs(u256(84)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(14)), encodeArgs(u256(7)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(30)), encodeArgs(u256(10)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(31)), encodeArgs(u256(11)));
ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(32)), encodeArgs(u256(12)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(21)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(14)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(21)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(42)));
ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(14)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(30)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(31)));
ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(32)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(30)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(31)));
ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(32)));
)
}
BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named)
{
char const* sourceCode = R"(
library Lib {
function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r)
{
r = a;
r[1] = 42;
r = b;
r[1] = 21;
}
}
contract Test {
mapping(uint => uint) a;
mapping(uint => uint) b;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.f(a, b)[2] = 84;
return (a[0], a[1], a[2], b[0], b[1], b[2]);
}
function g() public returns (uint, uint, uint, uint, uint, uint)
{
mapping(uint => uint) storage m = Lib.f(a, b);
m[2] = 17;
return (a[0], a[1], a[2], b[0], b[1], b[2]);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(84)));
ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17)));
)
}
BOOST_AUTO_TEST_CASE(using_library_mappings_public)
{
char const* sourceCode = R"(
library Lib {
function set(mapping(uint => uint) storage m, uint key, uint value) public
{
m[key] = value;
}
}
contract Test {
mapping(uint => uint) m1;
mapping(uint => uint) m2;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.set(m1, 0, 1);
Lib.set(m1, 2, 42);
Lib.set(m2, 0, 23);
Lib.set(m2, 2, 99);
return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99)));
)
}
BOOST_AUTO_TEST_CASE(using_library_mappings_external)
{
char const* libSourceCode = R"(
@ -2860,65 +2560,6 @@ BOOST_AUTO_TEST_CASE(using_library_mappings_external)
}
}
BOOST_AUTO_TEST_CASE(using_library_mappings_return)
{
char const* sourceCode = R"(
library Lib {
function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) {
return m[key];
}
}
contract Test {
mapping(uint => mapping(uint => uint)) m;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.choose(m, 0)[0] = 1;
Lib.choose(m, 0)[2] = 42;
Lib.choose(m, 1)[0] = 23;
Lib.choose(m, 1)[2] = 99;
return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99)));
)
}
BOOST_AUTO_TEST_CASE(using_library_structs)
{
char const* sourceCode = R"(
library Lib {
struct Data { uint a; uint[] b; }
function set(Data storage _s) public
{
_s.a = 7;
while (_s.b.length < 20)
_s.b.push();
_s.b[19] = 8;
}
}
contract Test {
mapping(string => Lib.Data) data;
function f() public returns (uint a, uint b)
{
Lib.set(data["abc"]);
a = data["abc"].a;
b = data["abc"].b[19];
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, h160>{{":Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7), u256(8)));
)
}
BOOST_AUTO_TEST_CASE(short_strings)
{
// This test verifies that the byte array encoding that combines length and data works
@ -3114,146 +2755,6 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)
}
}
BOOST_AUTO_TEST_CASE(using_for_function_on_struct)
{
char const* sourceCode = R"(
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 3;
return x.mul(a);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "D");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":D", m_contractAddress}});
ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(3 * 7)));
ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(3 * 7)));
)
}
BOOST_AUTO_TEST_CASE(using_for_overload)
{
char const* sourceCode = R"(
library D {
struct s { uint a; }
function mul(s storage self, uint x) public returns (uint) { return self.a *= x; }
function mul(s storage self, bytes32 x) public returns (bytes32) { }
}
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return x.mul(a);
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "D");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":D", m_contractAddress}});
ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7)));
ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7)));
)
}
BOOST_AUTO_TEST_CASE(using_for_by_name)
{
char const* sourceCode = R"(
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return x.mul({x: a});
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "D");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":D", m_contractAddress}});
ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7)));
ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7)));
)
}
BOOST_AUTO_TEST_CASE(bound_function_in_function)
{
char const* sourceCode = R"(
library L {
function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); }
}
contract C {
using L for *;
function f() public returns (uint) {
return t.g();
}
function t() public pure returns (uint) { return 7; }
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "L");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":L", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7)));
)
}
BOOST_AUTO_TEST_CASE(bound_function_in_var)
{
char const* sourceCode = R"(
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return (x.mul)({x: a});
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "D");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":D", m_contractAddress}});
ABI_CHECK(callContractFunction("f(uint256)", u256(7)), encodeArgs(u256(6 * 7)));
ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7)));
)
}
BOOST_AUTO_TEST_CASE(bound_function_to_string)
{
char const* sourceCode = R"(
library D { function length(string memory self) public returns (uint) { return bytes(self).length; } }
contract C {
using D for string;
string x;
function f() public returns (uint) {
x = "abc";
return x.length();
}
function g() public returns (uint) {
string memory s = "abc";
return s.length();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "D");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":D", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(3)));
ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(3)));
)
}
BOOST_AUTO_TEST_CASE(inline_long_string_return)
{
char const* sourceCode = R"(
@ -3406,26 +2907,6 @@ BOOST_AUTO_TEST_CASE(payable_function)
BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 27 + 27);
}
BOOST_AUTO_TEST_CASE(payable_function_calls_library)
{
char const* sourceCode = R"(
library L {
function f() public returns (uint) { return 7; }
}
contract C {
function f() public payable returns (uint) {
return L.f();
}
}
)";
ALSO_VIA_YUL(
DISABLE_EWASM_TESTRUN()
compileAndRun(sourceCode, 0, "L");
compileAndRun(sourceCode, 0, "C", bytes(), map<string, h160>{{":L", m_contractAddress}});
ABI_CHECK(callContractFunctionWithValue("f()", 27), encodeArgs(u256(7)));
)
}
BOOST_AUTO_TEST_CASE(non_payable_throw)
{
char const* sourceCode = R"(

View File

@ -0,0 +1,33 @@
contract receiver {
uint public received;
function recv(uint x) public { received += x + 1; }
fallback() external { received = 0x80; }
}
contract sender {
constructor() { rec = new receiver(); }
fallback() external { savedData1 = savedData2 = msg.data; }
function forward(bool selector) public returns (bool) {
if (selector) { address(rec).call(savedData1); delete savedData1; }
else { address(rec).call(savedData2); delete savedData2; }
return true;
}
function val() public returns (uint) { return rec.received(); }
receiver rec;
bytes savedData1;
bytes savedData2;
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// (): 7 ->
// gas irOptimized: 110941
// gas legacy: 111082
// gas legacyOptimized: 111027
// val() -> 0
// forward(bool): true -> true
// val() -> 0x80
// forward(bool): false -> true
// val() -> 0x80
// forward(bool): true -> true
// val() -> 0x80

View File

@ -0,0 +1,19 @@
contract c {
function set() public returns (bool) { data = msg.data; return true; }
function checkIfDataIsEmpty() public returns (bool) { return data.length == 0; }
function sendMessage() public returns (bool, bytes memory) { bytes memory emptyData; return address(this).call(emptyData);}
fallback() external { data = msg.data; }
bytes data;
}
// ====
// EVMVersion: >=byzantium
// compileToEwasm: false
// compileViaYul: also
// ----
// (): 1, 2, 3, 4, 5 ->
// gas irOptimized: 155178
// gas legacy: 155254
// gas legacyOptimized: 155217
// checkIfDataIsEmpty() -> false
// sendMessage() -> true, 0x40, 0
// checkIfDataIsEmpty() -> true

View File

@ -0,0 +1,41 @@
interface I {
enum Direction { A, B, Left, Right }
}
library L {
enum Direction { Left, Right }
function f() public pure returns (Direction) {
return Direction.Right;
}
function g() public pure returns (I.Direction) {
return I.Direction.Right;
}
}
contract C is I {
function f() public pure returns (Direction) {
return Direction.Right;
}
function g() public pure returns (I.Direction) {
return I.Direction.Right;
}
function h() public pure returns (L.Direction) {
return L.Direction.Right;
}
function x() public pure returns (L.Direction) {
return L.f();
}
function y() public pure returns (I.Direction) {
return L.g();
}
}
// ====
// compileViaYul: also
// compileToEwasm: false
// ----
// library: L
// f() -> 3
// g() -> 3
// f() -> 3
// g() -> 3
// h() -> 1
// x() -> 1
// y() -> 3

View File

@ -0,0 +1,27 @@
contract receiver {
uint256 public received;
function recv(uint256 x) public { received += x + 1; }
fallback() external { received = 0x80; }
}
contract sender {
constructor() { rec = new receiver();}
fallback() external { savedData = msg.data; }
function forward() public returns (bool) { address(rec).call(savedData); return true; }
function clear() public returns (bool) { delete savedData; return true; }
function val() public returns (uint) { return rec.received(); }
receiver rec;
bytes savedData;
}
// ====
// allowNonExistingFunctions: true
// compileToEwasm: false
// compileViaYul: also
// ----
// recv(uint256): 7 ->
// val() -> 0
// forward() -> true
// val() -> 8
// clear() -> true
// val() -> 8
// forward() -> true
// val() -> 0x80

View File

@ -0,0 +1,16 @@
library L {
function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); }
}
contract C {
using L for *;
function f() public returns (uint) {
return t.g();
}
function t() public pure returns (uint) { return 7; }
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: L
// f() -> 7

View File

@ -0,0 +1,16 @@
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return (x.mul)({x: a});
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: D
// f(uint256): 7 -> 0x2a
// x() -> 0x2a

View File

@ -0,0 +1,20 @@
library D { function length(string memory self) public returns (uint) { return bytes(self).length; } }
contract C {
using D for string;
string x;
function f() public returns (uint) {
x = "abc";
return x.length();
}
function g() public returns (uint) {
string memory s = "abc";
return s.length();
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: D
// f() -> 3
// g() -> 3

View File

@ -0,0 +1,30 @@
library Lib {
function find(uint16[] storage _haystack, uint16 _needle) public view returns (uint)
{
for (uint i = 0; i < _haystack.length; ++i)
if (_haystack[i] == _needle)
return i;
return type(uint).max;
}
}
contract Test {
mapping(string => uint16[]) data;
function f() public returns (uint a, uint b)
{
while (data["abc"].length < 20)
data["abc"].push();
data["abc"][4] = 9;
data["abc"][17] = 3;
a = Lib.find(data["abc"], 9);
b = Lib.find(data["abc"], 3);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f() -> 4, 0x11
// gas irOptimized: 115822
// gas legacy: 135952
// gas legacyOptimized: 119643

View File

@ -0,0 +1,15 @@
library Lib { function m() public returns (address) { return msg.sender; } }
contract Test {
address public sender;
function f() public {
sender = Lib.m();
}
}
// ====
// compileViaYul: also
// compileToEwasm: false
// EVMVersion: >=homestead
// ----
// library: Lib
// f() ->
// sender() -> 0x1212121212121212121212121212120000000012

View File

@ -0,0 +1,14 @@
library Lib { function m(uint x, uint y) public returns (uint) { return x * y; } }
contract Test {
function f(uint x) public returns (uint) {
Lib;
Lib.m;
return x + 9;
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f(uint256): 33 -> 0x2a

View File

@ -0,0 +1,41 @@
library Lib {
function set(mapping(uint => uint) storage m, uint key, uint value) internal
{
m[key] = value;
}
function get(mapping(uint => uint) storage m, uint key) internal view returns (uint)
{
return m[key];
}
}
contract Test {
mapping(uint => uint) m;
function set(uint256 key, uint256 value) public returns (uint)
{
uint oldValue = Lib.get(m, key);
Lib.set(m, key, value);
return oldValue;
}
function get(uint256 key) public view returns (uint) {
return Lib.get(m, key);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// set(uint256,uint256): 1, 42 -> 0
// set(uint256,uint256): 2, 84 -> 0
// set(uint256,uint256): 21, 7 -> 0
// get(uint256): 0 -> 0
// get(uint256): 1 -> 0x2a
// get(uint256): 2 -> 0x54
// get(uint256): 21 -> 7
// set(uint256,uint256): 1, 21 -> 0x2a
// set(uint256,uint256): 2, 42 -> 0x54
// set(uint256,uint256): 21, 14 -> 7
// get(uint256): 0 -> 0
// get(uint256): 1 -> 0x15
// get(uint256): 2 -> 0x2a
// get(uint256): 21 -> 14

View File

@ -0,0 +1,75 @@
library Lib {
function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage)
{
return c ? a : b;
}
}
contract Test {
mapping(uint => uint) a;
mapping(uint => uint) b;
function set(bool choice, uint256 key, uint256 value) public returns (uint)
{
mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice);
uint oldValue = m[key];
m[key] = value;
return oldValue;
}
function get(bool choice, uint256 key) public view returns (uint) {
return Lib.choose_mapping(a, b, choice)[key];
}
function get_a(uint256 key) public view returns (uint) {
return a[key];
}
function get_b(uint256 key) public view returns (uint) {
return b[key];
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// set(bool,uint256,uint256): true, 1, 42 -> 0
// set(bool,uint256,uint256): true, 2, 84 -> 0
// set(bool,uint256,uint256): true, 21, 7 -> 0
// set(bool,uint256,uint256): false, 1, 10 -> 0
// set(bool,uint256,uint256): false, 2, 11 -> 0
// set(bool,uint256,uint256): false, 21, 12 -> 0
// get(bool,uint256): true, 0 -> 0
// get(bool,uint256): true, 1 -> 0x2a
// get(bool,uint256): true, 2 -> 0x54
// get(bool,uint256): true, 21 -> 7
// get_a(uint256): 0 -> 0
// get_a(uint256): 1 -> 0x2a
// get_a(uint256): 2 -> 0x54
// get_a(uint256): 21 -> 7
// get(bool,uint256): false, 0 -> 0
// get(bool,uint256): false, 1 -> 10
// get(bool,uint256): false, 2 -> 11
// get(bool,uint256): false, 21 -> 12
// get_b(uint256): 0 -> 0
// get_b(uint256): 1 -> 10
// get_b(uint256): 2 -> 11
// get_b(uint256): 21 -> 12
// set(bool,uint256,uint256): true, 1, 21 -> 0x2a
// set(bool,uint256,uint256): true, 2, 42 -> 0x54
// set(bool,uint256,uint256): true, 21, 14 -> 7
// set(bool,uint256,uint256): false, 1, 30 -> 10
// set(bool,uint256,uint256): false, 2, 31 -> 11
// set(bool,uint256,uint256): false, 21, 32 -> 12
// get_a(uint256): 0 -> 0
// get_a(uint256): 1 -> 0x15
// get_a(uint256): 2 -> 0x2a
// get_a(uint256): 21 -> 14
// get(bool,uint256): true, 0 -> 0
// get(bool,uint256): true, 1 -> 0x15
// get(bool,uint256): true, 2 -> 0x2a
// get(bool,uint256): true, 21 -> 14
// get_b(uint256): 0 -> 0
// get_b(uint256): 1 -> 0x1e
// get_b(uint256): 2 -> 0x1f
// get_b(uint256): 21 -> 0x20
// get(bool,uint256): false, 0 -> 0
// get(bool,uint256): false, 1 -> 0x1e
// get(bool,uint256): false, 2 -> 0x1f
// get(bool,uint256): false, 21 -> 0x20

View File

@ -0,0 +1,31 @@
library Lib {
function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r)
{
r = a;
r[1] = 42;
r = b;
r[1] = 21;
}
}
contract Test {
mapping(uint => uint) a;
mapping(uint => uint) b;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.f(a, b)[2] = 84;
return (a[0], a[1], a[2], b[0], b[1], b[2]);
}
function g() public returns (uint, uint, uint, uint, uint, uint)
{
mapping(uint => uint) storage m = Lib.f(a, b);
m[2] = 17;
return (a[0], a[1], a[2], b[0], b[1], b[2]);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f() -> 0, 0x2a, 0, 0, 0x15, 0x54
// g() -> 0, 0x2a, 0, 0, 0x15, 0x11

View File

@ -0,0 +1,14 @@
library L {
function f() public returns (uint) { return 7; }
}
contract C {
function f() public payable returns (uint) {
return L.f();
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: L
// f(): 27 -> 7

View File

@ -0,0 +1,16 @@
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return x.mul({x: a});
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: D
// f(uint256): 7 -> 0x2a
// x() -> 0x2a

View File

@ -0,0 +1,20 @@
library D {
struct s { uint a; }
function mul(s storage self, uint x) public returns (uint) { return self.a *= x; }
function mul(s storage self, bytes32 x) public returns (bytes32) { }
}
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 6;
return x.mul(a);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: D
// f(uint256): 7 -> 0x2a
// x() -> 0x2a

View File

@ -0,0 +1,27 @@
library Lib {
function set(mapping(uint => uint) storage m, uint key, uint value) public
{
m[key] = value;
}
}
contract Test {
mapping(uint => uint) m1;
mapping(uint => uint) m2;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.set(m1, 0, 1);
Lib.set(m1, 2, 42);
Lib.set(m2, 0, 23);
Lib.set(m2, 2, 99);
return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f() -> 1, 0, 0x2a, 0x17, 0, 0x63
// gas irOptimized: 119757
// gas legacy: 124793
// gas legacyOptimized: 119694

View File

@ -0,0 +1,25 @@
library Lib {
function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) {
return m[key];
}
}
contract Test {
mapping(uint => mapping(uint => uint)) m;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.choose(m, 0)[0] = 1;
Lib.choose(m, 0)[2] = 42;
Lib.choose(m, 1)[0] = 23;
Lib.choose(m, 1)[2] = 99;
return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f() -> 1, 0, 0x2a, 0x17, 0, 0x63
// gas irOptimized: 120471
// gas legacy: 125245
// gas legacyOptimized: 120153

View File

@ -0,0 +1,27 @@
library Lib {
struct Data { uint a; uint[] b; }
function set(Data storage _s) public
{
_s.a = 7;
while (_s.b.length < 20)
_s.b.push();
_s.b[19] = 8;
}
}
contract Test {
mapping(string => Lib.Data) data;
function f() public returns (uint a, uint b)
{
Lib.set(data["abc"]);
a = data["abc"].a;
b = data["abc"].b[19];
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: Lib
// f() -> 7, 8
// gas irOptimized: 101869
// gas legacy: 101504

View File

@ -0,0 +1,61 @@
pragma abicoder v2;
interface I {
struct S { uint a; }
}
library L {
struct S { uint b; uint a; }
function f() public pure returns (S memory) {
S memory s;
s.a = 3;
return s;
}
function g() public pure returns (I.S memory) {
I.S memory s;
s.a = 4;
return s;
}
// argument-dependant lookup tests
function a(I.S memory) public pure returns (uint) { return 1; }
function a(S memory) public pure returns (uint) { return 2; }
}
contract C is I {
function f() public pure returns (S memory) {
S memory s;
s.a = 1;
return s;
}
function g() public pure returns (I.S memory) {
I.S memory s;
s.a = 2;
return s;
}
function h() public pure returns (L.S memory) {
L.S memory s;
s.a = 5;
return s;
}
function x() public pure returns (L.S memory) {
return L.f();
}
function y() public pure returns (I.S memory) {
return L.g();
}
function a1() public pure returns (uint) { S memory s; return L.a(s); }
function a2() public pure returns (uint) { L.S memory s; return L.a(s); }
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: L
// f() -> 1
// g() -> 2
// f() -> 1
// g() -> 2
// h() -> 0, 5
// x() -> 0, 3
// y() -> 4
// a1() -> 1
// a2() -> 2

View File

@ -0,0 +1,16 @@
library D { struct s { uint a; } function mul(s storage self, uint x) public returns (uint) { return self.a *= x; } }
contract C {
using D for D.s;
D.s public x;
function f(uint a) public returns (uint) {
x.a = 3;
return x.mul(a);
}
}
// ====
// compileToEwasm: false
// compileViaYul: also
// ----
// library: D
// f(uint256): 7 -> 0x15
// x() -> 0x15