Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
669f178
feat: Add bridge pause/unpause operations and status monitoring scripts
gfournierPro Aug 12, 2025
21a7e60
feat: Include pauser.mk in Makefile for enhanced bridge operations
gfournierPro Aug 12, 2025
35ffff9
feat: Implement pause and unpause scripts for bridge operations with …
gfournierPro Aug 12, 2025
20e87e4
feat: Add bridge pause/unpause operations with enhanced options and C…
gfournierPro Aug 12, 2025
56f559b
feat: Reorder network options in bridge pause operations workflow
gfournierPro Aug 12, 2025
1983acc
fix: Ensure newline at end of file in bridge pause operations scripts
gfournierPro Aug 12, 2025
7ee2fb1
feat: Update bridge pause operations workflow to support network type…
gfournierPro Aug 12, 2025
940511d
refactor: Clean up whitespace in PauseBridge and PauseBridgeScriptTes…
gfournierPro Aug 12, 2025
dc73330
refactor: Remove redundant pause/unpause sequence tests and helper fu…
gfournierPro Aug 12, 2025
1ced7d4
Merge branch 'main' into feature/pause-scripts
gfournierPro Sep 11, 2025
81a146a
fix: treat copilot suggestions
gfournierPro Sep 11, 2025
1b3e378
Merge branch 'main' into feature/pause-scripts
gfournierPro Sep 11, 2025
c07f29e
fix: Remove unnecessary output conversion for matrix in workflows
gfournierPro Sep 11, 2025
d2d94aa
fix: Set concurrency cancel-in-progress to false for bridge pause ope…
gfournierPro Sep 11, 2025
7d237be
fix: Update bridge address assignment and remove unused helper functi…
gfournierPro Sep 11, 2025
d49f5e4
fix: Simplify pause operation handling by removing redundant operatio…
gfournierPro Sep 11, 2025
c546e1e
fix: Update pauseOutboundTransfers log message to clarify transfer be…
gfournierPro Sep 11, 2025
4b88cb1
fix: Remove bridge address validation from pause and unpause functions
gfournierPro Sep 11, 2025
bfb63f8
fix: Remove unused PauseBridgeValidation import from PauseBridgeScrip…
gfournierPro Sep 11, 2025
d3cecfc
fix: Remove redundant UnpauseOutboundTransfers import from PauseBridg…
gfournierPro Sep 11, 2025
04ad851
fix: Remove redundant pauser role tests from PauseBridgeScriptTest
gfournierPro Sep 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions .github/workflows/bridge-pause-operations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Bridge Pause Operations

on:
workflow_dispatch:
inputs:
operation:
description: 'Pause operation to perform'
required: true
type: choice
options:
- 'pause-bridge'
- 'unpause-bridge'
- 'pause-outbound'
- 'unpause-outbound'
network_type:
description: 'Network type to configure'
required: true
type: choice
options:
- testnets
- mainnets
default: 'testnets'
jobs:
setup-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Set matrix based on network type
id: set-matrix
run: |
if [ "${{ github.event.inputs.network_type }}" == "testnets" ]; then
MATRIX='[
{
"chain": "sepolia"
},
{
"chain": "arbitrum_sepolia"
}
]'
else
MATRIX='[
{
"chain": "ethereum"
},
{
"chain": "arbitrum"
}
]'
fi

# Convert to single line for GitHub Output
echo "matrix=$(echo "$MATRIX" | jq -c .)" >> $GITHUB_OUTPUT

bridge-pause-operation:
needs: setup-matrix
runs-on: ubuntu-latest
strategy:
matrix:
include: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
fail-fast: false
concurrency:
group: pause-bridge-${{ matrix.chain }}
cancel-in-progress: true
env:
CI: true
environment: ${{ matrix.chain }}

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: stable
cache: true

- name: Set operation details
id: operation-details
run: |
case "${{ github.event.inputs.operation }}" in
pause-bridge)
echo "make_target=pause-bridge-single-chain" >> $GITHUB_OUTPUT
;;
unpause-bridge)
echo "make_target=unpause-bridge-single-chain" >> $GITHUB_OUTPUT
;;
pause-outbound)
echo "make_target=pause-outbound-single-chain" >> $GITHUB_OUTPUT
;;
unpause-outbound)
echo "make_target=unpause-outbound-single-chain" >> $GITHUB_OUTPUT
;;
esac

- name: Run pause operation on bridge from ${{ matrix.chain }}
env:
CHAIN: ${{ matrix.chain }}
RPC_URL: ${{ secrets.RPC_URL }}
PAUSER_PRIVATE_KEY: ${{ secrets.PAUSER_PRIVATE_KEY }}
run: make ${{ steps.operation-details.outputs.make_target }}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MAKEFLAGS += --no-print-directory

include tools/report.mk tools/verification.mk
include tools/report.mk tools/verification.mk tools/pauser.mk
-include .env


Expand Down
167 changes: 167 additions & 0 deletions script/PauseBridge.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// SPDX-FileCopyrightText: 2025 IEXEC BLOCKCHAIN TECH <[email protected]>
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.22;

import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
import {ConfigLib} from "./lib/ConfigLib.sol";
import {IexecLayerZeroBridge} from "../src/bridges/layerZero/IexecLayerZeroBridge.sol";

/**
* Levels of pause:
* Level 1 (Complete Pause): Blocks ALL bridge operations (inbound and outbound)
* Level 2 (Outbound Only): Blocks only outbound transfers, allows users to receive/withdraw
*/

/**
* @title PauseBridge
* @dev Script to pause bridge operations on the current chain.
*/
contract PauseBridge is Script {
/**
* @notice Pauses all bridge operations (Level 1 - Complete Pause)
* @dev This function blocks both inbound and outbound transfers
* Use this for critical security incidents
*/
function run() external virtual {
string memory chain = vm.envString("CHAIN");
console.log("Pausing ALL bridge operations on chain:", chain);

ConfigLib.CommonConfigParams memory params = ConfigLib.readCommonConfig(chain);
vm.startBroadcast();
pauseBridge(params);
vm.stopBroadcast();
}

/**
* @notice Pauses the bridge operations
* @param params The configuration parameters for the current chain
*/
function pauseBridge(ConfigLib.CommonConfigParams memory params) public virtual {
PauseBridgeValidation.validateBridgeAddress(params.iexecLayerZeroBridgeAddress);
IexecLayerZeroBridge bridge = IexecLayerZeroBridge(params.iexecLayerZeroBridgeAddress);

console.log("Executing complete pause on bridge at:", params.iexecLayerZeroBridgeAddress);
bridge.pause();
console.log("Bridge completely paused");
console.log("Both inbound and outbound transfers are now blocked");
}
}

/**
* @title UnpauseBridge
* @dev Script to unpause bridge operations on the current chain.
* This restores all bridge functionality.
*/
contract UnpauseBridge is Script {
/**
* @notice Unpauses all bridge operations
* @dev This function restores both inbound and outbound transfers
*/
function run() external virtual {
string memory chain = vm.envString("CHAIN");
console.log("Unpausing ALL bridge operations on chain:", chain);

ConfigLib.CommonConfigParams memory params = ConfigLib.readCommonConfig(chain);
vm.startBroadcast();
unpauseBridge(params);
vm.stopBroadcast();
}

/**
* @notice Unpauses the bridge operations
* @param params The configuration parameters for the current chain
*/
function unpauseBridge(ConfigLib.CommonConfigParams memory params) public virtual {
PauseBridgeValidation.validateBridgeAddress(params.iexecLayerZeroBridgeAddress);
IexecLayerZeroBridge bridge = IexecLayerZeroBridge(params.iexecLayerZeroBridgeAddress);

console.log("Executing unpause on bridge at:", params.iexecLayerZeroBridgeAddress);
bridge.unpause();
console.log("Bridge unpaused");
console.log("Both inbound and outbound transfers are now enabled");
}
}

/**
* @title PauseOutboundTransfers
* @dev Script to pause only outbound transfers (Level 2 - Partial Pause)
* This allows users to still receive funds and "exit" their positions while blocking new outbound transfers.
*/
contract PauseOutboundTransfers is Script {
/**
* @notice Pauses only outbound transfers (Level 2 - Partial Pause)
* @dev This function blocks outbound transfers but allows inbound transfers
* Use this for less critical issues when you want to allow user withdrawals
*/
function run() external virtual {
string memory chain = vm.envString("CHAIN");
console.log("Pausing OUTBOUND transfers only on chain:", chain);

ConfigLib.CommonConfigParams memory params = ConfigLib.readCommonConfig(chain);
vm.startBroadcast();
pauseOutboundTransfers(params);
vm.stopBroadcast();
}

/**
* @notice Pauses outbound transfers on the bridge
* @param params The configuration parameters for the current chain
*/
function pauseOutboundTransfers(ConfigLib.CommonConfigParams memory params) public virtual {
PauseBridgeValidation.validateBridgeAddress(params.iexecLayerZeroBridgeAddress);
IexecLayerZeroBridge bridge = IexecLayerZeroBridge(params.iexecLayerZeroBridgeAddress);

console.log("Executing outbound transfer pause on bridge at:", params.iexecLayerZeroBridgeAddress);
bridge.pauseOutboundTransfers();
console.log("Outbound transfers paused");
console.log("Outbound transfers are blocked, inbound transfers still work");
console.log("Users can still receive funds and exit their positions");
}
}

/**
* @title UnpauseOutboundTransfers
* @dev Script to unpause outbound transfers (restores send functionality)
* This restores outbound transfer capability while maintaining inbound functionality.
*/
contract UnpauseOutboundTransfers is Script {
/**
* @notice Unpauses outbound transfers (restores send functionality)
* @dev This function restores outbound transfer capability
*/
function run() external virtual {
string memory chain = vm.envString("CHAIN");
console.log("Unpausing OUTBOUND transfers on chain:", chain);

ConfigLib.CommonConfigParams memory params = ConfigLib.readCommonConfig(chain);
vm.startBroadcast();
unpauseOutboundTransfers(params);
vm.stopBroadcast();
}

/**
* @notice Unpauses outbound transfers on the bridge
* @param params The configuration parameters for the current chain
*/
function unpauseOutboundTransfers(ConfigLib.CommonConfigParams memory params) public virtual {
PauseBridgeValidation.validateBridgeAddress(params.iexecLayerZeroBridgeAddress);
IexecLayerZeroBridge bridge = IexecLayerZeroBridge(params.iexecLayerZeroBridgeAddress);

console.log("Executing outbound transfer unpause on bridge at:", params.iexecLayerZeroBridgeAddress);
bridge.unpauseOutboundTransfers();
console.log("Outbound transfers unpaused");
console.log("Both inbound and outbound transfers are now enabled");
}
}

library PauseBridgeValidation {
/**
* @notice Validates that the bridge contract address is not zero
* @param bridgeAddress The bridge contract address
*/
function validateBridgeAddress(address bridgeAddress) internal pure {
require(bridgeAddress != address(0), "Bridge address cannot be zero");
}
}
Loading