diff --git a/src/MultiBridgeMessageReceiver.sol b/src/MultiBridgeMessageReceiver.sol index 0ac5cb9..808c24d 100644 --- a/src/MultiBridgeMessageReceiver.sol +++ b/src/MultiBridgeMessageReceiver.sol @@ -174,6 +174,7 @@ contract MultiBridgeMessageReceiver is IMultiBridgeMessageReceiver, ExecutorAwar onlyGlobalOwner { _updateReceiverAdapters(_receiverAdapters, _operations); + _validateQuorum(quorum); } /// @notice Update bridge receiver adapters after quorum update @@ -183,18 +184,13 @@ contract MultiBridgeMessageReceiver is IMultiBridgeMessageReceiver, ExecutorAwar address[] calldata _receiverAdapters, bool[] calldata _operations ) external override onlyGlobalOwner { - if (_newQuorum > quorum) { - _updateReceiverAdapters(_receiverAdapters, _operations); - _updateQuorum(_newQuorum); - } else { - _updateQuorum(_newQuorum); - _updateReceiverAdapters(_receiverAdapters, _operations); - } + _updateReceiverAdapters(_receiverAdapters, _operations); + _validateAndUpdateQuorum(_newQuorum); } /// @notice Update power quorum threshold of message execution. function updateQuorum(uint64 _quorum) external override onlyGlobalOwner { - _updateQuorum(_quorum); + _validateAndUpdateQuorum(_quorum); } /*///////////////////////////////////////////////////////////////// @@ -228,10 +224,8 @@ contract MultiBridgeMessageReceiver is IMultiBridgeMessageReceiver, ExecutorAwar PRIVATE/INTERNAL FUNCTIONS ////////////////////////////////////////////////////////////////*/ - function _updateQuorum(uint64 _quorum) internal { - if (_quorum > trustedExecutorsCount() || _quorum == 0) { - revert Error.INVALID_QUORUM_THRESHOLD(); - } + function _validateAndUpdateQuorum(uint64 _quorum) internal { + _validateQuorum(_quorum); uint64 oldValue = quorum; @@ -268,11 +262,13 @@ contract MultiBridgeMessageReceiver is IMultiBridgeMessageReceiver, ExecutorAwar _addTrustedExecutor(_receiverAdapter); } else { _removeTrustedExecutor(_receiverAdapter); - - if (quorum > trustedExecutorsCount()) { - revert Error.INVALID_QUORUM_THRESHOLD(); - } } emit BridgeReceiverAdapterUpdated(_receiverAdapter, _add); } + + function _validateQuorum(uint256 _quorum) private view { + if (_quorum > trustedExecutorsCount() || _quorum == 0) { + revert Error.INVALID_QUORUM_THRESHOLD(); + } + } } diff --git a/test/Setup.t.sol b/test/Setup.t.sol index b29d3b9..a96db6a 100644 --- a/test/Setup.t.sol +++ b/test/Setup.t.sol @@ -316,9 +316,8 @@ abstract contract Setup is Test { MultiBridgeMessageReceiver dstMMReceiver = MultiBridgeMessageReceiver(contractAddress[chainId][bytes("MMA_RECEIVER")]); - dstMMReceiver.updateReceiverAdapters(_receiverAdapters, _operations); + dstMMReceiver.updateQuorumAndReceiverAdapter(2, _receiverAdapters, _operations); dstMMReceiver.updateGovernanceTimelock(contractAddress[chainId]["TIMELOCK"]); - dstMMReceiver.updateQuorum(2); MessageReceiverGAC receiverGAC = MessageReceiverGAC(contractAddress[chainId][bytes("GAC")]); receiverGAC.setMultiBridgeMessageReceiver(address(dstMMReceiver)); diff --git a/test/unit-tests/MultiBridgeMessageReceiver.t.sol b/test/unit-tests/MultiBridgeMessageReceiver.t.sol index 1bcf0b6..e3ac673 100644 --- a/test/unit-tests/MultiBridgeMessageReceiver.t.sol +++ b/test/unit-tests/MultiBridgeMessageReceiver.t.sol @@ -504,6 +504,32 @@ contract MultiBridgeMessageReceiverTest is Setup { assertEq(receiver.isTrustedExecutor(axelarAdapterAddr), false); } + /// @dev valid quorum and receiver updater in one single call, removing one, adding two and increasing quorum + function test_quorum_and_receiver_updater_remove_add_increase() public { + vm.startPrank(timelockAddr); + + // Remove one adapter and update quorum to 1 + address[] memory removeAddAdapters = new address[](3); + removeAddAdapters[0] = axelarAdapterAddr; + removeAddAdapters[1] = address(42); + removeAddAdapters[2] = address(43); + bool[] memory removeAddOps = new bool[](3); + removeAddOps[0] = false; + removeAddOps[1] = true; + removeAddOps[2] = true; + + uint64 newQuorum = 3; + + receiver.updateQuorumAndReceiverAdapter(newQuorum, removeAddAdapters, removeAddOps); + + /// @dev asserts the quorum and adapter lengths + assertEq(receiver.quorum(), newQuorum); + assertEq(receiver.isTrustedExecutor(wormholeAdapterAddr), true); + assertEq(receiver.isTrustedExecutor(axelarAdapterAddr), false); + assertEq(receiver.isTrustedExecutor(removeAddAdapters[1]), true); + assertEq(receiver.isTrustedExecutor(removeAddAdapters[2]), true); + } + /// @dev should get message info function test_get_message_info() public { vm.startPrank(wormholeAdapterAddr);