I am relatively new to smart contract development and am currently working on implementing a governance system using OpenZeppelin's contracts. (I test on a local HardHat node).
My contracts, MyToken and MyGovernor are from https://docs.openzeppelin.com/contracts/5.x/governance#governor
Objective:
I'm implementing a smart contract governance system using OpenZeppelin's contracts. The workflow includes creating proposals with MyGovernor
contract, scheduling operations in TimelockController
, and then executing these operations post-voting.
Problem:
The main issue arises during the execution stage. I'm facing a TimelockUnexpectedOperationState
error. This error seems to be triggered by an inconsistency in the operation IDs between the scheduling and execution phases.
Detailed Steps and Observations:
- Proposal Creation: Successfully created a proposal with the
MyGovernor
contract. - Operation Scheduling: Scheduled the operation in
TimelockController
usingscheduleBatch
. The operation successfully entered the pending state. - Voting and Queuing: Completed the voting process and queued the proposal in
MyGovernor
. - Execution Attempt: Encountered the
TimelockUnexpectedOperationState
error when trying to execute the operation withexecute
. The error references an operation ID different from the one I've been tracking.
The error itself:
Error: VM Exception while processing transaction: reverted with custom error 'TimelockUnexpectedOperationState("0x0f074607eabfa02e41554a483f284c975246cd60414b6be3ed139fe2df1fcfd6", "0x0000000000000000000000000000000000000000000000000000000000000004")' at TimelockController.updateDelay (@openzeppelin/contracts/governance/TimelockController.sol:452) at TimelockController.executeBatch (@openzeppelin/contracts/governance/TimelockController.sol:398) at MyGovernor._executeOperations (@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol:111) at MyGovernor._executeOperations (contracts/MyGovernor.sol:83) at MyGovernor.execute (@openzeppelin/contracts/governance/Governor.sol:418) at processTicksAndRejections (node:internal/process/task_queues:95:5) at runNextTicks (node:internal/process/task_queues:64:3) at listOnTimeout (node:internal/timers:533:9) at processTimers (node:internal/timers:507:7) at async HardhatNode._mineBlockWithPendingTxs1
The logs:
Operation ID: Promise {
'0xe9a0b217bae1e6321753629f67a3d5d370e40f7f153de2642c50d0899a607829'
}
Current state of proposal before voting: 1
Votes have been cast
Current state of proposal: 4
Operation ready: true
Operation status: Pending - true, Ready - true
timestamp : 1706882895
State of the proposal: 5
Upon examining the logs and error messages closely, I've noticed a discrepancy between the operation IDs. The operation ID logged during my process is 0xe9a0b217bae1e6321753629f67a3d5d370e40f7f153de2642c50d0899a607829
, yet the error message references a completely different operation ID: 0x0f074607eabfa02e41554a483f284c975246cd60414b6be3ed139fe2df1fcfd6
. This mismatch seems to be at the crux of the TimelockUnexpectedOperationState
error I'm encountering.
It appears that this discrepancy in operation IDs between the scheduled task and the executed task in the TimelockController
is causing the workflow to fail. Any insights into why these IDs are different, would be greatly appreciated.
The error occurs at
const executeTx = await myGovernor .connect(deployer) .execute(targets, values, calldatas, descriptionHash); await executeTx.wait();
I am using the same values to get the operation ID and to schedule the operation:
const operationId = await timelock.hashOperationBatch( targets, values, calldatas, ethers.constants.HashZero, salt );
await timelock.scheduleBatch( targets, values, calldatas, ethers.constants.HashZero, salt, minDelay );
I hope this information clearly outlines the issues I'm encountering. Thank you in advance for your time and assistance. If you need any further information, please leave a comment.