aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--Changelog.md2
-rw-r--r--docs/abi-spec.rst4
-rw-r--r--docs/assembly.rst25
-rw-r--r--docs/metadata.rst2
-rw-r--r--docs/security-considerations.rst23
-rw-r--r--docs/style-guide.rst6
-rw-r--r--docs/using-the-compiler.rst21
-rw-r--r--libjulia/optimiser/README.md61
-rw-r--r--libsolc/CMakeLists.txt9
-rw-r--r--libsolc/libsolc.cpp (renamed from solc/jsonCompiler.cpp)2
-rw-r--r--libsolc/libsolc.h (renamed from solc/jsonCompiler.h)0
-rw-r--r--libsolidity/analysis/TypeChecker.cpp11
-rwxr-xr-xscripts/bytecodecompare/storebytecode.sh2
-rwxr-xr-xscripts/test_emscripten.sh2
-rwxr-xr-xscripts/travis-emscripten/build_emscripten.sh4
-rw-r--r--solc/CMakeLists.txt8
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/fuzzer.cpp2
-rw-r--r--test/libsolidity/JSONCompiler.cpp2
-rw-r--r--test/libsolidity/SMTChecker.cpp1
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp3
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp4
23 files changed, 154 insertions, 47 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 105de851..8993f372 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,9 +43,10 @@ configure_project(TESTS)
add_subdirectory(libdevcore)
add_subdirectory(libevmasm)
add_subdirectory(libsolidity)
-add_subdirectory(solc)
+add_subdirectory(libsolc)
if (NOT EMSCRIPTEN)
+ add_subdirectory(solc)
add_subdirectory(liblll)
add_subdirectory(lllc)
endif()
diff --git a/Changelog.md b/Changelog.md
index 248165bb..cf6498a1 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,8 @@ Features:
* Inline Assembly: Issue warning for using jump labels (already existed for jump instructions).
Bugfixes:
+ * Type Checker: Suggest the experimental ABI encoder if using ``struct``s as function parameters
+ (instead of an internal compiler error).
### 0.4.19 (2017-11-30)
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index c93ce25b..e968fb06 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -377,10 +377,14 @@ As an example, the code
::
+ pragma solidity ^0.4.19;
+ pragma experimental ABIEncoderV2;
+
contract Test {
struct S { uint a; uint[] b; T[] c; }
struct T { uint x; uint y; }
function f(S s, T t, uint a) { }
+ function g() returns (S s, T t, uint a) {}
}
would result in the JSON:
diff --git a/docs/assembly.rst b/docs/assembly.rst
index c233985b..a4fa88c6 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -447,31 +447,6 @@ will have a wrong impression about the stack height at label ``two``:
three:
}
-This problem can be fixed by manually adjusting the stack height for the
-assembler - you can provide a stack height delta that is added
-to the stack height just prior to the label.
-Note that you will not have to care about these things if you just use
-loops and assembly-level functions.
-
-As an example how this can be done in extreme cases, please see the following.
-
-.. code::
-
- {
- let x := 8
- jump(two)
- 0 // This code is unreachable but will adjust the stack height correctly
- one:
- x := 9 // Now x can be accessed properly.
- jump(three)
- pop // Similar negative correction.
- two:
- 7 // push something onto the stack
- jump(one)
- three:
- pop // We have to pop the manually pushed value here again.
- }
-
Declaring Assembly-Local Variables
----------------------------------
diff --git a/docs/metadata.rst b/docs/metadata.rst
index dbde87e8..5e37219e 100644
--- a/docs/metadata.rst
+++ b/docs/metadata.rst
@@ -131,6 +131,8 @@ user interface for the contract.
Furthermore, Mist can use the userdoc to display a confirmation message to the user
whenever they interact with the contract.
+Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_.
+
Usage for Source Code Verification
==================================
diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst
index 337a3d3f..1e2138fa 100644
--- a/docs/security-considerations.rst
+++ b/docs/security-considerations.rst
@@ -69,10 +69,27 @@ complete contract):
}
The problem is not too serious here because of the limited gas as part
-of ``send``, but it still exposes a weakness: Ether transfer always
-includes code execution, so the recipient could be a contract that calls
+of ``send``, but it still exposes a weakness: Ether transfer can always
+include code execution, so the recipient could be a contract that calls
back into ``withdraw``. This would let it get multiple refunds and
-basically retrieve all the Ether in the contract.
+basically retrieve all the Ether in the contract. In particular, the
+following contract will allow an attacker to refund multiple times
+as it uses ``call`` which forwards all remaining gas by default:
+
+::
+
+ pragma solidity ^0.4.0;
+
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() {
+ if (msg.sender.call.value(shares[msg.sender])())
+ shares[msg.sender] = 0;
+ }
+ }
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
outlined further below:
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index a438b3d0..5b6f42a2 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -739,6 +739,12 @@ Modifier Names
Use mixedCase. Examples: ``onlyBy``, ``onlyAfter``, ``onlyDuringThePreSale``.
+Enums
+=====
+
+Enums, in the style of simple type declarations, should be named using the CapWords style. Examples: ``TokenGroup``, ``Frame``, ``HashStyle``, ``CharacterLocation``.
+
+
Avoiding Naming Collisions
==========================
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index c12750c8..f1f13b82 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -177,7 +177,8 @@ Output Description
start: 0,
end: 100
],
- // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc
+ // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
+ // See below for complete list of types.
type: "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc.
component: "general",
@@ -273,3 +274,21 @@ Output Description
}
}
}
+
+
+Error types
+~~~~~~~~~~~
+
+1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc.
+2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources.
+3. ``ParserError``: Source code doesn't conform to the language rules.
+4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed.
+5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop.
+6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found``
+7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc.
+8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions.
+9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue.
+10. ``Exception``: Unknown failure during compilation - this should be reported as an issue.
+11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue.
+12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue.
+13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible.
diff --git a/libjulia/optimiser/README.md b/libjulia/optimiser/README.md
new file mode 100644
index 00000000..771cb707
--- /dev/null
+++ b/libjulia/optimiser/README.md
@@ -0,0 +1,61 @@
+## IULIA Optimiser
+
+The iulia optimiser consists of several stages and components that all transform
+the AST in a semantically equivalent way. The goal is to end up either with code
+that is shorter or at least only marginally longer but will allow further
+optimisation steps.
+
+The optimiser currently follows a purely greedy strategy and does not do any
+backtracking.
+
+## Disambiguator
+
+The disambiguator takes an AST and returns a fresh copy where all identifiers have
+names unique to the input AST. This is a prerequisite for all other optimiser stages.
+One of the benefits is that identifier lookup does not need to take scopes into account
+and we can basically ignore the result of the analysis phase.
+
+All subsequent stages have the property that all names stay unique. This means if
+a new identifier needs to be introduced, a new unique name is generated.
+
+## Function Hoister
+
+The function hoister moves all function definitions to the topmost block. This is
+a semantically equivalent transformation as long as it is performed after the
+disambiguation stage. The reason is that moving a definition upwards cannot decrease
+its visibility and it is impossible to reference variables defined in a different function.
+
+The benefit of this stage is that function definitions can be lookup up more easily.
+
+## Function Grouper
+
+The function grouper has to be applied after the disambiguator and the function hoister.
+Its effect is that all topmost elements that are not function definitions are moved
+into a single block which is the first satement of the root block.
+
+After this step, a program has the following normal form:
+
+ { I F... }
+
+Where I is a block that does not contain any function definitions (not even recursively)
+and F is a list of function definitions such that no function contains a function definition.
+
+## Functional Inliner
+
+The functional inliner depends on the disambiguator, the function hoister and function grouper.
+It performs function inlining such that the result of the inlining is an expression. This can
+only be done if the body of the function to be inlined has the form ``{ r := E }`` where ``r``
+is the single return value of the function, ``E`` is an expression and all arguments in the
+function call are so-called movable expressions. A movable expression is either a literal, a
+variable or a function call (or EVM opcode) which does not have side-effects and also does not
+depend on any side-effects.
+
+As an example, neither ``mload`` nor ``mstore`` would be allowed.
+
+## Full Function Inliner
+
+## Variable Eliminator
+
+## Unused Declaration Pruner
+
+## Function Unifier
diff --git a/libsolc/CMakeLists.txt b/libsolc/CMakeLists.txt
new file mode 100644
index 00000000..e67583dd
--- /dev/null
+++ b/libsolc/CMakeLists.txt
@@ -0,0 +1,9 @@
+if (EMSCRIPTEN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
+ add_executable(soljson libsolc.cpp)
+ target_link_libraries(soljson PRIVATE solidity)
+else()
+ add_library(libsolc libsolc.cpp)
+ set_target_properties(libsolc PROPERTIES OUTPUT_NAME solc)
+ target_link_libraries(libsolc PRIVATE solidity)
+endif()
diff --git a/solc/jsonCompiler.cpp b/libsolc/libsolc.cpp
index 23feaa2a..3a6e1521 100644
--- a/solc/jsonCompiler.cpp
+++ b/libsolc/libsolc.cpp
@@ -20,7 +20,7 @@
* JSON interface for the solidity compiler to be used from Javascript.
*/
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include <libdevcore/Common.h>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/StandardCompiler.h>
diff --git a/solc/jsonCompiler.h b/libsolc/libsolc.h
index c392ce93..c392ce93 100644
--- a/solc/jsonCompiler.h
+++ b/libsolc/libsolc.h
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 96160a75..a578ad0f 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -570,6 +570,17 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions.");
+ if (
+ _function.visibility() > FunctionDefinition::Visibility::Internal &&
+ type(*var)->category() == Type::Category::Struct &&
+ !type(*var)->dataStoredIn(DataLocation::Storage) &&
+ !_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2)
+ )
+ m_errorReporter.typeError(
+ var->location(),
+ "Structs are only supported in the new experimental ABI encoder. "
+ "Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
+ );
var->accept(*this);
}
diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh
index 8d4100bf..557e3275 100755
--- a/scripts/bytecodecompare/storebytecode.sh
+++ b/scripts/bytecodecompare/storebytecode.sh
@@ -40,7 +40,7 @@ TMPDIR=$(mktemp -d)
if [[ "$SOLC_EMSCRIPTEN" = "On" ]]
then
- cp "$REPO_ROOT/build/solc/soljson.js" .
+ cp "$REPO_ROOT/build/libsolc/soljson.js" .
npm install solc
cat > solc <<EOF
#!/usr/bin/env node
diff --git a/scripts/test_emscripten.sh b/scripts/test_emscripten.sh
index 4996e957..b659e5e5 100755
--- a/scripts/test_emscripten.sh
+++ b/scripts/test_emscripten.sh
@@ -29,7 +29,7 @@
set -e
REPO_ROOT=$(cd $(dirname "$0")/.. && pwd)
-SOLJSON="$REPO_ROOT/build/solc/soljson.js"
+SOLJSON="$REPO_ROOT/build/libsolc/soljson.js"
DIR=$(mktemp -d)
(
diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh
index bf460e8e..56826997 100755
--- a/scripts/travis-emscripten/build_emscripten.sh
+++ b/scripts/travis-emscripten/build_emscripten.sh
@@ -87,8 +87,8 @@ make -j 4
cd ..
mkdir -p upload
-cp build/solc/soljson.js upload/
-cp build/solc/soljson.js ./
+cp build/libsolc/soljson.js upload/
+cp build/libsolc/soljson.js ./
OUTPUT_SIZE=`ls -la soljson.js`
diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt
index 656b27c3..d9b12a06 100644
--- a/solc/CMakeLists.txt
+++ b/solc/CMakeLists.txt
@@ -10,14 +10,6 @@ target_link_libraries(solc PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES})
include(GNUInstallDirs)
install(TARGETS solc DESTINATION "${CMAKE_INSTALL_BINDIR}")
-if (EMSCRIPTEN)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
- add_executable(soljson jsonCompiler.cpp)
-else()
- add_library(soljson jsonCompiler.cpp)
-endif()
-target_link_libraries(soljson PRIVATE solidity)
-
if(SOLC_LINK_STATIC AND UNIX AND NOT APPLE)
# Produce solc as statically linked binary (includes C/C++ standard libraries)
# This is not supported on macOS, see
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6a8a4399..f36ad4c5 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -3,7 +3,7 @@ list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/fuzzer.cpp")
file(GLOB_RECURSE headers "*.h")
add_executable(soltest ${sources} ${headers})
-target_link_libraries(soltest PRIVATE soljson solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
+target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
add_executable(solfuzzer fuzzer.cpp)
-target_link_libraries(solfuzzer soljson evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES})
+target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES})
diff --git a/test/fuzzer.cpp b/test/fuzzer.cpp
index 53ba7201..578e63a4 100644
--- a/test/fuzzer.cpp
+++ b/test/fuzzer.cpp
@@ -20,7 +20,7 @@
#include <libevmasm/Assembly.h>
#include <libevmasm/ConstantOptimiser.h>
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include <json/json.h>
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index 7dc4808b..0c904c77 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -23,7 +23,7 @@
#include <boost/test/unit_test.hpp>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/Version.h>
-#include <solc/jsonCompiler.h>
+#include <libsolc/libsolc.h>
#include "../Metadata.h"
#include "../TestHelper.h"
diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp
index 38d02601..3a65aa43 100644
--- a/test/libsolidity/SMTChecker.cpp
+++ b/test/libsolidity/SMTChecker.cpp
@@ -94,6 +94,7 @@ BOOST_AUTO_TEST_CASE(warn_on_typecast)
BOOST_AUTO_TEST_CASE(warn_on_struct)
{
string text = R"(
+ pragma experimental ABIEncoderV2;
contract C {
struct A { uint a; uint b; }
function f() public pure returns (A) {
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index 33962730..26bfb6d0 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -942,6 +942,7 @@ BOOST_AUTO_TEST_CASE(function_type)
BOOST_AUTO_TEST_CASE(return_structs)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; T[] sub; }
struct T { uint[2] x; }
@@ -991,6 +992,7 @@ BOOST_AUTO_TEST_CASE(return_structs)
BOOST_AUTO_TEST_CASE(return_structs_with_contracts)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
contract C {
struct S { C[] x; C y; }
function f() returns (S s, C c) {
@@ -1090,6 +1092,7 @@ BOOST_AUTO_TEST_CASE(event_structs)
BOOST_AUTO_TEST_CASE(structs_in_libraries)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
library L {
struct S { uint a; T[] sub; bytes b; }
struct T { uint[2] x; }
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 97d359e8..39dba0de 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -602,6 +602,7 @@ BOOST_AUTO_TEST_CASE(enum_external_type)
BOOST_AUTO_TEST_CASE(external_structs)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
contract Test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
struct Empty {}
@@ -629,6 +630,7 @@ BOOST_AUTO_TEST_CASE(external_structs)
BOOST_AUTO_TEST_CASE(external_structs_in_libraries)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
library Test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
struct Empty {}
@@ -3511,6 +3513,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_used)
BOOST_AUTO_TEST_CASE(library_memory_struct)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
library c {
struct S { uint x; }
function f() public returns (S ) {}
@@ -5696,6 +5699,7 @@ BOOST_AUTO_TEST_CASE(constructible_internal_constructor)
BOOST_AUTO_TEST_CASE(return_structs)
{
char const* text = R"(
+ pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; T[] sub; }
struct T { uint[] x; }