mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
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:
parent
6363ff31db
commit
19a74506e3
@ -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"(
|
||||
|
@ -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
|
@ -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
|
41
test/libsolidity/semanticTests/enums/enum_referencing.sol
Normal file
41
test/libsolidity/semanticTests/enums/enum_referencing.sol
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user