Skip to content

Latest commit

 

History

History
192 lines (142 loc) · 5.92 KB

File metadata and controls

192 lines (142 loc) · 5.92 KB

HLYX Hyperlane Bridge Security Audit

📅 Audit Date: January 9, 2025

🚨 Critical Security Finding

This repository contains a security audit of the HLYX Hyperlane Bridge contracts deployed on Ethereum mainnet.

CRITICAL: As of January 9, 2025, the bridge was controlled by EOAs (Externally Owned Accounts) instead of multisigs, creating severe centralization risks.

⚠️ IMPORTANT: The ownership and control structure may have changed since this audit. Always verify current state on-chain before making decisions.

📁 Repository Contents

📋 Main Documentation

  • AUDIT_REPORT.md - Complete security audit report by M8B.dev
  • CRITICAL_FINDING_PROOF.md - Detailed proof of the critical EOA control issue
  • HOW_TO_VERIFY_PROXY.md - Instructions for verifying proxy configuration

📄 Source Code

  • contracts/HypERC20Pausable.sol - Main pausable token contract
  • contracts/PausableController.sol - Abstract pause controller

🔧 Configuration

  • .solhint.json - Solidity linting configuration
  • hardhat.config.ts - Hardhat configuration
  • package.json - Dependencies and scripts
  • remappings.txt - Solidity import mappings

🔍 Verification Scripts

  • verify_critical_finding.js - Script to verify EOA control on mainnet
  • verify_pause_controller.js - Script to check pause controller status
  • scripts/run-security-audit.sh - Complete security audit runner
  • scripts/run-mythril-proper.sh - Mythril analysis script
  • scripts/mythril-with-deps.sh - Dependency-aware Mythril runner

📊 Audit Results

  • audit-results/ - All tool outputs and findings
    • mythril-success.txt/json - Mythril analysis results
    • slither-pausable.txt - Slither analysis results
    • solhint-complete.txt - Solhint linting results

🔴 Key Findings

Critical Operational Issues

  1. Single EOA Controls Everything: 0x8ea82F2DC6dAc2078eF0da432a66Ee43BB7193F9

    • Controls ProxyAdmin (can upgrade to steal funds)
    • Controls Token ownership (can change pause controller)
    • No multisig, no timelock
  2. Pause Controller is also EOA: 0xaa997F2B5C6cf291dc14ab1723f041f4FFC235A3

    • Not a multisig
    • Single key controls emergency pause

Automated Tool Results

  • Mythril: No vulnerabilities (contract code secure)
  • Solhint: 0 errors, good code quality
  • ⚠️ Slither: Found 1 structural issue (events outside contract scope)

🚀 Quick Start

  1. Clone the repository:
git clone <repo-url>
cd hlyx
  1. Install dependencies:
npm install
  1. Set up environment variables:
cp .env.example .env
# Edit .env and add your Infura/Alchemy key
  1. Run verification scripts:
# Replace YOUR_INFURA_KEY in the scripts first
node verify_critical_finding.js
node verify_pause_controller.js

🔍 How to Verify Findings Yourself

📅 Note: These instructions show how to verify the current on-chain state. The findings below were accurate as of January 9, 2025, but may have changed.

Method 1: Using Etherscan (No coding required)

  1. Verify ProxyAdmin Owner:

  2. Verify Token Owner:

  3. Check if addresses are EOAs or Contracts:

    • Search each address on Etherscan
    • If "Contract" tab is missing = EOA
    • If "Contract" tab exists = Smart Contract

Method 2: Using the Verification Scripts

  1. Setup:
# Clone this repo
git clone <repo-url>
cd hlyx
npm install
  1. Configure Infura Key:
# Edit the scripts and replace YOUR_INFURA_KEY with an actual key
# You can get a free key at: https://infura.io/
nano verify_critical_finding.js
# Replace: YOUR_INFURA_KEY with your actual key
  1. Run Verification:
node verify_critical_finding.js

Expected output will show:

  • ProxyAdmin Owner is EOA ❌
  • Token Owner is same EOA ❌
  • Pause Controller is EOA ❌

Method 3: Using Cast (Foundry)

# Install Foundry first: https://getfoundry.sh/

# Check ProxyAdmin owner
cast call 0x32fDda6b6Cfe7571c25e3eADeFC9F4faD60C912B "owner()" --rpc-url https://eth.llamarpc.com

# Check Token owner
cast call 0xC210B2cB65ed3484892167F5e05F7ab496Ab0598 "owner()" --rpc-url https://eth.llamarpc.com

# Check pausableController
cast call 0xC210B2cB65ed3484892167F5e05F7ab496Ab0598 "pausableController()" --rpc-url https://eth.llamarpc.com

# Check if address is EOA (returns 0x if EOA)
cast code 0x8ea82F2DC6dAc2078eF0da432a66Ee43BB7193F9 --rpc-url https://eth.llamarpc.com

Method 4: Using Web3.js in Browser Console

Open browser console and run:

// Using public RPC
const web3 = new Web3('https://eth.llamarpc.com');

// Check if address is EOA
const code = await web3.eth.getCode('0x8ea82F2DC6dAc2078eF0da432a66Ee43BB7193F9');
console.log(code === '0x' ? 'EOA' : 'Contract'); // Will print: EOA

📊 Contract Addresses

  • Proxy (Token): 0xC210B2cB65ed3484892167F5e05F7ab496Ab0598
  • ProxyAdmin: 0x32fDda6b6Cfe7571c25e3eADeFC9F4faD60C912B
  • Implementation: 0x28A32d8Ae251578421eD370cDC34faf01414ab22

⚠️ Recommendations

IMMEDIATE ACTION REQUIRED:

  1. Deploy a multisig (minimum 3/5 signers)
  2. Transfer ProxyAdmin ownership to multisig
  3. Transfer Token ownership to multisig
  4. Set pausableController to multisig
  5. Implement timelock for upgrades

📝 License

MIT

👥 Auditor

M8B.dev Security Team


⚠️ DISCLAIMER: This audit identified critical security issues that require immediate attention. The bridge should be considered HIGH RISK until these issues are resolved.