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 /docs | |
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
Diffstat (limited to 'docs')
-rw-r--r-- | docs/abi-spec.rst | 8 | ||||
-rw-r--r-- | docs/contracts.rst | 6 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 10 | ||||
-rw-r--r-- | docs/security-considerations.rst | 4 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 6 | ||||
-rw-r--r-- | docs/types.rst | 35 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 52 |
7 files changed, 57 insertions, 64 deletions
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`. |