> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zkp2p/zkp2p-contracts/llms.txt
> Use this file to discover all available pages before exploring further.

# Contract Verification

> Verify zkp2p-contracts on Etherscan and Basescan for transparency and trust

Contract verification publishes your source code on block explorers, allowing anyone to verify that the deployed bytecode matches the source code.

## Why Verify Contracts?

### Transparency

* Users can read and audit the contract code
* Builds trust in the protocol
* Enables community security review

### Functionality

* Block explorers can decode function calls
* Events display with readable parameter names
* Users can interact with contracts directly via UI

### Compliance

* Required for many DEX listings
* Necessary for security audits
* Standard practice for DeFi protocols

## Automated Verification

The zkp2p-contracts repository includes automated verification scripts.

### Base Mainnet

```bash theme={null}
yarn etherscan:base
```

This command:

1. Reads all deployments from `deployments/base/`
2. Verifies each contract on Basescan
3. Uses a 600ms delay between verifications (rate limiting)
4. Skips already verified contracts
5. Reports verification status

### Base Sepolia Testnet

```bash theme={null}
yarn etherscan:base_sepolia
```

Uses a 5-second delay between verifications.

### Base Staging

```bash theme={null}
yarn etherscan:base_staging
```

Verifies staging deployments on Base mainnet Basescan.

## Manual Verification

### Using Hardhat Verify Plugin

#### Single Contract

```bash theme={null}
npx hardhat verify --network base \
  <CONTRACT_ADDRESS> \
  <CONSTRUCTOR_ARG_1> \
  <CONSTRUCTOR_ARG_2>
```

#### Example: Verify Escrow

```bash theme={null}
npx hardhat verify --network base \
  0x2f121CDDCA6d652f35e8B3E560f9760898888888 \
  "0x0bC26FF515411396DD588Abd6Ef6846E04470227" \
  8453 \
  "0xPaymentVerifierRegistryAddress" \
  "0x0bC26FF515411396DD588Abd6Ef6846E04470227" \
  100000 \
  200 \
  21600
```

#### Constructor Arguments from Deployment

Extract constructor args from deployment file:

```bash theme={null}
cat deployments/base/Escrow.json | jq '.args'
```

Output:

```json theme={null}
[
  "0x0bC26FF515411396DD588Abd6Ef6846E04470227",
  8453,
  "0xPaymentVerifierRegistryAddress",
  "0x0bC26FF515411396DD588Abd6Ef6846E04470227",
  100000,
  200,
  21600
]
```

### Using Basescan Web Interface

#### 1. Navigate to Contract

Go to your contract on Basescan:

```
https://basescan.org/address/<CONTRACT_ADDRESS>
```

#### 2. Click "Verify and Publish"

On the contract page, select the "Contract" tab, then "Verify and Publish".

#### 3. Fill Verification Form

**Compiler Type**: Solidity (Single file) or Solidity (Standard-JSON-Input)

**Compiler Version**: `v0.8.18+commit.87f61d96`

**Open Source License Type**: MIT

**Optimization**: Enabled

**Optimization Runs**: 200

**Via IR**: Yes

These values match `hardhat.config.ts`:

```typescript theme={null}
solidity: {
  compilers: [
    {
      version: "0.8.18",
      settings: {
        optimizer: {
          enabled: true,
          runs: 200,
        },
        viaIR: true
      },
    },
  ],
}
```

#### 4. Upload Contract Code

For Standard JSON Input:

```bash theme={null}
# Generate standard JSON input
npx hardhat verify --network base \
  <CONTRACT_ADDRESS> \
  --constructor-args arguments.js \
  --show-stack-traces
```

Or manually combine:

* Main contract source
* All imported dependencies
* OpenZeppelin contracts
* Interfaces

#### 5. Submit for Verification

Basescan will:

* Compile your source code
* Compare bytecode to deployed contract
* Display verification result

## Verification Script Details

The automated verification task is defined in `tasks/etherscanVerifyWithDelay.ts`:

```typescript theme={null}
task('etherscan-verify-with-delay', 
  'Verify contracts on Etherscan with delays to avoid rate limiting'
)
  .addOptionalParam('delay', 'Delay in milliseconds', '600')
  .setAction(async ({ delay }, hre) => {
    const delayMs = parseInt(delay);
    const deployments = await hre.deployments.all();
    
    for (const [contractName, deployment] of Object.entries(deployments)) {
      try {
        await hre.run('verify:verify', {
          address: deployment.address,
          constructorArguments: deployment.args || [],
        });
        
        console.log(`✅ ${contractName} verified`);
      } catch (error) {
        if (error.message.includes('already verified')) {
          console.log(`⏭️  ${contractName} already verified`);
        } else {
          console.error(`❌ ${contractName} failed: ${error.message}`);
        }
      }
      
      await sleep(delayMs);
    }
  });
```

### How It Works

1. **Load Deployments**: Reads all `.json` files from `deployments/<network>/`
2. **Iterate Contracts**: Processes each contract sequentially
3. **Verify**: Calls Hardhat verify plugin with saved constructor args
4. **Handle Errors**: Skips already-verified contracts, logs failures
5. **Rate Limiting**: Waits specified delay between requests
6. **Summary**: Reports verification statistics

## Configuration

### API Keys

Set your Basescan API key in `.env`:

```bash theme={null}
BASESCAN_API_KEY=your_basescan_api_key_here
ETHERSCAN_KEY=your_etherscan_api_key_here
```

Get API keys:

* **Basescan**: [basescan.org/apis](https://basescan.org/apis)
* **Etherscan**: [etherscan.io/apis](https://etherscan.io/apis)

### Hardhat Config

Configure verification in `hardhat.config.ts`:

```typescript theme={null}
import '@nomicfoundation/hardhat-verify';

const config: HardhatUserConfig = {
  etherscan: {
    apiKey: process.env.ETHERSCAN_KEY || "",
  },
  networks: {
    base_staging: {
      verify: {
        etherscan: {
          apiUrl: "https://api.basescan.org/",
          apiKey: process.env.BASESCAN_API_KEY
        }
      },
    },
  },
};
```

## Verification Status

Check if a contract is verified:

### Via Block Explorer

Visit the contract page. Verified contracts show:

* Green checkmark next to contract address
* "Contract Source Code Verified" badge
* Readable source code in "Contract" tab

### Via API

```bash theme={null}
curl "https://api.basescan.org/api
  ?module=contract
  &action=getsourcecode
  &address=<CONTRACT_ADDRESS>
  &apikey=<YOUR_API_KEY>"
```

Response includes:

```json theme={null}
{
  "status": "1",
  "message": "OK",
  "result": [{
    "SourceCode": "contract Escrow { ... }",
    "ContractName": "Escrow",
    "CompilerVersion": "v0.8.18+commit.87f61d96",
    "OptimizationUsed": "1",
    "Runs": "200"
  }]
}
```

## Troubleshooting

### "Already Verified" Error

**Cause**: Contract was previously verified

**Solution**: No action needed. Contract is verified.

**Verify**: Check block explorer for green checkmark

### "Invalid API Key" Error

**Cause**: Missing or incorrect Basescan API key

**Solution**:

1. Get API key from [basescan.org/apis](https://basescan.org/apis)
2. Add to `.env`: `BASESCAN_API_KEY=your_key_here`
3. Restart verification

### "Bytecode Does Not Match" Error

**Cause**: Deployed bytecode differs from compiled source

**Possible Reasons**:

* Wrong compiler version
* Different optimization settings
* Wrong via IR setting
* Modified source code after deployment
* Incorrect constructor arguments

**Solution**:

1. Check compiler settings match `hardhat.config.ts`
2. Verify constructor arguments from deployment JSON
3. Ensure source code matches deployed version
4. Try compiling locally and comparing bytecode:

```bash theme={null}
npx hardhat compile
npx hardhat verify --network base <ADDRESS> <ARGS>
```

### "Max Rate Limit Reached" Error

**Cause**: Too many verification requests in short time

**Solution**: Increase delay between verifications:

```bash theme={null}
yarn hardhat --network base \
  etherscan-verify-with-delay \
  --delay 1000  # 1 second delay
```

Or wait 5-10 minutes and retry.

### "Contract Size Exceeds Limit" Error

**Cause**: Contract bytecode larger than 24KB

**Solution**:

* Refactor contract into smaller modules
* Use libraries for common functionality
* Enable optimizer with higher runs
* Remove unnecessary code

### "Failed to Fetch Constructor Arguments" Error

**Cause**: Can't automatically detect constructor args from blockchain

**Solution**: Manually specify arguments:

```bash theme={null}
# Create arguments.js
module.exports = [
  "0x0bC26FF515411396DD588Abd6Ef6846E04470227",
  8453,
  // ... other args
];

# Verify with arguments file
npx hardhat verify --network base \
  <ADDRESS> \
  --constructor-args arguments.js
```

## Verification Checklist

After verification, confirm:

* [ ] Contract shows as verified on Basescan
* [ ] Source code is readable on "Contract" tab
* [ ] Constructor arguments are correct
* [ ] Read/Write functions work on block explorer UI
* [ ] Contract ABI matches deployment JSON
* [ ] All dependencies are verified (registries, etc.)
* [ ] Contract name matches source file

## Best Practices

### 1. Verify Immediately After Deployment

Run verification right after deployment:

```bash theme={null}
yarn deploy:base && yarn etherscan:base
```

### 2. Save Deployment Artifacts

Commit `deployments/` directory to version control:

```bash theme={null}
git add deployments/base/
git commit -m "Add Base mainnet deployment artifacts"
```

This preserves:

* Contract addresses
* Constructor arguments
* Deployment transaction hashes
* ABIs

### 3. Document Verification

Record verification details:

```markdown theme={null}
## Base Mainnet Deployment

Deployed: 2024-03-04 14:30:00 UTC
Deployer: 0x...
Escrow: https://basescan.org/address/0x2f121CDDCA6d652f35e8B3E560f9760898888888#code
Orchestrator: https://basescan.org/address/0x88888883Ed048FF0a415271B28b2F52d431810D0#code
Verified: ✅ All contracts
```

### 4. Test on Testnet First

Practice verification on Base Sepolia:

```bash theme={null}
yarn deploy:base_sepolia
yarn etherscan:base_sepolia
```

Confirm the process works before mainnet deployment.

### 5. Verify Dependencies

Ensure all registry contracts are verified:

* PaymentVerifierRegistry
* NullifierRegistry
* EscrowRegistry
* RelayerRegistry
* PostIntentHookRegistry

## Reading Verified Contracts

Once verified, anyone can:

### View Source Code

```
https://basescan.org/address/<CONTRACT_ADDRESS>#code
```

### Interact with Contract

```
https://basescan.org/address/<CONTRACT_ADDRESS>#writeContract
```

Connect wallet and call functions directly.

### Read Contract State

```
https://basescan.org/address/<CONTRACT_ADDRESS>#readContract
```

Query view functions without connecting wallet.

### View Events

```
https://basescan.org/address/<CONTRACT_ADDRESS>#events
```

See decoded event logs with parameter names.

## Next Steps

After verifying contracts:

1. [Configure payment methods](/contracts/payment-verifier-registry)
2. [Set up relayers](/contracts/relayer-registry)
3. [Test core functionality](/guides/testing)
4. [Monitor contract events](/guides/testing)

<Note>
  Verification is a one-time process per deployment. Once verified, the contract remains verified permanently on the block explorer.
</Note>

<Warning>
  Always verify the contract address matches your deployment before interacting. Scammers may deploy fake contracts with similar names.
</Warning>
