- Contract is intended for deployment on an EVM-compatible chain other than Ethereum mainnet (zkSync Era, Arbitrum, Optimism, Polygon, BNB Chain, etc.)
// PUSH0 opcode: Solidity >=0.8.20 emits PUSH0
// Not supported on all chains — contract fails to deploy
pragma solidity 0.8.20;
contract Token {
// Compiled bytecode contains PUSH0 — reverts on chains without support
}
// .transfer() on zkSync Era — 2300 gas stipend insufficient
function withdraw() external {
// transfer() forwards only 2300 gas
// On zkSync Era, basic operations cost more — this always reverts
// Gemholic lost 921 ETH to this exact issue
payable(msg.sender).transfer(amount);
}
// Dynamic create on zkSync Era
function deploy(bytes memory bytecode) external {
assembly {
// zkSync requires bytecode known at compile time
// Runtime create from arbitrary bytecode fails
let addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
}
.transfer() and .send() — these use a 2300 gas stipend that may be insufficient on chains with different gas cost structures (especially zkSync Era)create / create2 with runtime-supplied bytecode — this fails on zkSync Eraselfdestruct — deprecated and non-functional on some chains post-Dencun.call{value: amount}("") is used instead of .transfer() (forwards all available gas).call{value: amount}("") instead of .transfer() or .send() for ETH transfers--evm-version paris to avoid PUSH0// Safe ETH transfer for all EVM chains
function withdraw(uint256 amount) external {
(bool success,) = msg.sender.call{value: amount}("");
require(success, "transfer failed");
}
// Avoid PUSH0: compile with Paris EVM target
// solc --evm-version paris