What's the difference between these 2 solidity interfaces methods?

Viewed 298

I've been following a new journey into solidity for about a month now, so far so good, however with the Interface I'm having a hard time understanding the difference between these 2 methods of implementing Interfaces.

I can clearly notice how useful the Interface is in the 2nd method, but not in the 1st method.

Method 1:

pragma solidity ^0.8.0;

interface ICounter {

    function count() external view returns (uint256);
    function addToCount() external;
}

contract myInterface is ICounter {

    uint256 counter = 0;

    function count() external view override returns (uint256) {
        return counter;
    }

    function addToCount() override external {
        counter++ ;
    }
}

Method 2:

pragma solidity ^0.8.0;

contract myContract {
    uint256 count =0;

    function increment() external {
    count++ ;
    }
}

pragma solidity ^0.8.0;

interface ICounter {

    function count() external view returns (uint256);
    function increment() external;
}

contract myInterface {

    function incrementCount(address _counter) external {
        ICounter(_counter).increment();
    }

    function getCount(address _counter) external view returns (uint256) {
        return ICounter(_counter).count();
    }
}
1 Answers

Interfaces in Solidity are mostly used for interacting with contracts deployed on other address, as you show in the Method 2.

Example of storing the pointer to another contract (assuming that it implements the interface) in a variable:

pragma solidity ^0.8.0;

interface ICounter {
    function increment() external;
}

contract MyContract {
    ICounter counter;

    constructor(address _counter) {
        counter = ICounter(_counter);
    }

    function incrementCount() external {
        counter.increment();
    }
}

In the Method 1, your code uses the is keyword for inheritance, which could be described as "myInterface is child of ICounter".

But there's no way to explicitly state implementation of an interface - that "myInterface implements ICounter". As you can see, you need to use the override modifier on the addToCount() function to state that you're overriding the parent function - which doesn't suggest implementing an interface at all.

I wouldn't consider the Method 2 a bad practice, as it can help you remember to implement all intended functions - otherwise the contract is treated as abstract and cannot be deployed. But for me personally, it's the less preferred method because there's no way to state an implementation instead of an inheritance (at least not in the current Solidity version 0.8).

Note: I'm aware that for example OpenZeppelin uses the Method 1 of "inheriting from an interface". I just don't agree with their approach.. :)

Related