Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ broadcast
docs/
.env
node_modules/
lcov.info
lcov.info
package-lock.json
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@
"prettier-plugin-solidity": "^1.1.3",
"solhint": "^3.4.1"
},
"dependencies": {
"dotenv": "^17.2.1"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
108 changes: 103 additions & 5 deletions script/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,116 @@
# Simple Rebalance Script
# Scripts

This directory contains utility scripts for managing and monitoring the TLX leveraged token protocol.

## Scripts

### `pause-tokens.js`

A utility script to pause all active leveraged tokens in the protocol.

**Purpose:** Pauses all active leveraged tokens to prevent new deposits and withdrawals during maintenance or emergency situations.

**Features:**
- Connects to the TLX factory contract to get all token addresses
- Checks each token's current pause status and activity state
- Pauses only active, non-paused tokens
- Skips already paused or liquidated tokens
- Provides detailed logging and summary statistics

**Usage:**
```bash
# Set environment variables
export ALCHEMY_URL="your_alchemy_rpc_url"
export PRIVATE_KEY="your_private_key_here"

# Run the script
node script/pause-tokens.js
```

**Environment Variables:**
- `ALCHEMY_URL`: Alchemy RPC endpoint (required)
- `PRIVATE_KEY`: Private key for transaction signing (required)

**Output:**
- Lists each token with its asset, leverage, and direction
- Shows pause status for each token
- Provides summary statistics at the end

### `token-summary.js`

A comprehensive monitoring script that generates detailed reports about all leveraged tokens in the protocol.

**Purpose:** Provides real-time insights into protocol health, TVL, leverage ratios, and token performance.

**Features:**
- Fetches detailed data from the LeveragedTokenHelper contract
- Displays active tokens sorted by TVL
- Shows protocol totals (TVL, Open Interest, Average Leverage)
- Breaks down data by asset and leverage levels
- Lists liquidated tokens with their final states
- Filters out tokens with TVL < 1,000 sUSD for cleaner display

**Usage:**
```bash
# Set environment variables
export ALCHEMY_URL="your_alchemy_rpc_url"

# Run the script
node script/token-summary.js
```

**Environment Variables:**
- `ALCHEMY_URL`: Alchemy RPC endpoint (required)

**Output:**
- Active tokens table with TVL, leverage, and rebalance status
- Protocol totals and averages
- Asset and leverage breakdowns
- Liquidated tokens summary
- Network and timestamp information

### `rebalance-simple.js`

Rebalances all leverage tokens that need it.

## Usage
**Purpose:** Automatically rebalances leveraged tokens to maintain their target leverage ratios.

**Usage:**
```bash
export PRIVATE_KEY="your_private_key"
export RPC_URL="your_rpc_url"
node script/rebalance-simple.js
```

## Requirements

**Requirements:**
- Your address must be authorized as a rebalancer
- Node.js with ethers.js installed

That's it!
## Contract Addresses

Both scripts use the following contract addresses (Optimism mainnet):
- **Factory**: `0x5Dd85f51e9fD6aDE8ecc216C07919ecD443eB14d`
- **Helper**: `0xBdAF7A2C4ee313Be468B9250609ba8496131B1f0`

## Dependencies

Both scripts require:
- `ethers` (v6+)
- `dotenv` for environment variable management

Install dependencies:
```bash
npm install ethers dotenv
```

## Security Notes

- The `pause-tokens.js` script requires a private key and will execute transactions
- The `token-summary.js` script is read-only and does not require a private key
- Only run with appropriate permissions and on the correct network
- Always verify contract addresses before execution
- Consider using a dedicated wallet for administrative operations

## Network Support

These scripts are configured for Optimism mainnet but can be adapted for other networks by updating the RPC URL and contract addresses.
102 changes: 102 additions & 0 deletions script/pause-tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
require('dotenv').config();
const { ethers } = require("ethers");

// ABI for the functions we need
const FACTORY_ABI = [
"function allTokens() external view returns (address[] memory)",
];

const TOKEN_ABI = [
"function isPaused() external view returns (bool)",
"function isActive() external view returns (bool)",
"function setIsPaused(bool isPaused) external",
"function targetAsset() external view returns (string memory)",
"function targetLeverage() external view returns (uint256)",
"function isLong() external view returns (bool)",
];

async function pauseAllTokens() {
// Connect to the network (update RPC URL as needed)
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);

// Load private key from environment
const privateKey = process.env.PRIVATE_KEY;
if (!privateKey) {
throw new Error("PRIVATE_KEY environment variable required");
}
const wallet = new ethers.Wallet(privateKey, provider);

// Contract addresses from deployments.json
const FACTORY_ADDRESS = "0x5Dd85f51e9fD6aDE8ecc216C07919ecD443eB14d";

const factory = new ethers.Contract(FACTORY_ADDRESS, FACTORY_ABI, wallet);

console.log("Getting all leveraged tokens...");
const allTokens = await factory.allTokens();
console.log(`Found ${allTokens.length} leveraged tokens`);

let pausedCount = 0;
let alreadyPausedCount = 0;
let inactiveCount = 0;

for (let i = 0; i < allTokens.length; i++) {
const tokenAddress = allTokens[i];
const token = new ethers.Contract(tokenAddress, TOKEN_ABI, wallet);

try {
// Get token info
const [isPaused, isActive, targetAsset, targetLeverage, isLong] = await Promise.all([
token.isPaused(),
token.isActive(),
token.targetAsset(),
token.targetLeverage(),
token.isLong()
]);

const tokenInfo = `${targetAsset} ${ethers.formatEther(targetLeverage)}x ${isLong ? 'LONG' : 'SHORT'}`;

if (isPaused) {
console.log(`[${i + 1}/${allTokens.length}] ${tokenInfo} (${tokenAddress}) - Already paused`);
alreadyPausedCount++;
continue;
}

if (!isActive) {
console.log(`[${i + 1}/${allTokens.length}] ${tokenInfo} (${tokenAddress}) - Inactive (liquidated), skipping`);
inactiveCount++;
continue;
}

// Pause the token
console.log(`[${i + 1}/${allTokens.length}] ${tokenInfo} (${tokenAddress}) - Pausing...`);
const tx = await token.setIsPaused(true);
await tx.wait();
console.log(` ✅ Paused! Tx: ${tx.hash}`);
pausedCount++;

} catch (error) {
console.error(`Error processing token ${tokenAddress}:`, error.message);
}
}

console.log("\n=== Summary ===");
console.log(`Total tokens: ${allTokens.length}`);
console.log(`Already paused: ${alreadyPausedCount}`);
console.log(`Newly paused: ${pausedCount}`);
console.log(`Inactive tokens: ${inactiveCount}`);
}

// Run the script
if (require.main === module) {
pauseAllTokens()
.then(() => {
console.log("Script completed successfully");
process.exit(0);
})
.catch((error) => {
console.error("Script failed:", error);
process.exit(1);
});
}

module.exports = { pauseAllTokens };
Loading
Loading