mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #4911 from ethereum/addressPayable
Payable and non-payable address type.
This commit is contained in:
		
						commit
						e7daed68c1
					
				| @ -7,6 +7,7 @@ How to update your code: | ||||
|  * Make your fallback functions ``external``. | ||||
|  * Explicitly state the data location for all variables of struct, array or mapping types (including function parameters), e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``. Note that ``external`` functions require parameters with a data location of ``calldata``. | ||||
|  * Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``. | ||||
|  * Declare variables and especially function arguments as ``address payable``, if you want to call ``transfer`` on them. | ||||
| 
 | ||||
| Breaking Changes: | ||||
|  * ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding. | ||||
| @ -62,6 +63,7 @@ Breaking Changes: | ||||
|  * Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore. | ||||
|  * Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types. | ||||
|  * Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size. | ||||
|  * Type System: Distinguish between payable and non-payable address types. | ||||
|  * View Pure Checker: Disallow ``msg.value`` in (or introducing it via a modifier to) a non-payable function. | ||||
|  * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. | ||||
|  * References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode. | ||||
|  | ||||
| @ -68,7 +68,7 @@ This is as opposed to the more intuitive sending pattern: | ||||
|     pragma solidity >0.4.24; | ||||
| 
 | ||||
|     contract SendContract { | ||||
|         address public richest; | ||||
|         address payable public richest; | ||||
|         uint public mostSent; | ||||
| 
 | ||||
|         constructor() public payable { | ||||
|  | ||||
| @ -334,7 +334,7 @@ inheritable properties of contracts and may be overridden by derived contracts. | ||||
| 
 | ||||
|     contract owned { | ||||
|         constructor() public { owner = msg.sender; } | ||||
|         address owner; | ||||
|         address payable owner; | ||||
| 
 | ||||
|         // This contract only defines a modifier but does not use | ||||
|         // it: it will be used in derived contracts. | ||||
| @ -650,9 +650,14 @@ Like any function, the fallback function can execute complex operations as long | ||||
|             require(success); | ||||
|             // results in test.x becoming == 1. | ||||
| 
 | ||||
|             // address(test) will not allow to call ``send`` directly, since ``test`` has no payable | ||||
|             // fallback function. It has to be converted to the ``address payable`` type via an | ||||
|             // intermediate conversion to ``uint160`` to even allow calling ``send`` on it. | ||||
|             address payable testPayable = address(uint160(address(test))); | ||||
| 
 | ||||
|             // If someone sends ether to that contract, | ||||
|             // the transfer will fail, i.e. this returns false here. | ||||
|             return address(test).send(2 ether); | ||||
|             return testPayable.send(2 ether); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -891,7 +896,7 @@ Details are given in the following example. | ||||
| 
 | ||||
|     contract owned { | ||||
|         constructor() public { owner = msg.sender; } | ||||
|         address owner; | ||||
|         address payable owner; | ||||
|     } | ||||
| 
 | ||||
|     // Use `is` to derive from another contract. Derived | ||||
| @ -963,7 +968,7 @@ seen in the following example:: | ||||
| 
 | ||||
|     contract owned { | ||||
|         constructor() public { owner = msg.sender; } | ||||
|         address owner; | ||||
|         address payable owner; | ||||
|     } | ||||
| 
 | ||||
|     contract mortal is owned { | ||||
| @ -992,7 +997,7 @@ derived override, but this function will bypass | ||||
| 
 | ||||
|     contract owned { | ||||
|         constructor() public { owner = msg.sender; } | ||||
|         address owner; | ||||
|         address payable owner; | ||||
|     } | ||||
| 
 | ||||
|     contract mortal is owned { | ||||
|  | ||||
| @ -421,7 +421,7 @@ a message string for ``require``, but not for ``assert``. | ||||
|     pragma solidity >0.4.24; | ||||
| 
 | ||||
|     contract Sharer { | ||||
|         function sendHalf(address addr) public payable returns (uint balance) { | ||||
|         function sendHalf(address payable addr) public payable returns (uint balance) { | ||||
|             require(msg.value % 2 == 0, "Even value required."); | ||||
|             uint balanceBeforeTransfer = address(this).balance; | ||||
|             addr.transfer(msg.value / 2); | ||||
|  | ||||
| @ -329,7 +329,7 @@ Global Variables | ||||
|    starting from the second and prepends the given four-byte selector | ||||
| - ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` | ||||
| - ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. | ||||
| - ``block.coinbase`` (``address``): current block miner's address | ||||
| - ``block.coinbase`` (``address payable``): current block miner's address | ||||
| - ``block.difficulty`` (``uint``): current block difficulty | ||||
| - ``block.gaslimit`` (``uint``): current block gaslimit | ||||
| - ``block.number`` (``uint``): current block number | ||||
| @ -337,11 +337,11 @@ Global Variables | ||||
| - ``gasleft() returns (uint256)``: remaining gas | ||||
| - ``msg.data`` (``bytes``): complete calldata | ||||
| - ``msg.gas`` (``uint``): remaining gas - deprecated in version 0.4.21 and to be replaced by ``gasleft()`` | ||||
| - ``msg.sender`` (``address``): sender of the message (current call) | ||||
| - ``msg.sender`` (``address payable``): sender of the message (current call) | ||||
| - ``msg.value`` (``uint``): number of wei sent with the message | ||||
| - ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``) | ||||
| - ``tx.gasprice`` (``uint``): gas price of the transaction | ||||
| - ``tx.origin`` (``address``): sender of the transaction (full call chain) | ||||
| - ``tx.origin`` (``address payable``): 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) | ||||
| - ``require(bool condition, string message)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component). Also provide error message. | ||||
| @ -360,8 +360,8 @@ Global Variables | ||||
| - ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address | ||||
| - ``suicide(address recipient)``: a deprecated alias to ``selfdestruct`` | ||||
| - ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei | ||||
| - ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure | ||||
| - ``<address>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure | ||||
| - ``<address payable>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure | ||||
| - ``<address payable>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure | ||||
| 
 | ||||
| .. note:: | ||||
|     Do not rely on ``block.timestamp``, ``now`` and ``blockhash`` as a source of randomness, | ||||
|  | ||||
| @ -192,7 +192,7 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like | ||||
|             owner = msg.sender; | ||||
|         } | ||||
| 
 | ||||
|         function transferTo(address dest, uint amount) public { | ||||
|         function transferTo(address payable dest, uint amount) public { | ||||
|             require(tx.origin == owner); | ||||
|             dest.transfer(amount); | ||||
|         } | ||||
| @ -205,11 +205,11 @@ Now someone tricks you into sending ether to the address of this attack wallet: | ||||
|     pragma solidity >0.4.24; | ||||
| 
 | ||||
|     interface TxUserWallet { | ||||
|         function transferTo(address dest, uint amount) external; | ||||
|         function transferTo(address payable dest, uint amount) external; | ||||
|     } | ||||
| 
 | ||||
|     contract TxAttackWallet { | ||||
|         address owner; | ||||
|         address payable owner; | ||||
| 
 | ||||
|         constructor() public { | ||||
|             owner = msg.sender; | ||||
|  | ||||
| @ -231,7 +231,7 @@ activate themselves. | ||||
|         // Parameters of the auction. Times are either | ||||
|         // absolute unix timestamps (seconds since 1970-01-01) | ||||
|         // or time periods in seconds. | ||||
|         address public beneficiary; | ||||
|         address payable public beneficiary; | ||||
|         uint public auctionEndTime; | ||||
| 
 | ||||
|         // Current state of the auction. | ||||
| @ -258,7 +258,7 @@ activate themselves. | ||||
|         /// beneficiary address `_beneficiary`. | ||||
|         constructor( | ||||
|             uint _biddingTime, | ||||
|             address _beneficiary | ||||
|             address payable _beneficiary | ||||
|         ) public { | ||||
|             beneficiary = _beneficiary; | ||||
|             auctionEndTime = now + _biddingTime; | ||||
| @ -396,7 +396,7 @@ high or low invalid bids. | ||||
|             uint deposit; | ||||
|         } | ||||
| 
 | ||||
|         address public beneficiary; | ||||
|         address payable public beneficiary; | ||||
|         uint public biddingEnd; | ||||
|         uint public revealEnd; | ||||
|         bool public ended; | ||||
| @ -421,7 +421,7 @@ high or low invalid bids. | ||||
|         constructor( | ||||
|             uint _biddingTime, | ||||
|             uint _revealTime, | ||||
|             address _beneficiary | ||||
|             address payable _beneficiary | ||||
|         ) public { | ||||
|             beneficiary = _beneficiary; | ||||
|             biddingEnd = now + _biddingTime; | ||||
| @ -545,8 +545,8 @@ Safe Remote Purchase | ||||
| 
 | ||||
|     contract Purchase { | ||||
|         uint public value; | ||||
|         address public seller; | ||||
|         address public buyer; | ||||
|         address payable public seller; | ||||
|         address payable public buyer; | ||||
|         enum State { Created, Locked, Inactive } | ||||
|         State public state; | ||||
| 
 | ||||
| @ -990,11 +990,11 @@ The full contract | ||||
|     pragma solidity ^0.4.24; | ||||
| 
 | ||||
|     contract SimplePaymentChannel { | ||||
|         address public sender;      // The account sending payments. | ||||
|         address public recipient;   // The account receiving the payments. | ||||
|         address payable public sender;      // The account sending payments. | ||||
|         address payable public recipient;   // The account receiving the payments. | ||||
|         uint256 public expiration;  // Timeout in case the recipient never closes. | ||||
| 
 | ||||
|         constructor (address _recipient, uint256 duration) | ||||
|         constructor (address payable _recipient, uint256 duration) | ||||
|             public | ||||
|             payable | ||||
|         { | ||||
|  | ||||
| @ -99,6 +99,15 @@ Address | ||||
| ------- | ||||
| 
 | ||||
| ``address``: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as a base for all contracts. | ||||
| ``address payable``: Same as ``address``, but with the additional members ``transfer`` and ``send``. | ||||
| 
 | ||||
| Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` are | ||||
| not possible (the only way to perform such a conversion is by using an intermediate conversion to ``uint160``). | ||||
| Conversions of the form ``address payable(x)`` are not allowed. Instead 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 payable fallback function. | ||||
| If ``x`` is a contract without payable fallback function ``address(x)`` will be of type ``address``. The type of address literals | ||||
| is ``address payable``. | ||||
| In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type. | ||||
| 
 | ||||
| Operators: | ||||
| 
 | ||||
| @ -113,7 +122,8 @@ Operators: | ||||
|     or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. | ||||
| 
 | ||||
| .. note:: | ||||
|     Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. | ||||
|     Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to | ||||
|     ``address`` or to ``address payable``, if they have a payable fallback function. | ||||
| 
 | ||||
| .. _members-of-addresses: | ||||
| 
 | ||||
| @ -125,11 +135,11 @@ Members of Addresses | ||||
| For a quick reference, see :ref:`address_related`. | ||||
| 
 | ||||
| It is possible to query the balance of an address using the property ``balance`` | ||||
| and to send Ether (in units of wei) to an address using the ``transfer`` function: | ||||
| and to send Ether (in units of wei) to a payable address using the ``transfer`` function: | ||||
| 
 | ||||
| :: | ||||
| 
 | ||||
|     address x = 0x123; | ||||
|     address payable x = address(0x123); | ||||
|     address myAddress = this; | ||||
|     if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); | ||||
| 
 | ||||
| @ -211,11 +221,14 @@ Contract Types | ||||
| 
 | ||||
| Every :ref:`contract<contracts>` defines its own type. | ||||
| You can implicitly convert contracts to contracts they inherit from, | ||||
| and explicitly convert them to and from the ``address`` type. | ||||
| and explicitly convert them to and from the ``address`` type, if they have no | ||||
| payable fallback functions, or to and from the ``address payable`` type, if they do | ||||
| have payable fallback functions. | ||||
| 
 | ||||
| .. note:: | ||||
|     Starting with version 0.5.0 contracts do not derive from the address type, | ||||
|     but can still be explicitly converted to address. | ||||
|     but can still be explicitly converted to ``address``, resp. to ``address payable``, | ||||
|     if they have a payable fallback function. | ||||
| 
 | ||||
| If you declare a local variable of contract type (`MyContract c`), you can call | ||||
| functions on that contract. Take care to assign it from somewhere that is the | ||||
| @ -860,7 +873,7 @@ shown in the following example: | ||||
|         } | ||||
| 
 | ||||
|         struct Campaign { | ||||
|             address beneficiary; | ||||
|             address payable beneficiary; | ||||
|             uint fundingGoal; | ||||
|             uint numFunders; | ||||
|             uint amount; | ||||
| @ -870,7 +883,7 @@ shown in the following example: | ||||
|         uint numCampaigns; | ||||
|         mapping (uint => Campaign) campaigns; | ||||
| 
 | ||||
|         function newCampaign(address beneficiary, uint goal) public returns (uint campaignID) { | ||||
|         function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) { | ||||
|             campaignID = numCampaigns++; // campaignID is return variable | ||||
|             // Creates new struct and saves in storage. We leave out the mapping type. | ||||
|             campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0); | ||||
|  | ||||
| @ -57,7 +57,7 @@ Block and Transaction Properties | ||||
| -------------------------------- | ||||
| 
 | ||||
| - ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``. | ||||
| - ``block.coinbase`` (``address``): current block miner's address | ||||
| - ``block.coinbase`` (``address payable``): current block miner's address | ||||
| - ``block.difficulty`` (``uint``): current block difficulty | ||||
| - ``block.gaslimit`` (``uint``): current block gaslimit | ||||
| - ``block.number`` (``uint``): current block number | ||||
| @ -65,12 +65,12 @@ Block and Transaction Properties | ||||
| - ``gasleft() returns (uint256)``: remaining gas | ||||
| - ``msg.data`` (``bytes``): complete calldata | ||||
| - ``msg.gas`` (``uint``): remaining gas - deprecated in version 0.4.21 and to be replaced by ``gasleft()`` | ||||
| - ``msg.sender`` (``address``): sender of the message (current call) | ||||
| - ``msg.sender`` (``address payable``): sender of the message (current call) | ||||
| - ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier) | ||||
| - ``msg.value`` (``uint``): number of wei sent with the message | ||||
| - ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``) | ||||
| - ``tx.gasprice`` (``uint``): gas price of the transaction | ||||
| - ``tx.origin`` (``address``): sender of the transaction (full call chain) | ||||
| - ``tx.origin`` (``address payable``): sender of the transaction (full call chain) | ||||
| 
 | ||||
| .. note:: | ||||
|     The values of all members of ``msg``, including ``msg.sender`` and | ||||
| @ -161,9 +161,9 @@ Address Related | ||||
| 
 | ||||
| ``<address>.balance`` (``uint256``): | ||||
|     balance of the :ref:`address` in Wei | ||||
| ``<address>.transfer(uint256 amount)``: | ||||
| ``<address payable>.transfer(uint256 amount)``: | ||||
|     send given amount of Wei to :ref:`address`, throws on failure, forwards 2300 gas stipend, not adjustable | ||||
| ``<address>.send(uint256 amount) returns (bool)``: | ||||
| ``<address payable>.send(uint256 amount) returns (bool)``: | ||||
|     send given amount of Wei to :ref:`address`, returns ``false`` on failure, forwards 2300 gas stipend, not adjustable | ||||
| ``<address>.call(bytes memory) returns (bool)``: | ||||
|     issue low-level ``CALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable | ||||
| @ -204,10 +204,10 @@ Contract Related | ||||
| ``this`` (current contract's type): | ||||
|     the current contract, explicitly convertible to :ref:`address` | ||||
| 
 | ||||
| ``selfdestruct(address recipient)``: | ||||
| ``selfdestruct(address payable recipient)``: | ||||
|     destroy the current contract, sending its funds to the given :ref:`address` | ||||
| 
 | ||||
| ``suicide(address recipient)``: | ||||
| ``suicide(address payable recipient)``: | ||||
|     deprecated alias to ``selfdestruct`` | ||||
| 
 | ||||
| Furthermore, all functions of the current contract are callable directly including the current function. | ||||
|  | ||||
| @ -56,10 +56,10 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ | ||||
| 	make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), | ||||
| 	make_shared<MagicVariableDeclaration>("revert", make_shared<FunctionType>(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), | ||||
| 	make_shared<MagicVariableDeclaration>("ripemd160", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)), | ||||
| 	make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), | ||||
| 	make_shared<MagicVariableDeclaration>("selfdestruct", make_shared<FunctionType>(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)), | ||||
| 	make_shared<MagicVariableDeclaration>("sha256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)), | ||||
| 	make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)), | ||||
| 	make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), | ||||
| 	make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)), | ||||
| 	make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction)) | ||||
| }) | ||||
| { | ||||
|  | ||||
| @ -119,11 +119,19 @@ bool ReferencesResolver::visit(ElementaryTypeName const& _typeName) | ||||
| 		{ | ||||
| 			// for non-address types this was already caught by the parser
 | ||||
| 			solAssert(_typeName.annotation().type->category() == Type::Category::Address, ""); | ||||
| 			if (!( | ||||
| 				*_typeName.stateMutability() == StateMutability::Payable || | ||||
| 				*_typeName.stateMutability() == StateMutability::NonPayable | ||||
| 			)) | ||||
| 				m_errorReporter.typeError(_typeName.location(), "Address types can only be payable or non-payable."); | ||||
| 			switch(*_typeName.stateMutability()) | ||||
| 			{ | ||||
| 				case StateMutability::Payable: | ||||
| 				case StateMutability::NonPayable: | ||||
| 					_typeName.annotation().type = make_shared<AddressType>(*_typeName.stateMutability()); | ||||
| 					break; | ||||
| 				default: | ||||
| 					m_errorReporter.typeError( | ||||
| 						_typeName.location(), | ||||
| 						"Address types can only be payable or non-payable." | ||||
| 					); | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
|  | ||||
| @ -571,6 +571,9 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c | ||||
| 			// data locations. Furthermore, storage can be a little dangerous and
 | ||||
| 			// calldata is not really implemented anyway.
 | ||||
| 			actualType = ReferenceType::copyForLocationIfReference(DataLocation::Memory, actualType); | ||||
| 			// We force address payable for address types.
 | ||||
| 			if (actualType->category() == Type::Category::Address) | ||||
| 				actualType = make_shared<AddressType>(StateMutability::Payable); | ||||
| 			solAssert( | ||||
| 				!actualType->dataStoredIn(DataLocation::CallData) && | ||||
| 				!actualType->dataStoredIn(DataLocation::Storage), | ||||
| @ -1732,14 +1735,39 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) | ||||
| 				dataLoc = argRefType->location(); | ||||
| 			resultType = ReferenceType::copyForLocationIfReference(dataLoc, resultType); | ||||
| 			if (!argType->isExplicitlyConvertibleTo(*resultType)) | ||||
| 				m_errorReporter.typeError( | ||||
| 					_functionCall.location(), | ||||
| 					"Explicit type conversion not allowed from \"" + | ||||
| 					argType->toString() + | ||||
| 					"\" to \"" + | ||||
| 					resultType->toString() + | ||||
| 					"\"." | ||||
| 				); | ||||
| 			{ | ||||
| 				if (resultType->category() == Type::Category::Contract && argType->category() == Type::Category::Address) | ||||
| 				{ | ||||
| 					solAssert(dynamic_cast<ContractType const*>(resultType.get())->isPayable(), ""); | ||||
| 					solAssert(dynamic_cast<AddressType const*>(argType.get())->stateMutability() < StateMutability::Payable, ""); | ||||
| 					SecondarySourceLocation ssl; | ||||
| 					if (auto const* identifier = dynamic_cast<Identifier const*>(arguments.front().get())) | ||||
| 						if (auto const* variableDeclaration = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration)) | ||||
| 							ssl.append("Did you mean to declare this variable as \"address payable\"?", variableDeclaration->location()); | ||||
| 					m_errorReporter.typeError( | ||||
| 						_functionCall.location(), ssl, | ||||
| 						"Explicit type conversion not allowed from non-payable \"address\" to \"" + | ||||
| 						resultType->toString() + | ||||
| 						"\", which has a payable fallback function." | ||||
| 					); | ||||
| 				} | ||||
| 				else | ||||
| 					m_errorReporter.typeError( | ||||
| 						_functionCall.location(), | ||||
| 						"Explicit type conversion not allowed from \"" + | ||||
| 						argType->toString() + | ||||
| 						"\" to \"" + | ||||
| 						resultType->toString() + | ||||
| 						"\"." | ||||
| 					); | ||||
| 			} | ||||
| 			if (resultType->category() == Type::Category::Address) | ||||
| 			{ | ||||
| 				bool payable = true; | ||||
| 				if (auto const* contractType = dynamic_cast<ContractType const*>(argType.get())) | ||||
| 					payable = contractType->isPayable(); | ||||
| 				resultType = make_shared<AddressType>(payable ? StateMutability::Payable : StateMutability::NonPayable); | ||||
| 			} | ||||
| 		} | ||||
| 		_functionCall.annotation().type = resultType; | ||||
| 		_functionCall.annotation().isPure = isPure; | ||||
| @ -2103,7 +2131,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) | ||||
| 				"after argument-dependent lookup in " + exprType->toString() + | ||||
| 				(memberName == "value" ? " - did you forget the \"payable\" modifier?" : "."); | ||||
| 		if (exprType->category() == Type::Category::Contract) | ||||
| 			for (auto const& addressMember: AddressType().nativeMembers(nullptr)) | ||||
| 			for (auto const& addressMember: AddressType(StateMutability::Payable).nativeMembers(nullptr)) | ||||
| 				if (addressMember.name == memberName) | ||||
| 				{ | ||||
| 					Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression()); | ||||
| @ -2354,7 +2382,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 = make_shared<AddressType>(); | ||||
| 		_literal.annotation().type = make_shared<AddressType>(StateMutability::Payable); | ||||
| 
 | ||||
| 		string msg; | ||||
| 		if (_literal.value().length() != 42) // "0x" + 40 hex digits
 | ||||
|  | ||||
| @ -394,10 +394,15 @@ bool ASTJsonConverter::visit(EventDefinition const& _node) | ||||
| 
 | ||||
| bool ASTJsonConverter::visit(ElementaryTypeName const& _node) | ||||
| { | ||||
| 	setJsonNode(_node, "ElementaryTypeName", { | ||||
| 	std::vector<pair<string, Json::Value>> attributes = { | ||||
| 		make_pair("name", _node.typeName().toString()), | ||||
| 		make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) | ||||
| 	}); | ||||
| 	}; | ||||
| 
 | ||||
| 	if (_node.stateMutability()) | ||||
| 		attributes.emplace_back(make_pair("stateMutability", stateMutabilityToString(*_node.stateMutability()))); | ||||
| 
 | ||||
| 	setJsonNode(_node, "ElementaryTypeName", std::move(attributes)); | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -299,7 +299,7 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) | ||||
| 	case Token::Byte: | ||||
| 		return make_shared<FixedBytesType>(1); | ||||
| 	case Token::Address: | ||||
| 		return make_shared<AddressType>(); | ||||
| 		return make_shared<AddressType>(StateMutability::NonPayable); | ||||
| 	case Token::Bool: | ||||
| 		return make_shared<BoolType>(); | ||||
| 	case Token::Bytes: | ||||
| @ -340,6 +340,17 @@ TypePointer Type::fromElementaryTypeName(string const& _name) | ||||
| 		} | ||||
| 		return ref->copyForLocation(location, true); | ||||
| 	} | ||||
| 	else if (t->category() == Type::Category::Address) | ||||
| 	{ | ||||
| 		if (nameParts.size() == 2) | ||||
| 		{ | ||||
| 			if (nameParts[1] == "payable") | ||||
| 				return make_shared<AddressType>(StateMutability::Payable); | ||||
| 			else | ||||
| 				solAssert(false, "Invalid state mutability for address type: " + nameParts[1]); | ||||
| 		} | ||||
| 		return make_shared<AddressType>(StateMutability::NonPayable); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		solAssert(nameParts.size() == 1, "Storage location suffix only allowed for reference types"); | ||||
| @ -439,20 +450,47 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition | ||||
| 	return members; | ||||
| } | ||||
| 
 | ||||
| AddressType::AddressType(StateMutability _stateMutability): | ||||
| 	m_stateMutability(_stateMutability) | ||||
| { | ||||
| 	solAssert(m_stateMutability == StateMutability::Payable || m_stateMutability == StateMutability::NonPayable, ""); | ||||
| } | ||||
| 
 | ||||
| string AddressType::richIdentifier() const | ||||
| { | ||||
| 	return "t_address"; | ||||
| 	if (m_stateMutability == StateMutability::Payable) | ||||
| 		return "t_address_payable"; | ||||
| 	else | ||||
| 		return "t_address"; | ||||
| } | ||||
| 
 | ||||
| bool AddressType::isImplicitlyConvertibleTo(Type const& _other) const | ||||
| { | ||||
| 	if (_other.category() != category()) | ||||
| 		return false; | ||||
| 	AddressType const& other = dynamic_cast<AddressType const&>(_other); | ||||
| 
 | ||||
| 	return other.m_stateMutability <= m_stateMutability; | ||||
| } | ||||
| 
 | ||||
| bool AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const | ||||
| { | ||||
| 	if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo)) | ||||
| 		return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable(); | ||||
| 	return isImplicitlyConvertibleTo(_convertTo) || | ||||
| 		   _convertTo.category() == Category::Contract || | ||||
| 		   _convertTo.category() == Category::Integer || | ||||
| 		   (_convertTo.category() == Category::FixedBytes && 160 == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8); | ||||
| } | ||||
| 
 | ||||
| string AddressType::toString(bool) const | ||||
| { | ||||
| 	if (m_stateMutability == StateMutability::Payable) | ||||
| 		return "address payable"; | ||||
| 	else | ||||
| 		return "address"; | ||||
| } | ||||
| 
 | ||||
| string AddressType::canonicalName() const | ||||
| { | ||||
| 	return "address"; | ||||
| } | ||||
| @ -479,17 +517,29 @@ TypePointer AddressType::binaryOperatorResult(Token::Value _operator, TypePointe | ||||
| 	return Type::commonType(shared_from_this(), _other); | ||||
| } | ||||
| 
 | ||||
| bool AddressType::operator==(Type const& _other) const | ||||
| { | ||||
| 	if (_other.category() != category()) | ||||
| 		return false; | ||||
| 	AddressType const& other = dynamic_cast<AddressType const&>(_other); | ||||
| 	return other.m_stateMutability == m_stateMutability; | ||||
| } | ||||
| 
 | ||||
| MemberList::MemberMap AddressType::nativeMembers(ContractDefinition const*) const | ||||
| { | ||||
| 	return { | ||||
| 	MemberList::MemberMap members = { | ||||
| 		{"balance", make_shared<IntegerType>(256)}, | ||||
| 		{"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, | ||||
| 		{"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, | ||||
| 		{"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false)}, | ||||
| 		{"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}, | ||||
| 		{"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, | ||||
| 		{"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)} | ||||
| 		{"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)} | ||||
| 	}; | ||||
| 	if (m_stateMutability == StateMutability::Payable) | ||||
| 	{ | ||||
| 		members.emplace_back(MemberList::Member{"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}); | ||||
| 		members.emplace_back(MemberList::Member{"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)}); | ||||
| 	} | ||||
| 	return members; | ||||
| } | ||||
| 
 | ||||
| namespace | ||||
| @ -1476,7 +1526,9 @@ bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const | ||||
| 
 | ||||
| bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const | ||||
| { | ||||
| 	return isImplicitlyConvertibleTo(_convertTo) || _convertTo.category() == Category::Address; | ||||
| 	if (auto const* addressType = dynamic_cast<AddressType const*>(&_convertTo)) | ||||
| 		return isPayable() || (addressType->stateMutability() < StateMutability::Payable); | ||||
| 	return isImplicitlyConvertibleTo(_convertTo); | ||||
| } | ||||
| 
 | ||||
| bool ContractType::isPayable() const | ||||
| @ -3275,7 +3327,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const | ||||
| 	{ | ||||
| 	case Kind::Block: | ||||
| 		return MemberList::MemberMap({ | ||||
| 			{"coinbase", make_shared<AddressType>()}, | ||||
| 			{"coinbase", make_shared<AddressType>(StateMutability::Payable)}, | ||||
| 			{"timestamp", make_shared<IntegerType>(256)}, | ||||
| 			{"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)}, | ||||
| 			{"difficulty", make_shared<IntegerType>(256)}, | ||||
| @ -3284,7 +3336,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const | ||||
| 		}); | ||||
| 	case Kind::Message: | ||||
| 		return MemberList::MemberMap({ | ||||
| 			{"sender", make_shared<AddressType>()}, | ||||
| 			{"sender", make_shared<AddressType>(StateMutability::Payable)}, | ||||
| 			{"gas", make_shared<IntegerType>(256)}, | ||||
| 			{"value", make_shared<IntegerType>(256)}, | ||||
| 			{"data", make_shared<ArrayType>(DataLocation::CallData)}, | ||||
| @ -3292,7 +3344,7 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const | ||||
| 		}); | ||||
| 	case Kind::Transaction: | ||||
| 		return MemberList::MemberMap({ | ||||
| 			{"origin", make_shared<AddressType>()}, | ||||
| 			{"origin", make_shared<AddressType>(StateMutability::Payable)}, | ||||
| 			{"gasprice", make_shared<IntegerType>(256)} | ||||
| 		}); | ||||
| 	case Kind::ABI: | ||||
|  | ||||
| @ -321,15 +321,16 @@ class AddressType: public Type | ||||
| public: | ||||
| 	virtual Category category() const override { return Category::Address; } | ||||
| 
 | ||||
| 	explicit AddressType() | ||||
| 	{ | ||||
| 	} | ||||
| 	explicit AddressType(StateMutability _stateMutability); | ||||
| 
 | ||||
| 	virtual std::string richIdentifier() const override; | ||||
| 	virtual bool isImplicitlyConvertibleTo(Type const& _other) const override; | ||||
| 	virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; | ||||
| 	virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; | ||||
| 	virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; | ||||
| 
 | ||||
| 	virtual bool operator==(Type const& _other) const override; | ||||
| 
 | ||||
| 	virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : 160 / 8; } | ||||
| 	virtual unsigned storageBytes() const override { return 160 / 8; } | ||||
| 	virtual bool isValueType() const override { return true; } | ||||
| @ -337,11 +338,17 @@ public: | ||||
| 	virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; | ||||
| 
 | ||||
| 	virtual std::string toString(bool _short) const override; | ||||
| 	virtual std::string canonicalName() const override; | ||||
| 
 | ||||
| 	virtual u256 literalValue(Literal const* _literal) const override; | ||||
| 
 | ||||
| 	virtual TypePointer encodingType() const override { return shared_from_this(); } | ||||
| 	virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } | ||||
| 
 | ||||
| 	StateMutability stateMutability(void) const { return m_stateMutability; } | ||||
| 
 | ||||
| private: | ||||
| 	StateMutability m_stateMutability; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -755,7 +762,7 @@ public: | ||||
| 	{ | ||||
| 		if (isSuper()) | ||||
| 			return TypePointer{}; | ||||
| 		return std::make_shared<AddressType>(); | ||||
| 		return std::make_shared<AddressType>(isPayable() ? StateMutability::Payable : StateMutability::NonPayable); | ||||
| 	} | ||||
| 	virtual TypePointer interfaceType(bool _inLibrary) const override | ||||
| 	{ | ||||
|  | ||||
| @ -242,8 +242,14 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) | ||||
| 			break; | ||||
| 		} | ||||
| 		case Type::Category::Contract: | ||||
| 			templ("body", "cleaned := " + cleanupFunction(AddressType()) + "(value)"); | ||||
| 		{ | ||||
| 			AddressType addressType(dynamic_cast<ContractType const&>(_type).isPayable() ? | ||||
| 				StateMutability::Payable : | ||||
| 				StateMutability::NonPayable | ||||
| 			); | ||||
| 			templ("body", "cleaned := " + cleanupFunction(addressType) + "(value)"); | ||||
| 			break; | ||||
| 		} | ||||
| 		case Type::Category::Enum: | ||||
| 		{ | ||||
| 			size_t members = dynamic_cast<EnumType const&>(_type).numberOfMembers(); | ||||
|  | ||||
| @ -1259,7 +1259,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | ||||
| 				identifier = FunctionType(*function).externalIdentifier(); | ||||
| 			else | ||||
| 				solAssert(false, "Contract member is neither variable nor function."); | ||||
| 			utils().convertType(type, AddressType(), true); | ||||
| 			utils().convertType(type, AddressType(type.isPayable() ? StateMutability::Payable : StateMutability::NonPayable), true); | ||||
| 			m_context << identifier; | ||||
| 		} | ||||
| 		else | ||||
| @ -1277,15 +1277,24 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) | ||||
| 		{ | ||||
| 			utils().convertType( | ||||
| 				*_memberAccess.expression().annotation().type, | ||||
| 				AddressType(), | ||||
| 				AddressType(StateMutability::NonPayable), | ||||
| 				true | ||||
| 			); | ||||
| 			m_context << Instruction::BALANCE; | ||||
| 		} | ||||
| 		else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall", "staticcall"}).count(member)) | ||||
| 		else if ((set<string>{"send", "transfer"}).count(member)) | ||||
| 		{ | ||||
| 			solAssert(dynamic_cast<AddressType const&>(*_memberAccess.expression().annotation().type).stateMutability() == StateMutability::Payable, ""); | ||||
| 			utils().convertType( | ||||
| 				*_memberAccess.expression().annotation().type, | ||||
| 				AddressType(), | ||||
| 				AddressType(StateMutability::Payable), | ||||
| 				true | ||||
| 			); | ||||
| 		} | ||||
| 		else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member)) | ||||
| 			utils().convertType( | ||||
| 				*_memberAccess.expression().annotation().type, | ||||
| 				AddressType(StateMutability::NonPayable), | ||||
| 				true | ||||
| 			); | ||||
| 		else | ||||
|  | ||||
							
								
								
									
										560
									
								
								test/libsolidity/ASTJSON/address_payable.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										560
									
								
								test/libsolidity/ASTJSON/address_payable.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,560 @@ | ||||
| { | ||||
| 	"absolutePath" : "a", | ||||
| 	"exportedSymbols" :  | ||||
| 	{ | ||||
| 		"C" :  | ||||
| 		[ | ||||
| 			37 | ||||
| 		] | ||||
| 	}, | ||||
| 	"id" : 38, | ||||
| 	"nodeType" : "SourceUnit", | ||||
| 	"nodes" :  | ||||
| 	[ | ||||
| 		{ | ||||
| 			"baseContracts" : [], | ||||
| 			"contractDependencies" : [], | ||||
| 			"contractKind" : "contract", | ||||
| 			"documentation" : null, | ||||
| 			"fullyImplemented" : true, | ||||
| 			"id" : 37, | ||||
| 			"linearizedBaseContracts" :  | ||||
| 			[ | ||||
| 				37 | ||||
| 			], | ||||
| 			"name" : "C", | ||||
| 			"nodeType" : "ContractDefinition", | ||||
| 			"nodes" :  | ||||
| 			[ | ||||
| 				{ | ||||
| 					"constant" : false, | ||||
| 					"id" : 4, | ||||
| 					"name" : "m", | ||||
| 					"nodeType" : "VariableDeclaration", | ||||
| 					"scope" : 37, | ||||
| 					"src" : "17:44:1", | ||||
| 					"stateVariable" : true, | ||||
| 					"storageLocation" : "default", | ||||
| 					"typeDescriptions" :  | ||||
| 					{ | ||||
| 						"typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", | ||||
| 						"typeString" : "mapping(address => address payable)" | ||||
| 					}, | ||||
| 					"typeName" :  | ||||
| 					{ | ||||
| 						"id" : 3, | ||||
| 						"keyType" :  | ||||
| 						{ | ||||
| 							"id" : 1, | ||||
| 							"name" : "address", | ||||
| 							"nodeType" : "ElementaryTypeName", | ||||
| 							"src" : "25:7:1", | ||||
| 							"typeDescriptions" :  | ||||
| 							{ | ||||
| 								"typeIdentifier" : "t_address", | ||||
| 								"typeString" : "address" | ||||
| 							} | ||||
| 						}, | ||||
| 						"nodeType" : "Mapping", | ||||
| 						"src" : "17:35:1", | ||||
| 						"typeDescriptions" :  | ||||
| 						{ | ||||
| 							"typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", | ||||
| 							"typeString" : "mapping(address => address payable)" | ||||
| 						}, | ||||
| 						"valueType" :  | ||||
| 						{ | ||||
| 							"id" : 2, | ||||
| 							"name" : "address", | ||||
| 							"nodeType" : "ElementaryTypeName", | ||||
| 							"src" : "36:15:1", | ||||
| 							"stateMutability" : "payable", | ||||
| 							"typeDescriptions" :  | ||||
| 							{ | ||||
| 								"typeIdentifier" : "t_address_payable", | ||||
| 								"typeString" : "address payable" | ||||
| 							} | ||||
| 						} | ||||
| 					}, | ||||
| 					"value" : null, | ||||
| 					"visibility" : "public" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"body" :  | ||||
| 					{ | ||||
| 						"id" : 35, | ||||
| 						"nodeType" : "Block", | ||||
| 						"src" : "134:122:1", | ||||
| 						"statements" :  | ||||
| 						[ | ||||
| 							{ | ||||
| 								"assignments" :  | ||||
| 								[ | ||||
| 									12 | ||||
| 								], | ||||
| 								"declarations" :  | ||||
| 								[ | ||||
| 									{ | ||||
| 										"constant" : false, | ||||
| 										"id" : 12, | ||||
| 										"name" : "a", | ||||
| 										"nodeType" : "VariableDeclaration", | ||||
| 										"scope" : 35, | ||||
| 										"src" : "144:17:1", | ||||
| 										"stateVariable" : false, | ||||
| 										"storageLocation" : "default", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										}, | ||||
| 										"typeName" :  | ||||
| 										{ | ||||
| 											"id" : 11, | ||||
| 											"name" : "address", | ||||
| 											"nodeType" : "ElementaryTypeName", | ||||
| 											"src" : "144:15:1", | ||||
| 											"stateMutability" : "payable", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_address_payable", | ||||
| 												"typeString" : "address payable" | ||||
| 											} | ||||
| 										}, | ||||
| 										"value" : null, | ||||
| 										"visibility" : "internal" | ||||
| 									} | ||||
| 								], | ||||
| 								"id" : 16, | ||||
| 								"initialValue" :  | ||||
| 								{ | ||||
| 									"argumentTypes" : null, | ||||
| 									"baseExpression" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"id" : 13, | ||||
| 										"name" : "m", | ||||
| 										"nodeType" : "Identifier", | ||||
| 										"overloadedDeclarations" : [], | ||||
| 										"referencedDeclaration" : 4, | ||||
| 										"src" : "164:1:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", | ||||
| 											"typeString" : "mapping(address => address payable)" | ||||
| 										} | ||||
| 									}, | ||||
| 									"id" : 15, | ||||
| 									"indexExpression" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"id" : 14, | ||||
| 										"name" : "arg", | ||||
| 										"nodeType" : "Identifier", | ||||
| 										"overloadedDeclarations" : [], | ||||
| 										"referencedDeclaration" : 6, | ||||
| 										"src" : "166:3:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										} | ||||
| 									}, | ||||
| 									"isConstant" : false, | ||||
| 									"isLValue" : true, | ||||
| 									"isPure" : false, | ||||
| 									"lValueRequested" : false, | ||||
| 									"nodeType" : "IndexAccess", | ||||
| 									"src" : "164:6:1", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address_payable", | ||||
| 										"typeString" : "address payable" | ||||
| 									} | ||||
| 								}, | ||||
| 								"nodeType" : "VariableDeclarationStatement", | ||||
| 								"src" : "144:26:1" | ||||
| 							}, | ||||
| 							{ | ||||
| 								"expression" :  | ||||
| 								{ | ||||
| 									"argumentTypes" : null, | ||||
| 									"id" : 19, | ||||
| 									"isConstant" : false, | ||||
| 									"isLValue" : false, | ||||
| 									"isPure" : false, | ||||
| 									"lValueRequested" : false, | ||||
| 									"leftHandSide" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"id" : 17, | ||||
| 										"name" : "r", | ||||
| 										"nodeType" : "Identifier", | ||||
| 										"overloadedDeclarations" : [], | ||||
| 										"referencedDeclaration" : 9, | ||||
| 										"src" : "180:1:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										} | ||||
| 									}, | ||||
| 									"nodeType" : "Assignment", | ||||
| 									"operator" : "=", | ||||
| 									"rightHandSide" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"id" : 18, | ||||
| 										"name" : "arg", | ||||
| 										"nodeType" : "Identifier", | ||||
| 										"overloadedDeclarations" : [], | ||||
| 										"referencedDeclaration" : 6, | ||||
| 										"src" : "184:3:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										} | ||||
| 									}, | ||||
| 									"src" : "180:7:1", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address_payable", | ||||
| 										"typeString" : "address payable" | ||||
| 									} | ||||
| 								}, | ||||
| 								"id" : 20, | ||||
| 								"nodeType" : "ExpressionStatement", | ||||
| 								"src" : "180:7:1" | ||||
| 							}, | ||||
| 							{ | ||||
| 								"assignments" :  | ||||
| 								[ | ||||
| 									22 | ||||
| 								], | ||||
| 								"declarations" :  | ||||
| 								[ | ||||
| 									{ | ||||
| 										"constant" : false, | ||||
| 										"id" : 22, | ||||
| 										"name" : "c", | ||||
| 										"nodeType" : "VariableDeclaration", | ||||
| 										"scope" : 35, | ||||
| 										"src" : "197:9:1", | ||||
| 										"stateVariable" : false, | ||||
| 										"storageLocation" : "default", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address", | ||||
| 											"typeString" : "address" | ||||
| 										}, | ||||
| 										"typeName" :  | ||||
| 										{ | ||||
| 											"id" : 21, | ||||
| 											"name" : "address", | ||||
| 											"nodeType" : "ElementaryTypeName", | ||||
| 											"src" : "197:7:1", | ||||
| 											"stateMutability" : "nonpayable", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_address", | ||||
| 												"typeString" : "address" | ||||
| 											} | ||||
| 										}, | ||||
| 										"value" : null, | ||||
| 										"visibility" : "internal" | ||||
| 									} | ||||
| 								], | ||||
| 								"id" : 26, | ||||
| 								"initialValue" :  | ||||
| 								{ | ||||
| 									"argumentTypes" : null, | ||||
| 									"arguments" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"argumentTypes" : null, | ||||
| 											"id" : 24, | ||||
| 											"name" : "this", | ||||
| 											"nodeType" : "Identifier", | ||||
| 											"overloadedDeclarations" : [], | ||||
| 											"referencedDeclaration" : 65, | ||||
| 											"src" : "217:4:1", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_contract$_C_$37", | ||||
| 												"typeString" : "contract C" | ||||
| 											} | ||||
| 										} | ||||
| 									], | ||||
| 									"expression" :  | ||||
| 									{ | ||||
| 										"argumentTypes" :  | ||||
| 										[ | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_contract$_C_$37", | ||||
| 												"typeString" : "contract C" | ||||
| 											} | ||||
| 										], | ||||
| 										"id" : 23, | ||||
| 										"isConstant" : false, | ||||
| 										"isLValue" : false, | ||||
| 										"isPure" : true, | ||||
| 										"lValueRequested" : false, | ||||
| 										"nodeType" : "ElementaryTypeNameExpression", | ||||
| 										"src" : "209:7:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_type$_t_address_$", | ||||
| 											"typeString" : "type(address)" | ||||
| 										}, | ||||
| 										"typeName" : "address" | ||||
| 									}, | ||||
| 									"id" : 25, | ||||
| 									"isConstant" : false, | ||||
| 									"isLValue" : false, | ||||
| 									"isPure" : false, | ||||
| 									"kind" : "typeConversion", | ||||
| 									"lValueRequested" : false, | ||||
| 									"names" : [], | ||||
| 									"nodeType" : "FunctionCall", | ||||
| 									"src" : "209:13:1", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address", | ||||
| 										"typeString" : "address" | ||||
| 									} | ||||
| 								}, | ||||
| 								"nodeType" : "VariableDeclarationStatement", | ||||
| 								"src" : "197:25:1" | ||||
| 							}, | ||||
| 							{ | ||||
| 								"expression" :  | ||||
| 								{ | ||||
| 									"argumentTypes" : null, | ||||
| 									"id" : 33, | ||||
| 									"isConstant" : false, | ||||
| 									"isLValue" : false, | ||||
| 									"isPure" : false, | ||||
| 									"lValueRequested" : false, | ||||
| 									"leftHandSide" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"baseExpression" :  | ||||
| 										{ | ||||
| 											"argumentTypes" : null, | ||||
| 											"id" : 27, | ||||
| 											"name" : "m", | ||||
| 											"nodeType" : "Identifier", | ||||
| 											"overloadedDeclarations" : [], | ||||
| 											"referencedDeclaration" : 4, | ||||
| 											"src" : "232:1:1", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_mapping$_t_address_$_t_address_payable_$", | ||||
| 												"typeString" : "mapping(address => address payable)" | ||||
| 											} | ||||
| 										}, | ||||
| 										"id" : 29, | ||||
| 										"indexExpression" :  | ||||
| 										{ | ||||
| 											"argumentTypes" : null, | ||||
| 											"id" : 28, | ||||
| 											"name" : "c", | ||||
| 											"nodeType" : "Identifier", | ||||
| 											"overloadedDeclarations" : [], | ||||
| 											"referencedDeclaration" : 22, | ||||
| 											"src" : "234:1:1", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_address", | ||||
| 												"typeString" : "address" | ||||
| 											} | ||||
| 										}, | ||||
| 										"isConstant" : false, | ||||
| 										"isLValue" : true, | ||||
| 										"isPure" : false, | ||||
| 										"lValueRequested" : true, | ||||
| 										"nodeType" : "IndexAccess", | ||||
| 										"src" : "232:4:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										} | ||||
| 									}, | ||||
| 									"nodeType" : "Assignment", | ||||
| 									"operator" : "=", | ||||
| 									"rightHandSide" :  | ||||
| 									{ | ||||
| 										"argumentTypes" : null, | ||||
| 										"arguments" :  | ||||
| 										[ | ||||
| 											{ | ||||
| 												"argumentTypes" : null, | ||||
| 												"hexValue" : "30", | ||||
| 												"id" : 31, | ||||
| 												"isConstant" : false, | ||||
| 												"isLValue" : false, | ||||
| 												"isPure" : true, | ||||
| 												"kind" : "number", | ||||
| 												"lValueRequested" : false, | ||||
| 												"nodeType" : "Literal", | ||||
| 												"src" : "247:1:1", | ||||
| 												"subdenomination" : null, | ||||
| 												"typeDescriptions" :  | ||||
| 												{ | ||||
| 													"typeIdentifier" : "t_rational_0_by_1", | ||||
| 													"typeString" : "int_const 0" | ||||
| 												}, | ||||
| 												"value" : "0" | ||||
| 											} | ||||
| 										], | ||||
| 										"expression" :  | ||||
| 										{ | ||||
| 											"argumentTypes" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"typeIdentifier" : "t_rational_0_by_1", | ||||
| 													"typeString" : "int_const 0" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 30, | ||||
| 											"isConstant" : false, | ||||
| 											"isLValue" : false, | ||||
| 											"isPure" : true, | ||||
| 											"lValueRequested" : false, | ||||
| 											"nodeType" : "ElementaryTypeNameExpression", | ||||
| 											"src" : "239:7:1", | ||||
| 											"typeDescriptions" :  | ||||
| 											{ | ||||
| 												"typeIdentifier" : "t_type$_t_address_$", | ||||
| 												"typeString" : "type(address)" | ||||
| 											}, | ||||
| 											"typeName" : "address" | ||||
| 										}, | ||||
| 										"id" : 32, | ||||
| 										"isConstant" : false, | ||||
| 										"isLValue" : false, | ||||
| 										"isPure" : true, | ||||
| 										"kind" : "typeConversion", | ||||
| 										"lValueRequested" : false, | ||||
| 										"names" : [], | ||||
| 										"nodeType" : "FunctionCall", | ||||
| 										"src" : "239:10:1", | ||||
| 										"typeDescriptions" :  | ||||
| 										{ | ||||
| 											"typeIdentifier" : "t_address_payable", | ||||
| 											"typeString" : "address payable" | ||||
| 										} | ||||
| 									}, | ||||
| 									"src" : "232:17:1", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address_payable", | ||||
| 										"typeString" : "address payable" | ||||
| 									} | ||||
| 								}, | ||||
| 								"id" : 34, | ||||
| 								"nodeType" : "ExpressionStatement", | ||||
| 								"src" : "232:17:1" | ||||
| 							} | ||||
| 						] | ||||
| 					}, | ||||
| 					"documentation" : null, | ||||
| 					"id" : 36, | ||||
| 					"implemented" : true, | ||||
| 					"isConstructor" : false, | ||||
| 					"modifiers" : [], | ||||
| 					"name" : "f", | ||||
| 					"nodeType" : "FunctionDefinition", | ||||
| 					"parameters" :  | ||||
| 					{ | ||||
| 						"id" : 7, | ||||
| 						"nodeType" : "ParameterList", | ||||
| 						"parameters" :  | ||||
| 						[ | ||||
| 							{ | ||||
| 								"constant" : false, | ||||
| 								"id" : 6, | ||||
| 								"name" : "arg", | ||||
| 								"nodeType" : "VariableDeclaration", | ||||
| 								"scope" : 36, | ||||
| 								"src" : "78:19:1", | ||||
| 								"stateVariable" : false, | ||||
| 								"storageLocation" : "default", | ||||
| 								"typeDescriptions" :  | ||||
| 								{ | ||||
| 									"typeIdentifier" : "t_address_payable", | ||||
| 									"typeString" : "address payable" | ||||
| 								}, | ||||
| 								"typeName" :  | ||||
| 								{ | ||||
| 									"id" : 5, | ||||
| 									"name" : "address", | ||||
| 									"nodeType" : "ElementaryTypeName", | ||||
| 									"src" : "78:15:1", | ||||
| 									"stateMutability" : "payable", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address_payable", | ||||
| 										"typeString" : "address payable" | ||||
| 									} | ||||
| 								}, | ||||
| 								"value" : null, | ||||
| 								"visibility" : "internal" | ||||
| 							} | ||||
| 						], | ||||
| 						"src" : "77:21:1" | ||||
| 					}, | ||||
| 					"returnParameters" :  | ||||
| 					{ | ||||
| 						"id" : 10, | ||||
| 						"nodeType" : "ParameterList", | ||||
| 						"parameters" :  | ||||
| 						[ | ||||
| 							{ | ||||
| 								"constant" : false, | ||||
| 								"id" : 9, | ||||
| 								"name" : "r", | ||||
| 								"nodeType" : "VariableDeclaration", | ||||
| 								"scope" : 36, | ||||
| 								"src" : "115:17:1", | ||||
| 								"stateVariable" : false, | ||||
| 								"storageLocation" : "default", | ||||
| 								"typeDescriptions" :  | ||||
| 								{ | ||||
| 									"typeIdentifier" : "t_address_payable", | ||||
| 									"typeString" : "address payable" | ||||
| 								}, | ||||
| 								"typeName" :  | ||||
| 								{ | ||||
| 									"id" : 8, | ||||
| 									"name" : "address", | ||||
| 									"nodeType" : "ElementaryTypeName", | ||||
| 									"src" : "115:15:1", | ||||
| 									"stateMutability" : "payable", | ||||
| 									"typeDescriptions" :  | ||||
| 									{ | ||||
| 										"typeIdentifier" : "t_address_payable", | ||||
| 										"typeString" : "address payable" | ||||
| 									} | ||||
| 								}, | ||||
| 								"value" : null, | ||||
| 								"visibility" : "internal" | ||||
| 							} | ||||
| 						], | ||||
| 						"src" : "114:19:1" | ||||
| 					}, | ||||
| 					"scope" : 37, | ||||
| 					"src" : "67:189:1", | ||||
| 					"stateMutability" : "nonpayable", | ||||
| 					"superFunction" : null, | ||||
| 					"visibility" : "public" | ||||
| 				} | ||||
| 			], | ||||
| 			"scope" : 38, | ||||
| 			"src" : "0:258:1" | ||||
| 		} | ||||
| 	], | ||||
| 	"src" : "0:259:1" | ||||
| } | ||||
							
								
								
									
										11
									
								
								test/libsolidity/ASTJSON/address_payable.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								test/libsolidity/ASTJSON/address_payable.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     mapping(address => address payable) public m; | ||||
|     function f(address payable arg) public returns (address payable r) { | ||||
|         address payable a = m[arg]; | ||||
|         r = arg; | ||||
|         address c = address(this); | ||||
|         m[c] = address(0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // ---- | ||||
							
								
								
									
										600
									
								
								test/libsolidity/ASTJSON/address_payable_legacy.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										600
									
								
								test/libsolidity/ASTJSON/address_payable_legacy.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,600 @@ | ||||
| { | ||||
| 	"attributes" :  | ||||
| 	{ | ||||
| 		"absolutePath" : "a", | ||||
| 		"exportedSymbols" :  | ||||
| 		{ | ||||
| 			"C" :  | ||||
| 			[ | ||||
| 				37 | ||||
| 			] | ||||
| 		} | ||||
| 	}, | ||||
| 	"children" :  | ||||
| 	[ | ||||
| 		{ | ||||
| 			"attributes" :  | ||||
| 			{ | ||||
| 				"baseContracts" :  | ||||
| 				[ | ||||
| 					null | ||||
| 				], | ||||
| 				"contractDependencies" :  | ||||
| 				[ | ||||
| 					null | ||||
| 				], | ||||
| 				"contractKind" : "contract", | ||||
| 				"documentation" : null, | ||||
| 				"fullyImplemented" : true, | ||||
| 				"linearizedBaseContracts" :  | ||||
| 				[ | ||||
| 					37 | ||||
| 				], | ||||
| 				"name" : "C", | ||||
| 				"scope" : 38 | ||||
| 			}, | ||||
| 			"children" :  | ||||
| 			[ | ||||
| 				{ | ||||
| 					"attributes" :  | ||||
| 					{ | ||||
| 						"constant" : false, | ||||
| 						"name" : "m", | ||||
| 						"scope" : 37, | ||||
| 						"stateVariable" : true, | ||||
| 						"storageLocation" : "default", | ||||
| 						"type" : "mapping(address => address payable)", | ||||
| 						"value" : null, | ||||
| 						"visibility" : "public" | ||||
| 					}, | ||||
| 					"children" :  | ||||
| 					[ | ||||
| 						{ | ||||
| 							"attributes" :  | ||||
| 							{ | ||||
| 								"type" : "mapping(address => address payable)" | ||||
| 							}, | ||||
| 							"children" :  | ||||
| 							[ | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"name" : "address", | ||||
| 										"type" : "address" | ||||
| 									}, | ||||
| 									"id" : 1, | ||||
| 									"name" : "ElementaryTypeName", | ||||
| 									"src" : "25:7:1" | ||||
| 								}, | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"name" : "address", | ||||
| 										"stateMutability" : "payable", | ||||
| 										"type" : "address payable" | ||||
| 									}, | ||||
| 									"id" : 2, | ||||
| 									"name" : "ElementaryTypeName", | ||||
| 									"src" : "36:15:1" | ||||
| 								} | ||||
| 							], | ||||
| 							"id" : 3, | ||||
| 							"name" : "Mapping", | ||||
| 							"src" : "17:35:1" | ||||
| 						} | ||||
| 					], | ||||
| 					"id" : 4, | ||||
| 					"name" : "VariableDeclaration", | ||||
| 					"src" : "17:44:1" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"attributes" :  | ||||
| 					{ | ||||
| 						"documentation" : null, | ||||
| 						"implemented" : true, | ||||
| 						"isConstructor" : false, | ||||
| 						"modifiers" :  | ||||
| 						[ | ||||
| 							null | ||||
| 						], | ||||
| 						"name" : "f", | ||||
| 						"scope" : 37, | ||||
| 						"stateMutability" : "nonpayable", | ||||
| 						"superFunction" : null, | ||||
| 						"visibility" : "public" | ||||
| 					}, | ||||
| 					"children" :  | ||||
| 					[ | ||||
| 						{ | ||||
| 							"children" :  | ||||
| 							[ | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"constant" : false, | ||||
| 										"name" : "arg", | ||||
| 										"scope" : 36, | ||||
| 										"stateVariable" : false, | ||||
| 										"storageLocation" : "default", | ||||
| 										"type" : "address payable", | ||||
| 										"value" : null, | ||||
| 										"visibility" : "internal" | ||||
| 									}, | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"name" : "address", | ||||
| 												"stateMutability" : "payable", | ||||
| 												"type" : "address payable" | ||||
| 											}, | ||||
| 											"id" : 5, | ||||
| 											"name" : "ElementaryTypeName", | ||||
| 											"src" : "78:15:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 6, | ||||
| 									"name" : "VariableDeclaration", | ||||
| 									"src" : "78:19:1" | ||||
| 								} | ||||
| 							], | ||||
| 							"id" : 7, | ||||
| 							"name" : "ParameterList", | ||||
| 							"src" : "77:21:1" | ||||
| 						}, | ||||
| 						{ | ||||
| 							"children" :  | ||||
| 							[ | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"constant" : false, | ||||
| 										"name" : "r", | ||||
| 										"scope" : 36, | ||||
| 										"stateVariable" : false, | ||||
| 										"storageLocation" : "default", | ||||
| 										"type" : "address payable", | ||||
| 										"value" : null, | ||||
| 										"visibility" : "internal" | ||||
| 									}, | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"name" : "address", | ||||
| 												"stateMutability" : "payable", | ||||
| 												"type" : "address payable" | ||||
| 											}, | ||||
| 											"id" : 8, | ||||
| 											"name" : "ElementaryTypeName", | ||||
| 											"src" : "115:15:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 9, | ||||
| 									"name" : "VariableDeclaration", | ||||
| 									"src" : "115:17:1" | ||||
| 								} | ||||
| 							], | ||||
| 							"id" : 10, | ||||
| 							"name" : "ParameterList", | ||||
| 							"src" : "114:19:1" | ||||
| 						}, | ||||
| 						{ | ||||
| 							"children" :  | ||||
| 							[ | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"assignments" :  | ||||
| 										[ | ||||
| 											12 | ||||
| 										] | ||||
| 									}, | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"constant" : false, | ||||
| 												"name" : "a", | ||||
| 												"scope" : 35, | ||||
| 												"stateVariable" : false, | ||||
| 												"storageLocation" : "default", | ||||
| 												"type" : "address payable", | ||||
| 												"value" : null, | ||||
| 												"visibility" : "internal" | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"name" : "address", | ||||
| 														"stateMutability" : "payable", | ||||
| 														"type" : "address payable" | ||||
| 													}, | ||||
| 													"id" : 11, | ||||
| 													"name" : "ElementaryTypeName", | ||||
| 													"src" : "144:15:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 12, | ||||
| 											"name" : "VariableDeclaration", | ||||
| 											"src" : "144:17:1" | ||||
| 										}, | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"argumentTypes" : null, | ||||
| 												"isConstant" : false, | ||||
| 												"isLValue" : true, | ||||
| 												"isPure" : false, | ||||
| 												"lValueRequested" : false, | ||||
| 												"type" : "address payable" | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"overloadedDeclarations" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"referencedDeclaration" : 4, | ||||
| 														"type" : "mapping(address => address payable)", | ||||
| 														"value" : "m" | ||||
| 													}, | ||||
| 													"id" : 13, | ||||
| 													"name" : "Identifier", | ||||
| 													"src" : "164:1:1" | ||||
| 												}, | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"overloadedDeclarations" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"referencedDeclaration" : 6, | ||||
| 														"type" : "address payable", | ||||
| 														"value" : "arg" | ||||
| 													}, | ||||
| 													"id" : 14, | ||||
| 													"name" : "Identifier", | ||||
| 													"src" : "166:3:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 15, | ||||
| 											"name" : "IndexAccess", | ||||
| 											"src" : "164:6:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 16, | ||||
| 									"name" : "VariableDeclarationStatement", | ||||
| 									"src" : "144:26:1" | ||||
| 								}, | ||||
| 								{ | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"argumentTypes" : null, | ||||
| 												"isConstant" : false, | ||||
| 												"isLValue" : false, | ||||
| 												"isPure" : false, | ||||
| 												"lValueRequested" : false, | ||||
| 												"operator" : "=", | ||||
| 												"type" : "address payable" | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"overloadedDeclarations" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"referencedDeclaration" : 9, | ||||
| 														"type" : "address payable", | ||||
| 														"value" : "r" | ||||
| 													}, | ||||
| 													"id" : 17, | ||||
| 													"name" : "Identifier", | ||||
| 													"src" : "180:1:1" | ||||
| 												}, | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"overloadedDeclarations" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"referencedDeclaration" : 6, | ||||
| 														"type" : "address payable", | ||||
| 														"value" : "arg" | ||||
| 													}, | ||||
| 													"id" : 18, | ||||
| 													"name" : "Identifier", | ||||
| 													"src" : "184:3:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 19, | ||||
| 											"name" : "Assignment", | ||||
| 											"src" : "180:7:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 20, | ||||
| 									"name" : "ExpressionStatement", | ||||
| 									"src" : "180:7:1" | ||||
| 								}, | ||||
| 								{ | ||||
| 									"attributes" :  | ||||
| 									{ | ||||
| 										"assignments" :  | ||||
| 										[ | ||||
| 											22 | ||||
| 										] | ||||
| 									}, | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"constant" : false, | ||||
| 												"name" : "c", | ||||
| 												"scope" : 35, | ||||
| 												"stateVariable" : false, | ||||
| 												"storageLocation" : "default", | ||||
| 												"type" : "address", | ||||
| 												"value" : null, | ||||
| 												"visibility" : "internal" | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"name" : "address", | ||||
| 														"stateMutability" : "nonpayable", | ||||
| 														"type" : "address" | ||||
| 													}, | ||||
| 													"id" : 21, | ||||
| 													"name" : "ElementaryTypeName", | ||||
| 													"src" : "197:7:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 22, | ||||
| 											"name" : "VariableDeclaration", | ||||
| 											"src" : "197:9:1" | ||||
| 										}, | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"argumentTypes" : null, | ||||
| 												"isConstant" : false, | ||||
| 												"isLValue" : false, | ||||
| 												"isPure" : false, | ||||
| 												"isStructConstructorCall" : false, | ||||
| 												"lValueRequested" : false, | ||||
| 												"names" :  | ||||
| 												[ | ||||
| 													null | ||||
| 												], | ||||
| 												"type" : "address", | ||||
| 												"type_conversion" : true | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" :  | ||||
| 														[ | ||||
| 															{ | ||||
| 																"typeIdentifier" : "t_contract$_C_$37", | ||||
| 																"typeString" : "contract C" | ||||
| 															} | ||||
| 														], | ||||
| 														"isConstant" : false, | ||||
| 														"isLValue" : false, | ||||
| 														"isPure" : true, | ||||
| 														"lValueRequested" : false, | ||||
| 														"type" : "type(address)", | ||||
| 														"value" : "address" | ||||
| 													}, | ||||
| 													"id" : 23, | ||||
| 													"name" : "ElementaryTypeNameExpression", | ||||
| 													"src" : "209:7:1" | ||||
| 												}, | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"overloadedDeclarations" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"referencedDeclaration" : 65, | ||||
| 														"type" : "contract C", | ||||
| 														"value" : "this" | ||||
| 													}, | ||||
| 													"id" : 24, | ||||
| 													"name" : "Identifier", | ||||
| 													"src" : "217:4:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 25, | ||||
| 											"name" : "FunctionCall", | ||||
| 											"src" : "209:13:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 26, | ||||
| 									"name" : "VariableDeclarationStatement", | ||||
| 									"src" : "197:25:1" | ||||
| 								}, | ||||
| 								{ | ||||
| 									"children" :  | ||||
| 									[ | ||||
| 										{ | ||||
| 											"attributes" :  | ||||
| 											{ | ||||
| 												"argumentTypes" : null, | ||||
| 												"isConstant" : false, | ||||
| 												"isLValue" : false, | ||||
| 												"isPure" : false, | ||||
| 												"lValueRequested" : false, | ||||
| 												"operator" : "=", | ||||
| 												"type" : "address payable" | ||||
| 											}, | ||||
| 											"children" :  | ||||
| 											[ | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"isConstant" : false, | ||||
| 														"isLValue" : true, | ||||
| 														"isPure" : false, | ||||
| 														"lValueRequested" : true, | ||||
| 														"type" : "address payable" | ||||
| 													}, | ||||
| 													"children" :  | ||||
| 													[ | ||||
| 														{ | ||||
| 															"attributes" :  | ||||
| 															{ | ||||
| 																"argumentTypes" : null, | ||||
| 																"overloadedDeclarations" :  | ||||
| 																[ | ||||
| 																	null | ||||
| 																], | ||||
| 																"referencedDeclaration" : 4, | ||||
| 																"type" : "mapping(address => address payable)", | ||||
| 																"value" : "m" | ||||
| 															}, | ||||
| 															"id" : 27, | ||||
| 															"name" : "Identifier", | ||||
| 															"src" : "232:1:1" | ||||
| 														}, | ||||
| 														{ | ||||
| 															"attributes" :  | ||||
| 															{ | ||||
| 																"argumentTypes" : null, | ||||
| 																"overloadedDeclarations" :  | ||||
| 																[ | ||||
| 																	null | ||||
| 																], | ||||
| 																"referencedDeclaration" : 22, | ||||
| 																"type" : "address", | ||||
| 																"value" : "c" | ||||
| 															}, | ||||
| 															"id" : 28, | ||||
| 															"name" : "Identifier", | ||||
| 															"src" : "234:1:1" | ||||
| 														} | ||||
| 													], | ||||
| 													"id" : 29, | ||||
| 													"name" : "IndexAccess", | ||||
| 													"src" : "232:4:1" | ||||
| 												}, | ||||
| 												{ | ||||
| 													"attributes" :  | ||||
| 													{ | ||||
| 														"argumentTypes" : null, | ||||
| 														"isConstant" : false, | ||||
| 														"isLValue" : false, | ||||
| 														"isPure" : true, | ||||
| 														"isStructConstructorCall" : false, | ||||
| 														"lValueRequested" : false, | ||||
| 														"names" :  | ||||
| 														[ | ||||
| 															null | ||||
| 														], | ||||
| 														"type" : "address payable", | ||||
| 														"type_conversion" : true | ||||
| 													}, | ||||
| 													"children" :  | ||||
| 													[ | ||||
| 														{ | ||||
| 															"attributes" :  | ||||
| 															{ | ||||
| 																"argumentTypes" :  | ||||
| 																[ | ||||
| 																	{ | ||||
| 																		"typeIdentifier" : "t_rational_0_by_1", | ||||
| 																		"typeString" : "int_const 0" | ||||
| 																	} | ||||
| 																], | ||||
| 																"isConstant" : false, | ||||
| 																"isLValue" : false, | ||||
| 																"isPure" : true, | ||||
| 																"lValueRequested" : false, | ||||
| 																"type" : "type(address)", | ||||
| 																"value" : "address" | ||||
| 															}, | ||||
| 															"id" : 30, | ||||
| 															"name" : "ElementaryTypeNameExpression", | ||||
| 															"src" : "239:7:1" | ||||
| 														}, | ||||
| 														{ | ||||
| 															"attributes" :  | ||||
| 															{ | ||||
| 																"argumentTypes" : null, | ||||
| 																"hexvalue" : "30", | ||||
| 																"isConstant" : false, | ||||
| 																"isLValue" : false, | ||||
| 																"isPure" : true, | ||||
| 																"lValueRequested" : false, | ||||
| 																"subdenomination" : null, | ||||
| 																"token" : "number", | ||||
| 																"type" : "int_const 0", | ||||
| 																"value" : "0" | ||||
| 															}, | ||||
| 															"id" : 31, | ||||
| 															"name" : "Literal", | ||||
| 															"src" : "247:1:1" | ||||
| 														} | ||||
| 													], | ||||
| 													"id" : 32, | ||||
| 													"name" : "FunctionCall", | ||||
| 													"src" : "239:10:1" | ||||
| 												} | ||||
| 											], | ||||
| 											"id" : 33, | ||||
| 											"name" : "Assignment", | ||||
| 											"src" : "232:17:1" | ||||
| 										} | ||||
| 									], | ||||
| 									"id" : 34, | ||||
| 									"name" : "ExpressionStatement", | ||||
| 									"src" : "232:17:1" | ||||
| 								} | ||||
| 							], | ||||
| 							"id" : 35, | ||||
| 							"name" : "Block", | ||||
| 							"src" : "134:122:1" | ||||
| 						} | ||||
| 					], | ||||
| 					"id" : 36, | ||||
| 					"name" : "FunctionDefinition", | ||||
| 					"src" : "67:189:1" | ||||
| 				} | ||||
| 			], | ||||
| 			"id" : 37, | ||||
| 			"name" : "ContractDefinition", | ||||
| 			"src" : "0:258:1" | ||||
| 		} | ||||
| 	], | ||||
| 	"id" : 38, | ||||
| 	"name" : "SourceUnit", | ||||
| 	"src" : "0:259:1" | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| contract C { | ||||
|     struct S { | ||||
|         address payable a; | ||||
|         address b; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     address a; | ||||
|     function f(address b) public pure returns (address c) { | ||||
|         address d = b; | ||||
|         return d; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										7
									
								
								test/libsolidity/syntaxTests/parsing/address_payable.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/libsolidity/syntaxTests/parsing/address_payable.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     address payable a; | ||||
|     function f(address payable b) public pure returns (address payable c) { | ||||
|         address payable d = b; | ||||
|         return d; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| contract C { | ||||
|     function f(bytes memory b) public pure returns (address payable) { | ||||
|         (address payable c) = abi.decode(b, (address)); | ||||
|         return c; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     address constant a = address(0); | ||||
|     address payable constant b = address(0); | ||||
|     function f() public pure returns (address, address) { | ||||
|         return (a,b); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     address constant a = address(0); | ||||
|     address payable constant b = address(0); | ||||
|     function f() public { | ||||
|         a = address(0); | ||||
|         b = address(0); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (129-130): Cannot assign to a constant variable. | ||||
| // TypeError: (153-154): Cannot assign to a constant variable. | ||||
| @ -0,0 +1,11 @@ | ||||
| contract A { | ||||
|     struct S { | ||||
|         address payable a; | ||||
|     } | ||||
|     S s; | ||||
|     function f() public { | ||||
|         s.a = address(this); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (110-123): Type address is not implicitly convertible to expected type address payable. | ||||
| @ -0,0 +1,20 @@ | ||||
| contract A { | ||||
|     struct S { | ||||
|         address a; | ||||
|     } | ||||
|     S s; | ||||
|     function f() public { | ||||
|         s.a = address(this); | ||||
|     } | ||||
| } | ||||
| contract B { | ||||
|     struct S { | ||||
|         address payable a; | ||||
|     } | ||||
|     S s; | ||||
|     function f() public { | ||||
|         s.a = address(this); | ||||
|     } | ||||
|     function() external payable { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f(address a) public { | ||||
|         selfdestruct(a); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (69-70): Invalid type for argument in function call. Invalid implicit conversion from address to address payable requested. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f(address) external pure {} | ||||
|     function f(address payable) external pure {} | ||||
| 
 | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (58-102): Function overload clash during conversion to external types for arguments. | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|     function f(address payable) internal pure {} | ||||
|     function f(address) internal pure returns (uint) {} | ||||
|     function g() internal pure { | ||||
|         address a = address(0); | ||||
|         uint b = f(a); // TODO: should this be valid? | ||||
|         b; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|     function f(address payable) internal pure {} | ||||
|     function f(address) internal pure {} | ||||
|     function g() internal pure { | ||||
|         address payable a = address(0); | ||||
|         f(a); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (184-185): No unique declaration found after argument-dependent lookup. | ||||
| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     function f() public pure { | ||||
|         address payable[] memory a = new address payable[](4); | ||||
|         address[] memory b = new address[](4); | ||||
|         a = b; | ||||
|         b = a; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (166-167): Type address[] memory is not implicitly convertible to expected type address payable[] memory. | ||||
| // TypeError: (181-182): Type address payable[] memory is not implicitly convertible to expected type address[] memory. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f(address) public pure {} | ||||
|     function f(address payable) public pure {} | ||||
| 
 | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (56-98): Function overload clash during conversion to external types for arguments. | ||||
| @ -0,0 +1,5 @@ | ||||
| contract C { | ||||
|     function f(address payable a) public { | ||||
|         selfdestruct(a); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     address payable[] a; | ||||
|     address[] b; | ||||
|     function f() public view { | ||||
|         address payable[] storage c = a; | ||||
|         address[] storage d = b; | ||||
|         d = c; // TODO: this could be allowed in the future | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (172-173): Type address payable[] storage pointer is not implicitly convertible to expected type address[] storage pointer. | ||||
| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     address payable[] a; | ||||
|     address[] b; | ||||
|     function f() public view { | ||||
|         address payable[] storage c = a; | ||||
|         address[] storage d = b; | ||||
|         c = d; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (172-173): Type address[] storage pointer is not implicitly convertible to expected type address payable[] storage pointer. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     C c = address(2); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-62): Type address payable is not implicitly convertible to expected type contract C. | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|   function f() public pure returns (C c) { | ||||
|     c = C(address(2)); | ||||
|   } | ||||
|   function() external payable { | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|     function f(address a) public pure { | ||||
|         address b; | ||||
|         address payable c = a; | ||||
|         c = b; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (80-101): Type address is not implicitly convertible to expected type address payable. | ||||
| // TypeError: (115-116): Type address is not implicitly convertible to expected type address payable. | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|     function f() public view returns (address payable a, address b) { | ||||
|         (address c, address payable d) = (address(this), address(0)); | ||||
|         (a,b) = (c,d); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (169-174): Type tuple(address,address payable) is not implicitly convertible to expected type tuple(address payable,address). | ||||
| @ -0,0 +1,6 @@ | ||||
| contract C { | ||||
|     function f() public view returns (address payable a, address b) { | ||||
|         (address c, address payable d) = (address(this), address(0)); | ||||
|         (a,b) = (d,c); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address payable a = address(this); | ||||
|     a; | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-79): Type address is not implicitly convertible to expected type address payable. | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address payable a = address(this); | ||||
|     a; | ||||
|   } | ||||
|   function() external { | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-79): Type address is not implicitly convertible to expected type address payable. | ||||
| @ -0,0 +1,9 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address payable a = address(this); | ||||
|     a; | ||||
|   } | ||||
|   function() external payable { | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address payable a = this; | ||||
|     a; | ||||
|   } | ||||
|   function() external payable { | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-70): Type contract C is not implicitly convertible to expected type address payable. | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|     function f() public pure { | ||||
|         address a = address(0); | ||||
|         a = address(1); | ||||
|         address b = 0x0123456789012345678901234567890123456789; | ||||
|         b = 0x9876543210987654321098765432109876543210; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|     function f() public pure { | ||||
|         address payable a = address(0); | ||||
|         a = address(1); | ||||
|         address payable b = 0x0123456789012345678901234567890123456789; | ||||
|         b = 0x9876543210987654321098765432109876543210; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| contract C { | ||||
|   function f() public pure returns (C c) { | ||||
|     address a = address(2); | ||||
|     c = C(a); | ||||
|   } | ||||
|   function() external payable { | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (92-96): Explicit type conversion not allowed from non-payable "address" to "contract C", which has a payable fallback function. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|     function f(address payable a) public pure { | ||||
|         address payable b; | ||||
|         address c = a; | ||||
|         c = b; | ||||
|     } | ||||
| } | ||||
| @ -1,7 +0,0 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     C c = address(2); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-62): Type address is not implicitly convertible to expected type contract C. | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user