Solidity Interfaces
An interface is a list of function declarations that a contract promises to provide. A declaration names a function and its inputs and outputs, but it has no body.
An interface declares functions only
The interface lists two functions and no bodies. A contract below it provides the real code.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface INumberBox {
function getNumber() external view returns (uint256);
function setNumber(uint256 newNumber) external;
}
contract NumberBox is INumberBox {
uint256 private storedNumber;
function getNumber() external view override returns (uint256) {
return storedNumber;
}
function setNumber(uint256 newNumber) external override {
storedNumber = newNumber;
}
}
The contract holds the state, not the interface
The interface holds no data at all. The number lives in the contract that keeps the promise.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface INumberBox {
function getNumber() external view returns (uint256);
function setNumber(uint256 newNumber) external;
}
contract NumberBox is INumberBox {
uint256 private storedNumber;
function getNumber() external view override returns (uint256) {
return storedNumber;
}
function setNumber(uint256 newNumber) external override {
storedNumber = newNumber;
}
}
Calling through an interface variable
A variable typed as the interface can hold a real contract's address. Calls through it run that contract's code.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface INumberBox {
function getNumber() external view returns (uint256);
function setNumber(uint256 newNumber) external;
}
contract NumberBox is INumberBox {
uint256 private storedNumber;
function getNumber() external view override returns (uint256) {
return storedNumber;
}
function setNumber(uint256 newNumber) external override {
storedNumber = newNumber;
}
}
contract FixedBox is INumberBox {
function getNumber() external pure override returns (uint256) {
return 10;
}
function setNumber(uint256 newNumber) external override {
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface IThermometer {
function temperature() external view returns (uint256);
function setTemperature(uint256 newTemperature) external;
}
contract Thermometer is IThermometer {
uint256 private storedTemperature;
function temperature() external view override returns (uint256) {
return storedTemperature;
}
function setTemperature(uint256 newTemperature) external override {
storedTemperature = newTemperature;
}
}
Key points
- Interface: a list of functions written with the interface keyword and a name.
- Declarations only: an interface function ends with a semicolon and has no code body.
- No state: an interface cannot hold state variables.
- External functions: functions in an interface are marked external.
- Keeping the promise: a contract provides the listed functions with matching names and inputs.
- Interface variable: a variable typed with the interface can call the real contract behind it.
In this example, IThermometer declares two functions and holds no state and no code bodies. Thermometer keeps the promise by writing both functions and storing the temperature. The proof calls the thermometer through an interface variable, and the real contract does the work.
Note
calling through an interface runs the real contract's code, not code from the interface.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
Which of these can an interface hold?