realy function which exists in the security council management contracts enables the owners of these contracts to make calls to other contracts.
But if native tokens is intended to be sent with the call; it will revert as the function is not payable,and there's noway for these management contracts to receive native tokens since receive() function is not implemented in these contracts.
testRelayWithValue() test is added to SecurityCouncilMemberElectionGovernorTest.t.sol file; where the relay function is invoked by the contract owner to call a contract address: first without a value where it will be executed, then with a value where the call will revert due to lack of funds.
first a ReceiverContract contract is added to the governance/test/security-council-mgmt/governors/ directory where the calls from the relay function are going to target the receiveFunds() functionin in this contract:
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.16;
contract ReceiverContract {
function receiveFunds() public payable {}
}
The testRelayWithValue() test:
add this import at the top of the SecurityCouncilMemberElectionGovernorTest.t.sol test file:
import "./ReceiverContract.sol";
function testRelayWithValue() public {
//0. deploy the receiver contract
ReceiverContract receiverContract = new ReceiverContract();
uint256 valueToSend = 10 ether;
// 1. memberElection contract owner calls receiverContract::receiveFunds via relay without a value, it will be executed:
assertEq(address(receiverContract).balance, 0);
vm.startPrank(initParams.owner);
governor.relay(
address(receiverContract),
0,
abi.encodeWithSelector(receiverContract.receiveFunds.selector)
);
assertEq(address(receiverContract).balance, 0);
// 2. memberElection contract owner calls receiverContract::receiveFunds via relay with a value, it will revert:
vm.expectRevert();
governor.relay(
address(receiverContract),
valueToSend,
abi.encodeWithSelector(receiverContract.receiveFunds.selector)
);
assertEq(address(receiverContract).balance, 0);
}
Test result:
$ forge test --match-test testRelayWithValue
[PASS] testRelayWithValue() (gas: 75277)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 4.40ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
Lines of code
https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilMemberElectionGovernor.sol#L103-L110 https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilMemberRemovalGovernor.sol#L203-L210 https://github.com/ArbitrumFoundation/governance/blob/c18de53820c505fc459f766c1b224810eaeaabc5/src/security-council-mgmt/governors/SecurityCouncilNomineeElectionGovernor.sol#L254-L261
Vulnerability details
Impact
realy
function which exists in the security council management contracts enables the owners of these contracts to make calls to other contracts.But if native tokens is intended to be sent with the call; it will revert as the function is not payable,and there's noway for these management contracts to receive native tokens since
receive()
function is not implemented in these contracts.Proof of Concept
Code:
SecurityCouncilMemberElectionGovernor contract/relay function
SecurityCouncilMemberRemovalGovernor contract/relay function
SecurityCouncilNomineeElectionGovernor contract/relay function
Foundry PoC:
testRelayWithValue()
test is added toSecurityCouncilMemberElectionGovernorTest.t.sol
file; where the relay function is invoked by the contract owner to call a contract address: first without a value where it will be executed, then with a value where the call will revert due to lack of funds.first a
ReceiverContract
contract is added to thegovernance/test/security-council-mgmt/governors/
directory where the calls from the relay function are going to target thereceiveFunds()
functionin in this contract:The
testRelayWithValue()
test: add this import at the top of theSecurityCouncilMemberElectionGovernorTest.t.sol
test file:Test result:
Tools Used
Manual Testing & Foundry.
Recommended Mitigation Steps
Update
relay
function to be payable:Assessed type
ETH-Transfer