mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12289 from nishant-sachdeva/extract_test_cases_from_sol_end_to_end
trial test cases extracted from SolidityEndToEndTest.cpp into .sol files
This commit is contained in:
commit
e49780362b
@ -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