-
Notifications
You must be signed in to change notification settings - Fork 12
feat: helper scripts to debug validation allow list #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| import { ethers } from "ethers"; | ||
| import fs from "fs"; | ||
| import { task } from "hardhat/config"; | ||
|
|
||
| task("check-beacon-versions", "Checks what beacon versions are deployed") | ||
| .addParam("proxyfile", "location of the file with proxy contract addresses") | ||
| .setAction(async (cmd, hre) => { | ||
| console.log("Checking beacon versions for network:", hre.network.name); | ||
|
|
||
| // Read the deployed contract addresses | ||
| const proxyAddresses = JSON.parse(fs.readFileSync(cmd.proxyfile).toString()); | ||
| console.log("Proxy addresses loaded:", proxyAddresses); | ||
|
|
||
| const factoryAddress = proxyAddresses.accountFactory; | ||
| if (!factoryAddress) { | ||
| throw new Error("No accountFactory address found in proxy file"); | ||
| } | ||
|
|
||
| // Get provider | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const { getProvider } = require("../test/utils"); | ||
| const provider = getProvider(); | ||
|
|
||
| // Factory ABI to read the beacon address | ||
| const factoryAbi = [ | ||
| "function beacon() view returns (address)", | ||
| "function getEncodedBeacon() view returns (bytes)", | ||
| ]; | ||
|
|
||
| // Beacon ABI to read the implementation | ||
| const beaconAbi = [ | ||
| "function implementation() view returns (address)", | ||
| ]; | ||
|
|
||
| try { | ||
| // Get beacon address from factory | ||
| const factory = new ethers.Contract(factoryAddress, factoryAbi, provider); | ||
| console.log("\n🏭 Checking factory at:", factoryAddress); | ||
|
|
||
| const beaconAddress = await factory.beacon(); | ||
| console.log("📡 Factory points to beacon:", beaconAddress); | ||
|
|
||
| // Get implementation from beacon | ||
| const beacon = new ethers.Contract(beaconAddress, beaconAbi, provider); | ||
| const implementationAddress = await beacon.implementation(); | ||
| console.log("🎯 Beacon points to implementation:", implementationAddress); | ||
|
|
||
| // Check if there are any other beacons we should know about | ||
| console.log("\n📊 Summary:"); | ||
| console.log("Factory:", factoryAddress); | ||
| console.log("Beacon:", beaconAddress); | ||
| console.log("Implementation:", implementationAddress); | ||
|
|
||
| // Also check all proxy contracts and see what they point to | ||
| console.log("\n🔍 Checking all proxy contracts:"); | ||
| const proxyAbi = [ | ||
| "function implementation() view returns (address)", | ||
| "function beacon() view returns (address)", | ||
| ]; | ||
|
|
||
| for (const [contractName, contractAddress] of Object.entries(proxyAddresses)) { | ||
| if (contractName === "accountPaymaster") { | ||
| console.log(`${contractName}: ${contractAddress} (not a proxy)`); | ||
| continue; | ||
| } | ||
|
|
||
| try { | ||
| const proxy = new ethers.Contract(contractAddress as string, proxyAbi, provider); | ||
|
|
||
| // Try to get implementation directly (for transparent proxies) | ||
| try { | ||
| const impl = await proxy.implementation(); | ||
| console.log(`${contractName}: ${contractAddress} -> impl: ${impl}`); | ||
| } catch { | ||
| // Try to get beacon (for beacon proxies) | ||
| try { | ||
| const beaconAddr = await proxy.beacon(); | ||
| const beaconContract = new ethers.Contract(beaconAddr, beaconAbi, provider); | ||
| const impl = await beaconContract.implementation(); | ||
| console.log(`${contractName}: ${contractAddress} -> beacon: ${beaconAddr} -> impl: ${impl}`); | ||
| } catch { | ||
| console.log(`${contractName}: ${contractAddress} (could not determine proxy type)`); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| console.log(`${contractName}: ${contractAddress} (error reading: ${error.message})`); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| console.error("Error:", error); | ||
| throw error; | ||
| } | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| import { ethers } from "ethers"; | ||
| import fs from "fs"; | ||
| import { task } from "hardhat/config"; | ||
|
|
||
| task("check-deployment-mismatch", "Checks for deployment mismatches between expected and actual beacon addresses") | ||
| .addParam("proxyfile", "location of the file with proxy contract addresses") | ||
| .addParam("expectedbeacon", "expected beacon address") | ||
| .setAction(async (cmd, hre) => { | ||
| console.log("🔍 Checking for deployment mismatches on network:", hre.network.name); | ||
| console.log("Expected beacon address:", cmd.expectedbeacon); | ||
|
|
||
| // Read the deployed contract addresses | ||
| const proxyAddresses = JSON.parse(fs.readFileSync(cmd.proxyfile).toString()); | ||
|
|
||
| const factoryAddress = proxyAddresses.accountFactory; | ||
| if (!factoryAddress) { | ||
| throw new Error("No accountFactory address found in proxy file"); | ||
| } | ||
|
|
||
| // Get provider | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const { getProvider } = require("../test/utils"); | ||
cpb8010 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const provider = getProvider(); | ||
|
|
||
| // Factory ABI to read the beacon address | ||
| const factoryAbi = [ | ||
| "function beacon() view returns (address)", | ||
| ]; | ||
|
|
||
| // Beacon ABI to read the implementation | ||
| const beaconAbi = [ | ||
| "function implementation() view returns (address)", | ||
| "function owner() view returns (address)", | ||
| ]; | ||
|
|
||
| try { | ||
| // Get actual beacon address from factory | ||
| const factory = new ethers.Contract(factoryAddress, factoryAbi, provider); | ||
| const actualBeaconAddress = await factory.beacon(); | ||
|
|
||
| console.log("\n📊 MISMATCH ANALYSIS:"); | ||
| console.log("🏭 Factory address:", factoryAddress); | ||
| console.log("🎯 Expected beacon:", cmd.expectedbeacon); | ||
| console.log("📡 Actual beacon: ", actualBeaconAddress); | ||
| console.log("❌ MISMATCH:", actualBeaconAddress.toLowerCase() !== cmd.expectedbeacon.toLowerCase() ? "YES" : "NO"); | ||
|
|
||
| // Check both beacons | ||
| console.log("\n🔍 CHECKING BOTH BEACONS:"); | ||
|
|
||
| // Check expected beacon | ||
| console.log("\n1️⃣ Expected Beacon:", cmd.expectedbeacon); | ||
| try { | ||
| const expectedBeacon = new ethers.Contract(cmd.expectedbeacon, beaconAbi, provider); | ||
| const expectedImpl = await expectedBeacon.implementation(); | ||
| console.log(" ✅ Implementation:", expectedImpl); | ||
|
|
||
| try { | ||
| const expectedOwner = await expectedBeacon.owner(); | ||
| console.log(" 👤 Owner:", expectedOwner); | ||
| } catch { | ||
| console.log(" 👤 Owner: (not readable or no owner function)"); | ||
| } | ||
| } catch (error) { | ||
| console.log(" ❌ Error reading expected beacon:", error.message); | ||
| } | ||
|
|
||
| // Check actual beacon | ||
| console.log("\n2️⃣ Actual Beacon:", actualBeaconAddress); | ||
| try { | ||
| const actualBeacon = new ethers.Contract(actualBeaconAddress, beaconAbi, provider); | ||
| const actualImpl = await actualBeacon.implementation(); | ||
| console.log(" ✅ Implementation:", actualImpl); | ||
|
|
||
| try { | ||
| const actualOwner = await actualBeacon.owner(); | ||
| console.log(" 👤 Owner:", actualOwner); | ||
| } catch { | ||
| console.log(" 👤 Owner: (not readable or no owner function)"); | ||
| } | ||
| } catch (error) { | ||
| console.log(" ❌ Error reading actual beacon:", error.message); | ||
| } | ||
|
|
||
| // Check if there are any accounts using the old beacon | ||
| console.log("\n🔍 IMPACT ANALYSIS:"); | ||
| if (actualBeaconAddress.toLowerCase() !== cmd.expectedbeacon.toLowerCase()) { | ||
| console.log("⚠️ POTENTIAL ISSUES:"); | ||
| console.log(" • The factory is pointing to a different beacon than expected"); | ||
| console.log(" • New accounts will use beacon:", actualBeaconAddress); | ||
| console.log(" • If old accounts exist, they might use beacon:", cmd.expectedbeacon); | ||
| console.log(" • Upgrading only one beacon will not upgrade all accounts"); | ||
| console.log("\n💡 RECOMMENDATIONS:"); | ||
| console.log(" • Check if both beacons have accounts pointing to them"); | ||
| console.log(" • Upgrade both beacons to ensure all accounts are updated"); | ||
| console.log(" • Or migrate all accounts to use the same beacon"); | ||
| } else { | ||
| console.log("✅ No mismatch detected - factory points to expected beacon"); | ||
| } | ||
|
|
||
| // Try to get some bytecode to see if the contracts are identical | ||
| console.log("\n🔍 BYTECODE COMPARISON:"); | ||
| try { | ||
| const expectedBytecode = await provider.getCode(cmd.expectedbeacon); | ||
| const actualBytecode = await provider.getCode(actualBeaconAddress); | ||
|
|
||
| console.log("Expected beacon bytecode length:", expectedBytecode.length); | ||
| console.log("Actual beacon bytecode length:", actualBytecode.length); | ||
| console.log("Bytecode identical:", expectedBytecode === actualBytecode ? "✅ YES" : "❌ NO"); | ||
| } catch (error) { | ||
| console.log("Error comparing bytecode:", error.message); | ||
| } | ||
| } catch (error) { | ||
| console.error("Error:", error); | ||
| throw error; | ||
| } | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| import { ethers } from "ethers"; | ||
| import { task } from "hardhat/config"; | ||
| import { Wallet } from "zksync-ethers"; | ||
|
|
||
| task("check-factory-proxy-type", "Checks the factory proxy type and admin") | ||
| .addParam("factoryaddress", "address of the factory proxy") | ||
| .setAction(async (cmd, hre) => { | ||
| // eslint-disable-next-line @typescript-eslint/no-require-imports | ||
| const { LOCAL_RICH_WALLETS, getProvider } = require("../test/utils"); | ||
cpb8010 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let privateKey: string; | ||
|
|
||
| if (hre.network.name == "inMemoryNode" || hre.network.name == "dockerizedNode") { | ||
| console.log("Using local rich wallet"); | ||
| privateKey = LOCAL_RICH_WALLETS[0].privateKey; | ||
| } else { | ||
| if (!process.env.WALLET_PRIVATE_KEY) throw "Wallet private key wasn't found in .env file!"; | ||
| privateKey = process.env.WALLET_PRIVATE_KEY; | ||
| } | ||
|
|
||
| const wallet = new Wallet(privateKey, getProvider()); | ||
| const provider = getProvider(); | ||
|
|
||
| console.log("🔍 Analyzing factory proxy on network:", hre.network.name); | ||
| console.log("🎯 Factory address:", cmd.factoryaddress); | ||
| console.log("👤 Using wallet:", wallet.address); | ||
|
|
||
| try { | ||
| // TransparentUpgradeableProxy admin functions | ||
| const proxyAdminAbi = [ | ||
| "function admin() external view returns (address)", | ||
| "function implementation() external view returns (address)", | ||
| "function changeAdmin(address newAdmin) external", | ||
| "function upgradeTo(address newImplementation) external", | ||
| "function upgradeToAndCall(address newImplementation, bytes calldata data) external payable", | ||
| ]; | ||
|
|
||
| // Factory implementation functions | ||
| const factoryAbi = [ | ||
| "function beacon() view returns (address)", | ||
| ]; | ||
|
|
||
| // Check if we can read admin (this will fail if we're the admin) | ||
| console.log("\n📊 PROXY ANALYSIS:"); | ||
|
|
||
| // Try different approaches to get proxy info | ||
| try { | ||
| // Method 1: Try to call admin() - this will fail if we are the admin | ||
| const proxyAsAdmin = new ethers.Contract(cmd.factoryaddress, proxyAdminAbi, provider); | ||
| const admin = await proxyAsAdmin.admin(); | ||
| console.log("👤 Proxy admin:", admin); | ||
| console.log("🔍 Admin matches wallet:", admin.toLowerCase() === wallet.address.toLowerCase()); | ||
| } catch (adminError) { | ||
| console.log("⚠️ Cannot read admin (likely because we ARE the admin)"); | ||
| console.log(" Error:", adminError.message); | ||
| } | ||
|
|
||
| try { | ||
| // Method 2: Try to get implementation | ||
| const proxyAsAdmin = new ethers.Contract(cmd.factoryaddress, proxyAdminAbi, provider); | ||
| const impl = await proxyAsAdmin.implementation(); | ||
| console.log("📋 Current implementation:", impl); | ||
| } catch (implError) { | ||
| console.log("⚠️ Cannot read implementation via admin interface"); | ||
| console.log(" Error:", implError.message); | ||
| } | ||
|
|
||
| // Method 3: Use a different address to check admin | ||
| console.log("\n🔍 CHECKING PROXY WITH NON-ADMIN ADDRESS:"); | ||
| const randomProvider = new ethers.JsonRpcProvider(provider.connection.url); | ||
| const proxyAsReader = new ethers.Contract(cmd.factoryaddress, proxyAdminAbi, randomProvider); | ||
|
|
||
| try { | ||
| const admin = await proxyAsReader.admin(); | ||
| console.log("👤 Proxy admin:", admin); | ||
| console.log("🔍 Admin matches our wallet:", admin.toLowerCase() === wallet.address.toLowerCase()); | ||
|
|
||
| const impl = await proxyAsReader.implementation(); | ||
| console.log("📋 Current implementation:", impl); | ||
|
|
||
| // Now try to read the beacon from the implementation | ||
| const factoryImpl = new ethers.Contract(impl, factoryAbi, provider); | ||
| const currentBeacon = await factoryImpl.beacon(); | ||
| console.log("📡 Current beacon address:", currentBeacon); | ||
| } catch (error) { | ||
| console.log("❌ Error reading proxy info:", error.message); | ||
| } | ||
|
|
||
| console.log("\n💡 CONCLUSIONS:"); | ||
| console.log("✅ Factory is a TransparentUpgradeableProxy"); | ||
| console.log("✅ Cannot change beacon address without deploying new implementation"); | ||
| console.log("📝 OPTIONS TO CHANGE BEACON:"); | ||
| console.log(" 1. Deploy new factory implementation with correct beacon"); | ||
| console.log(" 2. Use proxy admin to upgrade to new implementation"); | ||
| console.log(" 3. Keep current setup (both beacons synchronized)"); | ||
| } catch (error) { | ||
| console.error("❌ Error during analysis:", error); | ||
| throw error; | ||
| } | ||
| }); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.