From 8a6692b2cfb7cf53db6731acd6a9908bd36b5475 Mon Sep 17 00:00:00 2001 From: wadeAlexC Date: Thu, 5 Oct 2017 09:28:25 -0400 Subject: [PATCH] Improves address literal checksum error message --- Changelog.md | 1 + libdevcore/CommonData.cpp | 25 ++++++++++++++----------- libdevcore/CommonData.h | 4 ++++ libsolidity/analysis/TypeChecker.cpp | 8 +++++--- libsolidity/ast/AST.cpp | 6 ++++++ libsolidity/ast/AST.h | 2 ++ 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/Changelog.md b/Changelog.md index 45521f3e0..2487b87c6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Features: * Syntax Checker: Turn the usage of ``callcode`` into an error as experimental 0.5.0 feature. + * Type Checker: Improve address checksum warning. * Type Checker: More detailed errors for invalid array lengths (such as division by zero). Bugfixes: diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index db11e61c6..85ad685b8 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -86,20 +86,23 @@ bool dev::passesAddressChecksum(string const& _str, bool _strict) )) return true; + return _str == dev::getChecksummedAddress(_str); +} + +string dev::getChecksummedAddress(string const& _addr) +{ + string s = _addr.substr(0, 2) == "0x" ? _addr.substr(2) : _addr; h256 hash = keccak256(boost::algorithm::to_lower_copy(s, std::locale::classic())); - for (size_t i = 0; i < 40; ++i) + string ret = "0x"; + + for (size_t i = 0; i < s.length(); ++i) { char addressCharacter = s[i]; - bool lowerCase; - if ('a' <= addressCharacter && addressCharacter <= 'f') - lowerCase = true; - else if ('A' <= addressCharacter && addressCharacter <= 'F') - lowerCase = false; - else - continue; unsigned nibble = (unsigned(hash[i / 2]) >> (4 * (1 - (i % 2)))) & 0xf; - if ((nibble >= 8) == lowerCase) - return false; + if (nibble >= 8) + ret += toupper(addressCharacter); + else + ret += tolower(addressCharacter); } - return true; + return ret; } diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 765707f80..e76a09491 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -209,4 +209,8 @@ bool contains(T const& _t, V const& _v) /// are considered valid. bool passesAddressChecksum(std::string const& _str, bool _strict); +/// @returns the checksummed version of an address +/// @param hex strings that look like an address +std::string getChecksummedAddress(std::string const& _addr); + } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 746e762e8..fee607973 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1122,7 +1122,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) var.annotation().type->toString() + ". Try converting to type " + valueComponentType->mobileType()->toString() + - " or use an explicit conversion." + " or use an explicit conversion." ); else m_errorReporter.typeError( @@ -1320,7 +1320,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) _tuple.annotation().isPure = isPure; if (_tuple.isInlineArray()) { - if (!inlineArrayType) + if (!inlineArrayType) m_errorReporter.fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); _tuple.annotation().type = make_shared(DataLocation::Memory, inlineArrayType, types.size()); } @@ -2000,7 +2000,9 @@ void TypeChecker::endVisit(Literal const& _literal) m_errorReporter.warning( _literal.location(), "This looks like an address but has an invalid checksum. " - "If this is not used as an address, please prepend '00'." + "If this is not used as an address, please prepend '00'. " + "Correct checksummed address: '" + _literal.getChecksummedAddress() + "'. " + "For more information please see https://solidity.readthedocs.io/en/develop/types.html#address-literals" ); } if (!_literal.annotation().type) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 1048b610c..4911f1615 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -583,3 +583,9 @@ bool Literal::passesAddressChecksum() const solAssert(isHexNumber(), "Expected hex number"); return dev::passesAddressChecksum(value(), true); } + +std::string Literal::getChecksummedAddress() const +{ + solAssert(isHexNumber(), "Expected hex number"); + return dev::getChecksummedAddress(value()); +} diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 733e7c78c..5d6763cab 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1613,6 +1613,8 @@ public: bool looksLikeAddress() const; /// @returns true if it passes the address checksum test. bool passesAddressChecksum() const; + /// @returns the checksummed version of an address + std::string getChecksummedAddress() const; private: Token::Value m_token;