Solidity Abstract Contracts
An abstract contract is a contract that cannot be deployed on its own. It holds shared code and leaves some functions for its children to fill in.
A child fills in the unfinished function
Shape leaves area without a body. Square implements it as side times side.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
abstract contract Shape {
function area() public virtual returns (uint256);
function name() public pure returns (string memory) {
return "shape";
}
}
contract Square is Shape {
uint256 public side;
function setSide(uint256 newSide) public {
side = newSide;
}
function area() public override returns (uint256) {
return side * side;
}
}An abstract contract cannot be deployed
Creating Shape directly fails to compile. Only a finished child can be deployed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
abstract contract Shape {
function area() public virtual returns (uint256);
}
contract Factory {
function make() public returns (Shape) {
return new Shape();
}
}An abstract contract still holds shared state
VaultBase holds the balance and deposit. BasicVault only fills in the fee.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
abstract contract VaultBase {
uint256 public balance;
function deposit(uint256 amount) public {
balance += amount;
}
function fee() public virtual returns (uint256);
}
contract BasicVault is VaultBase {
function fee() public override returns (uint256) {
return 0;
}
}Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
abstract contract Account {
uint256 public balance;
function deposit(uint256 amount) public {
balance += amount;
}
function bonus() public virtual returns (uint256);
function applyBonus() public {
balance += bonus();
}
}
contract SavingsAccount is Account {
function bonus() public override returns (uint256) {
return 5;
}
}Key points
- Abstract keyword: Marking a contract abstract stops it from being deployed.
- Unfinished functions: A function with no body inside an abstract contract must be virtual.
- Children finish: A child implements the unfinished function with override.
- Shared code: An abstract contract can still hold state and finished functions its children inherit.
In this example, Account holds the balance and deposit, and leaves bonus without a body. SavingsAccount fills in bonus with 5. applyBonus is finished code in the parent, and it calls the child's bonus when it runs.
Note
You prove an abstract contract cannot deploy by a compile error, not by a runtime revert.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
What happens when code tries to deploy an abstract contract?