Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stop messaging #7

Merged
merged 10 commits into from
May 8, 2024
28 changes: 25 additions & 3 deletions src/contracts/BaseOpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ abstract contract BaseOpUSDCBridgeAdapter is Ownable, IOpUSDCBridgeAdapter {
/// @inheritdoc IOpUSDCBridgeAdapter
address public linkedAdapter;

/// @inheritdoc IOpUSDCBridgeAdapter
bool public isMessagingDisabled;

/**
* @notice Construct the OpUSDCBridgeAdapter contract
* @param _USDC The address of the USDC Contract to be used by the adapter
* @param _usdc The address of the USDC Contract to be used by the adapter
* @param _messenger The address of the messenger contract
*/
constructor(address _USDC, address _messenger) Ownable(msg.sender) {
USDC = _USDC;
constructor(address _usdc, address _messenger) Ownable(msg.sender) {
USDC = _usdc;
MESSENGER = _messenger;
}

Expand Down Expand Up @@ -49,4 +52,23 @@ abstract contract BaseOpUSDCBridgeAdapter is Ownable, IOpUSDCBridgeAdapter {
* @param _amount The amount of tokens to mint
*/
function receiveMessage(address _user, uint256 _amount) external virtual;

/**
* @notice Send a message to the linked adapter to call receiveStopMessaging() and stop outgoing messages.
* @dev Only callable by the owner of the adapter
excaliborr marked this conversation as resolved.
Show resolved Hide resolved
*/
function stopMessaging() external onlyOwner {
isMessagingDisabled = true;
IOpUSDCBridgeAdapter(linkedAdapter).receiveStopMessaging();
hexshire marked this conversation as resolved.
Show resolved Hide resolved
emit MessagingStopped();
}

/**
* @notice Receive the stop messaging message from the linked adapter and stop outgoing messages
*/
function receiveStopMessaging() external {
if (msg.sender != linkedAdapter) revert OpUSDCBridgeAdapter_NotLinkedAdapter();
isMessagingDisabled = true;
emit MessagingStopped();
}
}
31 changes: 29 additions & 2 deletions src/interfaces/IOpUSDCBridgeAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,35 @@
*/
event LinkedAdapterSet(address _linkedAdapter);

/**
* @notice Emitted when messaging is stopped
*/
event MessagingStopped();

/*///////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/

/**
* @notice Error when the stop messaging function is not called by the linked adapter
*/
error OpUSDCBridgeAdapter_NotLinkedAdapter();

/*///////////////////////////////////////////////////////////////
VARIABLES
//////////////////////////////////////////////////////////////*/

/**
* @notice Fetches address of the USDC token
* @return _USDC Address of the USDC token
* @return _usdc Address of the USDC token
*/
function USDC() external view returns (address _USDC);
function USDC() external view returns (address _usdc);

Check warning on line 37 in src/interfaces/IOpUSDCBridgeAdapter.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Function name must be in mixedCase

/**
* @notice Fetches address of the CrossDomainMessenger to send messages to L1 <-> L2
* @return _messenger Address of the messenger
*/
function MESSENGER() external view returns (address _messenger);

Check warning on line 43 in src/interfaces/IOpUSDCBridgeAdapter.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Function name must be in mixedCase

/**
* @notice Fetches address of the linked adapter on L2 to send messages to and receive from
Expand All @@ -38,6 +48,12 @@
*/
function linkedAdapter() external view returns (address _linkedAdapter);

/**
* @notice Fetches whether messaging is disabled
* @return _isMessagingDisabled Whether messaging is disabled
*/
function isMessagingDisabled() external view returns (bool _isMessagingDisabled);

/*///////////////////////////////////////////////////////////////
LOGIC
//////////////////////////////////////////////////////////////*/
Expand All @@ -47,7 +63,7 @@
* @dev Only the owner can call this function
* @param _linkedAdapter The address of the linked adapter
*/
function setLinkedAdapter(address _linkedAdapter) external;

Check warning on line 66 in src/interfaces/IOpUSDCBridgeAdapter.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Function order is incorrect, external function can not go after external view function (line 55)

/**
* @notice Send the message to the linked adapter to mint the bridged representation on the linked chain
Expand All @@ -64,4 +80,15 @@
* @param _amount The amount of tokens to mint
*/
function receiveMessage(address _user, uint256 _amount) external;

/**
* @notice Send a message to the linked adapter to call receiveStopMessaging() and stop outgoing messages.
* @dev Only callable by the owner of the adapter.
excaliborr marked this conversation as resolved.
Show resolved Hide resolved
*/
function stopMessaging() external;

/**
* @notice Receive the stop messaging message from the linked adapter and stop outgoing messages
*/
function receiveStopMessaging() external;
}
33 changes: 32 additions & 1 deletion test/unit/BaseOpUSDCBridgeAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.25;

import {BaseOpUSDCBridgeAdapter, IOpUSDCBridgeAdapter} from 'contracts/BaseOpUSDCBridgeAdapter.sol';
import {Test} from 'forge-std/Test.sol';
import {StdStorage, Test, stdStorage} from 'forge-std/Test.sol';

contract TestOpUSDCBridgeAdapter is BaseOpUSDCBridgeAdapter {
constructor(address _USDC, address _messenger) BaseOpUSDCBridgeAdapter(_USDC, _messenger) {}
Expand Down Expand Up @@ -52,3 +52,34 @@ contract UnitInitialization is Base {
adapter.setLinkedAdapter(_linkedAdapter);
}
}

contract UnitStopMessaging is Base {
using stdStorage for StdStorage;

function testStopMessaging() public {
vm.mockCall(adapter.linkedAdapter(), abi.encodeWithSignature('receiveStopMessaging()'), abi.encode(''));
vm.prank(_owner);
adapter.stopMessaging();
assertEq(adapter.isMessagingDisabled(), true, 'Messaging should be disabled');
}

function testReceiveStopMessaging() public {
address _linkedAdapter = makeAddr('linkedAdapter');

stdstore.target(address(adapter)).sig('linkedAdapter()').depth(0).checked_write(_linkedAdapter);
hexshire marked this conversation as resolved.
Show resolved Hide resolved
vm.prank(_linkedAdapter);
adapter.receiveStopMessaging();
assertEq(adapter.isMessagingDisabled(), true, 'Messaging should be disabled');
}

function testReceiveStopMessagingWrongSender() public {
address _linkedAdapter = makeAddr('linkedAdapter');
address _notLinkedAdapter = makeAddr('notLinkedAdapter');

stdstore.target(address(adapter)).sig('linkedAdapter()').depth(0).checked_write(_linkedAdapter);
hexshire marked this conversation as resolved.
Show resolved Hide resolved
vm.prank(_notLinkedAdapter);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg.sender is supposed to be MESSENGER I would change this to _notMessenger to be clear.

We also need one more test case for the case of when msg.sender is messenger but xDomainMessageSender() is not the linkedAdapter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

vm.expectRevert(IOpUSDCBridgeAdapter.OpUSDCBridgeAdapter_NotLinkedAdapter.selector);
adapter.receiveStopMessaging();
assertEq(adapter.isMessagingDisabled(), false, 'Messaging should not be disabled');
}
}
Loading