Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ Language Features:
Compiler Features:
* ethdebug: Experimental support for instructions and source locations under EOF.
* EVM: Set default EVM Version to `osaka`.
* DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`.
* Syntax Checker: Warn about deprecation of ABI coder v1.
* Syntax Checker: Warn about deprecation of virtual modifiers.
* Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`.
* Type Checker: Warn about deprecation of comparisons between variables of contract types.

Bugfixes:
* Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures.
Expand Down
5 changes: 3 additions & 2 deletions docs/assembly.rst
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,9 @@ of Solidity, you can use a special comment to annotate an assembly block as memo
...
}

Note that we will disallow the annotation via comment in a future breaking release; so, if you are not concerned with
backward-compatibility with older compiler versions, prefer using the dialect string.
.. warning::
The ``memory-safe-assembly`` special comment is deprecated and scheduled for removal.
In new code targeting recent compilers, use the assembly block annotation.

Advanced Safe Use of Memory
---------------------------
Expand Down
4 changes: 2 additions & 2 deletions docs/cheatsheet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ Members of ``address``
- ``<address>.staticcall(bytes memory) returns (bool, bytes memory)``: issue low-level ``STATICCALL`` with the given payload,
returns success condition and return data
- ``<address payable>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`,
returns ``false`` on failure
- ``<address payable>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure
returns ``false`` on failure (deprecated)
- ``<address payable>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure (deprecated)

.. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp
.. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin
Expand Down
12 changes: 8 additions & 4 deletions docs/common-patterns.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ you receive the funds of the person who is now the richest.
// Remember to zero the pending refund before
// sending to prevent reentrancy attacks
pendingWithdrawals[msg.sender] = 0;
payable(msg.sender).transfer(amount);
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success);
}
}
Expand All @@ -84,7 +85,8 @@ This is as opposed to the more intuitive sending pattern:
function becomeRichest() public payable {
if (msg.value <= mostSent) revert NotEnoughEther();
// This line can cause problems (explained below).
richest.transfer(msg.value);
(bool success, ) = richest.call{value: msg.value}("");
require(success);
richest = payable(msg.sender);
mostSent = msg.value;
}
Expand Down Expand Up @@ -210,8 +212,10 @@ restrictions highly readable.
revert NotEnoughEther();
_;
if (msg.value > amount)
payable(msg.sender).transfer(msg.value - amount);
if (msg.value > amount) {
(bool success, ) = payable(msg.sender).call{value: msg.value - amount}("");
require(success);
}
}
function forceOwnerChange(address newOwner)
Expand Down
6 changes: 5 additions & 1 deletion docs/contracts/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,10 @@ will consume more gas than the 2300 gas stipend:
- Calling an external function which consumes a large amount of gas
- Sending Ether

.. warning::
``send()`` and ``transfer()`` are deprecated and scheduled for removal.
See the section on :ref:`send <send-address-member>` and :ref:`transfer <balance-transfer-address-members>` for more information.

.. warning::
When Ether is sent directly to a contract (without a function call, i.e. sender uses ``send`` or ``transfer``)
but the receiving contract does not define a receive Ether function or a payable fallback function,
Expand All @@ -319,7 +323,6 @@ will consume more gas than the 2300 gas stipend:
not recommended, since the fallback is invoked and would not fail for interface confusions
on the part of the sender).


.. warning::
A contract without a receive Ether function can receive Ether as a
recipient of a *coinbase transaction* (aka *miner block reward*)
Expand Down Expand Up @@ -440,6 +443,7 @@ operations as long as there is enough gas passed on to it.

// If someone sends Ether to that contract,
// the transfer will fail, i.e. this returns false here.
// This will report a warning (deprecation)
return testPayable.send(2 ether);
}

Expand Down
9 changes: 7 additions & 2 deletions docs/contracts/inheritance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,8 @@ of the variable:

.. _modifier-overriding:

Modifier Overriding
===================
Modifier Overriding (deprecated)
================================

Function modifiers can override each other. This works in the same way as
:ref:`function overriding <function-overriding>` (except that there is no overloading for modifiers). The
Expand All @@ -392,6 +392,7 @@ and the ``override`` keyword must be used in the overriding modifier:

contract Base
{
// This will report a warning (deprecation)
modifier foo() virtual {_;}
}

Expand All @@ -411,11 +412,13 @@ explicitly:

contract Base1
{
// This will report a warning (deprecation)
modifier foo() virtual {_;}
}

contract Base2
{
// This will report a warning (deprecation)
modifier foo() virtual {_;}
}

Expand All @@ -424,6 +427,8 @@ explicitly:
modifier foo() override(Base1, Base2) {_;}
}

.. warning::
``virtual`` modifiers are deprecated and scheduled for removal.


.. index:: ! constructor
Expand Down
15 changes: 8 additions & 7 deletions docs/control-structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -692,16 +692,16 @@ and ``assert`` for internal error checking.
:force:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;
pragma solidity >=0.6.2 <0.9.0;

contract Sharer {
function sendHalf(address payable addr) public payable returns (uint balance) {
require(msg.value % 2 == 0, "Even value required.");
uint balanceBeforeTransfer = address(this).balance;
addr.transfer(msg.value / 2);
// Since transfer throws an exception on failure and
// cannot call back here, there should be no way for us to
// still have half of the Ether.
(bool success, ) = addr.call{value: msg.value / 2}("");
require(success);
// Since require will stop execution and revert if success is false,
// there should be no way for us to still have half of the Ether.
assert(address(this).balance == balanceBeforeTransfer - msg.value / 2);
return address(this).balance;
}
Expand Down Expand Up @@ -775,7 +775,8 @@ together with ``revert`` and the equivalent ``require``:
if (msg.sender != owner)
revert Unauthorized();

payable(msg.sender).transfer(address(this).balance);
(bool success, ) = payable(msg.sender).call{value: address(this).balance}("");
require(success);
}
}

Expand Down Expand Up @@ -914,4 +915,4 @@ in scope in the block that follows.
out-of-gas situation and not a deliberate error condition:
The caller always retains at least 1/64th of the gas in a call and thus
even if the called contract goes out of gas, the caller still
has some gas left.
has some gas left.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What changed here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No clue, maybe it needs a rebase.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe it's a newline at the end of the file.

21 changes: 13 additions & 8 deletions docs/examples/blind-auction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,14 @@ to receive their Ether - contracts cannot activate themselves.
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
// before `send` returns.
// before `call` returns.
pendingReturns[msg.sender] = 0;

// msg.sender is not of type `address payable` and must be
// explicitly converted using `payable(msg.sender)` in order
// use the member function `send()`.
if (!payable(msg.sender).send(amount)) {
// use the member function `call()`.
(bool success, ) = payable(msg.sender).call{value: amount}("");
if (!success) {
// No need to call throw here, just reset the amount owing
pendingReturns[msg.sender] = amount;
return false;
Expand Down Expand Up @@ -160,7 +161,8 @@ to receive their Ether - contracts cannot activate themselves.
emit AuctionEnded(highestBidder, highestBid);

// 3. Interaction
beneficiary.transfer(highestBid);
(bool success, ) = beneficiary.call{value: highestBid}("");
require(success);
}
}

Expand Down Expand Up @@ -310,7 +312,8 @@ invalid bids.
// the same deposit.
bidToCheck.blindedBid = bytes32(0);
}
payable(msg.sender).transfer(refund);
(bool success, ) = payable(msg.sender).call{value: refund}("");
require(success);
}

/// Withdraw a bid that was overbid.
Expand All @@ -319,11 +322,12 @@ invalid bids.
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
// before `transfer` returns (see the remark above about
// before `call` returns (see the remark above about
// conditions -> effects -> interaction).
pendingReturns[msg.sender] = 0;

payable(msg.sender).transfer(amount);
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success);
}
}

Expand All @@ -336,7 +340,8 @@ invalid bids.
if (ended) revert AuctionEndAlreadyCalled();
emit AuctionEnded(highestBidder, highestBid);
ended = true;
beneficiary.transfer(highestBid);
(bool success, ) = beneficiary.call{value: highestBid}("");
require(success);
}

// This is an "internal" function which means that it
Expand Down
15 changes: 10 additions & 5 deletions docs/examples/micropayment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ The full contract
// this recreates the message that was signed on the client
bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this)));
require(recoverSigner(message, signature) == owner);
payable(msg.sender).transfer(amount);
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success);
}
/// freeze the contract and reclaim the leftover funds.
Expand All @@ -195,7 +196,8 @@ The full contract
{
require(msg.sender == owner);
freeze();
payable(msg.sender).transfer(address(this).balance);
(bool success, ) = payable(msg.sender).call{value: address(this).balance}("");
require(success);
}
/// signature methods.
Expand Down Expand Up @@ -406,9 +408,11 @@ The full contract
require(msg.sender == recipient);
require(isValidSignature(amount, signature));
recipient.transfer(amount);
(bool success, ) = recipient.call{value: amount}("");
require(success);
freeze();
sender.transfer(address(this).balance);
(success, ) = sender.call{value: address(this).balance}("");
require(success);
}
/// the sender can extend the expiration at any time
Expand All @@ -430,7 +434,8 @@ The full contract
{
require(block.timestamp >= expiration);
freeze();
sender.transfer(address(this).balance);
(bool success, ) = sender.call{value: address(this).balance}("");
require(success);
}
function isValidSignature(uint256 amount, bytes memory signature)
Expand Down
15 changes: 9 additions & 6 deletions docs/examples/safe-remote.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ you can use state machine-like constructs inside a contract.
{
emit Aborted();
state = State.Inactive;
// We use transfer here directly. It is
// We use call here directly. It is
// reentrancy-safe, because it is the
// last call in this function and we
// already changed the state.
seller.transfer(address(this).balance);
(bool success, ) = seller.call{value: address(this).balance}("");
require(success);
}

/// Confirm the purchase as buyer.
Expand All @@ -124,11 +125,12 @@ you can use state machine-like constructs inside a contract.
{
emit ItemReceived();
// It is important to change the state first because
// otherwise, the contracts called using `send` below
// otherwise, the contracts called using `call` below
// can call in again here.
state = State.Release;

buyer.transfer(value);
(bool success, ) = buyer.call{value: value}("");
require(success);
}

/// This function refunds the seller, i.e.
Expand All @@ -140,10 +142,11 @@ you can use state machine-like constructs inside a contract.
{
emit SellerRefunded();
// It is important to change the state first because
// otherwise, the contracts called using `send` below
// otherwise, the contracts called using `call` below
// can call in again here.
state = State.Inactive;

seller.transfer(3 * value);
(bool success, ) = seller.call{value: 3 * value}("");
require(success);
}
}
8 changes: 6 additions & 2 deletions docs/layout-of-source-files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,14 @@ select between the two implementations of the ABI encoder and decoder.
The new ABI coder (v2) is able to encode and decode arbitrarily nested
arrays and structs. Apart from supporting more types, it involves more extensive
validation and safety checks, which may result in higher gas costs, but also heightened
security. It is considered
non-experimental as of Solidity 0.6.0 and it is enabled by default starting
security.
It is considered non-experimental as of Solidity 0.6.0 and it is enabled by default starting
with Solidity 0.8.0. The old ABI coder can still be selected using ``pragma abicoder v1;``.

.. warning::
The ABI coder v1 is deprecated and scheduled for removal.
Use ABI coder v2 instead.

The set of types supported by the new encoder is a strict superset of
the ones supported by the old one. Contracts that use it can interact with ones
that do not without limitations. The reverse is possible only as long as the
Expand Down
14 changes: 9 additions & 5 deletions docs/security-considerations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ To give an example, the following code contains a bug (it is just a snippet and
mapping(address => uint) shares;
/// Withdraw your share.
function withdraw() public {
// This will report a warning (deprecation)
if (payable(msg.sender).send(shares[msg.sender]))
shares[msg.sender] = 0;
}
Expand All @@ -76,7 +77,7 @@ Ether transfer can always include code execution,
so the recipient could be a contract that calls back into ``withdraw``.
This would let it get multiple refunds and, basically, retrieve all the Ether in the contract.
In particular, the following contract will allow an attacker to refund multiple times
as it uses ``call`` which forwards all remaining gas by default:
as it uses ``call`` which does not limit the amount of gas that is forwarded by default:

.. code-block:: solidity

Expand All @@ -100,7 +101,7 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo
.. code-block:: solidity

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
pragma solidity >=0.6.2 <0.9.0;

contract Fund {
/// @dev Mapping of ether shares of the contract.
Expand All @@ -109,7 +110,8 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo
function withdraw() public {
uint share = shares[msg.sender];
shares[msg.sender] = 0;
payable(msg.sender).transfer(share);
(bool success, ) = payable(msg.sender).call{value: share}("");
require(success);
}
}

Expand Down Expand Up @@ -158,8 +160,9 @@ 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)``, only that it forwards all remaining gas
and opens up the ability for the recipient to perform more expensive actions
This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas,
subject to additional limits imposed by some EVM versions (such as the `63/64th rule <https://eips.ethereum.org/EIPS/eip-150>`_
introduced by ``tangerineWhistle``), and opens up the ability for the recipient to perform more expensive actions
(and it returns a failure code instead of automatically propagating the error).
This might include calling back into the sending contract or other state changes you might not have thought of.
So it allows for great flexibility for honest users but also for malicious actors.
Expand Down Expand Up @@ -255,6 +258,7 @@ Let's say you have a wallet contract like this:
function transferTo(address payable dest, uint amount) public {
// THE BUG IS RIGHT HERE, you must use msg.sender instead of tx.origin
require(tx.origin == owner);
// This will report a warning (deprecation)
dest.transfer(amount);
}
}
Expand Down
Loading