Governor 5.0 GovernorTimelockControl

When using governor using GovernorTimelockControl module and the proposal is calling a function on timelock controller for instance cancel (cancelling a queued proposal)

it appears that msg sender of cancel is the timelock address and not governor.

Should I be using relay instead of execute for these cases?

In order for this to work the way I expected I needed to make timelock have the proposer and executor roles.

Hey @0xMySt1c,

The relay function is there for cases when the executor is not the governor itself as in the GovernorTimelockControl, so it should be fine to use it instead if you want the Governor to be the msg.sender.

Regarding your cancel example, the cancellation is desgined to be used by the proposer, so if the proposer is the Governor, then yes, only relay can cancel the operation and you'd need the Timelock to have both roles (proposer and executor). However, the proposer is generally not the governor itself, any reason to have it working this way?

Hi @ernestognw thanks for getting back to me.

I don't get your last sentence in context of

"A common use case is to position this TimelockController as the owner of a smart contract, with a multisig or a DAO as the sole proposer." - OZ Docs

I thought the entire purpose was to make the governor (DAO) the sole proposer.

Right, I just realized this is a bit confusing, but there are 2 types of proposer and executor here. Bear with me:

  • From the perspective of the Governor; a proposer (of a single proposal) is whoever called the propose(...) function, and an executor is not a role but a single address defined by the _executor() getter.
  • From the perspective of the TimelockController; a proposer is whoever is granted the PROPOSER_ROLE, and an executor is whoever is granted the EXECUTOR_ROLE.

The purpose of the GovernorTimelockControl is to bind the operation of the Governor to the Timelock so every successful governor proposal is delayed. However, the timelock requires an address granted with the PROPOSER_ROLE to propose timelock operations (not governor's).

So the Governor needs to be a proposer to the Timelock, but the Governor is not a proposer to itself.

Now, regarding cancel; when you cancel a governor proposal in GovernorTimelockControl, it also cancels it in the TimelockController.

"A common use case is to position this TimelockController as the owner of a smart contract, with a multisig or a DAO as the sole proposer." - OZ Docs

In this context, the recommendation is that the Governor becomes the sole proposer to the TimelockController.

So far you only need to grant the Governor with the PROPOSER_ROLE, EXECUTOR_ROLE and CANCELLER_ROLE in the Timelock and then operate everything from the governor.

Sorry, I didn't quite explain the situation well.

The cancel is not being called on a governor proposal, but on a scheduled transaction for the timelock.

The imaginary scenario I'm testing is:

  1. The DAO proposal passes and a txn is queued on the timelock.

  2. Someone realizes that there was is a bug and the DAO sends a 2nd proposal to call
    timelock.cancel from the governor, which is passed and queued.

  3. When you go to execute timelock.cancel from the governor to the timelock it fails without giving _timelock the CANCELLER_ROLE to itself.

Got it.

I understand the issue is that if a proposal calls cancel in the Timelock for the previous proposal it will fail because the Timelock itself is not the CANCELLER_ROLE.

Have you considered using the Governor's cancel function? I think it's better than queueing a new proposal to cancel the previous one but I recognize it's restricted only to the original proposer. For more general cases, using the relay function is good enough.

On a side note, GovernorTimelockAccess might be better suited for the example you're mentioning. Instead of a TimelockController it uses an AccessManager that has built-in guardians who can emergency-cancel scheduled operations. In case it sounds interesting to you, there's a good Access Manager explainer in the docs.

This is perfect. I didn't realize cancel allows you to unqueue transactions AS the timelock. I thought it was simply for cancelling proposals

1 Like