Interfaces and Abstract smart contracts in Solidity

In this tutorial, we are going to learn what are interfaces and abstract smart contracts in Solidity, what's the difference between them and how and when to use them.

In this tutorial, we are going to learn what are interfaces and abstract smart contracts in Solidity, what's the difference between them and how and when to use them.

Both interfaces and abstract smart contracts allow you to define the functions that a smart contract that uses them should implement and how these functions work.

First, we are going to start with interfaces, then we're going to see abstract contracts and to finish we will see the differences between interfaces and abstract contracts.

Interfaces in Solidity

An interface in Solidity allows you to define functions that the smart contracts that use that interface must implement.

These functions can only be external though.

Here is an example:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

interface Foo {
    function foo(uint x) external pure returns (uint);
    function bar() external payable;
}

contract FooChild is Foo {
    uint valueReceived = 0;
    
    function foo(uint x) external pure override returns (uint) {
        return x + 1;
    }

    function bar() external payable override {
        valueReceived += msg.value;
    }
}

Abstract Smart Contracts in Solidity

An abstract contract in Solidity allow you to define a contract with its constructor, properties and functions with their implementation or not.

Then, the contracts that inherit that abstract smart contract have to implement all the functions that are defined in that abstract contract if they are not implemented.

It will automatically have the functions that hare implemented in the abstract contract, the constructor (if implemented) and the properties of the abstract contract as if they were defined in the contract itself.

Here is an example:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

abstract contract Foo {
    uint internal valueReceived = 0;
    
    function foo(uint x) external pure virtual returns (uint);
    function bar() external payable virtual;
}

contract FooChild is Foo {

    function getValueReceived() public view returns (uint) {
        return valueReceived;
    }
   
    function foo(uint x) external pure override returns (uint) {
        return x + 1;
    }

    function bar() external payable override {
        valueReceived += msg.value;
    }
    
}

Note that functions that don't have an implementation in the abstract contract need to be marked as virtual and the contracts that inherit from it must override these functions.

What is the difference between an abstract contract and an interface in Solidity

An abstract smart contract can:

  • define the implementation of the functions inside of it
  • define properties
  • define a constructor

But the functions it defines must be marked as virtual if they don't have any implementation.

An interface, as opposed to an abstract contract, can do none of the above. It cannot define properties, a constructor or the implementation of the functions.

However, the functions inside interfaces can only be external.

Use case of abstract contracts and interfaces

Both interfaces and abstract contracts allow you to define patterns in your smart contracts. It tells your smart contracts how they should work and what functions should be implemented which is very useful to ensure consistency across your smart contracts.

They are also both used to interact with other smart contracts. For more information about that, check out this article:

How to interact with other smart contracts in Solidity
In this tutorial, we are going to learn how to interact with other smart contracts from your Solidity smart contract. We will learn how to call functions and read the state of other smart contracts in Solidity.

And that's it 🎉

Thank you for reading this article