Merge pull request #10496 from ethereum/address-payable

[BREAKING] tx.origin, msg.sender and address(literal) are non-payable addresses
This commit is contained in:
chriseth 2020-12-14 20:16:52 +01:00 committed by GitHub
commit 271a17d908
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 298 additions and 132 deletions

View File

@ -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: 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.
Language Features:

View File

@ -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<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,28 @@ 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.
* 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``.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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(<address>)``.
:ref:`Address literals<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(<address>)``.
.. 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<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.

View File

@ -1764,14 +1764,6 @@ TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
result.message()
);
}
if (auto addressType = dynamic_cast<AddressType const*>(resultType))
if (addressType->stateMutability() != StateMutability::Payable)
{
bool payable = false;
if (argType->category() != Type::Category::Address)
payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress());
resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address();
}
}
return resultType;
}
@ -3314,7 +3306,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

View File

@ -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:

View File

@ -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);
}

View File

@ -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) );

View File

@ -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;

View File

@ -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; }

View File

@ -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

View File

@ -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); }

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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])
@ -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;
@ -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));
}

View File

@ -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]}("");

View File

@ -445,8 +445,8 @@
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "232:17:1",

View File

@ -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 {

View File

@ -18,7 +18,7 @@ contract C {
assembly {
y := x
}
address payable z = address(y);
address payable z = payable(y);
assembly {
r := z
}

View File

@ -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 {}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
// ====

View File

@ -1,5 +1,5 @@
contract C {
function f() public returns (address payable) {
function f() public returns (address) {
return msg.sender;
}
}

View File

@ -1,5 +1,5 @@
contract C {
function f() public returns (address payable) {
function f() public returns (address) {
return tx.origin;
}
}

View File

@ -4,7 +4,7 @@ contract test {
x;
}
function g() public {
suicide(0x0000000000000000000000000000000000000001);
suicide(payable(0x0000000000000000000000000000000000000001));
}
}
// ----

View File

@ -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".

View File

@ -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".

View File

@ -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".

View File

@ -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".

View File

@ -1,6 +1,6 @@
contract test {
function f() public {
address(0x12).send(1);
payable(0x12).send(1);
}
}
// ----

View File

@ -1,6 +1,6 @@
contract C {
function f() public {
(0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E).transfer(2);
payable(0xfA0bFc97E48458494Ccd857e1A85DC91F7F0046E).transfer(2);
}
}
// ----

View File

@ -9,7 +9,7 @@ contract B {
A a;
fallback() external {
address(a).transfer(100);
payable(a).transfer(100);
}
}
// ----

View File

@ -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 {
}

View File

@ -1,3 +1,3 @@
contract C {
address payable constant a = address(0);
address payable constant a = payable(0);
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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);
}
}
// ----

View File

@ -13,8 +13,8 @@ contract B {
}
S s;
function f() public {
s.a = address(this);
s.a = payable(this);
}
receive() external payable {
}
}
}

View File

@ -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;
}
}
// ----

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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.

View File

@ -1,6 +1,6 @@
contract C {
function f() public pure returns (C c) {
c = C(address(2));
c = C(payable(2));
}
fallback() external payable {
}

View File

@ -1,6 +1,6 @@
contract C {
function f() public pure returns (C c) {
c = C(address(2));
c = C(payable(address(2)));
}
receive() external payable {
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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 {
}
}
// ----

View File

@ -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.

View File

@ -1,5 +1,5 @@
contract C {
function f(bytes20 x) public pure returns (address payable) {
return address(x);
return payable(x);
}
}

View File

@ -1,6 +1,6 @@
contract C {
function f() public view {
address payable a = address(this);
address payable a = payable(this);
a;
}
fallback() external payable {

View File

@ -1,6 +1,6 @@
contract C {
function f() public view {
address payable a = address(this);
address payable a = payable(this);
a;
}
receive() external payable {

View File

@ -0,0 +1,5 @@
contract C {
function f() public returns (bool success) {
(success, ) = (address(0)).call{value: 30}("");
}
}

View File

@ -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);
}
}
}

View File

@ -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.

View File

@ -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 {
}
}
// ----

View File

@ -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.

View File

@ -0,0 +1,8 @@
contract C {
function f() public pure returns (C c) {
c = C(payable(2));
}
receive() external payable {
}
}
// ----

View File

@ -1,5 +1,5 @@
contract C {
function f(uint x) public pure returns (address payable) {
return address(uint160(x));
return payable(uint160(x));
}
}

View File

@ -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".

View File

@ -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("");

View File

@ -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("");