The Governance::execute function is declared as a non-payable. This prevents the execution of any governance proposal that includes value transfers (i.e., where the values array in the proposal contains elements greater than 0). Because msg.value cannot be sent to a non-payable function, any attempt to execute such a proposal will revert with an "out of funds" error.
The Governance::execute function is responsible for executing a proposal after it has been queued in the TimelockController. Within execute, the contract calls the target contracts specified in the proposal, potentially transferring value using the values array and the call function. However, because the execute function itself is not payable, it cannot receive any msg.value. Consequently, when the execute function attempts to call the target contracts with value transfers (e.g., targets[i].call{value: values[i]}(calldatas[i])), the calls will fail because the Governance contract has no funds to send. The transaction will revert with an "out of funds" error, effectively blocking the execution of any proposal involving value transfers.
The crucial part is the targets[i].call{value: values[i]}(calldatas[i]) line in TimelockController.executeBatch fuction. If values[i] is greater than 0, this call will require the Governance contract to have some Ether to send. Since execute is not payable, the contract will not have any Ether, leading to the "out of funds" revert.
Proposal Execution Failure: Any proposal that requires transferring value to target contracts will fail to execute. This severely limits the types of actions that can be implemented through governance proposals.
Governance Functionality Breakdown: A core feature of a governance system is the ability to manage and modify the protocol, which often includes transferring assets. This vulnerability cripples this functionality.
Create Proposal (with Value Transfer): Create a governance proposal that includes at least one target contract address and a corresponding value in the values array greater than 0. This proposal should be designed to transfer some amount of tokens or Ether.
Queue Proposal: Have the proposal pass the quorum requirements and be queued in the TimelockController.
Attempt Execution: Call the Governance::execute function.
Observe Revert: The transaction will revert with an "out of funds" error because the execute function is not payable and cannot forward the required msg.value.
Make the Governance::execute function payable. This will allow the contract to receive and forward Ether or tokens to the target contracts during proposal execution.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.