Documentation Index
Fetch the complete documentation index at: https://core.anylayer.org/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide provides comprehensive instructions for deploying the ZKScore Identity SBT contract to various networks. It covers deployment preparation, configuration, execution, and verification.
Always test your deployment on testnet before deploying to mainnet. Use the testnet deployment addresses provided in the Contract Overview section.
Prerequisites
- Node.js: Version 16 or higher
- npm/yarn: Package manager
- Hardhat/Foundry: Development framework
- MetaMask: Wallet for deployment
- Etherscan API Key: For contract verification
Environment Setup
# Install dependencies
npm install @openzeppelin/contracts
npm install @nomiclabs/hardhat-ethers
npm install @nomiclabs/hardhat-etherscan
npm install hardhat
# Initialize project
npx hardhat init
Deployment Configuration
Network Configuration
// hardhat.config.js
require("@nomiclabs/hardhat-ethers");
require("@nomiclabs/hardhat-etherscan");
module.exports = {
solidity: {
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
mainnet: {
url: "https://mainnet.infura.io/v3/YOUR_INFURA_KEY",
accounts: [process.env.PRIVATE_KEY],
gasPrice: 20000000000, // 20 gwei
gas: 8000000
},
goerli: {
url: "https://goerli.infura.io/v3/YOUR_INFURA_KEY",
accounts: [process.env.PRIVATE_KEY],
gasPrice: 20000000000, // 20 gwei
gas: 8000000
},
polygon: {
url: "https://polygon-mainnet.infura.io/v3/YOUR_INFURA_KEY",
accounts: [process.env.PRIVATE_KEY],
gasPrice: 30000000000, // 30 gwei
gas: 8000000
},
mumbai: {
url: "https://polygon-mumbai.infura.io/v3/YOUR_INFURA_KEY",
accounts: [process.env.PRIVATE_KEY],
gasPrice: 30000000000, // 30 gwei
gas: 8000000
}
},
etherscan: {
apiKey: {
mainnet: process.env.ETHERSCAN_API_KEY,
goerli: process.env.ETHERSCAN_API_KEY,
polygon: process.env.POLYGONSCAN_API_KEY,
polygonMumbai: process.env.POLYGONSCAN_API_KEY
}
}
};
Environment Variables
# .env file
PRIVATE_KEY=your_private_key_here
ETHERSCAN_API_KEY=your_etherscan_api_key
POLYGONSCAN_API_KEY=your_polygonscan_api_key
INFURA_KEY=your_infura_key
Contract Deployment
Deployment Script
// scripts/deploy.js
const { ethers } = require("hardhat");
async function main() {
console.log("Starting Identity SBT deployment...");
// Get the contract factory
const IdentitySBT = await ethers.getContractFactory("IdentitySBT");
// Deploy the contract
console.log("Deploying Identity SBT...");
const identitySBT = await IdentitySBT.deploy(
"ZKScore Identity", // name
"ZKSID", // symbol
"https://api.onzks.com/metadata/", // baseURI
"https://api.onzks.com/contract-metadata" // contractURI
);
await identitySBT.deployed();
console.log("Identity SBT deployed to:", identitySBT.address);
// Grant initial roles
const [deployer] = await ethers.getSigners();
console.log("Deployer address:", deployer.address);
// Grant minter role to deployer
const MINTER_ROLE = await identitySBT.MINTER_ROLE();
await identitySBT.grantRole(MINTER_ROLE, deployer.address);
console.log("Minter role granted to deployer");
// Grant admin role to deployer
const ADMIN_ROLE = await identitySBT.ADMIN_ROLE();
await identitySBT.grantRole(ADMIN_ROLE, deployer.address);
console.log("Admin role granted to deployer");
// Grant metadata role to deployer
const METADATA_ROLE = await identitySBT.METADATA_ROLE();
await identitySBT.grantRole(METADATA_ROLE, deployer.address);
console.log("Metadata role granted to deployer");
// Verify deployment
console.log("Verifying deployment...");
const name = await identitySBT.name();
const symbol = await identitySBT.symbol();
const baseURI = await identitySBT.baseURI();
console.log("Contract name:", name);
console.log("Contract symbol:", symbol);
console.log("Base URI:", baseURI);
console.log("Deployment completed successfully!");
return {
address: identitySBT.address,
name,
symbol,
baseURI
};
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Deployment Commands
# Deploy to testnet
npx hardhat run scripts/deploy.js --network goerli
# Deploy to mainnet
npx hardhat run scripts/deploy.js --network mainnet
# Deploy to Polygon
npx hardhat run scripts/deploy.js --network polygon
# Deploy to Mumbai
npx hardhat run scripts/deploy.js --network mumbai
Contract Verification
Automatic Verification
// scripts/verify.js
const { run } = require("hardhat");
async function main() {
const contractAddress = "0x1234567890123456789012345678901234567890";
console.log("Verifying contract on Etherscan...");
try {
await run("verify:verify", {
address: contractAddress,
constructorArguments: [
"ZKScore Identity",
"ZKSID",
"https://api.onzks.com/metadata/",
"https://api.onzks.com/contract-metadata"
]
});
console.log("Contract verified successfully!");
} catch (error) {
if (error.message.includes("Already Verified")) {
console.log("Contract already verified");
} else {
console.error("Verification failed:", error.message);
}
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Manual Verification
# Verify on Etherscan
npx hardhat verify --network mainnet 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
# Verify on PolygonScan
npx hardhat verify --network polygon 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
Deployment Verification
Contract Verification Script
// scripts/verify-deployment.js
const { ethers } = require("hardhat");
async function main() {
const contractAddress = "0x1234567890123456789012345678901234567890";
console.log("Verifying deployment...");
// Get contract instance
const IdentitySBT = await ethers.getContractFactory("IdentitySBT");
const identitySBT = IdentitySBT.attach(contractAddress);
// Verify basic properties
const name = await identitySBT.name();
const symbol = await identitySBT.symbol();
const baseURI = await identitySBT.baseURI();
console.log("Contract name:", name);
console.log("Contract symbol:", symbol);
console.log("Base URI:", baseURI);
// Verify roles
const [deployer] = await ethers.getSigners();
const MINTER_ROLE = await identitySBT.MINTER_ROLE();
const ADMIN_ROLE = await identitySBT.ADMIN_ROLE();
const METADATA_ROLE = await identitySBT.METADATA_ROLE();
const hasMinterRole = await identitySBT.hasRole(MINTER_ROLE, deployer.address);
const hasAdminRole = await identitySBT.hasRole(ADMIN_ROLE, deployer.address);
const hasMetadataRole = await identitySBT.hasRole(METADATA_ROLE, deployer.address);
console.log("Deployer has minter role:", hasMinterRole);
console.log("Deployer has admin role:", hasAdminRole);
console.log("Deployer has metadata role:", hasMetadataRole);
// Test minting
console.log("Testing minting...");
try {
const tx = await identitySBT.mint(
deployer.address,
"test.zks",
"https://api.onzks.com/metadata/test.zks"
);
const receipt = await tx.wait();
const event = receipt.events.find(e => e.event === 'IdentityMinted');
const tokenId = event.args.tokenId;
console.log("Test mint successful, token ID:", tokenId.toString());
// Test activation
console.log("Testing activation...");
const activateTx = await identitySBT.activate(tokenId);
await activateTx.wait();
console.log("Test activation successful");
// Verify activation
const isActivated = await identitySBT.isActivated(tokenId);
console.log("Token is activated:", isActivated);
} catch (error) {
console.error("Test failed:", error.message);
}
console.log("Deployment verification completed!");
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Network-Specific Deployment
Ethereum Mainnet
# Deploy to Ethereum mainnet
npx hardhat run scripts/deploy.js --network mainnet
# Verify on Etherscan
npx hardhat verify --network mainnet 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
Polygon
# Deploy to Polygon
npx hardhat run scripts/deploy.js --network polygon
# Verify on PolygonScan
npx hardhat verify --network polygon 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
Arbitrum
# Deploy to Arbitrum
npx hardhat run scripts/deploy.js --network arbitrum
# Verify on Arbitrum Explorer
npx hardhat verify --network arbitrum 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
Deployment Checklist
Pre-Deployment
During Deployment
Post-Deployment
Troubleshooting
Common Issues
Gas Limit Exceeded
# Increase gas limit
npx hardhat run scripts/deploy.js --network mainnet --gas-limit 10000000
Verification Failed
# Try manual verification
npx hardhat verify --network mainnet 0x1234567890123456789012345678901234567890 "ZKScore Identity" "ZKSID" "https://api.onzks.com/metadata/" "https://api.onzks.com/contract-metadata"
Network Connection Issues
# Check network status
npx hardhat run scripts/deploy.js --network mainnet --verbose
Error Handling
// Enhanced deployment script with error handling
async function main() {
try {
console.log("Starting deployment...");
const IdentitySBT = await ethers.getContractFactory("IdentitySBT");
// Estimate gas
const gasEstimate = await IdentitySBT.getDeployTransaction(
"ZKScore Identity",
"ZKSID",
"https://api.onzks.com/metadata/",
"https://api.onzks.com/contract-metadata"
).gasLimit;
console.log("Estimated gas:", gasEstimate.toString());
// Deploy with gas limit
const identitySBT = await IdentitySBT.deploy(
"ZKScore Identity",
"ZKSID",
"https://api.onzks.com/metadata/",
"https://api.onzks.com/contract-metadata",
{
gasLimit: gasEstimate.mul(120).div(100) // 20% buffer
}
);
await identitySBT.deployed();
console.log("Deployment successful:", identitySBT.address);
} catch (error) {
console.error("Deployment failed:", error.message);
if (error.message.includes("gas limit exceeded")) {
console.error("Try increasing gas limit");
} else if (error.message.includes("insufficient funds")) {
console.error("Insufficient funds for deployment");
} else if (error.message.includes("network")) {
console.error("Network connection issue");
}
process.exit(1);
}
}
Best Practices
Security
- Use Hardware Wallets: Use hardware wallets for deployment
- Secure Private Keys: Store private keys securely
- Test on Testnet: Always test on testnet first
- Verify Contracts: Verify contracts on explorers
- Monitor Deployments: Monitor deployment transactions
- Optimize Gas: Use gas optimization techniques
- Batch Operations: Batch multiple operations
- Monitor Gas Prices: Deploy during low gas periods
- Use Efficient Networks: Choose appropriate networks
- Monitor Performance: Monitor contract performance
Maintenance
- Regular Updates: Keep dependencies updated
- Monitor Events: Monitor contract events
- Backup Data: Backup important data
- Document Changes: Document all changes
- Version Control: Use version control for deployments