How to restrict function calls to only governance process

I want to restrict my function calls to governance. I want to apply this restriction to functions that are not part of the governance contract. I can create a role for the governance contract and restrict the call as in this example:

// Assume that there is role named ONLY_GOVERNANCE
// Assume governance contract has this role granted
function dummyFunc() external onlyRole(ONLY_GOVERNANCE){}

But this doesn't ensure if a call is made after a governance process (a proposal, voting, etc) or not. It only check if the call is made from the governance contract. Is there a way to do this properly?

Sounds like onlyGovernance() is what you're looking for:

Restricts a function so it can only be executed through governance proposals. For example, governance parameter setters in GovernorSettings are protected using this modifier.
The governance executing address may be different from the Governor’s own address, for example it could be a timelock. This can be customized by modules by overriding _executor. The executor is only able to invoke these functions during the execution of the governor’s execute function, and not under any other circumstances. Thus, for example, additional timelock proposers are not able to change governance parameters without going through the governance protocol (since v4.6).

Sadly, I was also thinking the same thing but I don't want all of my contracts to be a governance contract: How to use onlyGovernance modifier? - #3 by ernestognw

So just replicate (in your contract) what this modifier does.

But there are private variables that I cannot get access to if my contract is not a governance contract.

So you need to explain what exactly you mean by "I don't want all of my contracts to be a governance contract", because it sounds like this is exactly what you want.

You can replicate those variables too, of course, but you just might find yourself with a governance-like contract at the end of that process.

1 Like

I shouldn't be doing this in all of my smart contracts:

import "@openzeppelin/contracts/governance/Governor.sol";

contract MyContract is Governer{
// add governer parameters inside constructor as well
}

Like I said on the previous comment, you can copy a bunch of stuff from the Governer contract into your own contract, but you will likely just end up with a governance-like contract.

So once again - you need to explain WHY you don't want to be a governance contract (rather than just showing the contract declaration line and saying "I don't want this").

I already have a governance contract. I also have 10 other smart contracts. Why would I want my 10 other smart contracts to become a governance contract? Is this a good practice?

Advice: define your product requirements, then design your system, then implement the code.

If one of these steps implies that your "10 other smart contracts to become a governance contract", then that's what you should do.

I disagree. I already have a working solution and I am looking for a better one. Replicating variables is a terrible idea since it is a waste of gas usage. Similarly: inheriting a whole smart contract solely for a single modifier is also waste of gas and bad code design (doesn't matter 10 or 1 smart contract).

Advice: Stop and think if you are not gonna provide any better solution than the one you already proposed. So that a "question" would be more welcoming to the new readers.

Hello @DoDzilla

Unfortunately, there is no way to do this. We expect the call recipient contract would use onlyOwner (Ownable) or onlyRole (AccessControl), and that checking the caller is the governor (or the attached timelock) would be sufficient.

1 Like