Complete markdown files cleanup and organization
- Organized 252 files across project - Root directory: 187 → 2 files (98.9% reduction) - Moved configuration guides to docs/04-configuration/ - Moved troubleshooting guides to docs/09-troubleshooting/ - Moved quick start guides to docs/01-getting-started/ - Moved reports to reports/ directory - Archived temporary files - Generated comprehensive reports and documentation - Created maintenance scripts and guides All files organized according to established standards.
This commit is contained in:
266
scripts/verify-weth-usdt-bridge.js
Executable file
266
scripts/verify-weth-usdt-bridge.js
Executable file
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* WETH → USDT Bridge Verification using thirdweb SDK
|
||||
* Verifies bytecode, ERC-20 compliance, and bridge route availability
|
||||
*/
|
||||
|
||||
const { ThirdwebSDK } = require("@thirdweb-dev/sdk");
|
||||
const { ethers } = require("ethers");
|
||||
|
||||
// Configuration
|
||||
const CHAIN138_RPC = process.env.RPC_URL_138 || "https://rpc-http-pub.d-bis.org";
|
||||
const CHAIN138_ID = 138;
|
||||
const ETHEREUM_MAINNET_ID = 1;
|
||||
|
||||
// Token addresses
|
||||
const WETH_CANONICAL = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
|
||||
const WETH_CHAIN138 = "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6"; // Actual deployed address
|
||||
const USDT_MAINNET = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
|
||||
|
||||
// ERC-20 ABI (minimal for verification)
|
||||
const ERC20_ABI = [
|
||||
"function symbol() view returns (string)",
|
||||
"function decimals() view returns (uint8)",
|
||||
"function totalSupply() view returns (uint256)"
|
||||
];
|
||||
|
||||
// Colors for console output
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
cyan: '\x1b[36m'
|
||||
};
|
||||
|
||||
function log(message, color = 'reset') {
|
||||
console.log(`${colors[color]}${message}${colors.reset}`);
|
||||
}
|
||||
|
||||
function logSection(title) {
|
||||
console.log(`\n${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}`);
|
||||
console.log(`${colors.cyan}${title}${colors.reset}`);
|
||||
console.log(`${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}\n`);
|
||||
}
|
||||
|
||||
async function checkBytecode(provider, address, label) {
|
||||
log(`Checking bytecode at ${label}: ${address}`, 'blue');
|
||||
try {
|
||||
const code = await provider.getCode(address);
|
||||
if (code === "0x" || code === "0x0") {
|
||||
log(` ❌ No bytecode found`, 'red');
|
||||
return false;
|
||||
} else {
|
||||
const codeLength = (code.length - 2) / 2; // Subtract "0x" and convert hex to bytes
|
||||
log(` ✅ Bytecode exists (${codeLength} bytes)`, 'green');
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
log(` ❌ Error checking bytecode: ${error.message}`, 'red');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyERC20(provider, address) {
|
||||
log(`Verifying ERC-20 compliance at: ${address}`, 'blue');
|
||||
const contract = new ethers.Contract(address, ERC20_ABI, provider);
|
||||
|
||||
const results = {
|
||||
symbol: null,
|
||||
decimals: null,
|
||||
totalSupply: null,
|
||||
valid: false
|
||||
};
|
||||
|
||||
try {
|
||||
// Check symbol()
|
||||
try {
|
||||
results.symbol = await contract.symbol();
|
||||
log(` ✅ symbol() = ${results.symbol}`, 'green');
|
||||
} catch (error) {
|
||||
log(` ❌ symbol() failed: ${error.message}`, 'red');
|
||||
}
|
||||
|
||||
// Check decimals()
|
||||
try {
|
||||
results.decimals = await contract.decimals();
|
||||
const expected = 18;
|
||||
if (results.decimals === expected) {
|
||||
log(` ✅ decimals() = ${results.decimals} (expected: ${expected})`, 'green');
|
||||
} else {
|
||||
log(` ⚠ decimals() = ${results.decimals} (expected: ${expected})`, 'yellow');
|
||||
}
|
||||
} catch (error) {
|
||||
log(` ❌ decimals() failed: ${error.message}`, 'red');
|
||||
}
|
||||
|
||||
// Check totalSupply()
|
||||
try {
|
||||
results.totalSupply = await contract.totalSupply();
|
||||
const formatted = ethers.formatEther(results.totalSupply);
|
||||
log(` ✅ totalSupply() = ${formatted} WETH`, 'green');
|
||||
} catch (error) {
|
||||
log(` ❌ totalSupply() failed: ${error.message}`, 'red');
|
||||
}
|
||||
|
||||
// Determine validity
|
||||
if (results.symbol && results.decimals !== null && results.totalSupply !== null) {
|
||||
results.valid = true;
|
||||
log(` ✅ Contract behaves as valid ERC-20`, 'green');
|
||||
} else {
|
||||
log(` ⚠ Some ERC-20 functions failed`, 'yellow');
|
||||
}
|
||||
} catch (error) {
|
||||
log(` ❌ ERC-20 verification error: ${error.message}`, 'red');
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
async function checkThirdwebBridgeRoute(fromChainId, toChainId, fromToken, toToken) {
|
||||
logSection("Step 3: Checking thirdweb Bridge Route");
|
||||
|
||||
log(`Checking route: ChainID ${fromChainId} (WETH) → ChainID ${toChainId} (USDT)`, 'blue');
|
||||
log(`WETH Address: ${fromToken}`, 'blue');
|
||||
log(`USDT Address: ${toToken}`, 'blue');
|
||||
log(``, 'blue');
|
||||
|
||||
try {
|
||||
// Initialize thirdweb SDK
|
||||
log(`Initializing thirdweb SDK...`, 'blue');
|
||||
const sdk = new ThirdwebSDK(new ethers.JsonRpcProvider(CHAIN138_RPC), {
|
||||
chainId: fromChainId
|
||||
});
|
||||
|
||||
// Try to get bridge quote
|
||||
// Note: thirdweb Bridge API may not be directly accessible via SDK
|
||||
// This is a placeholder - actual implementation may vary
|
||||
log(`Attempting to get bridge quote...`, 'blue');
|
||||
log(`⚠ Note: thirdweb Bridge may require specific setup or may not support ChainID 138`, 'yellow');
|
||||
|
||||
// For now, we'll indicate that manual verification is needed
|
||||
log(`⚠ Bridge route verification requires manual testing with thirdweb Bridge UI or API`, 'yellow');
|
||||
log(` Recommendation: Use thirdweb Bridge dashboard or contact thirdweb support`, 'blue');
|
||||
|
||||
return {
|
||||
available: false,
|
||||
reason: "Manual verification required - thirdweb Bridge API access needed"
|
||||
};
|
||||
} catch (error) {
|
||||
log(`❌ Error checking bridge route: ${error.message}`, 'red');
|
||||
return {
|
||||
available: false,
|
||||
reason: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
logSection("WETH → USDT Bridge Verification (ChainID 138 → Ethereum Mainnet)");
|
||||
|
||||
log(`IMPORTANT: WETH9 is NOT at canonical address on ChainID 138`, 'yellow');
|
||||
log(`Canonical address (mainnet): ${WETH_CANONICAL}`, 'blue');
|
||||
log(`Actual deployed address (ChainID 138): ${WETH_CHAIN138}`, 'blue');
|
||||
log(`Reason: Cannot recreate CREATE-deployed contracts with CREATE2`, 'blue');
|
||||
log(``, 'blue');
|
||||
|
||||
// Initialize provider
|
||||
const provider = new ethers.JsonRpcProvider(CHAIN138_RPC);
|
||||
|
||||
// Step 1: Check bytecode
|
||||
logSection("Step 1: Checking Bytecode");
|
||||
|
||||
const canonicalHasBytecode = await checkBytecode(provider, WETH_CANONICAL, "Canonical Address");
|
||||
log(``, 'blue');
|
||||
const actualHasBytecode = await checkBytecode(provider, WETH_CHAIN138, "Actual Deployed Address");
|
||||
|
||||
if (!canonicalHasBytecode) {
|
||||
log(`⚠ No bytecode at canonical address (expected - cannot recreate CREATE-deployed contracts)`, 'yellow');
|
||||
}
|
||||
|
||||
// Step 2: Verify ERC-20
|
||||
logSection("Step 2: Verifying ERC-20 Compliance");
|
||||
|
||||
let erc20Valid = false;
|
||||
if (actualHasBytecode) {
|
||||
const erc20Results = await verifyERC20(provider, WETH_CHAIN138);
|
||||
erc20Valid = erc20Results.valid;
|
||||
} else {
|
||||
log(`⚠ Skipping ERC-20 verification (no bytecode found)`, 'yellow');
|
||||
}
|
||||
|
||||
// Step 3: Check bridge route
|
||||
const bridgeRoute = await checkThirdwebBridgeRoute(
|
||||
CHAIN138_ID,
|
||||
ETHEREUM_MAINNET_ID,
|
||||
WETH_CHAIN138,
|
||||
USDT_MAINNET
|
||||
);
|
||||
|
||||
// Final verdict
|
||||
logSection("Final Verdict: GO / NO-GO");
|
||||
|
||||
log(`Verification Summary:`, 'blue');
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'blue');
|
||||
log(``, 'blue');
|
||||
|
||||
if (actualHasBytecode) {
|
||||
log(`✓ Bytecode exists at actual WETH address on ChainID 138`, 'green');
|
||||
log(` Address: ${WETH_CHAIN138}`, 'blue');
|
||||
} else {
|
||||
log(`✗ No bytecode at actual WETH address on ChainID 138`, 'red');
|
||||
}
|
||||
|
||||
if (erc20Valid) {
|
||||
log(`✓ Contract behaves as valid ERC-20`, 'green');
|
||||
} else {
|
||||
log(`⚠ ERC-20 verification incomplete or failed`, 'yellow');
|
||||
}
|
||||
|
||||
if (bridgeRoute.available) {
|
||||
log(`✓ Valid route available via thirdweb Bridge`, 'green');
|
||||
} else {
|
||||
log(`⚠ Route availability inconclusive: ${bridgeRoute.reason}`, 'yellow');
|
||||
}
|
||||
|
||||
log(``, 'blue');
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'blue');
|
||||
log(``, 'blue');
|
||||
|
||||
// Determine GO/NO-GO
|
||||
if (actualHasBytecode && erc20Valid && bridgeRoute.available) {
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'green');
|
||||
log(`✅ GO: Bridge route is viable`, 'green');
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'green');
|
||||
process.exit(0);
|
||||
} else if (actualHasBytecode && erc20Valid) {
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'yellow');
|
||||
log(`⚠ CONDITIONAL GO: Contract valid but route unverified`, 'yellow');
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'yellow');
|
||||
log(``, 'blue');
|
||||
log(`Contract verification passed, but bridge route needs manual verification.`, 'blue');
|
||||
log(`CRITICAL: WETH is NOT at canonical address on ChainID 138`, 'yellow');
|
||||
log(` • Canonical: ${WETH_CANONICAL} (no bytecode)`, 'blue');
|
||||
log(` • Actual: ${WETH_CHAIN138} (has bytecode)`, 'blue');
|
||||
log(``, 'blue');
|
||||
log(`Recommendation: Use CCIP Bridge instead (supports ChainID 138)`, 'blue');
|
||||
log(` CCIPWETH9Bridge: 0x89dd12025bfCD38A168455A44B400e913ED33BE2`, 'blue');
|
||||
process.exit(1);
|
||||
} else {
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'red');
|
||||
log(`❌ NO-GO: Bridge route is NOT viable`, 'red');
|
||||
log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, 'red');
|
||||
log(``, 'blue');
|
||||
log(`Recommendation: Use CCIP Bridge or fix contract deployment issues`, 'blue');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Run verification
|
||||
main().catch(error => {
|
||||
log(`Fatal error: ${error.message}`, 'red');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user