Skip to main content
The Rescuable contract provides emergency functionality to recover ERC20 tokens that are accidentally sent to or locked in CCTP contracts. This is a safety mechanism to prevent permanent loss of funds. Contract: src/roles/Rescuable.sol

Key Concepts

  • Rescuer Role: Authorized address that can rescue locked ERC20 tokens
  • Emergency Recovery: Allows withdrawal of tokens that shouldn’t be in the contract
  • Owner Control: Only the owner can assign the rescuer role

State Variables

_rescuer

address private _rescuer
Private state variable storing the address of the current rescuer.

Functions

rescueERC20

function rescueERC20(
    IERC20 tokenContract,
    address to,
    uint256 amount
) external onlyRescuer
Rescues ERC20 tokens locked in the contract by transferring them to a specified address. Parameters:
  • tokenContract: Address of the ERC20 token contract to rescue
  • to: Recipient address to receive the rescued tokens
  • amount: Amount of tokens to rescue
Requirements:
  • Caller must be the rescuer
  • Contract must have sufficient token balance
  • Token transfer must succeed
Source: Rescuable.sol:58 Example:
// Rescue 1000 USDC tokens accidentally sent to the contract
rescuable.rescueERC20(
    IERC20(0xUSDC_ADDRESS),
    0xRECOVERY_ADDRESS,
    1000 * 10**6 // 1000 USDC (6 decimals)
);

updateRescuer

function updateRescuer(address newRescuer) external onlyOwner
Assigns the rescuer role to a new address. Parameters:
  • newRescuer: Address of the new rescuer
Requirements:
  • Caller must be the owner
  • New rescuer must be non-zero address
Emits: RescuerChanged(address indexed newRescuer) Source: Rescuable.sol:70

rescuer

function rescuer() external view returns (address)
Returns the address of the current rescuer. Returns: Address of the current rescuer Source: Rescuable.sol:40

Internal Functions

_updateRescuer

function _updateRescuer(address newRescuer) internal
Internal function to update the rescuer role. Parameters:
  • newRescuer: Address of the new rescuer
Requirements:
  • New rescuer must be non-zero address
Emits: RescuerChanged(address indexed newRescuer) Source: Rescuable.sol:78

Modifiers

onlyRescuer

modifier onlyRescuer()
Restricts function access to the rescuer only. Reverts: “Rescuable: caller is not the rescuer” if caller is not the rescuer Source: Rescuable.sol:47

Events

RescuerChanged

event RescuerChanged(address indexed newRescuer)
Emitted when the rescuer role is transferred to a new address. Parameters:
  • newRescuer: Address of the new rescuer

Usage Example

// Set initial rescuer (as owner)
rescuable.updateRescuer(0xRESCUER_ADDRESS);

// Check current rescuer
address currentRescuer = rescuable.rescuer();

// Rescue accidentally sent tokens (as rescuer)
rescuable.rescueERC20(
    IERC20(0xTOKEN_ADDRESS),
    0xRECOVERY_ADDRESS,
    amount
);

Use Cases

When to Use Rescue

  1. Accidental Transfers: Users accidentally send tokens directly to the contract address
  2. Unsupported Tokens: Tokens other than those officially supported by CCTP end up in the contract
  3. Operational Errors: Tokens become stuck due to failed operations
  4. Protocol Upgrades: Recovery needed during migration or upgrade scenarios

When NOT to Use Rescue

  • Do not rescue tokens that are part of normal protocol operations (e.g., tokens held for pending burns/mints)
  • Do not rescue tokens that belong to users as part of legitimate deposits
  • The rescue function should only be used for truly locked or mistakenly sent funds

Security Considerations

  • The rescuer role is separate from the owner role for operational flexibility
  • Only the owner can change the rescuer address
  • Uses OpenZeppelin’s SafeERC20 library to handle tokens safely
  • The rescuer should be a trusted address (e.g., multisig or DAO)
  • Rescuing tokens does not affect the contract’s paused state
  • Consider implementing governance or timelock mechanisms for rescue operations
  • Log all rescue operations for transparency and auditability

Implementation Details

SafeERC20 Usage

The contract uses OpenZeppelin’s SafeERC20 library, which:
  • Handles tokens that don’t return a boolean on transfer
  • Reverts on failed transfers instead of returning false
  • Provides protection against common ERC20 implementation issues
using SafeERC20 for IERC20;
Source: Rescuable.sol:30

Origin

Forked from Centre USDC Rescuable with modifications:
  • Updated Solidity version from 0.6.12 to 0.7.6
  • Added internal _updateRescuer function

Build docs developers (and LLMs) love