Skip to content

Commit

Permalink
chore: add convenience helpers for receiver updates
Browse files Browse the repository at this point in the history
  • Loading branch information
sujithsomraaj committed Sep 12, 2023
1 parent 7941b27 commit b71c48b
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 68 deletions.
84 changes: 36 additions & 48 deletions src/MultiMessageReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,14 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ
////////////////////////////////////////////////////////////////*/

/// @notice sets the initial parameters
function initialize(address[] calldata _receiverAdapters, uint64 _quorum, address _governanceTimelock)
external
initializer
{
uint256 len = _receiverAdapters.length;

if (len == 0) {
revert Error.ZERO_RECEIVER_ADAPTER();
}

for (uint256 i; i < len;) {
if (_receiverAdapters[i] == address(0)) {
revert Error.ZERO_ADDRESS_INPUT();
}

_updateReceiverAdapter(_receiverAdapters[i], true);

unchecked {
++i;
}
}
function initialize(
address[] calldata _receiverAdapters,
bool[] calldata _operations,
uint64 _quorum,
address _governanceTimelock
) external initializer {
/// @dev adds the new receiver adapters before setting quorum and validations
_updateReceiverAdapters(_receiverAdapters, _operations);

if (_quorum > trustedExecutor.length || _quorum == 0) {
revert Error.INVALID_QUORUM_THRESHOLD();
Expand Down Expand Up @@ -180,23 +167,11 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ

/// @notice Update bridge receiver adapters.
/// @dev called by admin to update receiver bridge adapters on all other chains
function updateReceiverAdapter(address[] calldata _receiverAdapters, bool[] calldata _operations)
function updateReceiverAdapters(address[] calldata _receiverAdapters, bool[] calldata _operations)
external
onlyGovernanceTimelock
{
uint256 len = _receiverAdapters.length;

if (len != _operations.length) {
revert Error.ARRAY_LENGTH_MISMATCHED();
}

for (uint256 i; i < len;) {
_updateReceiverAdapter(_receiverAdapters[i], _operations[i]);

unchecked {
++i;
}
}
_updateReceiverAdapters(_receiverAdapters, _operations);
}

/// @notice Update bridge receiver adapters after quorum update
Expand All @@ -206,22 +181,11 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ
address[] calldata _receiverAdapters,
bool[] calldata _operations
) external onlyGovernanceTimelock {
uint256 len = _receiverAdapters.length;

if (len != _operations.length) {
revert Error.ARRAY_LENGTH_MISMATCHED();
}

/// @dev updates quorum here
_updateQuorum(_newQuorum);

for (uint256 i; i < len;) {
_updateReceiverAdapter(_receiverAdapters[i], _operations[i]);

unchecked {
++i;
}
}
/// @dev updates receiver adapter here
_updateReceiverAdapters(_receiverAdapters, _operations);
}

/// @notice Update power quorum threshold of message execution.
Expand Down Expand Up @@ -269,6 +233,30 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ
emit QuorumUpdated(oldValue, _quorum);
}

function _updateReceiverAdapters(address[] memory _receiverAdapters, bool[] memory _operations) internal {
uint256 len = _receiverAdapters.length;

if (len == 0) {
revert Error.ZERO_RECEIVER_ADAPTER();
}

if (len != _operations.length) {
revert Error.ARRAY_LENGTH_MISMATCHED();
}

for (uint256 i; i < len;) {
if (_receiverAdapters[i] == address(0)) {
revert Error.ZERO_ADDRESS_INPUT();
}

_updateReceiverAdapter(_receiverAdapters[i], _operations[i]);

unchecked {
++i;
}
}
}

function _updateReceiverAdapter(address _receiverAdapter, bool _add) private {
if (_add) {
_addTrustedExecutor(_receiverAdapter);
Expand Down
6 changes: 5 additions & 1 deletion test/Setup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,12 @@ abstract contract Setup is Test {
_recieverAdapters[0] = contractAddress[chainId][bytes("WORMHOLE_RECEIVER_ADAPTER")];
_recieverAdapters[1] = contractAddress[chainId][bytes("AXELAR_RECEIVER_ADAPTER")];

bool[] memory _operations = new bool[](2);
_operations[0] = true;
_operations[1] = true;

MultiMessageReceiver(contractAddress[DST_CHAINS[i]][bytes("MMA_RECEIVER")]).initialize(
_recieverAdapters, 2, contractAddress[chainId]["TIMELOCK"]
_recieverAdapters, _operations, 2, contractAddress[chainId]["TIMELOCK"]
);

unchecked {
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/MultiMessageAggregation.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract MultiMessageAggregationTest is Setup {
}

/// @dev just sends a message
function test_mmaTest() public {
function test_mmaSendMessage() public {
vm.selectFork(fork[1]);
vm.startPrank(caller);

Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/RemoteAdapterAdd.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract RemoteAdapterAdd is Setup {
MultiMessageSender(contractAddress[1][bytes("MMA_SENDER")]).remoteCall{value: 2 ether}(
137,
address(contractAddress[137][bytes("MMA_RECEIVER")]),
abi.encodeWithSelector(MultiMessageReceiver.updateReceiverAdapter.selector, adaptersToAdd, operation),
abi.encodeWithSelector(MultiMessageReceiver.updateReceiverAdapters.selector, adaptersToAdd, operation),
0,
block.timestamp + EXPIRATION_CONSTANT
);
Expand Down
2 changes: 1 addition & 1 deletion test/integration-tests/RemoteAdapterRemove.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ contract RemoteAdapterRemove is Setup {
operation[0] = true;

vm.startPrank(contractAddress[137]["TIMELOCK"]);
MultiMessageReceiver(contractAddress[137]["MMA_RECEIVER"]).updateReceiverAdapter(newDummyAdapter, operation);
MultiMessageReceiver(contractAddress[137]["MMA_RECEIVER"]).updateReceiverAdapters(newDummyAdapter, operation);
vm.stopPrank();
}
}
55 changes: 39 additions & 16 deletions test/unit-tests/MultiMessageReceiver.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ contract MultiMessageReceiverTest is Setup {
adapters[0] = wormholeAdapterAddr;
adapters[1] = axelarAdapterAddr;

bool[] memory operation = new bool[](2);
operation[0] = true;
operation[1] = true;

MultiMessageReceiver dummyReceiver = new MultiMessageReceiver();
dummyReceiver.initialize(adapters, 2, timelockAddr);
dummyReceiver.initialize(adapters, operation, 2, timelockAddr);

assertEq(dummyReceiver.quorum(), 2);
assertEq(dummyReceiver.trustedExecutor(0), wormholeAdapterAddr);
Expand All @@ -56,7 +60,7 @@ contract MultiMessageReceiverTest is Setup {
vm.startPrank(caller);

vm.expectRevert("Initializable: contract is already initialized");
receiver.initialize(new address[](0), 0, address(0));
receiver.initialize(new address[](0), new bool[](0), 0, address(0));
}

/// @dev cannot be called with zero adapter
Expand All @@ -66,7 +70,7 @@ contract MultiMessageReceiverTest is Setup {
MultiMessageReceiver dummyReceiver = new MultiMessageReceiver();

vm.expectRevert(Error.ZERO_RECEIVER_ADAPTER.selector);
dummyReceiver.initialize(new address[](0), 0, address(0));
dummyReceiver.initialize(new address[](0), new bool[](0), 0, address(0));
}

/// @dev cannot be called with zero address adapter
Expand All @@ -77,8 +81,11 @@ contract MultiMessageReceiverTest is Setup {
address[] memory adapters = new address[](1);
adapters[0] = address(0);

bool[] memory operation = new bool[](1);
operation[0] = true;

vm.expectRevert(Error.ZERO_ADDRESS_INPUT.selector);
dummyReceiver.initialize(adapters, 1, timelockAddr);
dummyReceiver.initialize(adapters, operation, 1, timelockAddr);
}

/// @dev quorum cannot be larger than the number of receiver adapters
Expand All @@ -89,8 +96,11 @@ contract MultiMessageReceiverTest is Setup {
address[] memory adapters = new address[](1);
adapters[0] = address(42);

bool[] memory operation = new bool[](1);
operation[0] = true;

vm.expectRevert(Error.INVALID_QUORUM_THRESHOLD.selector);
dummyReceiver.initialize(adapters, 2, timelockAddr);
dummyReceiver.initialize(adapters, operation, 2, timelockAddr);
}

/// @dev quorum cannot be larger than the number of unique receiver adapters
Expand All @@ -102,8 +112,12 @@ contract MultiMessageReceiverTest is Setup {
adapters[0] = address(42);
adapters[1] = address(42);

bool[] memory operation = new bool[](2);
operation[0] = true;
operation[1] = true;

vm.expectRevert(Error.INVALID_QUORUM_THRESHOLD.selector);
dummyReceiver.initialize(adapters, 2, timelockAddr);
dummyReceiver.initialize(adapters, operation, 2, timelockAddr);
}

/// @dev initializer quorum cannot be zero
Expand All @@ -114,8 +128,11 @@ contract MultiMessageReceiverTest is Setup {
address[] memory adapters = new address[](1);
adapters[0] = address(42);

bool[] memory operation = new bool[](1);
operation[0] = true;

vm.expectRevert(Error.INVALID_QUORUM_THRESHOLD.selector);
dummyReceiver.initialize(adapters, 0, timelockAddr);
dummyReceiver.initialize(adapters, operation, 0, timelockAddr);
}

/// @dev governance timelock cannot be zero address
Expand All @@ -126,8 +143,11 @@ contract MultiMessageReceiverTest is Setup {
address[] memory adapters = new address[](1);
adapters[0] = address(42);

bool[] memory operation = new bool[](1);
operation[0] = true;

vm.expectRevert(Error.ZERO_GOVERNANCE_TIMELOCK.selector);
dummyReceiver.initialize(adapters, 1, address(0));
dummyReceiver.initialize(adapters, operation, 1, address(0));
}

/// @dev receives message from one adapter
Expand Down Expand Up @@ -419,7 +439,7 @@ contract MultiMessageReceiverTest is Setup {
vm.expectEmit(true, true, true, true, address(receiver));
emit ReceiverAdapterUpdated(address(42), true);

receiver.updateReceiverAdapter(updatedAdapters, operations);
receiver.updateReceiverAdapters(updatedAdapters, operations);

assertEq(receiver.trustedExecutor(0), wormholeAdapterAddr);
assertEq(receiver.trustedExecutor(1), axelarAdapterAddr);
Expand All @@ -441,7 +461,7 @@ contract MultiMessageReceiverTest is Setup {
vm.expectEmit(true, true, true, true, address(receiver));
emit ReceiverAdapterUpdated(wormholeAdapterAddr, false);

receiver.updateReceiverAdapter(updatedAdapters, operations);
receiver.updateReceiverAdapters(updatedAdapters, operations);
assertEq(receiver.trustedExecutor(0), axelarAdapterAddr);
}

Expand All @@ -450,17 +470,20 @@ contract MultiMessageReceiverTest is Setup {
vm.startPrank(caller);

vm.expectRevert(Error.CALLER_NOT_GOVERNANCE_TIMELOCK.selector);
receiver.updateReceiverAdapter(new address[](0), new bool[](0));
receiver.updateReceiverAdapters(new address[](0), new bool[](0));
}

/// @dev adapters and operations length mismatched
function test_update_receiver_adapter_length_mismatched() public {
vm.startPrank(timelockAddr);

vm.expectRevert(Error.ARRAY_LENGTH_MISMATCHED.selector);
bool[] memory operations = new bool[](1);
operations[0] = true;
receiver.updateReceiverAdapter(new address[](0), operations);
address[] memory adapters = new address[](1);
adapters[0] = address(420);

bool[] memory operations = new bool[](2);

receiver.updateReceiverAdapters(adapters, operations);
}

/// @dev cannot remove one receiver adapter without reducing quorum first
Expand All @@ -472,7 +495,7 @@ contract MultiMessageReceiverTest is Setup {
bool[] memory operations = new bool[](1);
operations[0] = false;
vm.expectRevert(Error.INVALID_QUORUM_THRESHOLD.selector);
receiver.updateReceiverAdapter(updatedAdapters, operations);
receiver.updateReceiverAdapters(updatedAdapters, operations);
}

/// @dev updates quorum
Expand All @@ -484,7 +507,7 @@ contract MultiMessageReceiverTest is Setup {
updatedAdapters[0] = address(42);
bool[] memory operations = new bool[](1);
operations[0] = true;
receiver.updateReceiverAdapter(updatedAdapters, operations);
receiver.updateReceiverAdapters(updatedAdapters, operations);

vm.expectEmit(true, true, true, true, address(receiver));
emit QuorumUpdated(2, 3);
Expand Down

0 comments on commit b71c48b

Please sign in to comment.