diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2017-09-20 21:54:41 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-03-05 22:50:27 +0800 |
commit | fd60c1cf86e69931fda47bdd187f444550ca785f (patch) | |
tree | 793510c7aab2330b34940dab009403f897ab1413 | |
parent | cd6ffbdf790e4d3e4da2e7f3fba5524a2b8c3e1d (diff) | |
download | dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar.gz dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar.bz2 dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar.lz dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar.xz dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.tar.zst dexon-solidity-fd60c1cf86e69931fda47bdd187f444550ca785f.zip |
Warn if using address overloads on contracts
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 10 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 171 | ||||
-rw-r--r-- | test/libsolidity/ViewPureChecker.cpp | 10 |
4 files changed, 181 insertions, 11 deletions
diff --git a/Changelog.md b/Changelog.md index 3c875a8f..67634ea0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Features: * Syntax Analyser: Do not warn about experimental features if they do not concern code generation. * Syntax Checker: Mark ``throw`` as an error as experimental 0.5.0 feature. * Syntax Checker: Issue error if no visibility is specified on contract functions as experimental 0.5.0 feature. + * Syntax Checker: Issue warning when using overloads of ``address`` on contract instances. * Type Checker: disallow combining hex numbers and unit denominations as experimental 0.5.0 feature. Bugfixes: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9846a0d0..ac8b2b63 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1831,6 +1831,16 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) if (exprType->category() == Type::Category::Contract) { + // Warn about using address members on contracts + for (auto const& addressMember: IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr)) + if (addressMember.name == memberName && *annotation.type == *addressMember.type) + m_errorReporter.warning( + _memberAccess.location(), + "Using contract member \"" + memberName +"\" inherited from the address type is deprecated." + + " Convert the contract to \"address\" type to access the member." + ); + + // 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(); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 4fb62821..d4962b6c 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -7011,6 +7011,8 @@ BOOST_AUTO_TEST_CASE(callable_crash) BOOST_AUTO_TEST_CASE(error_transfer_non_payable_fallback) { + // This used to be a test for a.transfer to generate a warning + // because A's fallback function is not payable. char const* text = R"( contract A { function() public {} @@ -7024,12 +7026,17 @@ BOOST_AUTO_TEST_CASE(error_transfer_non_payable_fallback) } } )"; - CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function."); + CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); } BOOST_AUTO_TEST_CASE(error_transfer_no_fallback) { - char const* text = R"( + // This used to be a test for a.transfer to generate a warning + // because A does not have a payable fallback function. + std::string text = R"( contract A {} contract B { @@ -7040,12 +7047,17 @@ BOOST_AUTO_TEST_CASE(error_transfer_no_fallback) } } )"; - CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function."); + CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); } BOOST_AUTO_TEST_CASE(error_send_non_payable_fallback) { - char const* text = R"( + // This used to be a test for a.send to generate a warning + // because A does not have a payable fallback function. + std::string text = R"( contract A { function() public {} } @@ -7058,11 +7070,16 @@ BOOST_AUTO_TEST_CASE(error_send_non_payable_fallback) } } )"; - CHECK_ERROR(text, TypeError, "Value transfer to a contract without a payable fallback function."); + CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); } BOOST_AUTO_TEST_CASE(does_not_error_transfer_payable_fallback) { + // This used to be a test for a.transfer to generate a warning + // because A does not have a payable fallback function. char const* text = R"( contract A { function() payable public {} @@ -7076,7 +7093,7 @@ BOOST_AUTO_TEST_CASE(does_not_error_transfer_payable_fallback) } } )"; - CHECK_SUCCESS_NO_WARNINGS(text); + CHECK_WARNING(text, "Using contract member \"transfer\" inherited from the address type is deprecated."); } BOOST_AUTO_TEST_CASE(does_not_error_transfer_regular_function) @@ -7992,6 +8009,134 @@ BOOST_AUTO_TEST_CASE(array_length_invalid_expression) CHECK_ERROR(text, TypeError, "Operator / not compatible with types int_const 3 and int_const 0"); } +BOOST_AUTO_TEST_CASE(warn_about_address_members_on_contract) +{ + std::string text = R"( + contract C { + function f() view public { + this.balance; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated."); + text = R"( + contract C { + function f() view public { + this.transfer; + } + } + )"; + CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); + text = R"( + contract C { + function f() view public { + this.send; + } + } + )"; + CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); + text = R"( + contract C { + function f() view public { + this.call; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated."); + text = R"( + contract C { + function f() view public { + this.callcode; + } + } + )"; + CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"callcode\" inherited from the address type is deprecated"}, + {Error::Type::Warning, "\"callcode\" has been deprecated in favour of \"delegatecall\""} + })); + text = R"( + contract C { + function f() view public { + this.delegatecall; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated."); +} + +BOOST_AUTO_TEST_CASE(warn_about_address_members_on_non_this_contract) +{ + std::string text = R"( + contract C { + function f() view public { + C c; + c.balance; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"balance\" inherited from the address type is deprecated"); + text = R"( + contract C { + function f() view public { + C c; + c.transfer; + } + } + )"; + CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"transfer\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); + text = R"( + contract C { + function f() view public { + C c; + c.send; + } + } + )"; + CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, std::string>>{ + {Error::Type::Warning, "Using contract member \"send\" inherited from the address type is deprecated"}, + {Error::Type::TypeError, "Value transfer to a contract without a payable fallback function"} + })); + text = R"( + contract C { + function f() pure public { + C c; + c.call; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"call\" inherited from the address type is deprecated"); + text = R"( + contract C { + function f() pure public { + C c; + c.callcode; + } + } + )"; + CHECK_WARNING_ALLOW_MULTI(text, (std::vector<std::string>{ + "Using contract member \"callcode\" inherited from the address type is deprecated", + "\"callcode\" has been deprecated in favour of \"delegatecall\"" + })); + text = R"( + contract C { + function f() pure public { + C c; + c.delegatecall; + } + } + )"; + CHECK_WARNING(text, "Using contract member \"delegatecall\" inherited from the address type is deprecated"); +} + BOOST_AUTO_TEST_CASE(no_address_members_on_contract) { char const* text = R"( @@ -8050,6 +8195,20 @@ BOOST_AUTO_TEST_CASE(no_address_members_on_contract) CHECK_ERROR(text, TypeError, "Member \"delegatecall\" not found or not visible after argument-dependent lookup in contract"); } +BOOST_AUTO_TEST_CASE(no_warning_for_using_members_that_look_like_address_members) +{ + char const* text = R"( + pragma experimental "v0.5.0"; + contract C { + function transfer(uint) public; + function f() public { + this.transfer(10); + } + } + )"; + CHECK_WARNING(text, "Experimental features"); +} + BOOST_AUTO_TEST_CASE(emit_events) { char const* text = R"( diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index e6a5cfd0..6e8620f9 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -279,11 +279,11 @@ BOOST_AUTO_TEST_CASE(builtin_functions) string text = R"( contract C { function f() public { - this.transfer(1); - require(this.send(2)); - selfdestruct(this); - require(this.delegatecall()); - require(this.call()); + address(this).transfer(1); + require(address(this).send(2)); + selfdestruct(address(this)); + require(address(this).delegatecall()); + require(address(this).call()); } function g() pure public { bytes32 x = keccak256("abc"); |