Skip to content

Conversation

@ashitakah
Copy link

@ashitakah ashitakah commented Sep 30, 2025

CLOSES OPT-1189

@linear
Copy link

linear bot commented Oct 2, 2025

OPT-1189 POC: CGT Bridge

Comment on lines +56 to +59
error Paused();

/// @notice Thrown when caller is not the authorized L2 CGT Bridge.
error OnlyL2CGTBridge();
Copy link

Choose a reason for hiding this comment

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

this errors should also be L1CGTBridge_{error}():

Suggested change
error Paused();
/// @notice Thrown when caller is not the authorized L2 CGT Bridge.
error OnlyL2CGTBridge();
error L1CGTBridge_Paused();
/// @notice Thrown when caller is not the authorized L2 CGT Bridge.
error L1CGTBridge_OnlyL2CGTBridge();

/// @param _amount Amount of CGT tokens to bridge.
/// @param _minGasLimit Minimum gas limit for the bridge.
function bridgeCGT(address _to, uint256 _amount, uint32 _minGasLimit) external virtual {
if (!depositsEnabledL1toL2) revert L1CGTBridge_DepositsDisabled();
Copy link

Choose a reason for hiding this comment

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

Naming here can be confused with Portal's deposits. wdyt?

Copy link

@0xniha 0xniha Oct 3, 2025

Choose a reason for hiding this comment

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

Also, why do we need both the paused flag in superchainConfig and this boolean to block the bridge?
If there are already two booleans to control bridging, is it because paused can disable both directions at once?
I think we should choose one option:

  1. two independent booleans.
  2. paused

if (!depositsEnabledL1toL2) revert L1CGTBridge_DepositsDisabled();
if (superchainConfig.paused(address(this))) revert Paused();

cgtToken.safeTransferFrom(msg.sender, address(this), _amount);
Copy link

Choose a reason for hiding this comment

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

Just an experimental idea: Could tokens be locked in another contract instead of being transferred to the bridge? Would this bring modularity?

revert OnlyL1CGTBridge();
}

if (_to == address(this) || _to == address(messenger)) {
Copy link

Choose a reason for hiding this comment

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

Think this check can be removed: _to == address(this), except we decide to add a receive function.


/// @notice Address of the LiquidityController contract.
/// @custom:network-specific
ILiquidityController public liquidityController;
Copy link

Choose a reason for hiding this comment

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

This can be replaced to use Predeploys lib. e.g: Predeploys.LIQUIDITY_CONTROLLER. As done here.

/// @notice Tests for the `bridgeCGT` function of the `L1CGTBridge` contract.
contract L1CGTBridge_BridgeCGT_Test is L1CGTBridge_TestInit {
/// @notice Tests that bridgeCGT succeeds when called properly.
function test_bridgeCGT_withRecipient_succeeds(uint256 _amount, uint32 _minGasLimit) external {
Copy link

Choose a reason for hiding this comment

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

NITs:

  • shouldn't test name be testFuzz_...?
  • why using alice and bob fixed addresses? Couldn't we fuzz them?
  • Consider fuzzing the recipient address too.


// Approve the bridge to spend tokens
vm.prank(alice);
cgtToken.approve(address(l1CGTBridge), _amount);
Copy link

Choose a reason for hiding this comment

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

MEGA nit: allowance could be set manipulating the storage.
Leave it like this if you want.

function test_bridgeCGT_whenDepositsDisabled_reverts() external {
// Disable deposits
vm.prank(alice);
l1CGTBridge.setDepositsEnabledL1toL2(false);
Copy link

Choose a reason for hiding this comment

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

Could be set by manipulating the storage instead of a call.

Comment on lines +232 to +240
// First, simulate a deposit to set up the contract state
vm.prank(alice);
cgtToken.approve(address(l1CGTBridge), BRIDGE_AMOUNT);

vm.mockCall(address(messenger), abi.encodeWithSelector(ICrossDomainMessenger.sendMessage.selector), "");

vm.startPrank(alice, alice);
l1CGTBridge.bridgeCGT(alice, BRIDGE_AMOUNT, MIN_GAS_LIMIT);
vm.stopPrank();
Copy link

Choose a reason for hiding this comment

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

same as above, consider setting the storage manually instead of executing calls to isolate the function you're testing.


/// @notice Tests that setDepositsEnabledL1toL2 reverts when called by unauthorized account.
function test_setDepositsEnabledL1toL2_whenUnauthorized_reverts() external {
vm.expectRevert();
Copy link

Choose a reason for hiding this comment

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

Add custom error.


/// @notice Tests that setFinalizeEnabledL2toL1 reverts when called by unauthorized account.
function test_setFinalizeEnabledL2toL1_whenUnauthorized_reverts() external {
vm.expectRevert();
Copy link

Choose a reason for hiding this comment

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

Same as above, add custom error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants