Given a smart contract setup where there is an Interface object that defines multiple different functions that a new contract wishes to adhere to, and it wants to inherit some functionality to define some of that logic, I expected a structure like this to work:
pragma solidity ^0.8.9;
interface A {
function foo() external returns (uint256);
function bar() external returns (uint256);
}
contract B {
function foo() public returns (uint256) {
return 1;
}
}
contract MyContract is A, B {
function bar() public returns (uint256) {
return 2;
}
}
The Solidity compiler fails to compile this, giving the error "TypeError: Derived contract must override function "foo". Two or more base classes define function with same name and parameter types."
It finds the foo
reference in both the A
interface and the B
contract definition and seems to be unable to merge them, even though A
is an interface, and its definition of foo
is just a definition, not an implementation.
The only way I've found around this is to add a function to MyContract
like
function foo() public override(A, B) returns (uint256) {
return B.foo();
}
Is this a bug in the compiler (it's not ignoring function definitions that aren't implemented), or is there a more elegant way to combine logic like this?
Best Answer
Looking through past issue requests on the Solidity GitHub, it appears this situation falls into the same space as this request, and the answer is the Solidity compiler forces that additional declaration on the child contract as a design choice; forcing the developer to indicate they are aware that there are two methods with the same name, and to explicitly declare they're not just named the same, but are functionally/conceptually the same.
The other option, if the developer has control of the definition of
B
, is to do:Namely, change
B
to not be a Contract but an Abstract Contract, explicitly defining it as a partial implementation of interfaceA
, and haveMyContract
only inherit fromB
.