From 9bd778d72872ad3992496fd3cf3b51c0f5073ce6 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Thu, 3 Dec 2020 22:33:58 +0100 Subject: [PATCH 1/5] Make msg.sender and tx.origin have type address Previously both of them had type address payable. The idea is that anything that is not know to be payable should be non-payable. --- docs/cheatsheet.rst | 4 ++-- libsolidity/ast/Types.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index ef24ebcbd..22ca5cc8e 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -90,10 +90,10 @@ Global Variables - ``block.timestamp`` (``uint``): current block timestamp - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes``): complete calldata -- ``msg.sender`` (``address payable``): sender of the message (current call) +- ``msg.sender`` (``address``): sender of the message (current call) - ``msg.value`` (``uint``): number of wei sent with the message - ``tx.gasprice`` (``uint``): gas price of the transaction -- ``tx.origin`` (``address payable``): sender of the transaction (full call chain) +- ``tx.origin`` (``address``): sender of the transaction (full call chain) - ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) - ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index e85ff5157..e409e6aa1 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3838,7 +3838,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const }); case Kind::Message: return MemberList::MemberMap({ - {"sender", TypeProvider::payableAddress()}, + {"sender", TypeProvider::address()}, {"gas", TypeProvider::uint256()}, {"value", TypeProvider::uint256()}, {"data", TypeProvider::array(DataLocation::CallData)}, @@ -3846,7 +3846,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const }); case Kind::Transaction: return MemberList::MemberMap({ - {"origin", TypeProvider::payableAddress()}, + {"origin", TypeProvider::address()}, {"gasprice", TypeProvider::uint256()} }); case Kind::ABI: From e1a95cfd423c9fc3a048f57854d24d20413d9b9d Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Thu, 3 Dec 2020 22:36:56 +0100 Subject: [PATCH 2/5] Disallow conversions from literals to payable address To get a payable address, one has to go through address. For example, `payable(address(0))`. --- libsolidity/analysis/TypeChecker.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7de86ef5c..0b96fdb6d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1768,7 +1768,10 @@ TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( if (addressType->stateMutability() != StateMutability::Payable) { bool payable = false; - if (argType->category() != Type::Category::Address) + if ( + argType->category() != Type::Category::Address && + argType->category() != Type::Category::RationalNumber + ) payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress()); resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address(); } @@ -3314,7 +3317,7 @@ void TypeChecker::endVisit(Literal const& _literal) if (_literal.looksLikeAddress()) { // Assign type here if it even looks like an address. This prevents double errors for invalid addresses - _literal.annotation().type = TypeProvider::payableAddress(); + _literal.annotation().type = TypeProvider::address(); string msg; if (_literal.valueWithoutUnderscores().length() != 42) // "0x" + 40 hex digits From 88c99a753881794d718e3ca4bf864a55e0f2cafd Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Thu, 3 Dec 2020 23:05:05 +0100 Subject: [PATCH 3/5] Tests/Docs: changing type of msg.sender and tx.origin into address And also making the type of address(literal) as non-payable address. --- Changelog.md | 2 ++ docs/080-breaking-changes.rst | 13 +++++++++++++ docs/common-patterns.rst | 10 +++++----- docs/contracts/function-modifiers.rst | 2 +- docs/contracts/inheritance.rst | 6 +++--- docs/examples/blind-auction.rst | 6 +++--- docs/examples/micropayment.rst | 6 +++--- docs/examples/safe-remote.rst | 4 ++-- docs/security-considerations.rst | 10 +++++----- docs/types/value-types.rst | 15 ++++++--------- test/compilationTests/corion/ico.sol | 8 ++++---- test/compilationTests/corion/premium.sol | 2 +- test/compilationTests/corion/provider.sol | 8 ++++---- test/compilationTests/corion/publisher.sol | 2 +- test/compilationTests/corion/schelling.sol | 6 +++--- test/compilationTests/corion/token.sol | 12 ++++++------ .../compilationTests/gnosis/Tokens/EtherToken.sol | 2 +- test/contracts/AuctionRegistrar.cpp | 6 +++--- test/externalTests/solc-js/DAO/DAO.sol | 12 ++++++------ test/libsolidity/ASTJSON/address_payable.json | 4 ++-- .../inlineAssembly/constant_access.sol | 2 +- .../constant_access_referencing.sol | 4 ++-- .../syntaxTests/deprecated_functions.sol | 2 +- .../memberLookup/msg_sender_non_payable_send.sol | 7 +++++++ .../msg_sender_non_payable_transfer.sol | 7 +++++++ .../memberLookup/tx_origin_non_payable_send.sol | 7 +++++++ .../tx_origin_non_payable_transfer.sol | 7 +++++++ .../346_unused_return_value_send.sol | 2 +- .../405_address_checksum_type_deduction.sol | 2 +- .../parsing/address_payable_constant.sol | 2 +- .../types/address/address_binary_operators.sol | 8 ++++---- .../types/address/address_constant.sol | 2 +- .../types/address/address_constant_assignment.sol | 4 ++-- .../types/address/address_literal_to_payable.sol | 9 +++++++++ .../address/address_literal_to_payable_err.sol | 9 +++++++++ .../address_payable_internal_overload_payable.sol | 2 +- .../address/address_to_contract_implicitly.sol | 2 +- .../address_to_contract_payable_fallback.sol | 2 +- .../types/address/address_to_contract_receive.sol | 2 +- .../types/address/address_tuple_fail.sol | 2 +- .../types/address/address_tuple_fine.sol | 4 ++-- .../types/address/literal_to_address_call.sol | 5 +++++ .../types/address/literal_to_payable_address.sol | 10 +++++----- .../address/literal_to_payable_address_err.sol | 7 +++++++ .../syntaxTests/types/strict_explicit_err.sol | 2 +- 45 files changed, 159 insertions(+), 89 deletions(-) create mode 100644 test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_send.sol create mode 100644 test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_transfer.sol create mode 100644 test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_send.sol create mode 100644 test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_transfer.sol create mode 100644 test/libsolidity/syntaxTests/types/address/address_literal_to_payable.sol create mode 100644 test/libsolidity/syntaxTests/types/address/address_literal_to_payable_err.sol create mode 100644 test/libsolidity/syntaxTests/types/address/literal_to_address_call.sol create mode 100644 test/libsolidity/syntaxTests/types/address/literal_to_payable_address_err.sol diff --git a/Changelog.md b/Changelog.md index 870060019..6f9d88406 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,6 +27,8 @@ Breaking Changes: * Type System: Support ``address(...).codehash`` to retrieve the codehash of an account. * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * View Pure Checker: Mark ``chainid`` as view. + * Type System: Address-literals and explicit conversions of integer-literals into ``address `` have type ``address`` instead of ``address payable``. + * Type System: The global variables ``tx.origin`` and ``msg.sender`` have type ``address`` instead of ``address payable``. * Yul: Disallow the use of reserved identifiers, such as EVM instructions, even if they are not available in the given dialect / EVM version. Language Features: diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index e8d03a3e1..7143cad15 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -65,6 +65,13 @@ This section lists changes that might cause existing contracts to not compile an with ``type(uint).max``. 3. Explicit conversions between literals and enums are only allowed if the literal can represent a value in the enum. + 4. Explicit conversions between literals and ``address`` type (e.g. ``address(literal)``) have the + type ``address`` instead of ``address payable``. One can get a payable address type by using an + explicit conversion, i.e., ``payable(literal)``. + +* :ref:`Address literals` have the type ``address`` instead of ``address + payable``. They can be converted to ``address payable`` by using an explicit conversion, e.g. + ``payable(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF)``. * There are new restrictions on explicit type conversions. The conversion is only allowed when there is at most one change in sign, width or type-category (``int``, ``address``, ``bytesNN``, etc.). @@ -105,6 +112,12 @@ This section lists changes that might cause existing contracts to not compile an * Remove support for the ``\b``, ``\f``, and ``\v`` escape sequences in code. They can still be inserted via hexadecimal escapes, e.g. ``\x08``, ``\x0c``, and ``\x0b``, respectively. +* The global variables ``tx.origin`` and ``msg.sender`` have the type ``address`` instead of + ``address payable``. One can convert them into ``address payable`` by using an explicit + conversion, i.e., ``payable(tx.origin)`` or ``payable(msg.sender)``. + + This change was done since the compiler cannot determine whether or not these addresses + are payable or not, so it now requires an explicit conversion to make this requirement visible. * The ``chainid`` builtin in inline assembly is now considered ``view`` instead of ``pure``. diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index 07886b003..cf122cd67 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -53,7 +53,7 @@ you receive the funds of the person who is now the richest. // Remember to zero the pending refund before // sending to prevent re-entrancy attacks pendingWithdrawals[msg.sender] = 0; - msg.sender.transfer(amount); + payable(msg.sender).transfer(amount); } } @@ -69,7 +69,7 @@ This is as opposed to the more intuitive sending pattern: uint public mostSent; constructor() payable { - richest = msg.sender; + richest = payable(msg.sender); mostSent = msg.value; } @@ -77,7 +77,7 @@ This is as opposed to the more intuitive sending pattern: require(msg.value > mostSent, "Not enough money sent."); // This line can cause problems (explained below). richest.transfer(msg.value); - richest = msg.sender; + richest = payable(msg.sender); mostSent = msg.value; } } @@ -124,7 +124,7 @@ restrictions highly readable. :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.22 <0.9.0; + pragma solidity >=0.6.0 <0.9.0; contract AccessRestriction { // These will be assigned at the construction @@ -192,7 +192,7 @@ restrictions highly readable. ); _; if (msg.value > _amount) - msg.sender.transfer(msg.value - _amount); + payable(msg.sender).transfer(msg.value - _amount); } function forceOwnerChange(address _newOwner) diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index 301b900c6..1eb6e28a1 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -21,7 +21,7 @@ if they are marked ``virtual``. For details, please see pragma solidity >0.7.0 <0.9.0; contract owned { - constructor() { owner = msg.sender; } + constructor() { owner = payable(msg.sender); } address payable owner; // This contract only defines a modifier but does not use diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index cd3d127fd..c18cfd418 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -43,7 +43,7 @@ Details are given in the following example. contract Owned { - constructor() { owner = msg.sender; } + constructor() { owner = payable(msg.sender); } address payable owner; } @@ -130,7 +130,7 @@ seen in the following example:: pragma solidity >=0.7.0 <0.9.0; contract owned { - constructor() { owner = msg.sender; } + constructor() { owner = payable(msg.sender); } address payable owner; } @@ -160,7 +160,7 @@ explicitly in the final override, but this function will bypass pragma solidity >=0.7.0 <0.9.0; contract owned { - constructor() { owner = msg.sender; } + constructor() { owner = payable(msg.sender); } address payable owner; } diff --git a/docs/examples/blind-auction.rst b/docs/examples/blind-auction.rst index 0bb4abec0..fec9c279b 100644 --- a/docs/examples/blind-auction.rst +++ b/docs/examples/blind-auction.rst @@ -114,7 +114,7 @@ to receive their money - contracts cannot activate themselves. // before `send` returns. pendingReturns[msg.sender] = 0; - if (!msg.sender.send(amount)) { + if (!payable(msg.sender).send(amount)) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; @@ -280,7 +280,7 @@ invalid bids. // the same deposit. bidToCheck.blindedBid = bytes32(0); } - msg.sender.transfer(refund); + payable(msg.sender).transfer(refund); } /// Withdraw a bid that was overbid. @@ -293,7 +293,7 @@ invalid bids. // conditions -> effects -> interaction). pendingReturns[msg.sender] = 0; - msg.sender.transfer(amount); + payable(msg.sender).transfer(amount); } } diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 67426360d..8bfa764f8 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -159,13 +159,13 @@ The full contract require(recoverSigner(message, signature) == owner); - msg.sender.transfer(amount); + payable(msg.sender).transfer(amount); } /// destroy the contract and reclaim the leftover funds. function shutdown() public { require(msg.sender == owner); - selfdestruct(msg.sender); + selfdestruct(payable(msg.sender)); } /// signature methods. @@ -347,7 +347,7 @@ The full contract constructor (address payable _recipient, uint256 duration) payable { - sender = msg.sender; + sender = payable(msg.sender); recipient = _recipient; expiration = block.timestamp + duration; } diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst index 15e1bdee0..6b46007fd 100644 --- a/docs/examples/safe-remote.rst +++ b/docs/examples/safe-remote.rst @@ -74,7 +74,7 @@ you can use state machine-like constructs inside a contract. // Division will truncate if it is an odd number. // Check via multiplication that it wasn't an odd number. constructor() payable { - seller = msg.sender; + seller = payable(msg.sender); value = msg.value / 2; require((2 * value) == msg.value, "Value has to be even."); } @@ -107,7 +107,7 @@ you can use state machine-like constructs inside a contract. payable { emit PurchaseConfirmed(); - buyer = msg.sender; + buyer = payable(msg.sender); state = State.Locked; } diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index fade26134..7bb556c82 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -59,7 +59,7 @@ complete contract): :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.9.0; + pragma solidity >=0.6.0 <0.9.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract Fund { @@ -67,7 +67,7 @@ complete contract): mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - if (msg.sender.send(shares[msg.sender])) + if (payable(msg.sender).send(shares[msg.sender])) shares[msg.sender] = 0; } } @@ -103,7 +103,7 @@ outlined further below: :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.11 <0.9.0; + pragma solidity >=0.6.0 <0.9.0; contract Fund { /// @dev Mapping of ether shares of the contract. @@ -112,7 +112,7 @@ outlined further below: function withdraw() public { uint share = shares[msg.sender]; shares[msg.sender] = 0; - msg.sender.transfer(share); + payable(msg.sender).transfer(share); } } @@ -230,7 +230,7 @@ Now someone tricks you into sending Ether to the address of this attack wallet: address payable owner; constructor() { - owner = msg.sender; + owner = payable(msg.sender); } receive() external payable { diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 4629e5e36..0905820aa 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -188,25 +188,22 @@ Type conversions: Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` must be explicit via ``payable(
)``. -:ref:`Address literals` can be implicitly converted to ``address payable``. - Explicit conversions to and from ``address`` are allowed for integers, integer literals, ``bytes20`` and contract types with the following caveat: The result of a conversion of the form ``address(x)`` has the type ``address payable``, if ``x`` is of integer or fixed bytes type, -a literal or a contract with a receive or payable fallback function. +or a contract with a receive or payable fallback function. If ``x`` is a contract without a receive or payable fallback function, then ``address(x)`` will be of type ``address``. +Similarly, if ``x`` is a literal, then ``address(x)`` will also be of type ``address``. In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type. Only expressions of type ``address`` can be converted to type ``address payable`` via ``payable(
)``. .. note:: - It might very well be that you do not need to care about the distinction between ``address`` - and ``address payable`` and just use ``address`` everywhere. For example, - if you are using the :ref:`withdrawal pattern`, you can (and should) store the - address itself as ``address``, because you invoke the ``transfer`` function on - ``msg.sender``, which is an ``address payable``. + If you need a variable of type ``address`` and plan to send Ether to it, then + declare its type as ``address payable`` to make this requirement visible. Also, + try to make this distinction or conversion as early as possible. Operators: @@ -410,7 +407,7 @@ Address Literals ---------------- Hexadecimal literals that pass the address checksum test, for example -``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address payable`` type. +``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address`` type. Hexadecimal literals that are between 39 and 41 digits long and do not pass the checksum test produce an error. You can prepend (for integer types) or append (for bytesNN types) zeros to remove the error. diff --git a/test/compilationTests/corion/ico.sol b/test/compilationTests/corion/ico.sol index a0c31cbc3..36510ea65 100644 --- a/test/compilationTests/corion/ico.sol +++ b/test/compilationTests/corion/ico.sol @@ -65,7 +65,7 @@ contract ico is safeMath { icoExchangeRate = exchangeRate; icoExchangeRateSetBlock = block.number + exchangeRateDelay; icoEtcPriceAddr = priceSet; - owner = msg.sender; + owner = payable(msg.sender); if ( startBlockNum > 0 ) { require( startBlockNum >= block.number ); startBlock = startBlockNum; @@ -272,7 +272,7 @@ contract ico is safeMath { require( brought[msg.sender].eth > 0 ); uint256 _val = brought[msg.sender].eth * 90 / 100; delete brought[msg.sender]; - require( msg.sender.send(_val) ); + require( payable(msg.sender).send(_val) ); } receive () external payable { @@ -281,7 +281,7 @@ contract ico is safeMath { If they call the contract without any function then this process will be taken place. */ require( isICO() ); - require( buy(msg.sender, address(0x00)) ); + require( buy(payable(msg.sender), address(0x00)) ); } function buy(address payable beneficiaryAddress, address affilateAddress) public payable returns (bool success) { @@ -300,7 +300,7 @@ contract ico is safeMath { @affilateAddress The address of the person who offered who will get the referral reward. It can not be equal with the beneficiaryAddress. */ require( isICO() ); - if ( beneficiaryAddress == address(0x00)) { beneficiaryAddress = msg.sender; } + if ( beneficiaryAddress == address(0x00)) { beneficiaryAddress = payable(msg.sender); } if ( beneficiaryAddress == affilateAddress ) { affilateAddress = address(0x00); } diff --git a/test/compilationTests/corion/premium.sol b/test/compilationTests/corion/premium.sol index 7777530bb..8603b9590 100644 --- a/test/compilationTests/corion/premium.sol +++ b/test/compilationTests/corion/premium.sol @@ -19,7 +19,7 @@ contract ptokenDB is tokenDB {} */ contract premium is module, safeMath { function replaceModule(address payable addr) external override returns (bool success) { - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); require( db.replaceOwner(addr) ); super._replaceModule(addr); return true; diff --git a/test/compilationTests/corion/provider.sol b/test/compilationTests/corion/provider.sol index 1e2d308a1..524390b2e 100644 --- a/test/compilationTests/corion/provider.sol +++ b/test/compilationTests/corion/provider.sol @@ -10,7 +10,7 @@ contract provider is module, safeMath, announcementTypes { module callbacks */ function connectModule() external override returns (bool success) { - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); super._connectModule(); (bool _success, uint256 currentSchellingRound) = moduleHandler(moduleHandlerAddress).getCurrentSchellingRoundID(); require( _success ); @@ -26,7 +26,7 @@ contract provider is module, safeMath, announcementTypes { @value amount @bool Was the function successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); transferEvent_(from, value, true); transferEvent_(to, value, false); return true; @@ -41,7 +41,7 @@ contract provider is module, safeMath, announcementTypes { @reward token emission @bool Was the function successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); globalFunds[roundID].reward = reward; globalFunds[roundID].supply = globalFunds[roundID-1].supply; currentSchellingRound = roundID; @@ -133,7 +133,7 @@ contract provider is module, safeMath, announcementTypes { @a Type of the setting @b value */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); if ( a == announcementType.providerPublicFunds ) { minFundsForPublic = b; } else if ( a == announcementType.providerPrivateFunds ) { minFundsForPrivate = b; } else if ( a == announcementType.providerPrivateClientLimit ) { privateProviderLimit = b; } diff --git a/test/compilationTests/corion/publisher.sol b/test/compilationTests/corion/publisher.sol index ec8ce33bc..311e8d92e 100644 --- a/test/compilationTests/corion/publisher.sol +++ b/test/compilationTests/corion/publisher.sol @@ -14,7 +14,7 @@ contract publisher is announcementTypes, module, safeMath { Transaction completed. This function is available only for moduleHandler If a transaction is carried out from or to an address which participated in the objection of an announcement, its objection purport is automatically set */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); uint256 announcementID; uint256 a; // need reverse lookup diff --git a/test/compilationTests/corion/schelling.sol b/test/compilationTests/corion/schelling.sol index bbb16e250..2503748b8 100644 --- a/test/compilationTests/corion/schelling.sol +++ b/test/compilationTests/corion/schelling.sol @@ -136,7 +136,7 @@ contract schelling is module, announcementTypes, schellingVars { module callbacks */ function replaceModule(address payable addr) external override returns (bool) { - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); require( db.replaceOwner(addr) ); super._replaceModule(addr); return true; @@ -151,7 +151,7 @@ contract schelling is module, announcementTypes, schellingVars { @value Amount @bool Was the transaction successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); if ( to == address(this) ) { uint256 currentRound = getCurrentRound(); schellingVars._rounds memory round = getRound(currentRound); @@ -271,7 +271,7 @@ contract schelling is module, announcementTypes, schellingVars { @a Sort of configuration @b Value */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); if ( a == announcementType.schellingRoundBlockDelay ) { roundBlockDelay = b; } else if ( a == announcementType.schellingCheckRounds ) { interestCheckRounds = uint8(b); } else if ( a == announcementType.schellingCheckAboves ) { interestCheckAboves = uint8(b); } diff --git a/test/compilationTests/corion/token.sol b/test/compilationTests/corion/token.sol index 865372d5f..58c3e8cb4 100644 --- a/test/compilationTests/corion/token.sol +++ b/test/compilationTests/corion/token.sol @@ -22,7 +22,7 @@ contract token is safeMath, module, announcementTypes { module callbacks */ function replaceModule(address payable addr) external override returns (bool success) { - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); require( db.replaceOwner(addr) ); super._replaceModule(addr); return true; @@ -255,7 +255,7 @@ contract token is safeMath, module, announcementTypes { @success Was the Function successful? */ bytes memory _data; - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); _transfer( from, to, amount, fee); emit Transfer(from, to, amount, _data); return true; @@ -353,7 +353,7 @@ contract token is safeMath, module, announcementTypes { @success Was the Function successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); _processTransactionFee(owner, value); return true; } @@ -412,7 +412,7 @@ contract token is safeMath, module, announcementTypes { @success Was the Function successful? */ - require( super.isModuleHandler(msg.sender) || msg.sender == icoAddr ); + require( super.isModuleHandler(payable(msg.sender)) || msg.sender == icoAddr ); _mint(owner, value); return true; } @@ -441,7 +441,7 @@ contract token is safeMath, module, announcementTypes { @success Was the Function successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); _burn(owner, value); return true; } @@ -502,7 +502,7 @@ contract token is safeMath, module, announcementTypes { @success Was the Function successful? */ - require( super.isModuleHandler(msg.sender) ); + require( super.isModuleHandler(payable(msg.sender)) ); if ( aType == announcementType.transactionFeeRate ) { transactionFeeRate = value; } else if ( aType == announcementType.transactionFeeMin ) { transactionFeeMin = value; } else if ( aType == announcementType.transactionFeeMax ) { transactionFeeMax = value; } diff --git a/test/compilationTests/gnosis/Tokens/EtherToken.sol b/test/compilationTests/gnosis/Tokens/EtherToken.sol index 987b62c65..8552c72be 100644 --- a/test/compilationTests/gnosis/Tokens/EtherToken.sol +++ b/test/compilationTests/gnosis/Tokens/EtherToken.sol @@ -41,7 +41,7 @@ contract EtherToken is StandardToken { // Balance covers value balances[msg.sender] = balances[msg.sender].sub(value); totalTokens = totalTokens.sub(value); - msg.sender.transfer(value); + payable(msg.sender).transfer(value); emit Withdrawal(msg.sender, value); } } diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 22ac44f3e..dba13ee6d 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -43,7 +43,7 @@ namespace solidity::frontend::test namespace { static char const* registrarCode = R"DELIMITER( -pragma solidity >=0.4.0 <0.9.0; +pragma solidity >=0.7.0 <0.9.0; abstract contract NameRegister { function addr(string memory _name) public virtual view returns (address o_owner); @@ -143,12 +143,12 @@ contract GlobalRegistrar is Registrar, AuctionSystem { { if (block.timestamp < m_toRecord[_name].renewalDate) revert(); - bid(_name, msg.sender, msg.value); + bid(_name, payable(msg.sender), msg.value); } else { Record storage record = m_toRecord[_name]; if (record.owner != 0x0000000000000000000000000000000000000000) revert(); - m_toRecord[_name].owner = msg.sender; + m_toRecord[_name].owner = payable(msg.sender); emit Changed(_name); } } diff --git a/test/externalTests/solc-js/DAO/DAO.sol b/test/externalTests/solc-js/DAO/DAO.sol index 56e50d23d..c519bf70d 100644 --- a/test/externalTests/solc-js/DAO/DAO.sol +++ b/test/externalTests/solc-js/DAO/DAO.sol @@ -391,7 +391,7 @@ contract DAO is DAOInterface, Token, TokenCreation { receive() external payable override(DAOInterface, TokenCreation) { if (block.timestamp < closingTime + creationGracePeriod && msg.sender != address(extraBalance)) - createTokenProxy(msg.sender); + createTokenProxy(payable(msg.sender)); else receiveEther(); } @@ -459,7 +459,7 @@ contract DAO is DAOInterface, Token, TokenCreation { p.newCurator = _newCurator; if (_newCurator) p.splitData.push(); - p.creator = msg.sender; + p.creator = payable(msg.sender); p.proposalDeposit = msg.value; sumOfProposalDeposits += msg.value; @@ -663,7 +663,7 @@ contract DAO is DAOInterface, Token, TokenCreation { uint fundsToBeMoved = (balances[msg.sender] * p.splitData[0].splitBalance) / p.splitData[0].totalSupply; - if (p.splitData[0].newDAO.createTokenProxy{value: fundsToBeMoved}(msg.sender) == false) + if (p.splitData[0].newDAO.createTokenProxy{value: fundsToBeMoved}(payable(msg.sender)) == false) revert(); @@ -687,7 +687,7 @@ contract DAO is DAOInterface, Token, TokenCreation { // Burn DAO Tokens emit Transfer(msg.sender, 0x0000000000000000000000000000000000000000, balances[msg.sender]); - withdrawRewardFor(msg.sender); // be nice, and get his rewards + withdrawRewardFor(payable(msg.sender)); // be nice, and get his rewards totalSupply -= balances[msg.sender]; balances[msg.sender] = 0; paidOut[msg.sender] = 0; @@ -711,7 +711,7 @@ contract DAO is DAOInterface, Token, TokenCreation { function retrieveDAOReward(bool _toMembers) external override returns (bool _success) { - DAO dao = DAO(msg.sender); + DAO dao = DAO(payable(msg.sender)); if ((rewardToken[msg.sender] * DAOrewardAccount.accumulatedInput()) / totalRewardToken < DAOpaidOut[msg.sender]) @@ -736,7 +736,7 @@ contract DAO is DAOInterface, Token, TokenCreation { } function getMyReward() public override returns (bool _success) { - return withdrawRewardFor(msg.sender); + return withdrawRewardFor(payable(msg.sender)); } diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index 3365ec436..8d8e1f255 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -445,8 +445,8 @@ "tryCall": false, "typeDescriptions": { - "typeIdentifier": "t_address_payable", - "typeString": "address payable" + "typeIdentifier": "t_address", + "typeString": "address" } }, "src": "232:17:1", diff --git a/test/libsolidity/semanticTests/inlineAssembly/constant_access.sol b/test/libsolidity/semanticTests/inlineAssembly/constant_access.sol index 2da41a3da..317e92284 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/constant_access.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/constant_access.sol @@ -3,7 +3,7 @@ contract C { bytes2 constant b = 0xabcd; bytes3 constant c = "abc"; bool constant d = true; - address payable constant e = 0x1212121212121212121212121212121212121212; + address constant e = 0x1212121212121212121212121212121212121212; function f() public pure returns (uint w, bytes2 x, bytes3 y, bool z, address t) { assembly { w := a diff --git a/test/libsolidity/semanticTests/inlineAssembly/constant_access_referencing.sol b/test/libsolidity/semanticTests/inlineAssembly/constant_access_referencing.sol index 280397560..5b1120211 100644 --- a/test/libsolidity/semanticTests/inlineAssembly/constant_access_referencing.sol +++ b/test/libsolidity/semanticTests/inlineAssembly/constant_access_referencing.sol @@ -10,8 +10,8 @@ contract C { bytes3 constant cccc = ccc; bool constant d = true; bool constant dd = d; - address payable constant e = 0x1212121212121212121212121212121212121212; - address payable constant ee = e; + address constant e = 0x1212121212121212121212121212121212121212; + address constant ee = e; function f() public pure returns (uint w, bytes2 x, bytes3 y, bool z, address t) { assembly { w := aaa diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index fed56d305..239d22ab5 100644 --- a/test/libsolidity/syntaxTests/deprecated_functions.sol +++ b/test/libsolidity/syntaxTests/deprecated_functions.sol @@ -4,7 +4,7 @@ contract test { x; } function g() public { - suicide(0x0000000000000000000000000000000000000001); + suicide(payable(0x0000000000000000000000000000000000000001)); } } // ---- diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_send.sol b/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_send.sol new file mode 100644 index 000000000..661544ad7 --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_send.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + (msg.sender).send(10); + } +} +// ---- +// TypeError 9862: (47-64): "send" and "transfer" are only available for objects of type "address payable", not "address". diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_transfer.sol b/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_transfer.sol new file mode 100644 index 000000000..f44e0489f --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/msg_sender_non_payable_transfer.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + (msg.sender).transfer(10); + } +} +// ---- +// TypeError 9862: (47-68): "send" and "transfer" are only available for objects of type "address payable", not "address". diff --git a/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_send.sol b/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_send.sol new file mode 100644 index 000000000..b96568395 --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_send.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + (tx.origin).send(10); + } +} +// ---- +// TypeError 9862: (47-63): "send" and "transfer" are only available for objects of type "address payable", not "address". diff --git a/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_transfer.sol b/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_transfer.sol new file mode 100644 index 000000000..34f60ebae --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/tx_origin_non_payable_transfer.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + (tx.origin).transfer(10); + } +} +// ---- +// TypeError 9862: (47-67): "send" and "transfer" are only available for objects of type "address payable", not "address". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol index b5a716d65..0b5c53046 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/346_unused_return_value_send.sol @@ -1,6 +1,6 @@ contract test { function f() public { - address(0x12).send(1); + payable(0x12).send(1); } } // ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol index 81cc7d0d4..25acbfd42 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/405_address_checksum_type_deduction.sol @@ -1,6 +1,6 @@ contract C { function f() public { - (0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E).transfer(2); + payable(0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E).transfer(2); } } // ---- diff --git a/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol b/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol index 154bfb54b..b83ad3f94 100644 --- a/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol +++ b/test/libsolidity/syntaxTests/parsing/address_payable_constant.sol @@ -1,3 +1,3 @@ contract C { - address payable constant a = address(0); + address payable constant a = payable(0); } diff --git a/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol b/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol index dfeab7022..f26eed18a 100644 --- a/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol +++ b/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol @@ -9,7 +9,7 @@ contract C { } } // ---- -// TypeError 2271: (85-108): Operator + not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. -// TypeError 2271: (122-145): Operator - not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. -// TypeError 2271: (159-182): Operator * not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. -// TypeError 2271: (196-219): Operator / not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError 2271: (85-108): Operator + not compatible with types address and address. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError 2271: (122-145): Operator - not compatible with types address and address. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError 2271: (159-182): Operator * not compatible with types address and address. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError 2271: (196-219): Operator / not compatible with types address and address. Arithmetic operations on addresses are not supported. Convert to integer first before using them. diff --git a/test/libsolidity/syntaxTests/types/address/address_constant.sol b/test/libsolidity/syntaxTests/types/address/address_constant.sol index 0b1af9917..c8bbfc511 100644 --- a/test/libsolidity/syntaxTests/types/address/address_constant.sol +++ b/test/libsolidity/syntaxTests/types/address/address_constant.sol @@ -1,6 +1,6 @@ contract C { address constant a = address(0); - address payable constant b = address(0); + address payable constant b = payable(0); function f() public pure returns (address, address) { return (a,b); } diff --git a/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol b/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol index d843c5990..76df63cdd 100644 --- a/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol +++ b/test/libsolidity/syntaxTests/types/address/address_constant_assignment.sol @@ -1,9 +1,9 @@ contract C { address constant a = address(0); - address payable constant b = address(0); + address payable constant b = payable(0); function f() public { a = address(0); - b = address(0); + b = payable(0); } } // ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_literal_to_payable.sol b/test/libsolidity/syntaxTests/types/address/address_literal_to_payable.sol new file mode 100644 index 000000000..509eb0398 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_literal_to_payable.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + address payable a = payable(address(0x00000000219ab540356cBB839Cbe05303d7705Fa)); + address payable b = payable(0x00000000219ab540356cBB839Cbe05303d7705Fa); + a = b; + b = a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_literal_to_payable_err.sol b/test/libsolidity/syntaxTests/types/address/address_literal_to_payable_err.sol new file mode 100644 index 000000000..7a9edf32d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_literal_to_payable_err.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + address payable a = address(0x00000000219ab540356cBB839Cbe05303d7705Fa); + address payable b = 0x00000000219ab540356cBB839Cbe05303d7705Fa; + } +} +// ---- +// TypeError 9574: (52-123): Type address is not implicitly convertible to expected type address payable. +// TypeError 9574: (133-195): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol index e5eab5f50..c07dd81f6 100644 --- a/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol +++ b/test/libsolidity/syntaxTests/types/address/address_payable_internal_overload_payable.sol @@ -2,7 +2,7 @@ contract C { function f(address payable) internal pure {} function f(address) internal pure {} function g() internal pure { - address payable a = address(0); + address payable a = payable(0); f(a); } } diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol index 90fb3e85f..2aa032e0e 100644 --- a/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_implicitly.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError 9574: (46-62): Type address payable is not implicitly convertible to expected type contract C. +// TypeError 9574: (46-62): Type address is not implicitly convertible to expected type contract C. diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol index 69cb23342..00601c0ef 100644 --- a/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_payable_fallback.sol @@ -1,6 +1,6 @@ contract C { function f() public pure returns (C c) { - c = C(address(2)); + c = C(payable(2)); } fallback() external payable { } diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol index 19b702c6e..282985a77 100644 --- a/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol @@ -1,6 +1,6 @@ contract C { function f() public pure returns (C c) { - c = C(address(2)); + c = C(payable(2)); } receive() external payable { } diff --git a/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol b/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol index e9d1f6375..727be3404 100644 --- a/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol +++ b/test/libsolidity/syntaxTests/types/address/address_tuple_fail.sol @@ -1,6 +1,6 @@ contract C { function f() public view returns (address payable a, address b) { - (address c, address payable d) = (address(this), address(0)); + (address c, address payable d) = (address(this), payable(0)); (a,b) = (c,d); } } diff --git a/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol b/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol index 846de1f48..beee4d9c7 100644 --- a/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol +++ b/test/libsolidity/syntaxTests/types/address/address_tuple_fine.sol @@ -1,6 +1,6 @@ contract C { function f() public view returns (address payable a, address b) { - (address c, address payable d) = (address(this), address(0)); + (address c, address payable d) = (address(this), payable(0)); (a,b) = (d,c); } -} \ No newline at end of file +} diff --git a/test/libsolidity/syntaxTests/types/address/literal_to_address_call.sol b/test/libsolidity/syntaxTests/types/address/literal_to_address_call.sol new file mode 100644 index 000000000..81830c7a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/literal_to_address_call.sol @@ -0,0 +1,5 @@ +contract C { + function f() public returns (bool success) { + (success, ) = (address(0)).call{value: 30}(""); + } +} diff --git a/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol index 97f4d85d3..a64cdc96f 100644 --- a/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol +++ b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address.sol @@ -1,8 +1,8 @@ contract C { function f() public pure { - address payable a = address(0); - a = address(1); - address payable b = 0x0123456789012345678901234567890123456789; - b = 0x9876543210987654321098765432109876543210; + address payable a = payable(0); + a = payable(1); + address payable b = payable(0x0123456789012345678901234567890123456789); + b = payable(0x9876543210987654321098765432109876543210); } -} \ No newline at end of file +} diff --git a/test/libsolidity/syntaxTests/types/address/literal_to_payable_address_err.sol b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address_err.sol new file mode 100644 index 000000000..d72f7483f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/literal_to_payable_address_err.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + address payable a = address(0); + } +} +// ---- +// TypeError 9574: (52-82): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/strict_explicit_err.sol b/test/libsolidity/syntaxTests/types/strict_explicit_err.sol index 2c76bde11..2f0c9a080 100644 --- a/test/libsolidity/syntaxTests/types/strict_explicit_err.sol +++ b/test/libsolidity/syntaxTests/types/strict_explicit_err.sol @@ -41,7 +41,7 @@ contract C // TypeError 9640: (183-213): Explicit type conversion not allowed from "uint16" to "int8". // TypeError 9640: (270-277): Explicit type conversion not allowed from "uint16" to "int8". // TypeError 9640: (300-329): Explicit type conversion not allowed from "uint256" to "address". -// TypeError 9640: (349-365): Explicit type conversion not allowed from "address payable" to "uint256". +// TypeError 9640: (349-365): Explicit type conversion not allowed from "address" to "uint256". // TypeError 9640: (421-431): Explicit type conversion not allowed from "uint256" to "address". // TypeError 9640: (452-471): Explicit type conversion not allowed from "bytes10" to "int80". // TypeError 9640: (493-511): Explicit type conversion not allowed from "int80" to "bytes10". From f30c7cbac829ce51d65e5bfba7121f2daa001b4d Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 14 Dec 2020 16:36:40 +0100 Subject: [PATCH 4/5] All explicit address conversions return a non-payable address --- Changelog.md | 2 +- docs/080-breaking-changes.rst | 16 ++++++++++++++++ libsolidity/analysis/TypeChecker.cpp | 11 ----------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Changelog.md b/Changelog.md index 6f9d88406..7bbb9e64c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,7 +27,7 @@ Breaking Changes: * Type System: Support ``address(...).codehash`` to retrieve the codehash of an account. * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * View Pure Checker: Mark ``chainid`` as view. - * Type System: Address-literals and explicit conversions of integer-literals into ``address `` have type ``address`` instead of ``address payable``. + * Type System: Explicit conversion to ``address`` type always returns a non-payable ``address`` type. In particular, ``address(u)``, ``address(b)``, ``address(c)`` and ``address(this)`` have the type ``address`` instead of ``address payable`` (Here ``u``, ``b``, and ``c`` are arbitrary variables of type ``uint160``, ``bytes20`` and contract type respectively.) * Type System: The global variables ``tx.origin`` and ``msg.sender`` have type ``address`` instead of ``address payable``. * Yul: Disallow the use of reserved identifiers, such as EVM instructions, even if they are not available in the given dialect / EVM version. diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index 7143cad15..4ac937ec5 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -119,6 +119,22 @@ This section lists changes that might cause existing contracts to not compile an This change was done since the compiler cannot determine whether or not these addresses are payable or not, so it now requires an explicit conversion to make this requirement visible. +* Explicit conversion into ``address`` type always returns a non-payable ``address`` type. In + particular, the following explicit conversions have the type ``address`` instead of ``address + payable``: + + - ``address(u)`` where ``u`` is an arbitrary variable of type ``uint160``. One can convert ``u`` + into the type ``address payable`` by using an explicit conversion, i.e., ``payable(u)``. + - ``address(b)`` where ``b`` is an arbitrary variable of type ``bytes20``. One can convert ``b`` + into the type ``address payable`` by using an explicit conversion, i.e., ``payable(bytes20)``. + - ``address(c)`` where ``c`` is an arbitrary contract. Previously, the return type of this + conversion depended on whether the contract can receive Ether (either by having a receive + function or a payable fallback function). The conversion ``payable(c)`` has the type ``address + payable`` and is only allowed when the contract ``c`` can receive Ether. In general, one can + always convert ``c`` into the type ``address payable`` by using the following explicit + conversion: ``payable(address(c))``. Note that ``address(this)`` falls under the same category + as ``address(c)`` and the same rules apply for it. + * The ``chainid`` builtin in inline assembly is now considered ``view`` instead of ``pure``. Interface Changes diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 0b96fdb6d..ea71d0d40 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1764,17 +1764,6 @@ TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( result.message() ); } - if (auto addressType = dynamic_cast(resultType)) - if (addressType->stateMutability() != StateMutability::Payable) - { - bool payable = false; - if ( - argType->category() != Type::Category::Address && - argType->category() != Type::Category::RationalNumber - ) - payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress()); - resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address(); - } } return resultType; } From 7438c4dc167f39c250e1983c4044a98d8f794a95 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 14 Dec 2020 16:51:07 +0100 Subject: [PATCH 5/5] Tests after making all explicit address conversions as non-payable --- docs/contracts/functions.rst | 2 +- test/compilationTests/corion/module.sol | 4 +-- test/externalTests/solc-js/DAO/DAO.sol | 4 +-- .../solc-js/DAO/TokenCreation.sol | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 4 +-- .../cleanup_address_types_shortening.sol | 2 +- .../uncalled_address_transfer_send.sol | 2 +- .../functionCall/send_zero_ether.sol | 2 +- .../semanticTests/revertStrings/transfer.sol | 6 ++-- .../semanticTests/state/msg_sender.sol | 2 +- .../semanticTests/state/tx_origin.sol | 2 +- ...es_not_error_transfer_payable_fallback.sol | 2 +- .../535_address_overload_resolution.sol | 2 +- .../types/address/address_in_struct_fine.sol | 4 +-- .../address/address_to_contract_receive.sol | 2 +- .../address/address_uint_bytes20_this.sol | 23 +++++++++++++++ ...dress_uint_bytes20_this_to_payable_err.sol | 11 +++++++ .../address/bytes_to_payable_address.sol | 2 +- ...ct_payable_fallback_to_payable_address.sol | 2 +- .../contract_receive_to_payable_address.sol | 2 +- .../types/address/payable_conversion.sol | 29 +++++++++++++++++++ .../types/address/payable_conversion_err.sol | 17 +++++++++++ .../address/payable_to_contract_receive.sol | 8 +++++ .../types/address/uint_to_payable_address.sol | 2 +- .../viewPureChecker/builtin_functions.sol | 6 ++-- .../builtin_functions_view_fail.sol | 6 ++-- 26 files changed, 119 insertions(+), 31 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this.sol create mode 100644 test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this_to_payable_err.sol create mode 100644 test/libsolidity/syntaxTests/types/address/payable_conversion.sol create mode 100644 test/libsolidity/syntaxTests/types/address/payable_conversion_err.sol create mode 100644 test/libsolidity/syntaxTests/types/address/payable_to_contract_receive.sol diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index 279fec1f3..6aaa9d245 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -438,7 +438,7 @@ operations as long as there is enough gas passed on to it. // results in test.x becoming == 1 and test.y becoming 1. // If someone sends Ether to that contract, the receive function in TestPayable will be called. - require(address(test).send(2 ether)); + require(payable(test).send(2 ether)); // results in test.x becoming == 2 and test.y becoming 2 ether. return true; diff --git a/test/compilationTests/corion/module.sol b/test/compilationTests/corion/module.sol index ef0ffac21..1b52639d1 100644 --- a/test/compilationTests/corion/module.sol +++ b/test/compilationTests/corion/module.sol @@ -90,10 +90,10 @@ contract module { @newModuleAddress New module handler address */ require( moduleStatus != status.New && moduleStatus != status.Disconnected); - (bool _success, uint256 _balance) = abstractModuleHandler(moduleHandlerAddress).balanceOf(address(this)); + (bool _success, uint256 _balance) = abstractModuleHandler(moduleHandlerAddress).balanceOf(payable(this)); require( _success ); if ( _balance > 0 ) { - require( abstractModuleHandler(moduleHandlerAddress).transfer(address(this), newModuleAddress, _balance, false) ); + require( abstractModuleHandler(moduleHandlerAddress).transfer(payable(this), newModuleAddress, _balance, false) ); } if ( address(this).balance > 0 ) { require( newModuleAddress.send(address(this).balance) ); diff --git a/test/externalTests/solc-js/DAO/DAO.sol b/test/externalTests/solc-js/DAO/DAO.sol index c519bf70d..45778a3fc 100644 --- a/test/externalTests/solc-js/DAO/DAO.sol +++ b/test/externalTests/solc-js/DAO/DAO.sol @@ -724,11 +724,11 @@ contract DAO is DAOInterface, Token, TokenCreation { reward = address(DAOrewardAccount).balance < reward ? address(DAOrewardAccount).balance : reward; if(_toMembers) { - if (!DAOrewardAccount.payOut(address(dao.rewardAccount()), reward)) + if (!DAOrewardAccount.payOut(payable(dao.rewardAccount()), reward)) revert(); } else { - if (!DAOrewardAccount.payOut(address(dao), reward)) + if (!DAOrewardAccount.payOut(payable(dao), reward)) revert(); } DAOpaidOut[msg.sender] += reward; diff --git a/test/externalTests/solc-js/DAO/TokenCreation.sol b/test/externalTests/solc-js/DAO/TokenCreation.sol index cf0d27a53..64abf86ca 100644 --- a/test/externalTests/solc-js/DAO/TokenCreation.sol +++ b/test/externalTests/solc-js/DAO/TokenCreation.sol @@ -124,7 +124,7 @@ override returns (bool success) { if (block.timestamp > closingTime && !isFueled) { // Get extraBalance - will only succeed when called for the first time if (address(extraBalance).balance >= extraBalance.accumulatedInput()) - extraBalance.payOut(address(this), extraBalance.accumulatedInput()); + extraBalance.payOut(payable(this), extraBalance.accumulatedInput()); // Execute refund (bool success,) = msg.sender.call{value: weiGiven[msg.sender]}(""); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index cea3a8847..3f5bf5d2d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1328,7 +1328,7 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses) } contract test { helper h; - constructor() payable { h = new helper(); address(h).send(5); } + constructor() payable { h = new helper(); payable(h).send(5); } function getBalance() public returns (uint256 myBalance, uint256 helperBalance) { myBalance = address(this).balance; helperBalance = address(h).balance; @@ -4640,7 +4640,7 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer) revert("message"); } function f() public { - address(this).transfer(0); + payable(this).transfer(0); } } contract C { diff --git a/test/libsolidity/semanticTests/cleanup/cleanup_address_types_shortening.sol b/test/libsolidity/semanticTests/cleanup/cleanup_address_types_shortening.sol index f6dbdbc2f..9b9a695e1 100644 --- a/test/libsolidity/semanticTests/cleanup/cleanup_address_types_shortening.sol +++ b/test/libsolidity/semanticTests/cleanup/cleanup_address_types_shortening.sol @@ -18,7 +18,7 @@ contract C { assembly { y := x } - address payable z = address(y); + address payable z = payable(y); assembly { r := z } diff --git a/test/libsolidity/semanticTests/expressions/uncalled_address_transfer_send.sol b/test/libsolidity/semanticTests/expressions/uncalled_address_transfer_send.sol index 4511b9cb8..b7fe44beb 100644 --- a/test/libsolidity/semanticTests/expressions/uncalled_address_transfer_send.sol +++ b/test/libsolidity/semanticTests/expressions/uncalled_address_transfer_send.sol @@ -1,7 +1,7 @@ contract TransferTest { fallback() external payable { // This used to cause an ICE - address(this).transfer; + payable(this).transfer; } function f() pure public {} diff --git a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol index 401f33f34..059d0878c 100644 --- a/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol +++ b/test/libsolidity/semanticTests/functionCall/send_zero_ether.sol @@ -10,7 +10,7 @@ contract Main { function s() public returns (bool) { Receiver r = new Receiver(); - return address(r).send(0); + return payable(r).send(0); } } diff --git a/test/libsolidity/semanticTests/revertStrings/transfer.sol b/test/libsolidity/semanticTests/revertStrings/transfer.sol index 5d13f7d72..8ee6fd2e8 100644 --- a/test/libsolidity/semanticTests/revertStrings/transfer.sol +++ b/test/libsolidity/semanticTests/revertStrings/transfer.sol @@ -8,13 +8,13 @@ contract C { A a = new A(); receive() external payable {} function f() public { - address(a).transfer(1 wei); + payable(a).transfer(1 wei); } function h() public { - address(a).transfer(100 ether); + payable(a).transfer(100 ether); } function g() public view returns (uint) { - return address(this).balance; + return payable(this).balance; } } // ==== diff --git a/test/libsolidity/semanticTests/state/msg_sender.sol b/test/libsolidity/semanticTests/state/msg_sender.sol index 6348bb477..57c7fd5f3 100644 --- a/test/libsolidity/semanticTests/state/msg_sender.sol +++ b/test/libsolidity/semanticTests/state/msg_sender.sol @@ -1,5 +1,5 @@ contract C { - function f() public returns (address payable) { + function f() public returns (address) { return msg.sender; } } diff --git a/test/libsolidity/semanticTests/state/tx_origin.sol b/test/libsolidity/semanticTests/state/tx_origin.sol index caa27d180..34f19f616 100644 --- a/test/libsolidity/semanticTests/state/tx_origin.sol +++ b/test/libsolidity/semanticTests/state/tx_origin.sol @@ -1,5 +1,5 @@ contract C { - function f() public returns (address payable) { + function f() public returns (address) { return tx.origin; } } diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol index 47dbb3c7b..642ae8360 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/466_does_not_error_transfer_payable_fallback.sol @@ -9,7 +9,7 @@ contract B { A a; fallback() external { - address(a).transfer(100); + payable(a).transfer(100); } } // ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol index 7afc3fed8..a36aeed86 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/535_address_overload_resolution.sol @@ -4,7 +4,7 @@ contract C { return 1; } function transfer(uint amount) public { - address(this).transfer(amount); // to avoid pureness warning + payable(this).transfer(amount); // to avoid pureness warning } receive() payable external { } diff --git a/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol b/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol index 11d5e8677..6759bc11d 100644 --- a/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol +++ b/test/libsolidity/syntaxTests/types/address/address_in_struct_fine.sol @@ -13,8 +13,8 @@ contract B { } S s; function f() public { - s.a = address(this); + s.a = payable(this); } receive() external payable { } -} \ No newline at end of file +} diff --git a/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol b/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol index 282985a77..75bd25376 100644 --- a/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol +++ b/test/libsolidity/syntaxTests/types/address/address_to_contract_receive.sol @@ -1,6 +1,6 @@ contract C { function f() public pure returns (C c) { - c = C(payable(2)); + c = C(payable(address(2))); } receive() external payable { } diff --git a/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this.sol b/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this.sol new file mode 100644 index 000000000..4c62fa763 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this.sol @@ -0,0 +1,23 @@ +contract C { + function f() public view { + address a1 = address(uint160(0)); + address a2 = address(bytes20(0)); + address a3 = address(this); + + address payable a4 = payable(uint160(0)); + address payable a5 = payable(bytes20(0)); + address payable a6 = payable(this); + + // Trivial conversions + address payable a7 = payable(address(uint160(0))); + address payable a8 = payable(address(bytes20(0))); + address payable a9 = payable(address(this)); + + a1; a2; a3; a4; a5; a6; a7; a8; a9; + } + + // to make payable(this) work + receive() payable external { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this_to_payable_err.sol b/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this_to_payable_err.sol new file mode 100644 index 000000000..37f087e5b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_uint_bytes20_this_to_payable_err.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + address payable a = address(uint160(0)); + address payable b = address(bytes20(0)); + address payable c = address(this); + } +} +// ---- +// TypeError 9574: (52-91): Type address is not implicitly convertible to expected type address payable. +// TypeError 9574: (101-140): Type address is not implicitly convertible to expected type address payable. +// TypeError 9574: (150-183): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol index 5b6a6714d..f4912c8a6 100644 --- a/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol +++ b/test/libsolidity/syntaxTests/types/address/bytes_to_payable_address.sol @@ -1,5 +1,5 @@ contract C { function f(bytes20 x) public pure returns (address payable) { - return address(x); + return payable(x); } } diff --git a/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol index 66da36221..2d4ae3a72 100644 --- a/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol +++ b/test/libsolidity/syntaxTests/types/address/contract_payable_fallback_to_payable_address.sol @@ -1,6 +1,6 @@ contract C { function f() public view { - address payable a = address(this); + address payable a = payable(this); a; } fallback() external payable { diff --git a/test/libsolidity/syntaxTests/types/address/contract_receive_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/contract_receive_to_payable_address.sol index 7c308b39a..cf25a618a 100644 --- a/test/libsolidity/syntaxTests/types/address/contract_receive_to_payable_address.sol +++ b/test/libsolidity/syntaxTests/types/address/contract_receive_to_payable_address.sol @@ -1,6 +1,6 @@ contract C { function f() public view { - address payable a = address(this); + address payable a = payable(this); a; } receive() external payable { diff --git a/test/libsolidity/syntaxTests/types/address/payable_conversion.sol b/test/libsolidity/syntaxTests/types/address/payable_conversion.sol new file mode 100644 index 000000000..ce7c9078a --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/payable_conversion.sol @@ -0,0 +1,29 @@ +contract C { + function f() public { + address payable a = payable(address(new D())); + address payable b = payable(new E()); + address payable c = payable(new F()); + + a; + b; + c; + } +} + +// A contract that cannot receive Ether +contract D {} + +// A contract that can receive Ether +contract E { + receive() external payable { + } +} + +// A contract that can receive Ether using the fallback +contract F { + fallback() external payable { + + } +} + +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/payable_conversion_err.sol b/test/libsolidity/syntaxTests/types/address/payable_conversion_err.sol new file mode 100644 index 000000000..28bb52e23 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/payable_conversion_err.sol @@ -0,0 +1,17 @@ +contract C { + function f() public { + address payable a = address(new D()); + + // This conversion makes no sense anyway. + address payable b = address(D); + } +} + +contract D { + receive() external payable { + } +} +// ---- +// TypeError 9574: (47-83): Type address is not implicitly convertible to expected type address payable. +// TypeError 9640: (164-174): Explicit type conversion not allowed from "type(contract D)" to "address". +// TypeError 9574: (144-174): Type address is not implicitly convertible to expected type address payable. diff --git a/test/libsolidity/syntaxTests/types/address/payable_to_contract_receive.sol b/test/libsolidity/syntaxTests/types/address/payable_to_contract_receive.sol new file mode 100644 index 000000000..282985a77 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/payable_to_contract_receive.sol @@ -0,0 +1,8 @@ +contract C { + function f() public pure returns (C c) { + c = C(payable(2)); + } + receive() external payable { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol index 412201671..7fa3fbcf0 100644 --- a/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol +++ b/test/libsolidity/syntaxTests/types/address/uint_to_payable_address.sol @@ -1,5 +1,5 @@ contract C { function f(uint x) public pure returns (address payable) { - return address(uint160(x)); + return payable(uint160(x)); } } diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index f828a0cf1..225a954cc 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -1,8 +1,8 @@ contract C { function f() public { - address(this).transfer(1); - require(address(this).send(2)); - selfdestruct(address(this)); + payable(this).transfer(1); + require(payable(this).send(2)); + selfdestruct(payable(this)); (bool success,) = address(this).delegatecall(""); require(success); (success,) = address(this).call(""); diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol index ffd412375..000f5b009 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -1,12 +1,12 @@ contract C { function f() view public { - address(this).transfer(1); + payable(this).transfer(1); } function g() view public { - require(address(this).send(2)); + require(payable(this).send(2)); } function h() view public { - selfdestruct(address(this)); + selfdestruct(payable(this)); } function i() view public { (bool success,) = address(this).delegatecall("");