Disallow comparison operators on contracts

This commit is contained in:
Marenz 2022-01-20 17:05:52 +01:00
parent 777385f5d2
commit f426b5988e
12 changed files with 45 additions and 18 deletions

View File

@ -2,8 +2,9 @@
Breaking changes: Breaking changes:
* Disallow ``.pop()`` on arrays containing nested mappings. * Disallow ``.pop()`` on arrays containing nested mappings.
* Disallow ``delete`` on types that contain nested mappings.
* Disallow ``codecopy`` and ``codesize`` in ``pure`` functions. * Disallow ``codecopy`` and ``codesize`` in ``pure`` functions.
* Disallow ``delete`` on types that contain nested mappings.
* Disallow all comparison operators on contract types.
* Inline Assembly: Consider functions, function parameters and return variables for shadowing checks. * Inline Assembly: Consider functions, function parameters and return variables for shadowing checks.
* Commandline Interface: Remapping targets are not automatically added to allowed paths. * Commandline Interface: Remapping targets are not automatically added to allowed paths.
* Commandline Interface: Assembler mode no longer enables all outputs by default. * Commandline Interface: Assembler mode no longer enables all outputs by default.

View File

@ -927,6 +927,11 @@ public:
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override; BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
/// Contracts can only be explicitly converted to address types and base contracts. /// Contracts can only be explicitly converted to address types and base contracts.
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override; BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
/// Contracts do not support any comparison operators
TypeResult binaryOperatorResult(Token, Type const*) const override
{
return TypeResult::err("No arithmetic or comparison operations are allowed on contract types. Consider converting to \"address\".");
}
TypeResult unaryOperatorResult(Token _operator) const override; TypeResult unaryOperatorResult(Token _operator) const override;
std::string richIdentifier() const override; std::string richIdentifier() const override;
bool operator==(Type const& _other) const override; bool operator==(Type const& _other) const override;

View File

@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(value_types)
if (d != 4) return 4; if (d != 4) return 4;
if (x != "abc") return 5; if (x != "abc") return 5;
if (e != true) return 6; if (e != true) return 6;
if (g != this) return 7; if (address(g) != address(this)) return 7;
return 20; return 20;
} }
} }

View File

@ -6,7 +6,7 @@ contract A {
function different_salt() public returns (bool) { function different_salt() public returns (bool) {
B x = new B{salt: "abc"}(); B x = new B{salt: "abc"}();
B y = new B{salt: "abcef"}(); B y = new B{salt: "abcef"}();
return x != y; return address(x) != address(y);
} }
function same_salt() public returns (bool) { function same_salt() public returns (bool) {
B x = new B{salt: "xyz"}(); B x = new B{salt: "xyz"}();

View File

@ -5,11 +5,11 @@ contract C {
function f() public view { function f() public view {
D e = this.d(); D e = this.d();
assert(e == d); // should hold assert(address(e) == address(d)); // should hold
assert(address(e) == address(this)); // should fail assert(address(e) == address(this)); // should fail
} }
} }
// ==== // ====
// SMTEngine: all // SMTEngine: all
// ---- // ----
// Warning 6328: (123-158): CHC: Assertion violation happens here.\nCounterexample:\nd = 0\ne = 0\n\nTransaction trace:\nC.constructor()\nState: d = 0\nC.f() // Warning 6328: (141-176): CHC: Assertion violation happens here.\nCounterexample:\nd = 0\ne = 0\n\nTransaction trace:\nC.constructor()\nState: d = 0\nC.f()

View File

@ -11,7 +11,7 @@ contract C {
function test() public view { function test() public view {
(D d, function () external returns (uint) f) = this.s(); (D d, function () external returns (uint) f) = this.s();
assert(d == s.d); // should hold assert(address(d) == address(s.d)); // should hold
assert(address(d) == address(this)); // should fail assert(address(d) == address(this)); // should fail
} }
} }
@ -19,4 +19,4 @@ contract C {
// SMTEngine: all // SMTEngine: all
// ---- // ----
// Warning 2072: (146-183): Unused local variable. // Warning 2072: (146-183): Unused local variable.
// Warning 6328: (234-269): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 0, f: 0}\nd = 0\nf = 0\n\nTransaction trace:\nC.constructor()\nState: s = {d: 0, f: 0}\nC.test() // Warning 6328: (252-287): CHC: Assertion violation happens here.\nCounterexample:\ns = {d: 0, f: 0}\nd = 0\nf = 0\n\nTransaction trace:\nC.constructor()\nState: s = {d: 0, f: 0}\nC.test()

View File

@ -1,11 +1,11 @@
contract C contract C
{ {
function f(C c, C d) public pure { function f(C c, C d) public pure {
assert(c == d); assert(address(c) == address(d));
} }
} }
// ==== // ====
// SMTEngine: all // SMTEngine: all
// SMTIgnoreCex: yes // SMTIgnoreCex: yes
// ---- // ----
// Warning 6328: (51-65): CHC: Assertion violation happens here. // Warning 6328: (51-83): CHC: Assertion violation happens here.

View File

@ -6,11 +6,11 @@ contract D
contract C contract C
{ {
function f(D c, D d) public pure { function f(D c, D d) public pure {
assert(c == d); assert(address(c) == address(d));
} }
} }
// ==== // ====
// SMTEngine: all // SMTEngine: all
// SMTIgnoreCex: yes // SMTIgnoreCex: yes
// ---- // ----
// Warning 6328: (76-90): CHC: Assertion violation happens here. // Warning 6328: (76-108): CHC: Assertion violation happens here.

View File

@ -1,9 +1,9 @@
contract C contract C
{ {
function f(C c, C d, C e) public pure { function f(C c, C d, C e) public pure {
require(c == d); require(address(c) == address(d));
require(d == e); require(address(d) == address(e));
assert(c == e); assert(address(c) == address(e));
} }
} }
// ==== // ====

View File

@ -3,7 +3,7 @@ contract C
function f(C c, C d) public pure { function f(C c, C d) public pure {
assert(address(c) == address(c)); assert(address(c) == address(c));
address a = address(c); address a = address(c);
require(c == d); require(address(c) == address(d));
assert(a == address(d)); assert(a == address(d));
} }
} }

View File

@ -20,8 +20,8 @@ contract C {
} }
// ---- // ----
// TypeError 2271: (144-157): Operator != not compatible with types type(contract super C) and contract C // TypeError 2271: (144-157): Operator != not compatible with types type(contract super C) and contract C
// TypeError 2271: (167-180): Operator != not compatible with types contract C and type(contract super C) // TypeError 2271: (167-180): Operator != not compatible with types contract C and type(contract super C). No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (254-264): Operator != not compatible with types type(contract super C) and contract C // TypeError 2271: (254-264): Operator != not compatible with types type(contract super C) and contract C
// TypeError 2271: (274-284): Operator != not compatible with types contract C and type(contract super C) // TypeError 2271: (274-284): Operator != not compatible with types contract C and type(contract super C). No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (349-359): Operator != not compatible with types type(contract super C) and contract D // TypeError 2271: (349-359): Operator != not compatible with types type(contract super C) and contract D
// TypeError 2271: (369-379): Operator != not compatible with types contract D and type(contract super C) // TypeError 2271: (369-379): Operator != not compatible with types contract D and type(contract super C). No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".

View File

@ -0,0 +1,21 @@
contract C {
function f(string calldata data) external pure {
C c;
assert(this == this);
assert(this == c);
assert(this != c);
assert(this >= c);
assert(this <= c);
assert(this < c);
assert(this > c);
}
}
// ----
// TypeError 2271: (79-91): Operator == not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (104-113): Operator == not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (125-134): Operator != not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (146-155): Operator >= not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (167-176): Operator <= not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (188-196): Operator < not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".
// TypeError 2271: (208-216): Operator > not compatible with types contract C and contract C. No arithmetic or comparison operations are allowed on contract types. Consider converting to "address".