OpenZeppelin's repo uses abstract contracts rather than interfaces when defining structs and enums to not violate any best practices.
The two examples, IGoverner.sol
and IGovernorCompatibilityBravo.sol
, define an enum and a struct element (respectively). However, they are defined as abstract contracts rather than interfaces- and still use the same naming convention as normal interfaces. None of OpenZeppelin's "real" interfaces define enums or structs directly in them, likely in consideration of best practices.
Here's my example code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract IPersonContract {
struct Person {
string firstName;
string lastName;
uint8 age;
uint256 favNumber;
}
function getPerson(uint256 index) public view virtual returns (Person memory);
}
contract PersonContract is IPersonContract {
Person[] private _people;
function getPerson(uint256 index) public view override returns (Person memory) {
return _people[index];
}
}
Please note that in the files above and example code, inherited functions use public
instead of external
- and require using virtual
which normal interfaces don't.
UPDATE
It actually is more gas-efficient to return individual values in certain instances- which removes the need to use an abstract contract in place of a normal interface. For example, if you are deciding to wrap the variables in the struct before returning, you incur extra gas costs due to wrapping them. Here's an example. This is contrary to the original idea that returning one "element" would be cheaper than multiple ones.
// SPDX-License-Identifier: MIT
// Compiled with 0.8.19 with Remix and deployed on Mainnet Fork
pragma solidity ^0.8.0;
contract PersonContract {
struct Person {
string firstName;
string lastName;
uint8 age;
uint256 favNumber;
}
// execution cost: 3356 gas
function getPersonA(
string memory first,
string memory last,
uint256 fav
) public pure returns (Person memory) {
return Person(first, last, 100, fav);
}
// execution cost: 3023 gas
function getPersonB(
string memory first,
string memory last,
uint256 fav
)
public
pure
returns (
string memory,
string memory,
uint8,
uint256
)
{
return (first, last, 100, fav);
}
}