aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/contracts.rst6
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
2 files changed, 30 insertions, 1 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst
index faef3fc2..0d1b029b 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -485,7 +485,11 @@ Functions can be declared ``view`` in which case they promise not to modify the
.. note::
If the compiler's EVM target is Byzantium or newer (default) the opcode
``STATICCALL`` is used for ``view`` functions which enforces the state
- to stay unmodified as part of the EVM execution.
+ to stay unmodified as part of the EVM execution. For library ``view`` functions
+ ``DELEGATECALL`` is used, because there is no combined ``DELEGATECALL`` and ``STATICCALL``.
+ This means library ``view`` functions do not have run-time checks that prevent state
+ modifications. This should not impact security negatively because library code is
+ usually known at compile-time and the static checker performs compile-time checks.
The following statements are considered modifying the state:
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index f65c8b27..7a496e64 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -4519,6 +4519,31 @@ BOOST_AUTO_TEST_CASE(library_call_protection)
ABI_CHECK(callContractFunction("pu()"), encodeArgs(2));
}
+
+BOOST_AUTO_TEST_CASE(library_staticcall_delegatecall)
+{
+ char const* sourceCode = R"(
+ library Lib {
+ function x() public view returns (uint) {
+ return 1;
+ }
+ }
+ contract Test {
+ uint t;
+ function f() public returns (uint) {
+ t = 2;
+ return this.g();
+ }
+ function g() public view returns (uint) {
+ return Lib.x();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
+}
+
BOOST_AUTO_TEST_CASE(store_bytes)
{
// this test just checks that the copy loop does not mess up the stack