Skip to content

Commit 4a842ec

Browse files
authored
Merge pull request #4097 from ethereum/noPackedExceptForPacked
[BREAKING] call only takes a single argument and does not pad
2 parents ce4b233 + 92cb4ac commit 4a842ec

53 files changed

Lines changed: 357 additions & 351 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
### 0.5.0 (unreleased)
22

3+
How to update your code:
4+
* 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).
5+
* Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``.
6+
7+
38
Breaking Changes:
49
* ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding.
510
* 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:
2227
* Parser: Disallow trailing dots that are not followed by a number.
2328
* Type Checker: Disallow arithmetic operations for boolean variables.
2429
* Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size.
30+
* Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``.
2531
* 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.
2632
* Syntax Checker: Named return values in function types are an error.
2733

docs/abi-spec.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ would result in the JSON:
559559
Non-standard Packed Mode
560560
========================
561561

562-
Solidity supports a non-standard packed mode where:
562+
Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where:
563563

564564
- no :ref:`function selector <abi_function_selector>` is encoded,
565565
- 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
577577
and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without
578578
their length field. This means that the encoding is ambiguous as soon as there are two
579579
dynamically-sized elements.
580+
581+
Note that constants will be packed using the minimum number of bytes required to store them.
582+
This means that, for example, ``abi.encodePacked(0) == abi.encodePacked(uint8(0)) == hex"00"`` and
583+
``abi.encodePacked(0x12345678) == abi.encodePacked(uint32(0x12345678)) == hex"12345678"``.
584+
585+
If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``.

docs/contracts.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ This means that cyclic creation dependencies are impossible.
113113
{
114114
// Check some arbitrary condition.
115115
address tokenAddress = msg.sender;
116-
return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
116+
return (keccak256(abi.encodePacked(newOwner)) & 0xff) == (bytes20(tokenAddress) & 0xff);
117117
}
118118
}
119119

@@ -377,7 +377,7 @@ inheritable properties of contracts and may be overridden by derived contracts.
377377
/// The `return 7` statement assigns 7 to the return value but still
378378
/// executes the statement `locked = false` in the modifier.
379379
function f() public noReentrancy returns (uint) {
380-
require(msg.sender.call());
380+
require(msg.sender.call(""));
381381
return 7;
382382
}
383383
}
@@ -604,7 +604,7 @@ Like any function, the fallback function can execute complex operations as long
604604

605605
contract Caller {
606606
function callTest(Test test) public {
607-
test.call(0xabcdef01); // hash does not exist
607+
test.call(abi.encodeWithSignature("nonExistingFunction()"));
608608
// results in test.x becoming == 1.
609609

610610
// The following will not compile, but even

docs/miscellaneous.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ Global Variables
322322
- ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding <abi_packed_mode>` of the given arguments
323323
- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments
324324
starting from the second and prepends the given four-byte selector
325-
- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)```
325+
- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)```
326326
- ``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)``.
327327
- ``block.coinbase`` (``address``): current block miner's address
328328
- ``block.difficulty`` (``uint``): current block difficulty
@@ -343,10 +343,10 @@ Global Variables
343343
- ``revert()``: abort execution and revert state changes
344344
- ``revert(string message)``: abort execution and revert state changes providing an explanatory string
345345
- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks
346-
- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
347-
- ``sha3(...) returns (bytes32)``: an alias to ``keccak256``
348-
- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
349-
- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
346+
- ``keccak256(bytes memory) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the input
347+
- ``sha3(bytes memory) returns (bytes32)``: an alias to ``keccak256``
348+
- ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input
349+
- ``ripemd160(bytes memory) returns (bytes20)``: compute the RIPEMD-160 hash of the input
350350
- ``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
351351
- ``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.
352352
- ``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.

docs/security-considerations.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ as it uses ``call`` which forwards all remaining gas by default:
8686
mapping(address => uint) shares;
8787
/// Withdraw your share.
8888
function withdraw() public {
89-
if (msg.sender.call.value(shares[msg.sender])())
89+
if (msg.sender.call.value(shares[msg.sender])(""))
9090
shares[msg.sender] = 0;
9191
}
9292
}
@@ -140,7 +140,7 @@ Sending and Receiving Ether
140140
(for example in the "details" section in Remix).
141141

142142
- There is a way to forward more gas to the receiving contract using
143-
``addr.call.value(x)()``. This is essentially the same as ``addr.transfer(x)``,
143+
``addr.call.value(x)("")``. This is essentially the same as ``addr.transfer(x)``,
144144
only that it forwards all remaining gas and opens up the ability for the
145145
recipient to perform more expensive actions (and it only returns a failure code
146146
and does not automatically propagate the error). This might include calling back

docs/solidity-by-example.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,8 @@ high or low invalid bids.
428428
revealEnd = biddingEnd + _revealTime;
429429
}
430430

431-
/// Place a blinded bid with `_blindedBid` = keccak256(value,
432-
/// fake, secret).
431+
/// Place a blinded bid with `_blindedBid` =
432+
/// keccak256(abi.encodePacked(value, fake, secret)).
433433
/// The sent ether is only refunded if the bid is correctly
434434
/// revealed in the revealing phase. The bid is valid if the
435435
/// ether sent together with the bid is at least "value" and
@@ -470,7 +470,7 @@ high or low invalid bids.
470470
Bid storage bid = bids[msg.sender][i];
471471
(uint value, bool fake, bytes32 secret) =
472472
(_values[i], _fake[i], _secret[i]);
473-
if (bid.blindedBid != keccak256(value, fake, secret)) {
473+
if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
474474
// Bid was not actually revealed.
475475
// Do not refund deposit.
476476
continue;

docs/types.rst

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,27 +143,37 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c
143143
* ``call``, ``callcode`` and ``delegatecall``
144144

145145
Furthermore, to interface with contracts that do not adhere to the ABI,
146-
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.
146+
or to get more direct control over the encoding,
147+
the function ``call`` is provided which takes a single byte array as input.
148+
The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector``
149+
and ``abi.encodeWithSignature`` can be used to encode structured data.
147150

148-
::
151+
.. warning::
152+
All these functions are low-level functions and should be used with care.
153+
Specifically, any unknown contract might be malicious and if you call it, you
154+
hand over control to that contract which could in turn call back into
155+
your contract, so be prepared for changes to your state variables
156+
when the call returns. The regular way to interact with other contracts
157+
is to call a function on a contract object (``x.f()``).
149158

150-
address nameReg = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2;
151-
nameReg.call("register", "MyName");
152-
nameReg.call(bytes4(keccak256("fun(uint256)")), a);
159+
:: note::
160+
Previous versions of Solidity allowed these functions to receive
161+
arbitrary arguments and would also handle a first argument of type
162+
``bytes4`` differently. These edge cases were removed in version 0.5.0.
153163

154-
``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).
164+
``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.
155165

156166
It is possible to adjust the supplied gas with the ``.gas()`` modifier::
157167

158-
namReg.call.gas(1000000)("register", "MyName");
168+
namReg.call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName"));
159169

160170
Similarly, the supplied Ether value can be controlled too::
161171

162-
nameReg.call.value(1 ether)("register", "MyName");
172+
nameReg.call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName"));
163173

164174
Lastly, these modifiers can be combined. Their order does not matter::
165175

166-
nameReg.call.gas(1000000).value(1 ether)("register", "MyName");
176+
nameReg.call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName"));
167177

168178
.. note::
169179
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()``
184194
.. note::
185195
The use of ``callcode`` is discouraged and will be removed in the future.
186196

187-
.. warning::
188-
All these functions are low-level functions and should be used with care.
189-
Specifically, any unknown contract might be malicious and if you call it, you
190-
hand over control to that contract which could in turn call back into
191-
your contract, so be prepared for changes to your state variables
192-
when the call returns.
193-
194197
.. index:: byte array, bytes32
195198

196199

docs/units-and-global-variables.rst

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,16 @@ ABI Encoding Functions
100100
----------------------
101101

102102
- ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments
103-
- ``abi.encodePacked(...) returns (bytes)``: Performes packed encoding of the given arguments
103+
- ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding <abi_packed_mode>` of the given arguments
104104
- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments
105105
starting from the second and prepends the given four-byte selector
106-
- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)```
106+
- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)```
107107

108108
.. note::
109109
These encoding functions can be used to craft data for function calls without actually
110-
calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a more
111-
explicit way to compute ``keccak256(a, b)``, which will be deprecated in future
112-
versions.
110+
calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way
111+
to compute the hash of structured data (although be aware that it is possible to
112+
craft a "hash collision" using different inputs types).
113113

114114
See the documentation about the :ref:`ABI <ABI>` and the
115115
:ref:`tightly packed encoding <abi_packed_mode>` for details about the encoding.
@@ -139,34 +139,18 @@ Mathematical and Cryptographic Functions
139139
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.
140140
``mulmod(uint x, uint y, uint k) returns (uint)``:
141141
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.
142-
``keccak256(...) returns (bytes32)``:
143-
compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
144-
``sha256(...) returns (bytes32)``:
145-
compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
146-
``sha3(...) returns (bytes32)``:
142+
``keccak256(bytes memory) returns (bytes32)``:
143+
compute the Ethereum-SHA-3 (Keccak-256) hash of the input
144+
``sha256(bytes memory) returns (bytes32)``:
145+
compute the SHA-256 hash of the input
146+
``sha3(bytes memory) returns (bytes32)``:
147147
alias to ``keccak256``
148-
``ripemd160(...) returns (bytes20)``:
149-
compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
148+
``ripemd160(bytes memory) returns (bytes20)``:
149+
compute RIPEMD-160 hash of the input
150150
``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``:
151151
recover the address associated with the public key from elliptic curve signature or return zero on error
152152
(`example usage <https://ethereum.stackexchange.com/q/1777/222>`_)
153153

154-
In the above, "tightly packed" means that the arguments are concatenated without padding.
155-
This means that the following are all identical::
156-
157-
keccak256("ab", "c")
158-
keccak256("abc")
159-
keccak256(0x616263)
160-
keccak256(6382179)
161-
keccak256(97, 98, 99)
162-
163-
If padding is needed, explicit type conversions can be used: ``keccak256("\x00\x12")`` is the
164-
same as ``keccak256(uint16(0x12))``.
165-
166-
Note that constants will be packed using the minimum number of bytes required to store them.
167-
This means that, for example, ``keccak256(0) == keccak256(uint8(0))`` and
168-
``keccak256(0x12345678) == keccak256(uint32(0x12345678))``.
169-
170154
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.
171155

172156
.. index:: balance, send, transfer, call, callcode, delegatecall
@@ -181,12 +165,12 @@ Address Related
181165
send given amount of Wei to :ref:`address`, throws on failure, forwards 2300 gas stipend, not adjustable
182166
``<address>.send(uint256 amount) returns (bool)``:
183167
send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable
184-
``<address>.call(...) returns (bool)``:
185-
issue low-level ``CALL``, returns ``false`` on failure, forwards all available gas, adjustable
186-
``<address>.callcode(...) returns (bool)``:
187-
issue low-level ``CALLCODE``, returns ``false`` on failure, forwards all available gas, adjustable
188-
``<address>.delegatecall(...) returns (bool)``:
189-
issue low-level ``DELEGATECALL``, returns ``false`` on failure, forwards all available gas, adjustable
168+
``<address>.call(bytes memory) returns (bool)``:
169+
issue low-level ``CALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable
170+
``<address>.callcode(bytes memory) returns (bool)``:
171+
issue low-level ``CALLCODE`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable
172+
``<address>.delegatecall(bytes memory) returns (bool)``:
173+
issue low-level ``DELEGATECALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable
190174

191175
For more information, see the section on :ref:`address`.
192176

0 commit comments

Comments
 (0)