diff options
author | chriseth <chris@ethereum.org> | 2018-06-28 00:29:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-28 00:29:01 +0800 |
commit | 4a842ecc823c2d4152cdf2639eb83f2318499f1c (patch) | |
tree | 7733ac8095862aa2a9b43b93706ba56df7460a16 | |
parent | ce4b233f8f58f04d564aedc3061e7ecb1bf9737a (diff) | |
parent | 92cb4acd8a748ef2cf6a00a5a9f41975c23127c2 (diff) | |
download | dexon-solidity-4a842ecc823c2d4152cdf2639eb83f2318499f1c.tar.gz dexon-solidity-4a842ecc823c2d4152cdf2639eb83f2318499f1c.tar.zst dexon-solidity-4a842ecc823c2d4152cdf2639eb83f2318499f1c.zip |
Merge pull request #4097 from ethereum/noPackedExceptForPacked
[BREAKING] call only takes a single argument and does not pad
53 files changed, 357 insertions, 351 deletions
diff --git a/Changelog.md b/Changelog.md index 1e9b2787..b1f742bf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ ### 0.5.0 (unreleased) +How to update your code: + * Change every ``.call()`` to a ``.call("")`` and every ``.call(signature, a, b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the last one only works for value types). + * Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``. + + Breaking Changes: * ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding. * Code Generator: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code! @@ -22,6 +27,7 @@ Breaking Changes: * Parser: Disallow trailing dots that are not followed by a number. * Type Checker: Disallow arithmetic operations for boolean variables. * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. + * Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``. * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. * Syntax Checker: Named return values in function types are an error. diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 21e67201..e4f8ed4f 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -559,7 +559,7 @@ would result in the JSON: Non-standard Packed Mode ======================== -Solidity supports a non-standard packed mode where: +Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where: - no :ref:`function selector <abi_function_selector>` is encoded, - types shorter than 32 bytes are neither zero padded nor sign extended and @@ -577,3 +577,9 @@ More specifically, each statically-sized type takes as many bytes as its range h and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without their length field. This means that the encoding is ambiguous as soon as there are two dynamically-sized elements. + +Note that constants will be packed using the minimum number of bytes required to store them. +This means that, for example, ``abi.encodePacked(0) == abi.encodePacked(uint8(0)) == hex"00"`` and +``abi.encodePacked(0x12345678) == abi.encodePacked(uint32(0x12345678)) == hex"12345678"``. + +If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``.
\ No newline at end of file diff --git a/docs/contracts.rst b/docs/contracts.rst index 5e7eab80..19eba047 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -113,7 +113,7 @@ This means that cyclic creation dependencies are impossible. { // Check some arbitrary condition. address tokenAddress = msg.sender; - return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff); + return (keccak256(abi.encodePacked(newOwner)) & 0xff) == (bytes20(tokenAddress) & 0xff); } } @@ -377,7 +377,7 @@ inheritable properties of contracts and may be overridden by derived contracts. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() public noReentrancy returns (uint) { - require(msg.sender.call()); + require(msg.sender.call("")); return 7; } } @@ -604,7 +604,7 @@ Like any function, the fallback function can execute complex operations as long contract Caller { function callTest(Test test) public { - test.call(0xabcdef01); // hash does not exist + test.call(abi.encodeWithSignature("nonExistingFunction()")); // results in test.x becoming == 1. // The following will not compile, but even diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index f6cfdc2c..30ece7e1 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -322,7 +322,7 @@ Global Variables - ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding <abi_packed_mode>` of the given arguments - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)``` +- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` - ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. - ``block.coinbase`` (``address``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty @@ -343,10 +343,10 @@ Global Variables - ``revert()``: abort execution and revert state changes - ``revert(string message)``: abort execution and revert state changes providing an explanatory string - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks -- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` -- ``sha3(...) returns (bytes32)``: an alias to ``keccak256`` -- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` -- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` +- ``keccak256(bytes memory) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the input +- ``sha3(bytes memory) returns (bytes32)``: an alias to ``keccak256`` +- ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input +- ``ripemd160(bytes memory) returns (bytes20)``: compute the RIPEMD-160 hash of the input - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 4133edb1..52a755ca 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -86,7 +86,7 @@ as it uses ``call`` which forwards all remaining gas by default: mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - if (msg.sender.call.value(shares[msg.sender])()) + if (msg.sender.call.value(shares[msg.sender])("")) shares[msg.sender] = 0; } } @@ -140,7 +140,7 @@ Sending and Receiving Ether (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using - ``addr.call.value(x)()``. This is essentially the same as ``addr.transfer(x)``, + ``addr.call.value(x)("")``. This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas and opens up the ability for the recipient to perform more expensive actions (and it only returns a failure code and does not automatically propagate the error). This might include calling back diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index e8fddd61..fcdd1862 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -428,8 +428,8 @@ high or low invalid bids. revealEnd = biddingEnd + _revealTime; } - /// Place a blinded bid with `_blindedBid` = keccak256(value, - /// fake, secret). + /// Place a blinded bid with `_blindedBid` = + /// keccak256(abi.encodePacked(value, fake, secret)). /// The sent ether is only refunded if the bid is correctly /// revealed in the revealing phase. The bid is valid if the /// ether sent together with the bid is at least "value" and @@ -470,7 +470,7 @@ high or low invalid bids. Bid storage bid = bids[msg.sender][i]; (uint value, bool fake, bytes32 secret) = (_values[i], _fake[i], _secret[i]); - if (bid.blindedBid != keccak256(value, fake, secret)) { + if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { // Bid was not actually revealed. // Do not refund deposit. continue; diff --git a/docs/types.rst b/docs/types.rst index 009896d5..528807d9 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -143,27 +143,37 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c * ``call``, ``callcode`` and ``delegatecall`` Furthermore, to interface with contracts that do not adhere to the ABI, -the function ``call`` is provided which takes an arbitrary number of arguments of any type. These arguments are padded to 32 bytes and concatenated. One exception is the case where the first argument is encoded to exactly four bytes. In this case, it is not padded to allow the use of function signatures here. +or to get more direct control over the encoding, +the function ``call`` is provided which takes a single byte array as input. +The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` +and ``abi.encodeWithSignature`` can be used to encode structured data. -:: +.. warning:: + All these functions are low-level functions and should be used with care. + Specifically, any unknown contract might be malicious and if you call it, you + hand over control to that contract which could in turn call back into + your contract, so be prepared for changes to your state variables + when the call returns. The regular way to interact with other contracts + is to call a function on a contract object (``x.f()``). - address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2; - nameReg.call("register", "MyName"); - nameReg.call(bytes4(keccak256("fun(uint256)")), a); +:: note:: + Previous versions of Solidity allowed these functions to receive + arbitrary arguments and would also handle a first argument of type + ``bytes4`` differently. These edge cases were removed in version 0.5.0. -``call`` returns a boolean indicating whether the invoked function terminated (``true``) or caused an EVM exception (``false``). It is not possible to access the actual data returned (for this we would need to know the encoding and size in advance). +``call`` returns a boolean indicating whether the invoked function terminated (``true``) or caused an EVM exception (``false``). It is not possible to access the actual data returned with plain Solidity. However, using inline assembly it is possible to make a raw ``call`` and access the actual data returned with the ``returndatacopy`` instruction. It is possible to adjust the supplied gas with the ``.gas()`` modifier:: - namReg.call.gas(1000000)("register", "MyName"); + namReg.call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); Similarly, the supplied Ether value can be controlled too:: - nameReg.call.value(1 ether)("register", "MyName"); + nameReg.call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); Lastly, these modifiers can be combined. Their order does not matter:: - nameReg.call.gas(1000000).value(1 ether)("register", "MyName"); + nameReg.call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); .. note:: It is not yet possible to use the gas or value modifiers on overloaded functions. @@ -184,13 +194,6 @@ The ``.gas()`` option is available on all three methods, while the ``.value()`` .. note:: The use of ``callcode`` is discouraged and will be removed in the future. -.. warning:: - All these functions are low-level functions and should be used with care. - Specifically, any unknown contract might be malicious and if you call it, you - hand over control to that contract which could in turn call back into - your contract, so be prepared for changes to your state variables - when the call returns. - .. index:: byte array, bytes32 diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 3b0be438..455231cd 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -100,16 +100,16 @@ ABI Encoding Functions ---------------------- - ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments -- ``abi.encodePacked(...) returns (bytes)``: Performes packed encoding of the given arguments +- ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding <abi_packed_mode>` of the given arguments - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)``` +- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` .. note:: These encoding functions can be used to craft data for function calls without actually - calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a more - explicit way to compute ``keccak256(a, b)``, which will be deprecated in future - versions. + calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way + to compute the hash of structured data (although be aware that it is possible to + craft a "hash collision" using different inputs types). See the documentation about the :ref:`ABI <ABI>` and the :ref:`tightly packed encoding <abi_packed_mode>` for details about the encoding. @@ -139,34 +139,18 @@ Mathematical and Cryptographic Functions compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. -``keccak256(...) returns (bytes32)``: - compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` -``sha256(...) returns (bytes32)``: - compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` -``sha3(...) returns (bytes32)``: +``keccak256(bytes memory) returns (bytes32)``: + compute the Ethereum-SHA-3 (Keccak-256) hash of the input +``sha256(bytes memory) returns (bytes32)``: + compute the SHA-256 hash of the input +``sha3(bytes memory) returns (bytes32)``: alias to ``keccak256`` -``ripemd160(...) returns (bytes20)``: - compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>` +``ripemd160(bytes memory) returns (bytes20)``: + compute RIPEMD-160 hash of the input ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover the address associated with the public key from elliptic curve signature or return zero on error (`example usage <https://ethereum.stackexchange.com/q/1777/222>`_) -In the above, "tightly packed" means that the arguments are concatenated without padding. -This means that the following are all identical:: - - keccak256("ab", "c") - keccak256("abc") - keccak256(0x616263) - keccak256(6382179) - keccak256(97, 98, 99) - -If padding is needed, explicit type conversions can be used: ``keccak256("\x00\x12")`` is the -same as ``keccak256(uint16(0x12))``. - -Note that constants will be packed using the minimum number of bytes required to store them. -This means that, for example, ``keccak256(0) == keccak256(uint8(0))`` and -``keccak256(0x12345678) == keccak256(uint32(0x12345678))``. - It might be that you run into Out-of-Gas for ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net. .. index:: balance, send, transfer, call, callcode, delegatecall @@ -181,12 +165,12 @@ Address Related send given amount of Wei to :ref:`address`, throws on failure, forwards 2300 gas stipend, not adjustable ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable -``<address>.call(...) returns (bool)``: - issue low-level ``CALL``, returns ``false`` on failure, forwards all available gas, adjustable -``<address>.callcode(...) returns (bool)``: - issue low-level ``CALLCODE``, returns ``false`` on failure, forwards all available gas, adjustable -``<address>.delegatecall(...) returns (bool)``: - issue low-level ``DELEGATECALL``, returns ``false`` on failure, forwards all available gas, adjustable +``<address>.call(bytes memory) returns (bool)``: + issue low-level ``CALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable +``<address>.callcode(bytes memory) returns (bool)``: + issue low-level ``CALLCODE`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable +``<address>.delegatecall(bytes memory) returns (bool)``: + issue low-level ``DELEGATECALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable For more information, see the section on :ref:`address`. diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 756bb540..7b4bc3aa 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -42,7 +42,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ make_shared<MagicVariableDeclaration>("blockhash", make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)), make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("gasleft", make_shared<FunctionType>(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)), - make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("log0", make_shared<FunctionType>(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), make_shared<MagicVariableDeclaration>("log1", make_shared<FunctionType>(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), make_shared<MagicVariableDeclaration>("log2", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), @@ -55,10 +55,10 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ make_shared<MagicVariableDeclaration>("require", make_shared<FunctionType>(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), - make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction)) }) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e833b8fe..77e7cf67 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1745,35 +1745,6 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } } - if (functionType->takesSinglePackedBytesParameter()) - { - if ( - (arguments.size() > 1) || - (arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) - ) - { - string msg = - "This function only accepts a single \"bytes\" argument. Please use " - "\"abi.encodePacked(...)\" or a similar function to encode the data."; - if (v050) - m_errorReporter.typeError(_functionCall.location(), msg); - else - m_errorReporter.warning(_functionCall.location(), msg); - } - - if (arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) - { - string msg = - "The provided argument of type " + - type(*arguments.front())->toString() + - " is not implicitly convertible to expected type bytes memory."; - if (v050) - m_errorReporter.typeError(_functionCall.location(), msg); - else - m_errorReporter.warning(_functionCall.location(), msg); - } - } - if (functionType->takesArbitraryParameters() && arguments.size() < parameterTypes.size()) { solAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, ""); @@ -1805,6 +1776,26 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) for (auto const& member: membersRemovedForStructConstructor) msg += " " + member; } + else if ( + functionType->kind() == FunctionType::Kind::BareCall || + functionType->kind() == FunctionType::Kind::BareCallCode || + functionType->kind() == FunctionType::Kind::BareDelegateCall + ) + { + if (arguments.empty()) + msg += " This function requires a single bytes argument. Use \"\" as argument to provide empty calldata."; + else + msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it."; + } + else if ( + functionType->kind() == FunctionType::Kind::SHA3 || + functionType->kind() == FunctionType::Kind::SHA256 || + functionType->kind() == FunctionType::Kind::RIPEMD160 + ) + msg += + " This function requires a single bytes argument." + " Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour" + " or abi.encode(...) to use ABI encoding."; m_errorReporter.typeError(_functionCall.location(), msg); } else if (isPositionalCall) @@ -1841,15 +1832,31 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } } else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) - m_errorReporter.typeError( - arguments[i]->location(), + { + string msg = "Invalid type for argument in function call. " "Invalid implicit conversion from " + type(*arguments[i])->toString() + " to " + parameterTypes[i]->toString() + - " requested." - ); + " requested."; + if ( + functionType->kind() == FunctionType::Kind::BareCall || + functionType->kind() == FunctionType::Kind::BareCallCode || + functionType->kind() == FunctionType::Kind::BareDelegateCall + ) + msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it."; + else if ( + functionType->kind() == FunctionType::Kind::SHA3 || + functionType->kind() == FunctionType::Kind::SHA256 || + functionType->kind() == FunctionType::Kind::RIPEMD160 + ) + msg += + " This function requires a single bytes argument." + " Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour" + " or abi.encode(...) to use ABI encoding."; + m_errorReporter.typeError(arguments[i]->location(), msg); + } } } else diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 69124705..1c4eb76e 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -599,9 +599,9 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons if (isAddress()) return { {"balance", make_shared<IntegerType>(256)}, - {"call", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareCall, true, StateMutability::Payable)}, - {"callcode", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareCallCode, true, StateMutability::Payable)}, - {"delegatecall", make_shared<FunctionType>(strings(), strings{"bool"}, FunctionType::Kind::BareDelegateCall, true)}, + {"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, + {"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, + {"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, false)}, {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}, {"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)} }; @@ -3005,6 +3005,25 @@ ASTPointer<ASTString> FunctionType::documentation() const return ASTPointer<ASTString>(); } +bool FunctionType::padArguments() const +{ + // No padding only for hash functions, low-level calls and the packed encoding function. + switch (m_kind) + { + case Kind::BareCall: + case Kind::BareCallCode: + case Kind::BareDelegateCall: + case Kind::SHA256: + case Kind::RIPEMD160: + case Kind::SHA3: + case Kind::ABIEncodePacked: + return false; + default: + return true; + } + return true; +} + string MappingType::richIdentifier() const { return "t_mapping" + identifierList(m_keyType, m_valueType); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index b2f34dee..4415fb4b 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1058,18 +1058,21 @@ public: ASTPointer<ASTString> documentation() const; /// true iff arguments are to be padded to multiples of 32 bytes for external calls - bool padArguments() const { return !(m_kind == Kind::SHA3 || m_kind == Kind::SHA256 || m_kind == Kind::RIPEMD160 || m_kind == Kind::ABIEncodePacked); } + /// The only functions that do not pad are hash functions, the low-level call functions + /// and abi.encodePacked. + bool padArguments() const; bool takesArbitraryParameters() const { return m_arbitraryParameters; } /// true iff the function takes a single bytes parameter and it is passed on without padding. - /// @todo until 0.5.0, this is just a "recommendation". bool takesSinglePackedBytesParameter() const { - // @todo add the call kinds here with 0.5.0 and perhaps also log0. switch (m_kind) { case FunctionType::Kind::SHA3: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: + case FunctionType::Kind::BareCall: + case FunctionType::Kind::BareCallCode: + case FunctionType::Kind::BareDelegateCall: return true; default: return false; diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 0470c3ec..ecbd0243 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -699,16 +699,24 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } case FunctionType::Kind::SHA3: { - TypePointers argumentTypes; - for (auto const& arg: arguments) + solAssert(arguments.size() == 1, ""); + solAssert(!function.padArguments(), ""); + TypePointer const& argType = arguments.front()->annotation().type; + solAssert(argType, ""); + 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)) { - arg->accept(*this); - argumentTypes.push_back(arg->annotation().type); + ArrayUtils(m_context).retrieveLength(ArrayType(DataLocation::Memory)); + m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD; + } + else + { + utils().fetchFreeMemoryPointer(); + utils().packedEncode({argType}, TypePointers()); + utils().toSizeAfterFreeMemoryPointer(); } - utils().fetchFreeMemoryPointer(); - solAssert(!function.padArguments(), ""); - utils().packedEncode(argumentTypes, TypePointers()); - utils().toSizeAfterFreeMemoryPointer(); m_context << Instruction::KECCAK256; break; } @@ -1802,13 +1810,14 @@ void ExpressionCompiler::appendExternalFunctionCall( if (_functionType.bound()) utils().moveToStackTop(gasValueSize, _functionType.selfType()->sizeOnStack()); + bool const v050 = m_context.experimentalFeatureActive(ExperimentalFeature::V050); auto funKind = _functionType.kind(); 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; bool useStaticCall = _functionType.stateMutability() <= StateMutability::View && - m_context.experimentalFeatureActive(ExperimentalFeature::V050) && + v050 && m_context.evmVersion().hasStaticCall(); bool haveReturndatacopy = m_context.evmVersion().supportsReturndata(); @@ -1836,38 +1845,12 @@ void ExpressionCompiler::appendExternalFunctionCall( // Evaluate arguments. TypePointers argumentTypes; TypePointers parameterTypes = _functionType.parameterTypes(); - bool manualFunctionId = false; - if ( - (funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall) && - !_arguments.empty() - ) - { - solAssert(_arguments.front()->annotation().type->mobileType(), ""); - manualFunctionId = - _arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) == - CompilerUtils::dataStartOffset; - } - if (manualFunctionId) - { - // If we have a Bare* and the first type has exactly 4 bytes, use it as - // function identifier. - _arguments.front()->accept(*this); - utils().convertType( - *_arguments.front()->annotation().type, - IntegerType(8 * CompilerUtils::dataStartOffset), - true - ); - for (unsigned i = 0; i < gasValueSize; ++i) - m_context << swapInstruction(gasValueSize - i); - gasStackPos++; - valueStackPos++; - } if (_functionType.bound()) { argumentTypes.push_back(_functionType.selfType()); parameterTypes.insert(parameterTypes.begin(), _functionType.selfType()); } - for (size_t i = manualFunctionId ? 1 : 0; i < _arguments.size(); ++i) + for (size_t i = 0; i < _arguments.size(); ++i) { _arguments[i]->accept(*this); argumentTypes.push_back(_arguments[i]->annotation().type); @@ -1903,19 +1886,20 @@ void ExpressionCompiler::appendExternalFunctionCall( // Copy function identifier to memory. utils().fetchFreeMemoryPointer(); - if (!_functionType.isBareCall() || manualFunctionId) + if (!_functionType.isBareCall()) { m_context << dupInstruction(2 + gasValueSize + CompilerUtils::sizeOnStack(argumentTypes)); utils().storeInMemoryDynamic(IntegerType(8 * CompilerUtils::dataStartOffset), false); } - // If the function takes arbitrary parameters, copy dynamic length data in place. + + // If the function takes arbitrary parameters or is a bare call, copy dynamic length data in place. // Move arguments to memory, will not update the free memory pointer (but will update the memory // pointer on the stack). utils().encodeToMemory( argumentTypes, parameterTypes, _functionType.padArguments(), - _functionType.takesArbitraryParameters(), + _functionType.takesArbitraryParameters() || _functionType.isBareCall(), isCallCode || isDelegateCall ); @@ -1996,9 +1980,9 @@ void ExpressionCompiler::appendExternalFunctionCall( unsigned remainsSize = 2 + // contract address, input_memory_end - _functionType.valueSet() + - _functionType.gasSet() + - (!_functionType.isBareCall() || manualFunctionId); + (_functionType.valueSet() ? 1 : 0) + + (_functionType.gasSet() ? 1 : 0) + + (!_functionType.isBareCall() ? 1 : 0); if (returnSuccessCondition) m_context << swapInstruction(remainsSize); diff --git a/test/compilationTests/corion/moduleHandler.sol b/test/compilationTests/corion/moduleHandler.sol index 080f599c..e77d9e09 100644 --- a/test/compilationTests/corion/moduleHandler.sol +++ b/test/compilationTests/corion/moduleHandler.sol @@ -117,7 +117,7 @@ contract moduleHandler is multiOwner, announcementTypes { @id Index of module. @found Was there any result or not. */ - bytes32 _name = keccak256(name); + bytes32 _name = keccak256(bytes(name)); for ( uint256 a=0 ; a<modules.length ; a++ ) { if ( modules[a].name == _name ) { return (true, true, a); @@ -153,7 +153,7 @@ contract moduleHandler is multiOwner, announcementTypes { require( _success ); if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(name, addr, callCallback))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(abi.encodePacked(name, addr, callCallback)))) ) { return true; } } @@ -169,7 +169,7 @@ contract moduleHandler is multiOwner, announcementTypes { function callReplaceCallback(string moduleName, address newModule) external returns (bool success) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("callReplaceCallback", keccak256(moduleName, newModule))) ) { + if ( ! insertAndCheckDo(calcDoHash("callReplaceCallback", keccak256(abi.encodePacked(moduleName, newModule)))) ) { return true; } (bool _success, bool _found, uint256 _id) = getModuleIDByName(moduleName); @@ -192,11 +192,11 @@ contract moduleHandler is multiOwner, announcementTypes { require( _success ); if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("newModule", keccak256(name, addr, schellingEvent, transferEvent))) ) { + if ( ! insertAndCheckDo(calcDoHash("newModule", keccak256(abi.encodePacked(name, addr, schellingEvent, transferEvent)))) ) { return true; } } - addModule( modules_s(addr, keccak256(name), schellingEvent, transferEvent), true); + addModule( modules_s(addr, keccak256(bytes(name)), schellingEvent, transferEvent), true); return true; } function dropModule(string name, bool callCallback) external returns (bool success) { @@ -211,7 +211,7 @@ contract moduleHandler is multiOwner, announcementTypes { require( _success ); if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(name, callCallback))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModule", keccak256(abi.encodePacked(name, callCallback)))) ) { return true; } } @@ -226,7 +226,7 @@ contract moduleHandler is multiOwner, announcementTypes { function callDisableCallback(string moduleName) external returns (bool success) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("callDisableCallback", keccak256(moduleName))) ) { + if ( ! insertAndCheckDo(calcDoHash("callDisableCallback", keccak256(bytes(moduleName)))) ) { return true; } (bool _success, bool _found, uint256 _id) = getModuleIDByName(moduleName); @@ -289,7 +289,7 @@ contract moduleHandler is multiOwner, announcementTypes { require( _success ); if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("replaceModuleHandler", keccak256(newHandler))) ) { + if ( ! insertAndCheckDo(calcDoHash("replaceModuleHandler", keccak256(abi.encodePacked(newHandler)))) ) { return true; } } @@ -419,7 +419,7 @@ contract moduleHandler is multiOwner, announcementTypes { require( _success ); if ( ! ( _found && modules[_id].name == keccak256('Publisher') )) { require( block.number < debugModeUntil ); - if ( ! insertAndCheckDo(calcDoHash("configureModule", keccak256(moduleName, aType, value))) ) { + if ( ! insertAndCheckDo(calcDoHash("configureModule", keccak256(abi.encodePacked(moduleName, aType, value)))) ) { return true; } } @@ -437,7 +437,7 @@ contract moduleHandler is multiOwner, announcementTypes { */ require( owners[msg.sender] ); if ( forever ) { - if ( ! insertAndCheckDo(calcDoHash("freezing", keccak256(forever))) ) { + if ( ! insertAndCheckDo(calcDoHash("freezing", keccak256(abi.encodePacked(forever)))) ) { return; } } diff --git a/test/compilationTests/corion/multiOwner.sol b/test/compilationTests/corion/multiOwner.sol index 0a0a44c5..2b8a46b9 100644 --- a/test/compilationTests/corion/multiOwner.sol +++ b/test/compilationTests/corion/multiOwner.sol @@ -21,12 +21,12 @@ contract multiOwner is safeMath { Externals */ function insertOwner(address addr) external { - if ( insertAndCheckDo(calcDoHash("insertOwner", keccak256(addr))) ) { + if ( insertAndCheckDo(calcDoHash("insertOwner", keccak256(abi.encodePacked(addr)))) ) { _addOwner(addr); } } function dropOwner(address addr) external { - if ( insertAndCheckDo(calcDoHash("dropOwner", keccak256(addr))) ) { + if ( insertAndCheckDo(calcDoHash("dropOwner", keccak256(abi.encodePacked(addr)))) ) { _delOwner(addr); } } @@ -42,7 +42,7 @@ contract multiOwner is safeMath { return ownerCount * 75 / 100; } function calcDoHash(string job, bytes32 data) public constant returns (bytes32 hash) { - return keccak256(job, data); + return keccak256(abi.encodePacked(job, data)); } function validDoHash(bytes32 doHash) public constant returns (bool valid) { return doDB[doHash].length > 0; diff --git a/test/compilationTests/corion/schelling.sol b/test/compilationTests/corion/schelling.sol index e092e311..f8c36fc5 100644 --- a/test/compilationTests/corion/schelling.sol +++ b/test/compilationTests/corion/schelling.sol @@ -335,7 +335,7 @@ contract schelling is module, announcementTypes, schellingVars { require( voter.status == voterStatus.afterPrepareVote ); require( voter.roundID < currentRound ); - if ( keccak256(vote) == voter.hash ) { + if ( keccak256(bytes(vote)) == voter.hash ) { delete voter.hash; if (round.blockHeight+roundBlockDelay/2 >= block.number) { if ( bytes(vote)[0] == aboveChar ) { diff --git a/test/compilationTests/gnosis/Events/CategoricalEvent.sol b/test/compilationTests/gnosis/Events/CategoricalEvent.sol index 4433bdfd..0f5196e8 100644 --- a/test/compilationTests/gnosis/Events/CategoricalEvent.sol +++ b/test/compilationTests/gnosis/Events/CategoricalEvent.sol @@ -48,6 +48,6 @@ contract CategoricalEvent is Event { constant returns (bytes32) { - return keccak256(collateralToken, oracle, outcomeTokens.length); + return keccak256(abi.encodePacked(collateralToken, oracle, outcomeTokens.length)); } } diff --git a/test/compilationTests/gnosis/Events/EventFactory.sol b/test/compilationTests/gnosis/Events/EventFactory.sol index acef3330..cfe772ec 100644 --- a/test/compilationTests/gnosis/Events/EventFactory.sol +++ b/test/compilationTests/gnosis/Events/EventFactory.sol @@ -35,7 +35,7 @@ contract EventFactory { public returns (CategoricalEvent eventContract) { - bytes32 eventHash = keccak256(collateralToken, oracle, outcomeCount); + bytes32 eventHash = keccak256(abi.encodePacked(collateralToken, oracle, outcomeCount)); // Event should not exist yet require(address(categoricalEvents[eventHash]) == address(0)); // Create event @@ -63,7 +63,7 @@ contract EventFactory { public returns (ScalarEvent eventContract) { - bytes32 eventHash = keccak256(collateralToken, oracle, lowerBound, upperBound); + bytes32 eventHash = keccak256(abi.encodePacked(collateralToken, oracle, lowerBound, upperBound)); // Event should not exist yet require(address(scalarEvents[eventHash]) == address(0)); // Create event diff --git a/test/compilationTests/gnosis/Events/ScalarEvent.sol b/test/compilationTests/gnosis/Events/ScalarEvent.sol index 4f268a38..d5cbef14 100644 --- a/test/compilationTests/gnosis/Events/ScalarEvent.sol +++ b/test/compilationTests/gnosis/Events/ScalarEvent.sol @@ -82,6 +82,6 @@ contract ScalarEvent is Event { constant returns (bytes32) { - return keccak256(collateralToken, oracle, lowerBound, upperBound); + return keccak256(abi.encodePacked(collateralToken, oracle, lowerBound, upperBound)); } } diff --git a/test/compilationTests/gnosis/Oracles/SignedMessageOracle.sol b/test/compilationTests/gnosis/Oracles/SignedMessageOracle.sol index 83990b9b..121824ff 100644 --- a/test/compilationTests/gnosis/Oracles/SignedMessageOracle.sol +++ b/test/compilationTests/gnosis/Oracles/SignedMessageOracle.sol @@ -58,7 +58,7 @@ contract SignedMessageOracle is Oracle { // Result is not set yet and nonce and signer are valid require( !isSet && _nonce > nonce - && signer == ecrecover(keccak256(descriptionHash, newSigner, _nonce), v, r, s)); + && signer == ecrecover(keccak256(abi.encodePacked(descriptionHash, newSigner, _nonce)), v, r, s)); nonce = _nonce; signer = newSigner; emit SignerReplacement(newSigner); @@ -74,7 +74,7 @@ contract SignedMessageOracle is Oracle { { // Result is not set yet and signer is valid require( !isSet - && signer == ecrecover(keccak256(descriptionHash, _outcome), v, r, s)); + && signer == ecrecover(keccak256(abi.encodePacked(descriptionHash, _outcome)), v, r, s)); isSet = true; outcome = _outcome; emit OutcomeAssignment(_outcome); diff --git a/test/compilationTests/zeppelin/MultisigWallet.sol b/test/compilationTests/zeppelin/MultisigWallet.sol index 83df125c..ea620fc0 100644 --- a/test/compilationTests/zeppelin/MultisigWallet.sol +++ b/test/compilationTests/zeppelin/MultisigWallet.sol @@ -66,7 +66,7 @@ contract MultisigWallet is Multisig, Shareable, DayLimit { return 0; } // determine our operation hash. - _r = keccak256(msg.data, block.number); + _r = keccak256(abi.encodePacked(msg.data, block.number)); if (!confirm(_r) && txs[_r].to == address(0)) { txs[_r].to = _to; txs[_r].value = _value; diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index c167745c..142f4144 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -82,7 +82,7 @@ contract FixedFeeRegistrar is Registrar { } } function disown(string _name, address _refund) onlyrecordowner(_name) { - delete m_recordData[uint(keccak256(_name)) / 8]; + delete m_recordData[uint(keccak256(bytes(_name))) / 8]; if (!_refund.send(c_fee)) throw; emit Changed(_name); @@ -118,7 +118,7 @@ contract FixedFeeRegistrar is Registrar { Record[2**253] m_recordData; function m_record(string _name) constant internal returns (Record storage o_record) { - return m_recordData[uint(keccak256(_name)) / 8]; + return m_recordData[uint(keccak256(bytes(_name))) / 8]; } uint constant c_fee = 69 ether; } diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 0e42eeb1..98be562c 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -398,7 +398,7 @@ contract Wallet is multisig, multiowned, daylimit { return 0; } // determine our operation hash. - _r = keccak256(msg.data, block.number); + _r = keccak256(abi.encodePacked(msg.data, block.number)); if (!confirm(_r) && m_txs[_r].to == 0x0000000000000000000000000000000000000000) { m_txs[_r].to = _to; m_txs[_r].value = _value; diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index f16d9abe..62711107 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(simple_contract) contract test { bytes32 public shaValue; function f(uint a) { - shaValue = keccak256(a); + shaValue = keccak256(abi.encodePacked(a)); } } )"; @@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE(store_keccak256) contract test { bytes32 public shaValue; function test(uint a) { - shaValue = keccak256(a); + shaValue = keccak256(abi.encodePacked(a)); } } )"; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 65a0a216..57204c61 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1456,7 +1456,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) function test() { data = 8; name = "Celina"; - a_hash = keccak256(123); + a_hash = keccak256("\x7b"); an_address = address(0x1337); super_secret_data = 42; } @@ -1992,7 +1992,7 @@ BOOST_AUTO_TEST_CASE(keccak256) char const* sourceCode = R"( contract test { function a(bytes32 input) returns (bytes32 hash) { - return keccak256(input); + return keccak256(abi.encodePacked(input)); } } )"; @@ -2011,7 +2011,7 @@ BOOST_AUTO_TEST_CASE(sha256) char const* sourceCode = R"( contract test { function a(bytes32 input) returns (bytes32 sha256hash) { - return sha256(input); + return sha256(abi.encodePacked(input)); } } )"; @@ -2036,7 +2036,7 @@ BOOST_AUTO_TEST_CASE(ripemd) char const* sourceCode = R"( contract test { function a(bytes32 input) returns (bytes32 sha256hash) { - return ripemd160(input); + return ripemd160(abi.encodePacked(input)); } } )"; @@ -2063,7 +2063,7 @@ BOOST_AUTO_TEST_CASE(packed_keccak256) function a(bytes32 input) returns (bytes32 hash) { var b = 65536; uint c = 256; - return keccak256(8, input, b, input, c); + return keccak256(abi.encodePacked(8, input, b, input, c)); } } )"; @@ -2093,9 +2093,9 @@ BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types) x[0] = y[0] = uint120(-2); x[1] = y[1] = uint120(-3); x[2] = y[2] = uint120(-4); - hash1 = keccak256(x); - hash2 = keccak256(y); - hash3 = keccak256(this.f); + hash1 = keccak256(abi.encodePacked(x)); + hash2 = keccak256(abi.encodePacked(y)); + hash3 = keccak256(abi.encodePacked(this.f)); } } )"; @@ -2115,7 +2115,7 @@ BOOST_AUTO_TEST_CASE(packed_sha256) function a(bytes32 input) returns (bytes32 hash) { var b = 65536; uint c = 256; - return sha256(8, input, b, input, c); + return sha256(abi.encodePacked(8, input, b, input, c)); } } )"; @@ -2142,7 +2142,7 @@ BOOST_AUTO_TEST_CASE(packed_ripemd160) function a(bytes32 input) returns (bytes32 hash) { var b = 65536; uint c = 256; - return ripemd160(8, input, b, input, c); + return ripemd160(abi.encodePacked(8, input, b, input, c)); } } )"; @@ -3082,13 +3082,13 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function) BOOST_AUTO_TEST_CASE(default_fallback_throws) { - char const* sourceCode = R"( + char const* sourceCode = R"YY( contract A { function f() returns (bool) { - return this.call(); + return this.call(""); } } - )"; + )YY"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); } @@ -3503,7 +3503,7 @@ BOOST_AUTO_TEST_CASE(sha256_empty) char const* sourceCode = R"( contract C { function f() returns (bytes32) { - return sha256(); + return sha256(""); } } )"; @@ -3516,7 +3516,7 @@ BOOST_AUTO_TEST_CASE(ripemd160_empty) char const* sourceCode = R"( contract C { function f() returns (bytes20) { - return ripemd160(); + return ripemd160(""); } } )"; @@ -3529,7 +3529,7 @@ BOOST_AUTO_TEST_CASE(keccak256_empty) char const* sourceCode = R"( contract C { function f() returns (bytes32) { - return keccak256(); + return keccak256(""); } } )"; @@ -3543,7 +3543,7 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) contract c { function foo(uint a, uint b, uint c) returns (bytes32 d) { - d = keccak256(a, b, c); + d = keccak256(abi.encodePacked(a, b, c)); } } )"; @@ -3564,7 +3564,7 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_numeric_literals) contract c { function foo(uint a, uint16 b) returns (bytes32 d) { - d = keccak256(a, b, 145); + d = keccak256(abi.encodePacked(a, b, 145)); } } )"; @@ -3589,7 +3589,7 @@ BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments_with_string_literals) } function bar(uint a, uint16 b) returns (bytes32 d) { - d = keccak256(a, b, 145, "foo"); + d = keccak256(abi.encodePacked(a, b, 145, "foo")); } } )"; @@ -3628,7 +3628,7 @@ BOOST_AUTO_TEST_CASE(keccak256_with_bytes) BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) { - char const* sourceCode = R"( + char const* sourceCode = R"ABC( contract c { bytes data; function foo() returns (bytes32) @@ -3637,10 +3637,10 @@ BOOST_AUTO_TEST_CASE(iterated_keccak256_with_bytes) data[0] = "x"; data[1] = "y"; data[2] = "z"; - return keccak256("b", keccak256(data), "a"); + return keccak256(abi.encodePacked("b", keccak256(data), "a")); } } - )"; + )ABC"; compileAndRun(sourceCode); ABI_CHECK(callContractFunction("foo()"), encodeArgs( u256(dev::keccak256(bytes{'b'} + dev::keccak256("xyz").asBytes() + bytes{'a'})) @@ -3659,7 +3659,7 @@ BOOST_AUTO_TEST_CASE(generic_call) function doSend(address rec) returns (uint d) { bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - rec.call.value(2)(signature, 23); + rec.call.value(2)(abi.encodeWithSelector(signature, 23)); return receiver(rec).received(); } } @@ -3689,7 +3689,7 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) function doSend(address rec) payable { bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - if (rec.delegatecall(signature, 23)) {} + if (rec.delegatecall(abi.encodeWithSelector(signature, 23))) {} } } )**"; @@ -3786,7 +3786,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) char const* sourceCode = R"( contract C { function f() returns (bytes32) { - return keccak256("abc", msg.data); + return keccak256(abi.encodePacked("abc", msg.data)); } } )"; @@ -3855,21 +3855,15 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) compileAndRun(sourceCode, 0, "sender"); // No additional data, just function selector - ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(4)); - ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(4)); - ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(4)); + ABI_CHECK(callContractFunction("viaCalldata()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("viaMemory()"), encodeArgs(4)); + ABI_CHECK(callContractFunction("viaStorage()"), encodeArgs(4)); // Some additional unpadded data bytes unpadded = asBytes(string("abc")); - ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(7)); - ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(0x20)); - // Should be this with 0.5.0: encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaCalldata()", unpadded), encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaMemory()", unpadded), encodeArgs(7)); + ABI_CHECK(callContractFunctionNoEncoding("viaStorage()", unpadded), encodeArgs(7)); } BOOST_AUTO_TEST_CASE(copying_bytes_multiassign) @@ -6324,7 +6318,7 @@ BOOST_AUTO_TEST_CASE(reusing_memory) mapping(uint => uint) map; function f(uint x) returns (uint) { map[x] = x; - return (new Helper(uint(keccak256(this.g(map[x]))))).flag(); + return (new Helper(uint(keccak256(abi.encodePacked(this.g(map[x])))))).flag(); } function g(uint a) returns (uint) { @@ -9312,7 +9306,7 @@ BOOST_AUTO_TEST_CASE(mutex) // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. if (amount > shares) throw; - if (!msg.sender.call.value(amount)()) throw; + if (!msg.sender.call.value(amount)("")) throw; shares -= amount; return shares; } @@ -9320,7 +9314,7 @@ BOOST_AUTO_TEST_CASE(mutex) // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. if (amount > shares) throw; - if (!msg.sender.call.value(amount)()) throw; + if (!msg.sender.call.value(amount)("")) throw; shares -= amount; return shares; } @@ -9393,7 +9387,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_proper) function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s, uint blockExpired, bytes32 salt) returns (address) { - require(hash == keccak256(blockExpired, salt)); + require(hash == keccak256(abi.encodePacked(blockExpired, salt))); return ecrecover(hash, v, r, s); } } @@ -9425,7 +9419,7 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input_asm) BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) { - char const* sourceCode = R"( + char const* sourceCode = R"YY( contract D { function g(); } contract C { D d = D(0x1212); @@ -9438,11 +9432,11 @@ BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws) return 7; } function h() returns (uint) { - d.call(); // this does not throw (low-level) + d.call(""); // this does not throw (low-level) return 7; } } - )"; + )YY"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeArgs()); ABI_CHECK(callContractFunction("g()"), encodeArgs()); @@ -11446,17 +11440,17 @@ BOOST_AUTO_TEST_CASE(inlineasm_empty_let) BOOST_AUTO_TEST_CASE(bare_call_invalid_address) { - char const* sourceCode = R"( + char const* sourceCode = R"YY( contract C { /// Calling into non-existant account is successful (creates the account) function f() external returns (bool) { - return address(0x4242).call(); + return address(0x4242).call(""); } function h() external returns (bool) { - return address(0x4242).delegatecall(); + return address(0x4242).delegatecall(""); } } - )"; + )YY"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); ABI_CHECK(callContractFunction("h()"), encodeArgs(u256(1))); @@ -11474,13 +11468,13 @@ BOOST_AUTO_TEST_CASE(delegatecall_return_value) return value; } function get_delegated() external returns (bool) { - return this.delegatecall(bytes4(keccak256("get()"))); + return this.delegatecall(abi.encodeWithSignature("get()")); } function assert0() external view { assert(value == 0); } function assert0_delegated() external returns (bool) { - return this.delegatecall(bytes4(keccak256("assert0()"))); + return this.delegatecall(abi.encodeWithSignature("assert0()")); } } )DELIMITER"; diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 3a8585f7..4ea307c0 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -265,18 +265,18 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops) // Information in joining branches is not retained anymore. BOOST_AUTO_TEST_CASE(retain_information_in_branches) { - // This tests that the optimizer knows that we already have "z == keccak256(y)" inside both branches. + // This tests that the optimizer knows that we already have "z == keccak256(abi.encodePacked(y))" inside both branches. char const* sourceCode = R"( contract c { bytes32 d; uint a; function f(uint x, bytes32 y) returns (uint r_a, bytes32 r_d) { - bytes32 z = keccak256(y); + bytes32 z = keccak256(abi.encodePacked(y)); if (x > 8) { - z = keccak256(y); + z = keccak256(abi.encodePacked(y)); a = x; } else { - z = keccak256(y); + z = keccak256(abi.encodePacked(y)); a = x; } r_a = a; @@ -313,19 +313,19 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) contract test { bytes32 data; function f(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); shared(y); - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); r_a = 5; } function g(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { - r_d = keccak256(y); + r_d = keccak256(abi.encodePacked(y)); shared(y); - r_d = bytes32(uint(keccak256(y)) + 2); + r_d = bytes32(uint(keccak256(abi.encodePacked(y))) + 2); r_a = 7; } function shared(bytes32 y) internal { - data = keccak256(y); + data = keccak256(abi.encodePacked(y)); } } )"; @@ -370,7 +370,7 @@ BOOST_AUTO_TEST_CASE(sequence_number_for_calls) // to storage), so the sequence number should be incremented. char const* sourceCode = R"( contract test { - function f(string a, string b) returns (bool) { return sha256(a) == sha256(b); } + function f(string a, string b) returns (bool) { return sha256(bytes(a)) == sha256(bytes(b)); } } )"; compileBothVersions(sourceCode); diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol index 08d20c3a..9f1d9722 100644 --- a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol @@ -1,12 +1,10 @@ contract C { uint constant a = b * c; uint constant b = 7; - uint constant c = b + uint(keccak256(d)); + uint constant c = b + uint(keccak256(abi.encodePacked(d))); uint constant d = 2 + a; } // ---- -// Warning: (98-110): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (98-110): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. // TypeError: (17-40): The value of the constant a has a cyclic dependency via c. -// TypeError: (71-111): The value of the constant c has a cyclic dependency via d. -// TypeError: (117-140): The value of the constant d has a cyclic dependency via a. +// TypeError: (71-129): The value of the constant c has a cyclic dependency via d. +// TypeError: (135-158): The value of the constant d has a cyclic dependency via a. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol index df5cd969..cc34fad2 100644 --- a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol @@ -1,9 +1,7 @@ contract C { uint constant a = b * c; uint constant b = 7; - uint constant c = 4 + uint(keccak256(d)); + uint constant c = 4 + uint(keccak256(abi.encode(d))); uint constant d = 2 + b; } // ---- -// Warning: (98-110): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (98-110): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index 99ca4542..62dfcff9 100644 --- a/test/libsolidity/syntaxTests/deprecated_functions.sol +++ b/test/libsolidity/syntaxTests/deprecated_functions.sol @@ -1,6 +1,6 @@ contract test { function f() pure public { - bytes32 x = sha3(); + bytes32 x = sha3(""); x; } function g() public { @@ -8,5 +8,5 @@ contract test { } } // ---- -// TypeError: (58-64): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (99-150): "suicide" has been deprecated in favour of "selfdestruct" +// TypeError: (58-66): "sha3" has been deprecated in favour of "keccak256" +// TypeError: (101-152): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol new file mode 100644 index 00000000..e8134539 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol @@ -0,0 +1,13 @@ +contract C { + function f() public { + require(address(this).call()); + require(address(this).call(bytes4(0x12345678))); + require(address(this).call(uint(1))); + require(address(this).call(uint(1), uint(2))); + } +} +// ---- +// TypeError: (55-75): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (113-131): Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (170-177): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (197-233): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol new file mode 100644 index 00000000..2b424d53 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(address(this).callcode()); + require(address(this).callcode(uint(1))); + require(address(this).callcode(uint(1), uint(2))); + } +} +// ---- +// TypeError: (55-79): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (121-128): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (148-188): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol new file mode 100644 index 00000000..be0347de --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(address(this).delegatecall()); + require(address(this).delegatecall(uint(1))); + require(address(this).delegatecall(uint(1), uint(2))); + } +} +// ---- +// TypeError: (55-83): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (129-136): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (156-200): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol new file mode 100644 index 00000000..4857bc2e --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/keccak256_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(keccak256() != 0); + require(keccak256(uint(1)) != 0); + require(keccak256(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-66): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (100-107): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (132-159): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol new file mode 100644 index 00000000..da41fccd --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/ripemd160_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(ripemd160() != 0); + require(ripemd160(uint(1)) != 0); + require(ripemd160(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-66): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (100-107): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (132-159): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol new file mode 100644 index 00000000..2939e7fc --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/sha256_with_wrong_arg_count.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + require(sha256() != 0); + require(sha256(uint(1)) != 0); + require(sha256(uint(1), uint(2)) != 0); + } +} +// ---- +// TypeError: (55-63): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (94-101): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (126-150): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol new file mode 100644 index 00000000..fd9717f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/235_abi_encode_with_large_integer_constant.sol @@ -0,0 +1,5 @@ +contract C { + function f() pure public { abi.encode(2**500); } +} +// ---- +// TypeError: (55-61): Invalid rational number (too large or division by zero). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/235_keccak256_with_large_integer_constant.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/235_keccak256_with_large_integer_constant.sol deleted file mode 100644 index c39d0fe2..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/235_keccak256_with_large_integer_constant.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract C { - function f() public { keccak256(2**500); } -} -// ---- -// Warning: (39-56): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (39-56): The provided argument of type int_const 3273...(143 digits omitted)...9376 is not implicitly convertible to expected type bytes memory. -// TypeError: (49-55): Invalid rational number (too large or division by zero). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol index d0c3769c..9c42bc8f 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol @@ -2,8 +2,8 @@ contract C { function f() public { address addr; uint balance = addr.balance; - bool callRet = addr.call(); - bool delegatecallRet = addr.delegatecall(); + bool callRet = addr.call(""); + bool delegatecallRet = addr.delegatecall(""); bool sendRet = addr.send(1); addr.transfer(1); balance; callRet; delegatecallRet; sendRet; diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol index bc8c7867..b99431f9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/493_builtin_keccak256_reject_gas.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function () pure returns (bytes32) +// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol index f29cd7dd..23c90acb 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/494_builtin_sha256_reject_gas.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-57): Member "gas" not found or not visible after argument-dependent lookup in function () pure returns (bytes32) +// TypeError: (47-57): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol index b20255fb..5884e212 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/495_builtin_ripemd160_reject_gas.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function () pure returns (bytes20) +// TypeError: (47-60): Member "gas" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol index a58891d2..61e51eff 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/502_builtin_keccak256_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function () pure returns (bytes32) - did you forget the "payable" modifier? +// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol index 19d671ff..11141a9b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/503_builtin_sha256_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-59): Member "value" not found or not visible after argument-dependent lookup in function () pure returns (bytes32) - did you forget the "payable" modifier? +// TypeError: (47-59): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes32) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol index 38bb2cb6..d120f3dd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/504_builtin_ripemd160_reject_value.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function () pure returns (bytes20) - did you forget the "payable" modifier? +// TypeError: (47-62): Member "value" not found or not visible after argument-dependent lookup in function (bytes memory) pure returns (bytes20) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol b/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol index a6ee4bf1..c17d0849 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/single_non_bytes_arg.sol @@ -7,9 +7,6 @@ contract C { function g(bytes32) pure internal {} } // ---- -// Warning: (54-72): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (54-72): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. -// Warning: (85-100): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (85-100): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. -// Warning: (113-131): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (113-131): The provided argument of type uint256 is not implicitly convertible to expected type bytes memory. +// TypeError: (64-71): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (92-99): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. +// TypeError: (123-130): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol index f1b5606e..c97f588e 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol @@ -1,13 +1,13 @@ contract C { function f() public pure { - bool a = address(this).call(address(this).delegatecall, super); - bool b = address(this).delegatecall(log0, tx, mulmod); + bool a = address(this).call(abi.encode(address(this).delegatecall, super)); + bool b = address(this).delegatecall(abi.encode(log0, tx, mulmod)); a; b; } } // ---- -// TypeError: (80-106): This type cannot be encoded. -// TypeError: (108-113): This type cannot be encoded. -// TypeError: (160-164): This type cannot be encoded. -// TypeError: (166-168): This type cannot be encoded. -// TypeError: (170-176): This type cannot be encoded. +// TypeError: (91-117): This type cannot be encoded. +// TypeError: (119-124): This type cannot be encoded. +// TypeError: (183-187): This type cannot be encoded. +// TypeError: (189-191): This type cannot be encoded. +// TypeError: (193-199): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol index 05f5db0b..a1d3f5af 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol @@ -4,11 +4,10 @@ contract C { struct T { uint y; } T t; function f() public view { - bytes32 a = sha256(s, t); + bytes32 a = sha256(abi.encodePacked(s, t)); a; } } // ---- -// Warning: (132-144): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (139-140): This type cannot be encoded. -// TypeError: (142-143): This type cannot be encoded. +// TypeError: (156-157): This type cannot be encoded. +// TypeError: (159-160): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol index 977a7d73..38702825 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol @@ -6,12 +6,11 @@ contract C { struct T { uint y; } T t; function f() public view { - bytes32 a = sha256(s, t); + bytes32 a = sha256(abi.encodePacked(s, t)); a; } } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (167-179): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (174-175): This type cannot be encoded. -// TypeError: (177-178): This type cannot be encoded. +// TypeError: (191-192): This type cannot be encoded. +// TypeError: (194-195): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol index e46a9050..b50d4449 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol @@ -5,12 +5,13 @@ contract C { T t; enum A { X, Y } function f() public pure { - bool a = address(this).delegatecall(S, A, A.X, T, uint, uint[]); + bytes memory a = abi.encodePacked(S, A, A.X, T, uint, uint[]); + a; } } // ---- -// TypeError: (176-177): This type cannot be encoded. -// TypeError: (179-180): This type cannot be encoded. -// TypeError: (187-188): This type cannot be encoded. -// TypeError: (190-194): This type cannot be encoded. -// TypeError: (196-202): This type cannot be encoded. +// TypeError: (174-175): This type cannot be encoded. +// TypeError: (177-178): This type cannot be encoded. +// TypeError: (185-186): This type cannot be encoded. +// TypeError: (188-192): This type cannot be encoded. +// TypeError: (194-200): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/tight_packing_literals.sol index d6c7f0ba..be8482ff 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals.sol @@ -1,26 +1,8 @@ contract C { - function f() pure public returns (bytes32) { - return keccak256(1); - } - function h() pure public returns (bytes32) { - return sha256(1); - } - function j() pure public returns (bytes32) { - return ripemd160(1); - } function k() pure public returns (bytes) { return abi.encodePacked(1); } } // ---- -// Warning: (87-88): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (77-89): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (77-89): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (168-169): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (161-170): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (161-170): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (252-253): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. -// Warning: (242-254): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (242-254): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// Warning: (341-342): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (92-93): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_050.sol b/test/libsolidity/syntaxTests/tight_packing_literals_050.sol index b7557d2a..4e6210c6 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals_050.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals_050.sol @@ -1,34 +1,9 @@ pragma experimental "v0.5.0"; contract C { - function f() pure public returns (bytes32) { - return keccak256(1); - } - function g() pure public returns (bytes32) { - return sha3(1); - } - function h() pure public returns (bytes32) { - return sha256(1); - } - function j() pure public returns (bytes32) { - return ripemd160(1); - } function k() pure public returns (bytes) { return abi.encodePacked(1); } } // ---- -// TypeError: (117-118): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (107-119): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (107-119): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (191-198): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (196-197): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (191-198): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (191-198): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (277-278): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (270-279): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (270-279): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (361-362): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. -// TypeError: (351-363): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// TypeError: (351-363): The provided argument of type int_const 1 is not implicitly convertible to expected type bytes memory. -// TypeError: (450-451): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. +// TypeError: (122-123): Cannot perform packed encoding for a literal. Please convert it to an explicit type first. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol index 27665b52..7bbc36d0 100644 --- a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol +++ b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol @@ -1,13 +1,4 @@ contract C { - function f() pure public returns (bytes32) { - return keccak256(uint8(1)); - } - function h() pure public returns (bytes32) { - return sha256(uint8(1)); - } - function j() pure public returns (bytes32) { - return ripemd160(uint8(1)); - } function k() pure public returns (bytes) { return abi.encodePacked(uint8(1)); } @@ -16,9 +7,3 @@ contract C { } } // ---- -// Warning: (77-96): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (77-96): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (168-184): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (168-184): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. -// Warning: (256-275): This function only accepts a single "bytes" argument. Please use "abi.encodePacked(...)" or a similar function to encode the data. -// Warning: (256-275): The provided argument of type uint8 is not implicitly convertible to expected type bytes memory. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index dbefb8b6..e4be73c6 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -3,13 +3,13 @@ contract C { address(this).transfer(1); require(address(this).send(2)); selfdestruct(address(this)); - require(address(this).delegatecall()); - require(address(this).call()); + require(address(this).delegatecall("")); + require(address(this).call("")); } function g() pure public { bytes32 x = keccak256("abc"); bytes32 y = sha256("abc"); - address z = ecrecover(1, 2, 3, 4); + address z = ecrecover(bytes32(1), uint8(2), bytes32(3), bytes32(4)); require(true); assert(true); x; y; z; |