Skip to content
Open
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
81 changes: 81 additions & 0 deletions docs/cookbook/smart-contracts/definitive-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
### Phase 1: The "Senior Engineer" Content

**The Problem: The "Black Box" Contract**
Deploying a contract is only half the job. An unverified contract on BaseScan displays as raw hexadecimal bytecode. This is a massive red flag for users and limits functionality (e.g., you cannot Read/Write from the explorer UI).

**The Science of Verification**
Verification is a matching game. BaseScan compiles your submitted source code and compares the resulting bytecode against what is currently on the blockchain.
**Crucial Concept:** The deployed bytecode is actually:
`Runtime Bytecode` + `Metadata Hash` + `ABI-Encoded Constructor Arguments`.

If *any* of the following differ, verification fails:

1. **Compiler Version:** `0.8.20` produces different opcodes than `0.8.19`.
2. **Optimization Settings:** 200 runs vs. 10,000 runs changes the bytecode structure significantly.
3. **Constructor Arguments:** These are immutable values set at deployment. If you tell BaseScan you deployed with value `A`, but you actually deployed with `B`, the trailing bytes won't match.

---

### Phase 2: The "Copy-Paste" Implementation

**1. The "Magic" ABI Encoding Command**
The most common failure reason is "Constructor Arguments Mismatch." Do not guess these. Use `cast` (from Foundry) to generate the exact hex string.

**Scenario:** Your constructor takes `(address owner, uint256 initialSupply, string memory name)`.

**Command:**

```bash
# Syntax: cast abi-encode "constructor(types)" values...
cast abi-encode "constructor(address,uint256,string)" 0x123... 1000000 "MyToken"

```

**Output:**
`0x000000000000000000000000123...000000000000000000000000000000000000000000000000000f4240...`

* **Usage:** Copy this output (minus the leading `0x`) and paste it into the "Constructor Arguments" box on BaseScan manually if needed, or use it in scripts.

**2. Verifying with Foundry (The Production Way)**
Don't use the web UI. It's prone to human error. Use `forge verify-contract`.

**Prerequisite:** Get a BaseScan API Key (not Etherscan) from [basescan.org/myapikey](https://www.google.com/search?q=https://basescan.org/myapikey).

**Command:**

```bash
# 1. Set your key
export BASESCAN_API_KEY="Your_Key_Here"

# 2. Run Verification
# Syntax: forge verify-contract <ADDRESS> <CONTRACT_PATH:CONTRACT_NAME> --chain-id 8453 --watch
forge verify-contract \
0xYourContractAddress \
src/MyToken.sol:MyToken \
--chain-id 8453 \
--etherscan-api-key $BASESCAN_API_KEY \
--verifier-url https://api.basescan.org/api \
--watch \
--constructor-args $(cast abi-encode "constructor(uint256)" 1000)

```

**3. Troubleshooting "Bytecode Mismatch"**
If the above fails with "Bytecode does not match," your local compilation settings likely differ from the deployment settings.

**The Fix (foundry.toml):**
Force a specific setup in your config to ensure reproducibility.

```toml
[profile.default]
solc_version = "0.8.23"
optimizer = true
optimizer_runs = 200
via_ir = false # Toggle this if verification fails!
bytecode_hash = "none" # Removes the metadata hash to reduce mismatch errors

```

**Senior Tip:** If you deployed using Hardhat but are trying to verify with Foundry (or vice versa), it will almost always fail because they handle metadata hashes differently. **Always verify using the same framework you deployed with.**

---