diff options
23 files changed, 200 insertions, 90 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f30872af..20b4d97b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.25") +set(PROJECT_VERSION "0.4.26") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) diff --git a/Changelog.md b/Changelog.md index 18062c9c..2619801f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -94,9 +94,6 @@ Compiler Features: * Code Generator: Allocate and free local variables according to their scope. * Removed ``pragma experimental "v0.5.0";``. -Critical Bugfixes: - * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. - Bugfixes: * Build System: Support versions of CVC4 linked against CLN instead of GMP. In case of compilation issues due to the experimental SMT solver support, the solvers can be disabled when configuring the project with CMake using ``-DUSE_CVC4=OFF`` or ``-DUSE_Z3=OFF``. * Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum. @@ -117,13 +114,19 @@ Bugfixes: * Type Checker: Consider fixed size arrays when checking for recursive structs. * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined. * Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``. - * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. - * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Dynamic types as key for public mappings return error instead of assertion fail. * Type Checker: Fix internal error when array index value is too large. * Type System: Allow arbitrary exponents for literals with a mantissa of zero. * Parser: Fix incorrect source location for nameless parameters. - * Parser: Treat unicode line endings as terminating strings and single-line comments. + +### 0.4.25 (2018-09-12) + +Important Bugfixes: + * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. + * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. + * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. + * Parser: Consider all unicode line terminators (LF, VF, FF, CR, NEL, LS, PS) for single-line comments + and string literals. They are invalid in strings and will end comments. * Parser: Disallow unterminated multi-line comments at the end of input. * Parser: Treat ``/** /`` as unterminated multi-line comment. diff --git a/docs/assembly.rst b/docs/assembly.rst index 2cbad06f..91935293 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -141,6 +141,8 @@ these curly braces, the following can be used (see the later sections for more d - assignments in functional style, e.g. ``x := add(y, 3)`` - blocks where local variables are scoped inside, e.g. ``{ let x := 3 { let y := add(x, 1) } }`` +.. _opcodes: + Opcodes ------- diff --git a/docs/bugs.json b/docs/bugs.json index 980b3897..28c0fe62 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -12,7 +12,7 @@ "summary": "Using structs in events logged wrong data.", "description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.", "introduced": "0.4.17", - "fixed": "0.5.0", + "fixed": "0.4.25", "severity": "very low", "check": {"ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"} }, diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 96cc3c5c..0318ac89 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -515,6 +515,10 @@ ], "released": "2018-05-16" }, + "0.4.25": { + "bugs": [], + "released": "2018-09-12" + }, "0.4.3": { "bugs": [ "ExpExponentCleanup", diff --git a/docs/contracts.rst b/docs/contracts.rst index b9179b27..470d775e 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1210,6 +1210,8 @@ Abstract contracts are useful in the same way that defining methods in an interf .. index:: ! contract;interface, ! interface contract +.. _interfaces: + ********** Interfaces ********** diff --git a/docs/contributing.rst b/docs/contributing.rst index 8a83ca55..6fe96be4 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -92,7 +92,7 @@ To run a subset of tests, filters can be used: ``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc --testpath ./test``, where ``TestName`` can be a wildcard ``*``. -Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests and runs +Alternatively, there is a testing script at ``scripts/tests.sh`` which executes all tests and runs ``cpp-ethereum`` automatically if it is in the path (but does not download it). Travis CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 34806f4a..3332a83b 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -35,13 +35,15 @@ npm / Node.js ============= Use `npm` for a convenient and portable way to install `solcjs`, a Solidity compiler. The -`solcjs` program has fewer features than all options further down this page. Our +`solcjs` program has fewer features than the ways to access the compiler described +further down this page. The :ref:`commandline-compiler` documentation assumes you are using -the full-featured compiler, `solc`. So if you install `solcjs` from `npm` then you will -stop reading the documentation here and then continue to `solc-js <https://github.com/ethereum/solc-js>`_. +the full-featured compiler, `solc`. The usage of `solcjs` is documented inside its own +`repository <https://github.com/ethereum/solc-js>`_. Note: The solc-js project is derived from the C++ -`solc` by using Emscripten. `solc-js` can be used in JavaScript projects directly (such as Remix). +`solc` by using Emscripten which means that both use the same compiler source code. +`solc-js` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash @@ -50,7 +52,7 @@ Please refer to the solc-js repository for instructions. .. note:: - The commandline is named `solcjs`. + The commandline executable is named `solcjs`. The comandline options of `solcjs` are not compatible with `solc` and tools (such as `geth`) expecting the behaviour of `solc` will not work with `solcjs`. @@ -76,7 +78,8 @@ Binary Packages Binary packages of Solidity are available at `solidity/releases <https://github.com/ethereum/solidity/releases>`_. -We also have PPAs for Ubuntu. For the latest stable version. +We also have PPAs for Ubuntu, you can get the latest stable +version using the following commands: .. code-block:: bash @@ -84,7 +87,7 @@ We also have PPAs for Ubuntu. For the latest stable version. sudo apt-get update sudo apt-get install solc -If you want to use the cutting edge developer version: +The nightly version can be installed using these commands: .. code-block:: bash @@ -99,7 +102,8 @@ We are also releasing a `snap package <https://snapcraft.io/>`_, which is instal sudo snap install solc -Or if you want to help testing the unstable solc with the most recent changes from the development branch: +If you want to help testing the latest development version of Solidity +with the most recent changes, please use the following: .. code-block:: bash @@ -111,10 +115,9 @@ Arch Linux also has packages, albeit limited to the latest development version: pacman -S solidity -Homebrew is missing pre-built bottles at the time of writing, -following a Jenkins to TravisCI migration, but Homebrew -should still work just fine as a means to build-from-source. -We will re-add the pre-built bottles soon. +We distribute the Solidity compiler through Homebrow +as a build-from-source version. Pre-built bottles are +currently not supported. .. code-block:: bash @@ -166,7 +169,6 @@ you should fork Solidity and add your personal fork as a second remote: .. code-block:: bash - cd solidity git remote add personal git@github.com:[username]/solidity.git Solidity has git submodules. Ensure they are properly loaded: @@ -240,9 +242,8 @@ in Visual Studio 2017 Build Tools or Visual Studio 2017: External Dependencies --------------------- -We now have a "one button" script which installs all required external dependencies -on macOS, Windows and on numerous Linux distros. This used to be a multi-step -manual process, but is now a one-liner: +We have a helper script which installs all required external dependencies +on macOS, Windows and on numerous Linux distros. .. code-block:: bash @@ -261,6 +262,8 @@ Command-Line Build **Be sure to install External Dependencies (see above) before build.** Solidity project uses CMake to configure the build. +You might want to install ccache to speed up repeated builds. +CMake will pick it up automatically. Building Solidity is quite similar on Linux, macOS and other Unices: .. code-block:: bash @@ -276,7 +279,7 @@ or even easier: #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh -And even for Windows: +And for Windows: .. code-block:: bash @@ -329,7 +332,7 @@ The Solidity version string contains four parts: - the version number - pre-release tag, usually set to ``develop.YYYY.MM.DD`` or ``nightly.YYYY.MM.DD`` - commit in the format of ``commit.GITHASH`` -- platform has arbitrary number of items, containing details about the platform and compiler +- platform, which has an arbitrary number of items, containing details about the platform and compiler If there are local modifications, the commit will be postfixed with ``.mod``. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 7de0d19b..bd30a8fd 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -359,36 +359,38 @@ Gas Upon creation, each transaction is charged with a certain amount of **gas**, whose purpose is to limit the amount of work that is needed to execute -the transaction and to pay for this execution. While the EVM executes the +the transaction and to pay for this execution at the same time. While the EVM executes the transaction, the gas is gradually depleted according to specific rules. The **gas price** is a value set by the creator of the transaction, who has to pay ``gas_price * gas`` up front from the sending account. -If some gas is left after the execution, it is refunded in the same way. +If some gas is left after the execution, it is refunded to the creator in the same way. -If the gas is used up at any point (i.e. it is negative), +If the gas is used up at any point (i.e. it would be negative), an out-of-gas exception is triggered, which reverts all modifications made to the state in the current call frame. -Any unused gas is refunded at the end of the transaction. - .. index:: ! storage, ! memory, ! stack Storage, Memory and the Stack ============================= -The Ethereum Virtual Machine has three areas where it can store data. +The Ethereum Virtual Machine has three areas where it can store data, +storage, memory and the stack, which are explained in the following +paragraphs. -Each account has a data area called **storage**, which is persistent between function calls. +Each account has a data area called **storage**, which is persistent between function calls +and transactions. Storage is a key-value store that maps 256-bit words to 256-bit words. -It is not possible to enumerate storage from within a contract and it is comparatively costly to read, and even more to modify storage. +It is not possible to enumerate storage from within a contract and it is +comparatively costly to read, and even more to modify storage. A contract can neither read nor write to any storage apart from its own. The second data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when -accessing (either reading or writing) a previously untouched memory word (ie. any offset +accessing (either reading or writing) a previously untouched memory word (i.e. any offset within a word). At the time of expansion, the cost in gas must be paid. Memory is more costly the larger it grows (it scales quadratically). @@ -401,7 +403,8 @@ the topmost 16 elements to the top of the stack or swap the topmost element with one of the 16 elements below it. All other operations take the topmost two (or one, or more, depending on the operation) elements from the stack and push the result onto the stack. -Of course it is possible to move stack elements to storage or memory, +Of course it is possible to move stack elements to storage or memory +in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack. @@ -411,13 +414,17 @@ Instruction Set =============== The instruction set of the EVM is kept minimal in order to avoid -incorrect implementations which could cause consensus problems. -All instructions operate on the basic data type, 256-bit words. +incorrect or inconsistent implementations which could cause consensus problems. +All instructions operate on the basic data type, 256-bit words or on slices of memory +(or other byte arrays). The usual arithmetic, bit, logical and comparison operations are present. Conditional and unconditional jumps are possible. Furthermore, contracts can access relevant properties of the current block like its number and timestamp. +For a complete list, please see the :ref:`list of opcodes <opcodes>` as part of the inline +assembly documentation. + .. index:: ! message call, function;call Message Calls @@ -442,9 +449,12 @@ will receive a freshly cleared instance of memory and has access to the call payload - which will be provided in a separate area called the **calldata**. After it has finished execution, it can return data which will be stored at a location in the caller's memory preallocated by the caller. +All such calls are fully synchronous. Calls are **limited** to a depth of 1024, which means that for more complex -operations, loops should be preferred over recursive calls. +operations, loops should be preferred over recursive calls. Furthermore, +only 63/64th of the gas can be forwarded in a message call, which causes a +depth limit of a little less than 1000 in practice. .. index:: delegatecall, callcode, library @@ -462,7 +472,7 @@ refer to the calling contract, only the code is taken from the called address. This makes it possible to implement the "library" feature in Solidity: Reusable library code that can be applied to a contract's storage, e.g. in -order to implement a complex data structure. +order to implement a complex data structure. .. index:: log @@ -471,13 +481,13 @@ Logs It is possible to store data in a specially indexed data structure that maps all the way up to the block level. This feature called **logs** -is used by Solidity in order to implement **events**. +is used by Solidity in order to implement :ref:`events <events>`. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. Since some part of the log data is stored in `bloom filters <https://en.wikipedia.org/wiki/Bloom_filter>`_, it is possible to search for this data in an efficient and cryptographically secure way, so network peers that do not download the whole blockchain -("light clients") can still find these logs. +(so-called "light clients") can still find these logs. .. index:: contract creation @@ -485,7 +495,7 @@ Create ====== Contracts can even create other contracts using a special opcode (i.e. -they do not simply call the zero address). The only difference between +they do not simply call the zero address as a transaction would). The only difference between these **create calls** and normal message calls is that the payload data is executed and the result stored as code and the caller / creator receives the address of the new contract on the stack. diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index ae349055..1b4a6c55 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -11,6 +11,11 @@ Each contract can contain declarations of :ref:`structure-state-variables`, :ref :ref:`structure-function-modifiers`, :ref:`structure-events`, :ref:`structure-struct-types` and :ref:`structure-enum-types`. Furthermore, contracts can inherit from other contracts. +There are also special kinds of contracts called :ref:`libraries<libraries>` and :ref:`interfaces<interfaces>`. + +The section about :ref:`contracts<contracts>` contains more details than this section, +which serves to provide a quick overview. + .. _structure-state-variables: State Variables @@ -49,7 +54,7 @@ Functions are the executable units of code within a contract. } :ref:`function-calls` can happen internally or externally -and have different levels of visibility (:ref:`visibility-and-getters`) +and have different levels of :ref:`visibility<visibility-and-getters>` towards other contracts. .. _structure-function-modifiers: @@ -58,7 +63,7 @@ Function Modifiers ================== Function modifiers can be used to amend the semantics of functions in a declarative way -(see :ref:`modifiers` in contracts section). +(see :ref:`modifiers` in the contracts section). :: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e023dc38..3056561b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -535,7 +535,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c toString(arguments.size()) + " were provided." ); - if (arguments.size() >= 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) + if (arguments.size() >= 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType::bytesMemory())) m_errorReporter.typeError( arguments.front()->location(), "Invalid type for argument in function call. " @@ -1733,8 +1733,23 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) DataLocation dataLoc = DataLocation::Memory; if (auto argRefType = dynamic_cast<ReferenceType const*>(argType.get())) dataLoc = argRefType->location(); - resultType = ReferenceType::copyForLocationIfReference(dataLoc, resultType); - if (!argType->isExplicitlyConvertibleTo(*resultType)) + if (auto type = dynamic_cast<ReferenceType const*>(resultType.get())) + resultType = type->copyForLocation(dataLoc, type->isPointer()); + if (argType->isExplicitlyConvertibleTo(*resultType)) + { + if (auto argArrayType = dynamic_cast<ArrayType const*>(argType.get())) + { + auto resultArrayType = dynamic_cast<ArrayType const*>(resultType.get()); + solAssert(!!resultArrayType, ""); + solAssert( + argArrayType->location() != DataLocation::Storage || + ((resultArrayType->isPointer() || (argArrayType->isByteArray() && resultArrayType->isByteArray())) && + resultArrayType->location() == DataLocation::Storage), + "Invalid explicit conversion to storage type." + ); + } + } + else { if (resultType->category() == Type::Category::Contract && argType->category() == Type::Category::Address) { @@ -2131,7 +2146,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) "after argument-dependent lookup in " + exprType->toString() + (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "."); if (exprType->category() == Type::Category::Contract) - for (auto const& addressMember: AddressType(StateMutability::Payable).nativeMembers(nullptr)) + for (auto const& addressMember: AddressType::addressPayable().nativeMembers(nullptr)) if (addressMember.name == memberName) { Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression()); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index a2d18b0a..65a70019 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -319,6 +319,9 @@ protected: class AddressType: public Type { public: + static AddressType& address() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::NonPayable)); return *addr; } + static AddressType& addressPayable() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::Payable)); return *addr; } + virtual Category category() const override { return Category::Address; } explicit AddressType(StateMutability _stateMutability); @@ -361,6 +364,7 @@ public: { Unsigned, Signed }; + virtual Category category() const override { return Category::Integer; } explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned); @@ -661,6 +665,9 @@ protected: class ArrayType: public ReferenceType { public: + static ArrayType& bytesMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory)); return *addr; } + static ArrayType& stringMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory, true)); return *addr; } + virtual Category category() const override { return Category::Array; } /// Constructor for a byte array ("bytes") and string. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index bd863e05..8645f653 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -710,9 +710,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) arguments.front()->accept(*this); // Optimization: If type is bytes or string, then do not encode, // but directly compute keccak256 on memory. - if (*argType == ArrayType(DataLocation::Memory) || *argType == ArrayType(DataLocation::Memory, true)) + if (*argType == ArrayType::bytesMemory() || *argType == ArrayType::stringMemory()) { - ArrayUtils(m_context).retrieveLength(ArrayType(DataLocation::Memory)); + ArrayUtils(m_context).retrieveLength(ArrayType::bytesMemory()); m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD; } else @@ -1086,7 +1086,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().abiDecode(targetTypes, false); else { - utils().convertType(*firstArgType, ArrayType(DataLocation::Memory)); + utils().convertType(*firstArgType, ArrayType::bytesMemory()); m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; m_context << Instruction::SWAP1 << Instruction::MLOAD; // stack now: <mem_pos> <length> @@ -1259,7 +1259,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) identifier = FunctionType(*function).externalIdentifier(); else solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, AddressType(type.isPayable() ? StateMutability::Payable : StateMutability::NonPayable), true); + utils().convertType(type, type.isPayable() ? AddressType::addressPayable() : AddressType::address(), true); m_context << identifier; } else @@ -1277,7 +1277,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { utils().convertType( *_memberAccess.expression().annotation().type, - AddressType(StateMutability::NonPayable), + AddressType::address(), true ); m_context << Instruction::BALANCE; @@ -1294,7 +1294,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member)) utils().convertType( *_memberAccess.expression().annotation().type, - AddressType(StateMutability::NonPayable), + AddressType::address(), true ); else diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index 06e9f9ea..8a9aa0a7 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -56,9 +56,10 @@ def extract_docs_cases(path): if re.search(r'^ [ ]*(pragma solidity|contract |library |interface )', test, re.MULTILINE) ] -def write_cases(tests): +def write_cases(f, tests): + cleaned_filename = f.replace(".","_").replace("-","_").replace(" ","_").lower() for test in tests: - open('test_%s.sol' % hashlib.sha256(test).hexdigest(), 'wb').write(test) + open('test_%s_%s.sol' % (hashlib.sha256(test).hexdigest(), cleaned_filename), 'wb').write(test) def extract_and_write(f, path): @@ -69,7 +70,7 @@ def extract_and_write(f, path): cases = [open(path, 'r').read()] else: cases = extract_test_cases(path) - write_cases(cases) + write_cases(f, cases) if __name__ == '__main__': path = sys.argv[1] diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index ea624735..3922d5e9 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -122,9 +122,9 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 if (!_isCreation) { d.to = dev::toString(m_contractAddress); - BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2); + BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "pending").size() > 2); // Use eth_call to get the output - m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw); + m_output = fromHex(m_rpc.eth_call(d, "pending"), WhenError::Throw); } string txHash = m_rpc.eth_sendTransaction(d); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 642c9929..f65c8b27 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -3039,26 +3039,26 @@ BOOST_AUTO_TEST_CASE(gasprice) BOOST_AUTO_TEST_CASE(blockhash) { - char const* sourceCode = R"( - contract C { - uint256 counter; - function g() public returns (bool) { counter++; return true; } - function f() public returns (bytes32[] memory r) { - r = new bytes32[](259); - for (uint i = 0; i < 259; i++) - r[i] = blockhash(block.number - 257 + i); - } - } - )"; - compileAndRun(sourceCode); - // generate a sufficient amount of blocks - while (blockNumber() < u256(255)) - ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); - - vector<u256> hashes; - // currently the test only works for pre-constantinople + // depending on the aleth version, this test only works for pre-constantinople if (Options::get().evmVersion() < EVMVersion::constantinople()) { + char const* sourceCode = R"( + contract C { + uint256 counter; + function g() public returns (bool) { counter++; return true; } + function f() public returns (bytes32[] memory r) { + r = new bytes32[](259); + for (uint i = 0; i < 259; i++) + r[i] = blockhash(block.number - 257 + i); + } + } + )"; + compileAndRun(sourceCode); + // generate a sufficient amount of blocks + while (blockNumber() < u256(255)) + ABI_CHECK(callContractFunction("g()"), encodeArgs(true)); + + vector<u256> hashes; // ``blockhash()`` is only valid for the last 256 blocks, otherwise zero hashes.emplace_back(0); for (u256 i = blockNumber() - u256(255); i <= blockNumber(); i++) @@ -3067,18 +3067,9 @@ BOOST_AUTO_TEST_CASE(blockhash) hashes.emplace_back(0); // future block hashes are zero hashes.emplace_back(0); + + ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes)); } - else - // TODO: Starting from constantinople blockhash always seems to return zero. - // The blockhash contract introduced in EIP96 seems to break in our setup of - // aleth (setting the constantinople fork block to zero and resetting the chain - // to block zero before each test run). Pre-deploying the blockchain contract - // during genesis seems to help, but currently causes problems with other tests. - // Set the expectation to zero for now, so that this test tracks changes in this - // behavior. - hashes.assign(259, 0); - - ABI_CHECK(callContractFunction("f()"), encodeDyn(hashes)); } BOOST_AUTO_TEST_CASE(value_complex) diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol new file mode 100644 index 00000000..78c40e53 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol @@ -0,0 +1,9 @@ +contract C { + bytes a; + bytes b; + function f() public view { + bytes storage c = a; + bytes memory d = b; + d = bytes(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol new file mode 100644 index 00000000..f7e96f35 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol @@ -0,0 +1,9 @@ +contract C { + string a; + string b; + function f() public view { + string storage c = a; + string memory d = b; + d = string(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol new file mode 100644 index 00000000..458adda6 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,10 @@ +contract C { + int[10] x; + function f() public view { + int[](x); + int(x); + } +} +// ---- +// TypeError: (55-63): Explicit type conversion not allowed from "int256[10] storage ref" to "int256[] storage pointer". +// TypeError: (67-73): Explicit type conversion not allowed from "int256[10] storage ref" to "int256". diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol new file mode 100644 index 00000000..31e298d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,7 @@ +contract C { + int[10] x; + int[] y; + function f() public { + y = x; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol new file mode 100644 index 00000000..3aa59612 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] storage d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol new file mode 100644 index 00000000..060c9707 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] memory d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol new file mode 100644 index 00000000..a441b540 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol @@ -0,0 +1,12 @@ +contract C { + int[] x; + function f() public { + int[] storage a = x; + int[] memory b; + a = b; + a = int[](b); + } +} +// ---- +// TypeError: (93-94): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. +// TypeError: (102-110): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. |