diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index e5a4b027c..05deab9c4 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -89,6 +89,10 @@ This section lists changes that might cause existing contracts to not compile an - ``address(uint)`` and ``uint(address)``: converting both type-category and width. Replace this by ``address(uint160(uint))`` and ``uint(uint160(address))`` respectively. + - ``payable(uint160)``, ``payable(bytes20)`` and ``payable(integer-literal)``: converting both + type-category and state-mutability. Replace this by ``payable(address(uint160))``, + ``payable(address(bytes20))`` and ``payable(address(integer-literal))`` respectively. Note that + ``payable(0)`` is valid and is an exception to the rule. - ``int80(bytes10)`` and ``bytes10(int80)``: converting both type-category and sign. Replace this by ``int80(uint80(bytes10))`` and ``bytes10(uint80(int80)`` respectively. - ``Contract(uint)``: converting both type-category and width. Replace this by @@ -126,9 +130,11 @@ This section lists changes that might cause existing contracts to not compile an payable``: - ``address(u)`` where ``u`` is an arbitrary variable of type ``uint160``. One can convert ``u`` - into the type ``address payable`` by using an explicit conversion, i.e., ``payable(u)``. + into the type ``address payable`` by using two explicit conversions, i.e., + ``payable(address(u))``. - ``address(b)`` where ``b`` is an arbitrary variable of type ``bytes20``. One can convert ``b`` - into the type ``address payable`` by using an explicit conversion, i.e., ``payable(bytes20)``. + into the type ``address payable`` by using two explicit conversions, i.e., + ``payable(address(b))``. - ``address(c)`` where ``c`` is an arbitrary contract. Previously, the return type of this conversion depended on whether the contract can receive Ether (either by having a receive function or a payable fallback function). The conversion ``payable(c)`` has the type ``address diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 98ef299af..349435115 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -399,13 +399,13 @@ BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const return true; else if (auto const* contractType = dynamic_cast(&_convertTo)) return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable(); - else if (auto integerType = dynamic_cast(&_convertTo)) - return (!integerType->isSigned() && integerType->numBits() == 160); - else if ( - (_convertTo.category() == Category::FixedBytes) && - (160 == dynamic_cast(_convertTo).numBytes() * 8) - ) - return true; + else if (m_stateMutability == StateMutability::NonPayable) + { + if (auto integerType = dynamic_cast(&_convertTo)) + return (!integerType->isSigned() && integerType->numBits() == 160); + else if (auto fixedBytesType = dynamic_cast(&_convertTo)) + return (fixedBytesType->numBytes() == 20); + } return false; } @@ -530,8 +530,11 @@ BoolResult IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const return true; else if (auto integerType = dynamic_cast(&_convertTo)) return (numBits() == integerType->numBits()) || (isSigned() == integerType->isSigned()); - else if (_convertTo.category() == Category::Address) - return (!isSigned() && numBits() == 160); + else if (auto addressType = dynamic_cast(&_convertTo)) + return + (addressType->stateMutability() != StateMutability::Payable) && + !isSigned() && + (numBits() == 160); else if (auto fixedBytesType = dynamic_cast(&_convertTo)) return (!isSigned() && (numBits() == fixedBytesType->numBytes() * 8)); else if (dynamic_cast(&_convertTo)) @@ -939,8 +942,13 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) auto category = _convertTo.category(); if (category == Category::FixedBytes) return false; - else if (category == Category::Address) - return !(isNegative() || isFractional() || !integerType() || integerType()->numBits() > 160); + else if (auto addressType = dynamic_cast(&_convertTo)) + return (m_value == 0) || + ((addressType->stateMutability() != StateMutability::Payable) && + !isNegative() && + !isFractional() && + integerType() && + (integerType()->numBits() <= 160)); else if (category == Category::Integer) return false; else if (auto enumType = dynamic_cast(&_convertTo)) @@ -1250,8 +1258,10 @@ BoolResult FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) con return true; else if (auto integerType = dynamic_cast(&_convertTo)) return (!integerType->isSigned() && integerType->numBits() == numBytes() * 8); - else if (_convertTo.category() == Category::Address && numBytes() == 20) - return true; + else if (auto addressType = dynamic_cast(&_convertTo)) + return + (addressType->stateMutability() != StateMutability::Payable) && + (numBytes() == 20); else if (auto fixedPointType = dynamic_cast(&_convertTo)) return fixedPointType->numBits() == numBytes() * 8;