aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity/SolidityEndToEndTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/libsolidity/SolidityEndToEndTest.cpp')
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp562
1 files changed, 562 insertions, 0 deletions
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index d8924250..ed95d687 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -7606,6 +7606,568 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
}
+BOOST_AUTO_TEST_CASE(calling_uninitialized_function)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function intern() returns (uint) {
+ function (uint) internal returns (uint) x;
+ x(2);
+ return 7;
+ }
+ function extern() returns (uint) {
+ function (uint) external returns (uint) x;
+ x(2);
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ // This should throw exceptions
+ BOOST_CHECK(callContractFunction("intern()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("extern()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint) x;
+ int mutex;
+ function t() returns (uint) {
+ if (mutex > 0)
+ return 7;
+ mutex = 1;
+ // Avoid re-executing this function if we jump somewhere.
+ x();
+ return 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(pass_function_types_internally)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint x) returns (uint) {
+ return eval(g, x);
+ }
+ function eval(function(uint) returns (uint) x, uint a) internal returns (uint) {
+ return x(a);
+ }
+ function g(uint x) returns (uint) { return x + 1; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(pass_function_types_externally)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint x) returns (uint) {
+ return this.eval(this.g, x);
+ }
+ function f2(uint x) returns (uint) {
+ return eval(this.g, x);
+ }
+ function eval(function(uint) external returns (uint) x, uint a) returns (uint) {
+ return x(a);
+ }
+ function g(uint x) returns (uint) { return x + 1; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(receive_external_function_type)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function g() returns (uint) { return 7; }
+ function f(function() external returns (uint) g) returns (uint) {
+ return g();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction(
+ "f(function)",
+ m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
+ ) == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(return_external_function_type)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function g() {}
+ function f() returns (function() external) {
+ return this.g;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(
+ callContractFunction("f()") ==
+ m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(store_function)
+{
+ char const* sourceCode = R"(
+ contract Other {
+ function addTwo(uint x) returns (uint) { return x + 2; }
+ }
+ contract C {
+ function (function (uint) external returns (uint)) returns (uint) ev;
+ function (uint) external returns (uint) x;
+ function store(function(uint) external returns (uint) y) {
+ x = y;
+ }
+ function eval(function(uint) external returns (uint) y) returns (uint) {
+ return y(7);
+ }
+ function t() returns (uint) {
+ ev = eval;
+ this.store((new Other()).addTwo);
+ return ev(x);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(9)));
+}
+
+BOOST_AUTO_TEST_CASE(store_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public result_in_constructor;
+ function (uint) internal returns (uint) x;
+ function C () {
+ x = double;
+ result_in_constructor = use(2);
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ function use(uint _arg) returns (uint) {
+ return x(_arg);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6)));
+ BOOST_CHECK(callContractFunction("result_in_constructor()") == encodeArgs(u256(4)));
+}
+
+// TODO: store bound internal library functions
+
+BOOST_AUTO_TEST_CASE(store_internal_unused_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function () internal returns (uint) x;
+ function C () {
+ x = unused;
+ }
+ function unused() internal returns (uint) {
+ return 7;
+ }
+ function t() returns (uint) {
+ return x();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ library L { function x() internal returns (uint) { return 7; } }
+ contract C {
+ function () internal returns (uint) x;
+ function C () {
+ x = L.x;
+ }
+ function t() returns (uint) {
+ return x();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public initial;
+ function C() {
+ initial = double(2);
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ function runtime(uint _arg) returns (uint) {
+ return double(_arg);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6)));
+ BOOST_CHECK(callContractFunction("initial()") == encodeArgs(u256(4)));
+}
+
+BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function (uint) internal returns (uint) x;
+ function C() {
+ x = double;
+ }
+ function test() returns (bool) {
+ return x == double;
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_library_internal)
+{
+ char const* sourceCode = R"(
+ library Utils {
+ function reduce(uint[] memory array, function(uint, uint) returns (uint) f, uint init) internal returns (uint) {
+ for (uint i = 0; i < array.length; i++) {
+ init = f(array[i], init);
+ }
+ return init;
+ }
+ function sum(uint a, uint b) internal returns (uint) {
+ return a + b;
+ }
+ }
+ contract C {
+ function f(uint[] x) returns (uint) {
+ return Utils.reduce(x, Utils.sum, 0);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)) == encodeArgs(u256(11)));
+}
+
+
+BOOST_AUTO_TEST_CASE(call_function_returning_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function f0() returns (uint) {
+ return 2;
+ }
+ function f1() internal returns (function() returns (uint)) {
+ return f0;
+ }
+ function f2() internal returns (function() returns (function () returns (uint))) {
+ return f1;
+ }
+ function f3() internal returns (function() returns (function () returns (function () returns (uint))))
+ {
+ return f2;
+ }
+ function f() returns (uint) {
+ function() returns(function() returns(function() returns(function() returns(uint)))) x;
+ x = f3;
+ return x()()()();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "test");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_of_functions)
+{
+ char const* sourceCode = R"(
+ contract Flow {
+ bool public success;
+
+ mapping (address => function () internal) stages;
+
+ function stage0() internal {
+ stages[msg.sender] = stage1;
+ }
+
+ function stage1() internal {
+ stages[msg.sender] = stage2;
+ }
+
+ function stage2() internal {
+ success = true;
+ }
+
+ function Flow() {
+ stages[msg.sender] = stage0;
+ }
+
+ function f() returns (uint) {
+ stages[msg.sender]();
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "Flow");
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(false));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(false));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(true));
+}
+
+BOOST_AUTO_TEST_CASE(packed_functions)
+{
+ char const* sourceCode = R"(
+ contract C {
+ // these should take the same slot
+ function() returns (uint) a;
+ function() external returns (uint) b;
+ function() external returns (uint) c;
+ function() returns (uint) d;
+ uint8 public x;
+
+ function set() {
+ x = 2;
+ d = g;
+ c = this.h;
+ b = this.h;
+ a = g;
+ }
+ function t1() returns (uint) {
+ return a();
+ }
+ function t2() returns (uint) {
+ return b();
+ }
+ function t3() returns (uint) {
+ return a();
+ }
+ function t4() returns (uint) {
+ return b();
+ }
+ function g() returns (uint) {
+ return 7;
+ }
+ function h() returns (uint) {
+ return 8;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("set()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("t1()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("t3()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("t4()") == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(2)));
+}
+
+BOOST_AUTO_TEST_CASE(function_memory_array)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a(uint x) returns (uint) { return x + 1; }
+ function b(uint x) returns (uint) { return x + 2; }
+ function c(uint x) returns (uint) { return x + 3; }
+ function d(uint x) returns (uint) { return x + 5; }
+ function e(uint x) returns (uint) { return x + 8; }
+ function test(uint x, uint i) returns (uint) {
+ function(uint) internal returns (uint)[] memory arr =
+ new function(uint) internal returns (uint)[](10);
+ arr[0] = a;
+ arr[1] = b;
+ arr[2] = c;
+ arr[3] = d;
+ arr[4] = e;
+ return arr[i](x);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)) == encodeArgs(u256(11)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)) == encodeArgs(u256(12)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)) == encodeArgs(u256(13)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)) == encodeArgs(u256(15)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)) == encodeArgs(u256(18)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)) == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(function_delete_storage)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a() returns (uint) { return 7; }
+ function() internal returns (uint) y;
+ function set() returns (uint) {
+ y = a;
+ return y();
+ }
+ function d() returns (uint) {
+ delete y;
+ return 1;
+ }
+ function ca() returns (uint) {
+ return y();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("set()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("ca()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("d()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("ca()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(function_delete_stack)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a() returns (uint) { return 7; }
+ function test() returns (uint) {
+ var y = a;
+ delete y;
+ y();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(copy_function_storage_array)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint)[] x;
+ function() internal returns (uint)[] y;
+ function test() returns (uint) {
+ x.length = 10;
+ x[9] = a;
+ y = x;
+ return y[9]();
+ }
+ function a() returns (uint) {
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(function_array_cross_calls)
+{
+ char const* sourceCode = R"(
+ contract D {
+ function f(function() external returns (function() external returns (uint))[] x)
+ returns (function() external returns (uint)[3] r)
+ {
+ r[0] = x[0]();
+ r[1] = x[1]();
+ r[2] = x[2]();
+ }
+ }
+ contract C {
+ function test() returns (uint, uint, uint) {
+ function() external returns (function() external returns (uint))[] memory x =
+ new function() external returns (function() external returns (uint))[](10);
+ for (uint i = 0; i < x.length; i ++)
+ x[i] = this.h;
+ x[0] = this.htwo;
+ var y = (new D()).f(x);
+ return (y[0](), y[1](), y[2]());
+ }
+ function e() returns (uint) { return 5; }
+ function f() returns (uint) { return 6; }
+ function g() returns (uint) { return 7; }
+ uint counter;
+ function h() returns (function() external returns (uint)) {
+ return counter++ == 0 ? this.f : this.g;
+ }
+ function htwo() returns (function() external returns (uint)) {
+ return this.e;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(5), u256(6), u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(copy_internal_function_array_to_storage)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint)[20] x;
+ int mutex;
+ function one() returns (uint) {
+ function() internal returns (uint)[20] xmem;
+ x = xmem;
+ return 3;
+ }
+ function two() returns (uint) {
+ if (mutex > 0)
+ return 7;
+ mutex = 1;
+ // If this test fails, it might re-execute this function.
+ x[0]();
+ return 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("one()") == encodeArgs(u256(3)));
+ BOOST_CHECK(callContractFunction("two()") == encodeArgs());
+}
+
BOOST_AUTO_TEST_CASE(shift_constant_left)
{
char const* sourceCode = R"(