solidity icon indicating copy to clipboard operation
solidity copied to clipboard

Reconsider operators on ContractType

Open hrkrshnn opened this issue 4 years ago • 14 comments

contract Test {}
contract Derived is Test {}
function f(Test a, Test b) {
    a < b;
    a == b;
    a > b;
    a <= b;
    a >= b;
}

function g(Derived a, Test b) {
    a < b;
    a == b;
    a > b;
    a <= b;
    a >= b;
}

Currently, the above code compiles. I think the comparison operators does not belong with the ContractType. Even the equality operator is questionable. Disallowing all these operators is especially important to be consistent with how operators are disallowed by default in user defined types: https://github.com/ethereum/solidity/issues/11531.

hrkrshnn avatar Jul 27 '21 08:07 hrkrshnn

Oh wow! I think this is a remnant of contracts being treated as addresses. If you want to compare contracts like that, I think it would be better to require conversion to address first, which then also makes it much clearer how they are compared.

chriseth avatar Jul 27 '21 08:07 chriseth

I was of the impression that this is permitted due to an implicit cast to addresses. The fuzzer is currently churning these out happily :-)

bshastry avatar Jul 27 '21 09:07 bshastry

I think that disallowing <, <=, > and >= is a good thing.

With != and == it's not so clear but I would also be in favor of disallowing it.

While version without the cast looks cleaner and it's not hard to realize that it's a comparison of addresses (not state variables):

if (myERC20Token == whitelistedTokens[i]) { ... }

the one with casts reads much better as a condition even despite being longer and makes the meaning very clear:

if (address(myERC20Token) == address(whitelistedTokens[i])) { ... }

Also, in many cases the other side of the comparison is already an address so it's not even that much longer:

if (address(myERC20Token) == whitelistedTokens[i]) { ... }

cameel avatar Jul 27 '21 15:07 cameel

Do we have comparison operators on the contract type (i.e. Test == Derived or type(a) != type(b))? There I think != and == can make sense, but I agree that these operators should not exist on the contract instances.

axic avatar Jul 27 '21 16:07 axic

Do we have comparison operators on the contract type (i.e. Test == Derived or type(a) != type(b))?

Looks like we don't:

Error: Operator == not compatible with types type(contract C) and type(contract C)
 --> test.sol:3:9:
  |
3 |         C == C;
  |         ^^^^^^

Error: Operator != not compatible with types type(contract C) and type(contract C)
 --> test.sol:4:9:
  |
4 |         C != C;
  |         ^^^^^^

Error: Operator < not compatible with types type(contract C) and type(contract C)
 --> test.sol:5:9:
  |
5 |         C < C;
  |

cameel avatar Jul 27 '21 16:07 cameel

With != and == it's not so clear but I would also be in favor of disallowing it.

The following may be a reason to disallow it: does it mean comparison between the type or the instance? The type may be equal in the case the child contract has no changes (contract B is A {}), but what should it return in case the underlying address is different? Because of this confusing aspect, it is better not to allow comparison of instances, but potentially allow comparison of the type, and of course comparison of the address is supported via explicit cast.

axic avatar Jul 27 '21 16:07 axic

Decision: disallow everything. Even ==.

hrkrshnn avatar Aug 04 '21 12:08 hrkrshnn

On our side, everything is implemented in #12568 but we need to update our external tests, that would be the next step for this task

Marenz avatar Jun 21 '22 12:06 Marenz

We should reevaluate this since so many ext tests are failing. Isn't it just too common?

cameel avatar Sep 12 '22 15:09 cameel

This issue has been marked as stale due to inactivity for the last 90 days. It will be automatically closed in 7 days.

github-actions[bot] avatar Mar 20 '23 12:03 github-actions[bot]

Staging this for re-evaluation again for 0.9. At least comparisons between different contract types should probably be restricted. Or I'd still say removing all of them should be up for discussion.

ekpyron avatar Mar 22 '23 12:03 ekpyron

I recently noticed that our docs on the contract types actually state that contracts have no operators:

Contracts do not support any operators.

So this is actually an undocumented feature :)

cameel avatar Mar 22 '23 22:03 cameel

Ah, then let's just exercise our right to remove it despite breaking every second contract ;-P. Well, I guess we'll have to consider this an incidence of Hyrum's Law :-).

ekpyron avatar Mar 27 '23 18:03 ekpyron

It would make sense for me if eq/neq operations compare address.codeHash, allowing in runtime to detect whether addresses contain equal bytecode.

peersky avatar Jul 11 '24 18:07 peersky