How handle diamond heritance when using Openzeppelin 5.0 `Ownable` contract?

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract A is Ownable {
    constructor(address owner) Ownable(owner) {}
}

contract B is Ownable {
    constructor(address owner) Ownable(owner) {}
}

contract C is A, B {
    constructor(address owner) B(owner) A(owner) {}
}

Here is a simple file demonstrating a diamond linearization involving Openzeppelin 5.0 Ownable contract, however this file won't compile and the error code is Base constructor arguments given twice.solidity(3364) since try to construct both in A and B contract, one work-around is declare both A and B as abstract contracts.

pragma solidity ^0.8.13;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

abstract contract A is Ownable {
    constructor() {}
}

abstract contract B is Ownable {
    constructor() {}
}

contract C is A, B {
    constructor(address owner) Ownable(owner) {}
}

This file compiles, but it clearly has its own limitations in real life. So is there another way to handle the diamond linearization?

1 Like

No it's not, because a contract can be declared abstract even when all of its functions ARE implemented, as stated in the official documentation:

Contracts must be marked as abstract when at least one of their functions is not implemented or when they do not provide arguments for all of their base contract constructors. Even if this is not the case, a contract may still be marked abstract

So you can just declare each one of them as abstract and go about your business...

The only downside here, also stated in the official documentation, is that doing so implies to anyone reading your contract that you do not intend for it to be created directly (i.e., you do not intend to deploy any instances of it).

Thanks for your explanation, but the problem here is, what if I want to deploy both contract A and B directly?

What part in my previous answer suggests that you cannot do this?

Could you possibly show me the code?

What code? You said it yourself - adding abstract solves the problem.

I only explained why your "clearly has its own limitations" statement was wrong.