Fix error msg hint for non-payable contracts

This commit is contained in:
Mathias Baumann 2019-02-12 16:56:22 +01:00
parent f003696d7e
commit 10a9960eb3
3 changed files with 33 additions and 21 deletions

View File

@ -2064,7 +2064,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
errorMsg += " Did you intend to call the function?";
}
}
if (exprType->category() == Type::Category::Contract)
else if (exprType->category() == Type::Category::Contract)
{
for (auto const& addressMember: AddressType::addressPayable().nativeMembers(nullptr))
if (addressMember.name == memberName)
{
@ -2073,6 +2074,21 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member.";
break;
}
}
else if (auto addressType = dynamic_cast<AddressType const*>(exprType.get()))
{
// Trigger error when using send or transfer with a non-payable fallback function.
if (memberName == "send" || memberName == "transfer")
{
solAssert(
addressType->stateMutability() != StateMutability::Payable,
"Expected address not-payable as members were not found"
);
errorMsg = "\"send\" and \"transfer\" are only available for objects of type \"address payable\", not \"" + exprType->toString() + "\".";
}
}
m_errorReporter.fatalTypeError(
_memberAccess.location(),
errorMsg
@ -2115,26 +2131,6 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
annotation.isLValue = annotation.referencedDeclaration->isLValue();
}
if (exprType->category() == Type::Category::Contract)
{
// Warn about using send or transfer with a non-payable fallback function.
if (auto callType = dynamic_cast<FunctionType const*>(type(_memberAccess).get()))
{
auto kind = callType->kind();
auto contractType = dynamic_cast<ContractType const*>(exprType.get());
solAssert(!!contractType, "Should be contract type.");
if (
(kind == FunctionType::Kind::Send || kind == FunctionType::Kind::Transfer) &&
!contractType->isPayable()
)
m_errorReporter.typeError(
_memberAccess.location(),
"Value transfer to a contract without a payable fallback function."
);
}
}
// TODO some members might be pure, but for example `address(0x123).balance` is not pure
// although every subexpression is, so leaving this limited for now.
if (auto tt = dynamic_cast<TypeType const*>(exprType.get()))

View File

@ -0,0 +1,8 @@
contract C {
function f() public {
address(this).send(10);
}
}
// ----
// TypeError: (47-65): "send" and "transfer" are only available for objects of type "address payable", not "address".

View File

@ -0,0 +1,8 @@
contract C {
function f() public {
address(this).transfer(10);
}
}
// ----
// TypeError: (47-69): "send" and "transfer" are only available for objects of type "address payable", not "address".