Cronos EVM Contract Verification With Original Build Settings
Cronos EVM supports Solidity contract source verification, which connects published source files to an existing deployment through a reproducible bytecode comparison. Verification leaves the contract address and on-chain behavior unchanged. Its practical value depends on retaining the build that produced the deployment, including compiler settings, imported files, linked libraries, and constructor values. A matching contract name or compatible compiler range cannot establish the same result. Direct deployments, factory-created contracts, and proxies require different treatment when identifying the code under review. Those distinctions determine which files and deployment inputs belong together, and what a successful verification can establish about the contract.
Source files, bytecode, and the explorer
Source files describe the contract's logic, the compiler produces executable bytecode, and the explorer associates submitted code with a particular network and address. Source verification compares recompiled bytecode with the code at an existing contract address. The network remains part of that identity. A familiar address on another chain does not establish a match for the EVM deployment being examined.
The application binary interface, or ABI, describes callable functions and their argument types. It helps software encode interactions, but it cannot reproduce the implementation by itself. Source code supplies the function bodies, inherited behavior, and dependencies that the compiler needs. An ABI and a contract name therefore serve different purposes from a reproducible build.
Cronos Explorer supports verification using Solidity files or Standard JSON compiler input. Those submission modes can use reformatted contract data exported from Cronoscan. An existing verification record can supply build details without creating another contract.
Creation code and deployed runtime code
Creation bytecode and runtime bytecode belong to different stages of deployment, so their differences can explain a failed comparison without implying that the published source is unrelated.
Constructor execution
The creation code runs during deployment and includes the constructor's work. The constructor executes once, then the resulting runtime code becomes the deployed contract. That runtime excludes the constructor code. Constructor inputs can initialize storage or affect immutable values, making the original deployment context relevant even when later calls use only public functions.
Runtime and deployment artifacts
A Hardhat artifact distinguishes bytecode from deployedBytecode. These fields provide creation and runtime output, respectively. Comparing a deployment transaction's entire input against runtime output combines different objects. Linked library addresses and constructor-assigned immutable values also need their applicable treatment during matching. Retaining the original artifacts helps identify the intended comparison without changing the deployed code or rebuilding from a later source revision.
Can constructor arguments be recovered from a deployment transaction?
Constructor arguments can be recovered from a direct Solidity deployment when the creation bytecode boundary and constructor types are known. The transaction input alone does not identify every value's meaning.
Direct contract creation
A direct Solidity deployment appends ABI-encoded constructor arguments to the creation bytecode. Matching the original creation bytecode establishes where that encoded suffix begins. Decoding then requires the constructor's parameter types and their declared order. Using the runtime code's length to locate the suffix would identify the wrong boundary.
Dynamic values, including strings and dynamic arrays, contain offsets and length information. Their encoding cannot be interpreted reliably by dividing the suffix into guessed argument-sized pieces. The constructor ABI provides the structure needed to distinguish complete values from references to other parts of the encoding.
Factory-created contracts
A factory creates another contract internally. If the transaction calls an existing factory directly, its input describes the factory call. It may differ from the child contract's creation input because the factory can construct or transform that input. Recovering the child's arguments therefore requires its actual creation data or the corresponding deployment records. Availability through a particular explorer or tracing interface must be established separately.
Array and tuple constructor inputs
Array and tuple inputs must retain the constructor's declared types, nesting, and order. A serialized value that looks plausible can still encode a different structure from the deployed arguments.
Hardhat 3's verification task accepts complex arguments through a TypeScript or JavaScript file. The file must provide the constructor argument array as its default export, and --constructor-args-path identifies it. Each top-level entry corresponds to one constructor parameter. An array parameter remains a nested array within that argument list. A tuple requires the component structure expected by the ABI encoder; its field order comes from the constructor definition.
Manual verification forms may require ABI-encoded hexadecimal arguments instead of language-level values. Those are different representations of the same constructor inputs. Supplying a JavaScript array to a hexadecimal field does not meet that field's format. Conversely, passing an encoded suffix as an ordinary argument can change what a tooling encoder receives. Preserve the values first, then use the representation that the selected interface requires.
Compiler settings retained from deployment
Compiler settings belong to the deployed build, including options that affect code generation or metadata. Verification needs those recorded values, even when a newer tool offers different defaults.
| Build parameter | Matching value and required build record |
|---|---|
| Compiler release |
The deployed compiler's exact release; Hardhat build info records solcLongVersion.
|
settings.optimizer.enabled
|
The original true or false setting; retain any custom optimizer details too.
|
settings.optimizer.runs
|
The deployment build's execution-frequency parameter; read it from the saved compiler input. |
settings.evmVersion
|
The original target EVM version; an omitted value depends on that compiler release's default. |
settings.viaIR
|
The original pipeline choice, true or false; recover it from the deployment build.
|
settings.metadata.bytecodeHash
|
The selected hash mode: ipfs, bzzr1, or none; preserve the original metadata settings.
|
settings.libraries
|
The linked library addresses, where applicable; retain their source-file and library-name mapping. |
Hardhat 3 stores the compiler input in build-info files alongside version information. A build-info file wraps that input with other fields. For a form expecting Standard JSON, the relevant object is the saved input, rather than the entire wrapper. Keeping that record avoids reconstructing compilation choices from memory.
Which build profile does Hardhat 3 use for verification?
In Hardhat 3, the verify task uses the production build profile by default.
Verification must still use the compiler configuration that actually produced the deployed contract.
Most other tasks use default when no profile is specified. Hardhat Ignition deployments use production by default, while profiles can carry different compiler configurations. A successful development build therefore does not establish that verification will reproduce the deployment's output.
The --build-profile option selects another profile when the deployment used it. Selecting that profile preserves the intended compiler configuration; changing settings solely to satisfy a default creates a different build. These are Hardhat 3 conventions. Older project recipes need their own version context, and the chosen verification service must support the configured network independently of the build-profile choice.
Optimizer runs and execution assumptions
The optimizer's runs setting estimates how often deployed instructions will execute over the contract's lifetime. It guides the tradeoff between deployment size and later execution cost. It does not count optimizer passes or report observed transactions. Larger values favor execution efficiency more heavily, while smaller values favor compact code. For verification, the relevant number is the one used during deployment, with the same optimizer configuration. A different estimate can produce different bytecode. Changing the number in a verification submission cannot optimize a contract that already exists.
Flattened files and preserved project structure
Flattening combines source files into one file, changing the compilation input that originally described separate source units. Successful compilation of that combined file does not guarantee the same verification match.
Source paths, file contents, and compiler settings contribute to Solidity metadata. Where the build includes a metadata hash in bytecode, changes to those inputs can change the hash. A flattened representation can therefore preserve substantial executable behavior while losing an exact metadata match. The result depends on the verifier's matching rules and the original build's metadata configuration.
Standard JSON input preserves separate source units and their compilation settings. It also retains named dependencies without relying on a flattened substitute. Keep the deployed dependency versions and source-unit names: fetching today's library release can change the compilation even when the application file stays identical.
A single-file submission suits a contract originally compiled from that source structure. For a deployed multi-file project, the saved compiler input gives a more faithful starting point.
Solidity metadata and Standard JSON input
Solidity metadata and Standard JSON compiler input are different JSON formats, although both describe parts of a compilation. A verification interface needs the format that its selected mode accepts.
Metadata as compiler output
Solidity metadata records compiler information, source hashes, settings, and interface output. Source entries may identify retrievable content instead of containing every source file. Its settings also include a compilation target, and its library-address mapping differs from Standard JSON. A metadata file can support reconstruction, but renaming it does not turn it into valid compiler input.
Standard JSON as compiler input
Standard JSON provides the language, source units, and compilation settings in the compiler's input schema. Verification services can also offer a separate metadata-based mode that combines metadata with the necessary source files. Keep those submission modes distinct. For Cronos Explorer's Standard JSON option, use the compiler input structure and preserve its sources and deployment settings. The ABI output alone supplies neither a complete source project nor its compilation configuration.
Verification limits, proxies, and private variables
Source verification establishes a relationship between published code and a deployment. It does not assess whether the contract's logic is safe or whether its current permissions suit an intended interaction.
A proxy separates the address that users call from an implementation that supplies executable logic. Delegated execution uses the proxy's storage. Verifying the proxy's source leaves the implementation's source and current address as separate questions. An upgradeable proxy may point to a different implementation later, so an earlier verification cannot identify every future implementation.
Private Solidity state variables remain observable through blockchain data. The private keyword restricts access through Solidity's language rules; it does not encrypt stored values. Publishing verified source can make their layout easier to understand, but withholding source does not make the underlying storage secret.
Constructor values describe initialization, while mutable storage can change afterward. Current ownership and permissions therefore require their current state and applicable code. A source match gives the reader a concrete implementation to examine; it does not replace those checks before authorizing an interaction.
Cronos FAQ
Will source verification change an existing contract address?
Source verification does not change an existing contract's address or stored state. It publishes source information and checks its relationship to deployed code through an explorer service. Changing the Solidity files submitted for verification also cannot update that deployment's executable code.
How should array and tuple constructor arguments be supplied for verification?
Array and tuple arguments must retain their original structure, types, and order. When shell arguments are awkward, Hardhat 3's --constructor-args-path option accepts a file whose default export is the constructor argument array. An API that requests ABI-encoded constructor arguments instead requires the encoded values, rather than the file itself.
Which build profile does Hardhat 3 use for verification?
Hardhat 3's verify task uses the production build profile by default. A contract deployed with another profile can be verified using the matching profile, selected through --build-profile. The relevant requirement is the original compilation configuration, because choosing a different profile can produce different bytecode.
What does the Solidity optimizer runs setting mean?
The optimizer runs setting approximates how often each opcode will execute over the contract's lifetime. It influences the trade-off between code size and execution cost. It is not a count of optimizer iterations. For verification, preserve the deployment's setting instead of choosing a new value.
Are private Solidity variables hidden on Cronos EVM?
A private Solidity variable is not secret blockchain data. The visibility modifier restricts access within Solidity's contract interfaces and inheritance rules. Public observers can still inspect blockchain storage, so a contract must not rely on private visibility to conceal passwords, signing keys, or other confidential values.
Does flattening a Solidity project always preserve a verification match?
Flattening a Solidity project does not always preserve an exact verification match. Combining files changes the source-unit layout and can alter compiler metadata. Standard JSON input retains the original multi-file sources and settings. Preserve the original input when exact reproduction of the deployed build is needed.
Is Solidity metadata interchangeable with Standard JSON compiler input?
Solidity metadata and Standard JSON compiler input use different structures. Metadata records compilation details and generated interface information; compiler input supplies source units and settings for a build. Library mappings differ between the formats, and metadata includes fields absent from compiler input. Submitting one as the other can cause errors.