VoidChain Shanghai Setup
VoidChain contract development environment setup for EVM Shanghai.
Prerequisite: VoidChain mainnet has completed its Shanghai compatibility upgrade and supports PUSH0 (0x5f) on-chain.
Use compiler version 0.8.37 throughout and explicitly pin the EVM version to shanghai.
1. Version Matrix (Must Match)
| Component | Version / Value | Notes |
|---|---|---|
| Solidity compiler | 0.8.37+commit.f401782d | The file may be named solc-0.8.7.exe; use the --version output as the source of truth |
| pragma | pragma solidity 0.8.37; | Pin the exact version; do not use ^ |
| EVM version | shanghai | Must be explicitly specified; do not rely on defaults |
| Optimizer | enabled: true, runs: 200 | Adjust as needed |
| License | GPL-3.0 | Be aware of copyleft obligations; do not copy directly into closed-source components |
Why the EVM Version Must Be Explicitly Pinned
The default EVM version changes with the Solidity compiler version, and toolchains use different defaults:
| Compiler / Tool | Default EVM |
|---|---|
| solc 0.8.20 – 0.8.24 | shanghai |
| solc 0.8.25 – 0.8.29 | cancun |
| solc ≥ 0.8.30 | prague |
| solc 0.8.37 | osaka |
| Hardhat (for Solidity 0.8.20 onward) | paris (does not follow solc) |
| Foundry | Follows solc |
VoidChain targets Shanghai. Any drift in the default version can cause the following:
- A newer default (cancun/prague/osaka) → generates
MCOPY/TLOAD/TSTORE/BLOB*→ deployment fails withinvalid opcode. - An older default (paris/london) → does not generate
PUSH0, missing out on gas savings.
Conclusion: explicitly set evmVersion: "shanghai" in every toolchain.
2. Compiler Installation (Windows)
Option A: Official Binary (Recommended for Direct CLI Use)
- Open the Releases page.
- Find v0.8.37 → Assets → download
solc-windows.exe. - Move and rename it, for example to
C:\Chain00\sol\solc-837.exe.
mkdir C:\Chain00\sol
cd C:\Chain00\sol
Invoke-WebRequest -Uri "https://github.com/ethereum/solidity/releases/download/v0.8.37/solc-windows.exe" -OutFile "solc-837.exe"
.\solc-837.exe --versionExpected output:
solc, the solidity compiler commandline interface
Version: 0.8.37+commit.f401782dOptional: add the directory to PATH.
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Chain00\sol", "User")Option B: Static Binary Repository (Comprehensive Versions with SHA256)
Option C: npm (Quick Verification Only)
npm install -g solc # The command is solcjs, a JS implementation slower than the native binaryNot recommended as a production compiler.
Option D: Automatic Downloads with Hardhat / Foundry
The framework downloads the specified version into its cache. Simply specify the version in the configuration.
3. Source Code Guidelines
1. Use Consistent pragma Declarations
Update the header of every .sol file in the project to:
pragma solidity 0.8.37;⚠️ The original
pragma solidity >=0.7.0 <0.9.0;allows 0.7.x, which has no built-in overflow checks. Replace all occurrences. Updating only some files can cause compilation failures due to conflicting version constraints.
2. Do Not Introduce SafeMath
Solidity 0.8.x already provides built-in arithmetic overflow checks. Adding SafeMath is redundant and increases code size and gas usage.
3. Issues Requiring Manual Fixes After Upgrading
| Issue | Does upgrading to 0.8 resolve it? |
|---|---|
| Arithmetic overflow / underflow | ✅ Resolved automatically |
Tokens locked at the zero address via transfer(0x0) | ❌ Add require(_to != address(0)) |
| Missing function authorization / overwriting shared state pointers | ❌ Use view, local variables, and permission checks |
| Array deletion without an existence check | ❌ Add require checks |
| Records consumed more than once / insufficient txid entropy | ❌ Fix the application logic |
4. Compiler Configuration
Hardhat
// hardhat.config.js
module.exports = {
solidity: {
version: "0.8.37",
settings: {
evmVersion: "shanghai",
optimizer: { enabled: true, runs: 200 }
}
},
networks: {
voidchain: {
url: "https://<VoidChain RPC>", // TODO: enter the actual RPC URL
chainId: <chainId>, // TODO: enter the actual chainId
accounts: ["0x<private-key>"]
}
}
};npx hardhat compileFoundry
# foundry.toml
[profile.default]
solc_version = "0.8.37"
evm_version = "shanghai"
optimizer = true
optimizer_runs = 200forge buildsolc CLI (Windows PowerShell)
cd C:\Chain00\sol\dex
solc-837.exe --evm-version shanghai --optimize `
--asm --bin --abi `
-o C:\TChain00\sol\class `
fullchain.solParameters:
| Parameter | Purpose |
|---|---|
--evm-version shanghai | Required; pins the EVM target |
--asm | Generates assembly for opcode verification |
--bin / --abi | Generates bytecode and ABI |
-o <dir> | Writes output to a directory; stdout then contains only status messages |
5. Understanding Compiler Output Files
When writing output to a directory with -o, the file extensions are:
| Extension | Contents |
|---|---|
.bin | Deployment bytecode (hexadecimal) |
.bin-runtime | Runtime bytecode |
.abi | ABI JSON |
.evm | Assembly mnemonics (the output of --asm, not .asm) |
⚠️ Common misconception:
--asmgenerates.asmfiles. In fact, solc uses.evmwhen writing to a directory specified by-o.
6. Required Opcode Checks
1. Check for Prohibited Post-Shanghai Opcodes
Select-String -Path C:\TChain00\sol\class\*.evm `
-Pattern 'MCOPY|TLOAD|TSTORE|BLOBHASH|BLOBBASEFEE'Expected result: no output.
Do not search only for COPY: that would also match valid instructions such as CODECOPY, EXTCODECOPY, CALLDATACOPY, and RETURNDATACOPY. Search for the full name MCOPY.
2. Confirm Shanghai Is Active (PUSH0)
Select-String -Path C:\TChain00\sol\class\*.evm -Pattern 'PUSH0' |
Select-Object -First 3Expected result: output confirming compilation for shanghai rather than a downgrade to paris/london.
PUSH0 is generated only when the compiler needs to push the constant 0. If the contract has no relevant operations, such as comparisons with address(0), no output may be normal. Also check the evmVersion metadata field described below.
3. Definitive Confirmation: Metadata Fields
solc-837.exe --evm-version shanghai --metadata fullchain.sol > meta.txt
Select-String -Path meta.txt -Pattern '"evmVersion":"[a-z]+"' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object -UniqueExpected output: exactly one unique line.
"evmVersion":"shanghai"Also confirm the compiler version:
Select-String -Path meta.txt -Pattern '"version":"[0-9][^"]*"' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object -UniqueExpected: "version":"0.8.37+commit.f401782d"
7. Troubleshooting
1. findstr Finds Nothing, but the Editor Finds Matches
Cause: PowerShell's > redirection defaults to UTF-16LE (with \0 after each character), while findstr reads single bytes and fails to match.
Solution: use Select-String, which detects the encoding automatically; redirect through CMD (ANSI); or explicitly specify the encoding:
solc-837.exe --evm-version shanghai --metadata fullchain.sol |
Out-File -Encoding utf8 meta.txt2. asm.txt Contains Only Compiler run successful...
Cause: the command includes -o <dir>, so assembly is written to that directory and stdout contains only status messages.
Solution: to obtain a single file, remove -o and capture stdout with >:
solc-837.exe --evm-version shanghai --asm fullchain.sol > asm.txt3. No Assembly Files Are Generated
Cause: --asm is missing. The --bin --abi options generate only bytecode and ABI.
4. Deployment Reports invalid opcode: opcode 0x5f not defined
0x5f is PUSH0. This means the compiler generated Shanghai bytecode, but the chain had not yet completed its Shanghai upgrade.
- Before the VoidChain upgrade: downgrade to
--evm-version london(orparis). - After the VoidChain upgrade (current): keep
shanghai.
For other opcode errors, use the following downgrade table:
| Opcode in Error | Name | Introduced In | Downgrade To |
|---|---|---|---|
0x5f | PUSH0 | Shanghai | paris |
0x44 | PREVRANDAO | Paris | london |
0x48 | BASEFEE | London | berlin |
0x46/0x47 | CHAINID/SELFBALANCE | Istanbul | istanbul |
5. Error: unrecognised option '-Path'
Cause: the two commands in solc ... | Select-String -Path ... were pasted together and executed as one, causing solc to interpret -Path as its own argument.
Solution: run the two commands separately, pressing Enter after each; or use CMD's findstr.
6. Numbered Variants Appear, Such as BaseToken1.evm
This indicates conflicting contract names: multiple source files define contracts with the same name, or the same file is imported repeatedly through different paths.
Risk: ABI and bytecode ownership becomes ambiguous, and the wrong artifacts may be deployed. Remove duplicate imports.
7. Some .bin Files Are 0 KB
A 0 KB file indicates an abstract contract, an interface, or a pure library with no deployment bytecode.
If any of BaseToken, FullChain, Export, Import, MyChain, or MyToken is 0 KB, it has been declared abstract or has unimplemented functions. Resolve this before deployment.
Get-ChildItem C:\TChain00\sol\class\*.bin |
Where-Object { $_.Length -eq 0 } | Select-Object Name8. Pre-Deployment Checklist
- Every
.solfile starts withpragma solidity 0.8.37;. -
solc --versionoutputs0.8.37+commit.f401782d. - The
evmVersionmetadata value isshanghai, with no other values present. - No matches for
MCOPY|TLOAD|TSTORE|BLOB*appear in.evmfiles. - Every
.binfile intended for deployment is nonempty. - No duplicate contract variants with the same name exist.
- Perform a trial deployment on VoidChain mainnet (successful local compilation does not guarantee on-chain execution).
- Invariant tests:
Σ balances == _totalSupplyalways holds aftertransfer/MapAssets/Payouts/GasPay(in 0.8,-=reverts instead of silently wrapping around). - Resubmit contract verification to the block explorer (the bytecode has changed, invalidating the previous verification record).
Deployed contracts cannot be upgraded in place. Bytecode changes require redeployment and state migration.
9. Quick Self-Check Script (Ready to Copy)
cd C:\Chain00\sol\dex
# 1. Version
solc-837.exe --version
# 2. Compile
solc-837.exe --evm-version shanghai --optimize --asm --bin --abi `
-o C:\TChain00\sol\class fullchain.sol
# 3. Confirm metadata
solc-837.exe --evm-version shanghai --metadata fullchain.sol > meta.txt
Select-String -Path meta.txt -Pattern '"evmVersion":"[a-z]+"' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object -Unique
# 4. Prohibited opcodes (expect no output)
Select-String -Path C:\TChain00\sol\class\*.evm `
-Pattern 'MCOPY|TLOAD|TSTORE|BLOBHASH|BLOBBASEFEE'
# 5. PUSH0 (expect output)
Select-String -Path C:\TChain00\sol\class\*.evm -Pattern 'PUSH0' |
Select-Object -First 3
# 6. Check for empty bytecode
Get-ChildItem C:\TChain00\sol\class\*.bin |
Where-Object { $_.Length -eq 0 } | Select-Object Name