Skip to content
Merged
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
50 changes: 36 additions & 14 deletions packages/contracts-bedrock/scripts/deploy/VerifyOPCM.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -472,20 +472,8 @@ contract VerifyOPCM is Script {

// If requested and this is not a blueprint, we also need to check the creation code.
if (!_target.blueprint && !_skipConstructorVerification) {
// Use the Etherscan API to get the creation code.
bytes memory actualCreationCode = bytes(
Process.bash(
string.concat(
"curl -s 'https://api.etherscan.io/v2/api?chainid=",
vm.toString(block.chainid),
"&module=contract&action=getcontractcreation&contractaddresses=",
vm.toString(_target.addr),
"&apikey=",
Config.etherscanApiKey(),
"' | jq -r '.result[0].creationBytecode'"
)
)
);
// Get the creation code from the selected block explorer.
bytes memory actualCreationCode = _getCreationCode(_target.addr);

// Verify that the artifact bytecode is a prefix of the actual creation code and
// extract any remaining bytes so we can verify the constructor arguments.
Expand Down Expand Up @@ -523,6 +511,40 @@ contract VerifyOPCM is Script {
return success;
}

/// @notice Gets the creation code for a given contract address from the configured block explorer.
/// @param _addr The address of the contract to get the creation code for.
/// @return The creation code of the contract.
function _getCreationCode(address _addr) internal returns (bytes memory) {
// Prepare the command to execute.
string memory cmd;

// Check which block explorer to use.
if (LibString.eq(Config.blockExplorer(), "blockscout")) {
console.log(" Fetching creation code from Blockscout...");
cmd = string.concat(
"curl -s '",
Config.blockscoutApiUrl(),
"/api?module=contract&action=getcontractcreation&contractaddresses=",
vm.toString(_addr),
"' | jq -r '.result[0].creationBytecode'"
);
Comment on lines +524 to +530
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Malformed curl command when blockscoutApiUrl() returns empty string for unsupported chains. If the chain ID is not in the hardcoded list in Config.blockscoutApiUrl() and BLOCKSCOUT_API_URL environment variable is not set, the function returns an empty string. This results in an invalid curl URL like curl -s '/api?module=... which will fail.

// Add validation before using the URL:
string memory apiUrl = Config.blockscoutApiUrl();
require(bytes(apiUrl).length > 0, "Blockscout API URL not configured for this chain");
cmd = string.concat(
    "curl -s '",
    apiUrl,
    "/api?module=contract&action=getcontractcreation&contractaddresses=",
    vm.toString(_addr),
    "' | jq -r '.result[0].creationBytecode'"
);
Suggested change
cmd = string.concat(
"curl -s '",
Config.blockscoutApiUrl(),
"/api?module=contract&action=getcontractcreation&contractaddresses=",
vm.toString(_addr),
"' | jq -r '.result[0].creationBytecode'"
);
string memory apiUrl = Config.blockscoutApiUrl();
require(bytes(apiUrl).length > 0, "Blockscout API URL not configured for this chain");
cmd = string.concat(
"curl -s '",
apiUrl,
"/api?module=contract&action=getcontractcreation&contractaddresses=",
vm.toString(_addr),
"' | jq -r '.result[0].creationBytecode'"
);

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

} else {
console.log(" Fetching creation code from Etherscan...");
cmd = string.concat(
"curl -s 'https://api.etherscan.io/v2/api?chainid=",
vm.toString(block.chainid),
"&module=contract&action=getcontractcreation&contractaddresses=",
vm.toString(_addr),
"&apikey=",
Config.etherscanApiKey(),
"' | jq -r '.result[0].creationBytecode'"
);
}

// Execute the command.
return bytes(Process.bash(cmd));
}

/// @notice Checks if V2 dispute games feature is enabled in the dev feature bitmap.
/// @param _opcm The OPContractsManager to check.
/// @return True if V2 dispute games are enabled.
Expand Down
35 changes: 35 additions & 0 deletions packages/contracts-bedrock/scripts/libraries/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,41 @@ library Config {
env_ = vm.envString("ETHERSCAN_API_KEY");
}

/// @notice Returns the block explorer to use for fetching creation code.
function blockExplorer() internal view returns (string memory env_) {
env_ = vm.envOr("BLOCK_EXPLORER", string("blockscout"));
}

/// @notice Returns the base URL for the Blockscout API.
function blockscoutApiUrl() internal view returns (string memory) {
string memory envUrl = vm.envOr("BLOCKSCOUT_API_URL", string(""));
if (bytes(envUrl).length > 0) {
return envUrl;
}

if (block.chainid == 1) {
// Ethereum
return "https://eth.blockscout.com";
} else if (block.chainid == 10) {
// OP Mainnet
return "https://explorer.optimism.io";
} else if (block.chainid == 11155111) {
// Sepolia
return "https://eth-sepolia.blockscout.com";
} else if (block.chainid == 8453) {
// Base
return "https://base.blockscout.com";
} else if (block.chainid == 84532) {
// Base Sepolia
return "https://base-sepolia.blockscout.com";
} else if (block.chainid == 11155420) {
// OP Sepolia
return "https://optimism-sepolia.blockscout.com";
} else {
return "";
}
}

/// @notice Returns the OutputMode for genesis allocs generation.
/// It reads the mode from the environment variable OUTPUT_MODE.
/// If it is unset, OutputMode.ALL is returned.
Expand Down