aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp36
3 files changed, 38 insertions, 1 deletions
diff --git a/Changelog.md b/Changelog.md
index 7e4606bd..4b3f2ddc 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -3,6 +3,7 @@
Features:
Bugfixes:
+ * Code Generator: ``.delegatecall()`` should always return execution outcome.
* Code Generator: Provide "new account gas" for low-level ``callcode`` and ``delegatecall``.
### 0.4.14 (2017-07-31)
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 2c8cfd76..521d485f 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1560,7 +1560,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
utils().moveToStackTop(gasValueSize, _functionType.selfType()->sizeOnStack());
auto funKind = _functionType.kind();
- bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode;
+ bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall;
bool isCallCode = funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::CallCode;
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 2c9dfad9..60a0607a 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -9897,6 +9897,42 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0), u256(0)));
}
+BOOST_AUTO_TEST_CASE(delegatecall_return_value)
+{
+ char const* sourceCode = R"DELIMITER(
+ contract C {
+ uint value;
+ function set(uint _value) external {
+ value = _value;
+ }
+ function get() external constant returns (uint) {
+ return value;
+ }
+ function get_delegated() external constant returns (bool) {
+ return this.delegatecall(bytes4(sha3("get()")));
+ }
+ function assert0() external constant {
+ assert(value == 0);
+ }
+ function assert0_delegated() external constant returns (bool) {
+ return this.delegatecall(bytes4(sha3("assert0()")));
+ }
+ }
+ )DELIMITER";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("set(uint256)", u256(1)) == encodeArgs());
+ BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("set(uint256)", u256(42)) == encodeArgs());
+ BOOST_CHECK(callContractFunction("get()") == encodeArgs(u256(42)));
+ BOOST_CHECK(callContractFunction("assert0_delegated()") == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("get_delegated()") == encodeArgs(u256(1)));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}