Size of file extending in openZeppelin governance contract taken from Wizard

I was making a DAO in my project ,and I took the Governance contract from openzeppelin wizard ,as it was shown in the course ,but when i tried to deploy on anvil ,it was giving this error --> Error: Unknown5 is above the contract size limit (28857 > 24576).

After which I ran this command `forge build --sizes`
after which it was clear that the size of the Governor file was extending the 24kb limit

This is the DAO contract code which i took from Wizzards:

// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.4.0
pragma solidity ^0.8.27;

import {Governor} from "@openzeppelin/contracts/governance/Governor.sol";
import {GovernorCountingSimple} from "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import {GovernorSettings} from "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import {GovernorTimelockControl} from "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
import {GovernorVotes} from "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import {GovernorVotesQuorumFraction} from
    "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";

contract MyGovernor is
    Governor,
    GovernorSettings,
    GovernorCountingSimple,
    GovernorVotes,
    GovernorVotesQuorumFraction,
    GovernorTimelockControl
{
    constructor(IVotes _token, TimelockController _timelock)
        Governor("MyGovernor")
        GovernorSettings(1, /* 1 block */ 50400, /* 1 week */ 0)
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4)
        GovernorTimelockControl(_timelock)
    {}

    // The following functions are overrides required by Solidity.

    function state(uint256 proposalId)
        public
        view
        override(Governor, GovernorTimelockControl)
        returns (ProposalState)
    {
        return super.state(proposalId);
    }

    function proposalNeedsQueuing(uint256 proposalId)
        public
        view
        override(Governor, GovernorTimelockControl)
        returns (bool)
    {
        return super.proposalNeedsQueuing(proposalId);
    }

    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
        return super.proposalThreshold();
    }

    function _queueOperations(
        uint256 proposalId,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) returns (uint48) {
        return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
    }

    function _executeOperations(
        uint256 proposalId,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) {
        super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
    }

    function _cancel(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) returns (uint256) {
        return super._cancel(targets, values, calldatas, descriptionHash);
    }

    function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
        return super._executor();
    }
}

After doing a bit research about this error ,i came to know that it is recommended to split the contract into small contracts ,but I am not able to figure out how can I split this Governance Contract ,can someone please guide me how to do this ?or maybe soome otheer alternative ?

Thanks

Every Governor extension adds boilerplate and override functions.

When you combine 5–6 extensions, the compiler merges all inherited methods, which bloats the bytecode.

Ethereum mainnet enforces a 24KB contract size limit, so your contract simply can’t be deployed.

Solution:

Use Solidity's “external” libraries:

Move big functions (like _executeOperations, _queueOperations) into a library, then using LibGovernor for *.

This reduces in-contract code size.

1 Like

Hi, I ran into the same limit once when stacking multiple extensions. What helped me was moving some heavy logic into a separate library and calling it externally instead of keeping everything inside the Governor. It feels a bit counterintuitive at first, but the bytecode reduction was significant enough to fit under the 24kb cap. Have you tried checking which functions take the biggest chunk with forge build --sizes and offloading just those?"

1 Like

You can enable the optimizer in your Solidity compiler settings to reduce the bytecode size.

1 Like

I will try that out for sure .

Although, I have used Diamond Proxy Pattern for now .