diff options
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/GlobalContext.cpp | 8 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 108 |
2 files changed, 66 insertions, 50 deletions
diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 756bb540..7b4bc3aa 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -42,7 +42,7 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ make_shared<MagicVariableDeclaration>("blockhash", make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)), make_shared<MagicVariableDeclaration>("ecrecover", make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("gasleft", make_shared<FunctionType>(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)), - make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + make_shared<MagicVariableDeclaration>("keccak256", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA3, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("log0", make_shared<FunctionType>(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), make_shared<MagicVariableDeclaration>("log1", make_shared<FunctionType>(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), make_shared<MagicVariableDeclaration>("log2", make_shared<FunctionType>(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), @@ -55,10 +55,10 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{ make_shared<MagicVariableDeclaration>("require", make_shared<FunctionType>(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), 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(), strings{"bytes20"}, FunctionType::Kind::RIPEMD160, true, 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>("sha256", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA256, true, StateMutability::Pure)), - make_shared<MagicVariableDeclaration>("sha3", make_shared<FunctionType>(strings(), strings{"bytes32"}, FunctionType::Kind::SHA3, true, StateMutability::Pure)), + 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::SHA3, false, StateMutability::Pure)), make_shared<MagicVariableDeclaration>("suicide", make_shared<FunctionType>(strings{"address"}, strings{}, FunctionType::Kind::Selfdestruct)), make_shared<MagicVariableDeclaration>("tx", make_shared<MagicType>(MagicType::Kind::Transaction)) }) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e89ce27a..b9e3f8d0 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1712,12 +1712,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) m_errorReporter.typeError(_functionCall.location(), "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } if (!m_insideEmitStatement && functionType->kind() == FunctionType::Kind::Event) - { - if (m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050)) - m_errorReporter.typeError(_functionCall.location(), "Event invocations have to be prefixed by \"emit\"."); - else - m_errorReporter.warning(_functionCall.location(), "Invoking events without \"emit\" prefix is deprecated."); - } + m_errorReporter.typeError(_functionCall.location(), "Event invocations have to be prefixed by \"emit\"."); TypePointers parameterTypes = functionType->parameterTypes(); @@ -1750,35 +1745,6 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } } - if (functionType->takesSinglePackedBytesParameter()) - { - if ( - (arguments.size() > 1) || - (arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) - ) - { - string msg = - "This function only accepts a single \"bytes\" argument. Please use " - "\"abi.encodePacked(...)\" or a similar function to encode the data."; - if (v050) - m_errorReporter.typeError(_functionCall.location(), msg); - else - m_errorReporter.warning(_functionCall.location(), msg); - } - - if (arguments.size() == 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) - { - string msg = - "The provided argument of type " + - type(*arguments.front())->toString() + - " is not implicitly convertible to expected type bytes memory."; - if (v050) - m_errorReporter.typeError(_functionCall.location(), msg); - else - m_errorReporter.warning(_functionCall.location(), msg); - } - } - if (functionType->takesArbitraryParameters() && arguments.size() < parameterTypes.size()) { solAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, ""); @@ -1810,6 +1776,26 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) for (auto const& member: membersRemovedForStructConstructor) msg += " " + member; } + else if ( + functionType->kind() == FunctionType::Kind::BareCall || + functionType->kind() == FunctionType::Kind::BareCallCode || + functionType->kind() == FunctionType::Kind::BareDelegateCall + ) + { + if (arguments.empty()) + msg += " This function requires a single bytes argument. Use \"\" as argument to provide empty calldata."; + else + msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it."; + } + else if ( + functionType->kind() == FunctionType::Kind::SHA3 || + functionType->kind() == FunctionType::Kind::SHA256 || + functionType->kind() == FunctionType::Kind::RIPEMD160 + ) + msg += + " This function requires a single bytes argument." + " Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour" + " or abi.encode(...) to use ABI encoding."; m_errorReporter.typeError(_functionCall.location(), msg); } else if (isPositionalCall) @@ -1846,15 +1832,31 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } } else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) - m_errorReporter.typeError( - arguments[i]->location(), + { + string msg = "Invalid type for argument in function call. " "Invalid implicit conversion from " + type(*arguments[i])->toString() + " to " + parameterTypes[i]->toString() + - " requested." - ); + " requested."; + if ( + functionType->kind() == FunctionType::Kind::BareCall || + functionType->kind() == FunctionType::Kind::BareCallCode || + functionType->kind() == FunctionType::Kind::BareDelegateCall + ) + msg += " This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it."; + else if ( + functionType->kind() == FunctionType::Kind::SHA3 || + functionType->kind() == FunctionType::Kind::SHA256 || + functionType->kind() == FunctionType::Kind::RIPEMD160 + ) + msg += + " This function requires a single bytes argument." + " Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour" + " or abi.encode(...) to use ABI encoding."; + m_errorReporter.typeError(arguments[i]->location(), msg); + } } } else @@ -2287,14 +2289,28 @@ void TypeChecker::endVisit(Literal const& _literal) if (_literal.looksLikeAddress()) { - if (_literal.passesAddressChecksum()) - _literal.annotation().type = make_shared<IntegerType>(160, IntegerType::Modifier::Address); - else - m_errorReporter.warning( + // Assign type here if it even looks like an address. This prevents double error in 050 mode for invalid address + _literal.annotation().type = make_shared<IntegerType>(160, IntegerType::Modifier::Address); + + string msg; + if (_literal.value().length() != 42) // "0x" + 40 hex digits + // looksLikeAddress enforces that it is a hex literal starting with "0x" + msg = + "This looks like an address but is not exactly 40 hex digits. It is " + + to_string(_literal.value().length() - 2) + + " hex digits."; + else if (!_literal.passesAddressChecksum()) + { + msg = "This looks like an address but has an invalid checksum."; + if (!_literal.getChecksummedAddress().empty()) + msg += " Correct checksummed address: \"" + _literal.getChecksummedAddress() + "\"."; + } + + if (!msg.empty()) + m_errorReporter.syntaxError( _literal.location(), - "This looks like an address but has an invalid checksum. " - "If this is not used as an address, please prepend '00'. " + - (!_literal.getChecksummedAddress().empty() ? "Correct checksummed address: '" + _literal.getChecksummedAddress() + "'. " : "") + + msg + + " If this is not used as an address, please prepend '00'. " + "For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals" ); } |