Deployment Guide
Pre-Deployment Checklist
- [ ] All tests passing (
forge test -vvv) - [ ] Coverage >95% (
forge coverage) - [ ] Fuzz tests passed (
FOUNDRY_FUZZ_RUNS=10000 forge test) - [ ] Invariant tests passed (
FOUNDRY_INVARIANT_RUNS=2000 forge test) - [ ] Security review completed
- [ ] Treasury address configured
- [ ] Parameters validated
Environment Variables
bash
# Required
export POIDH_TREASURY=0x... # Fee recipient address
export POIDH_START_CLAIM_INDEX=1 # Starting claim ID (must be >= 1)
# Optional (with defaults)
export POIDH_MIN_BOUNTY_AMOUNT=1000000000000000 # 0.001 ETH
export POIDH_MIN_CONTRIBUTION=10000000000000 # 0.00001 ETH
export POIDH_NFT_NAME="poidh claims v3"
export POIDH_NFT_SYMBOL="POIDH3"
# Deployment
export DEPLOYER_PK="0x..." # Deployer private key
export RPC_URL="https://..." # Chain RPC URLDeployment Scripts
Generic Deployment
bash
forge script script/Deploy.s.sol:Deploy \
--rpc-url $RPC_URL \
--private-key $DEPLOYER_PK \
--broadcast \
--verify \
-vvvBase
bash
forge script script/deploy/Base.s.sol:DeployBase \
--rpc-url https://mainnet.base.org \
--private-key $DEPLOYER_PK \
--broadcast \
--verify \
--etherscan-api-key $BASESCAN_API_KEYArbitrum
bash
forge script script/deploy/Arbitrum.s.sol:DeployArbitrum \
--rpc-url https://arb1.arbitrum.io/rpc \
--private-key $DEPLOYER_PK \
--broadcast \
--verifyBase Sepolia
bash
forge script script/deploy/BaseSepolia.s.sol:DeployBaseSepolia \
--rpc-url https://sepolia.base.org \
--private-key $DEPLOYER_PK \
--broadcast \
--verifyPost-Deployment Steps
1. Verify Contracts
bash
# Check verification status
cast code <CONTRACT_ADDRESS> --rpc-url $RPC_URL
# Verify on Etherscan/BaseScan
forge verify-contract <CONTRACT_ADDRESS> \
"PoidhV3" \
--constructor-args $(cast abi-encode "constructor(address,uint256,uint256)" "$TREASURY" "$MIN_BOUNTY" "$MIN_CONTRIB") \
--chain-id $CHAIN_ID2. Verify Parameters
bash
# Check treasury
cast call <CONTRACT_ADDRESS> "treasury()(address)" --rpc-url $RPC_URL
# Check MIN_BOUNTY_AMOUNT
cast call <CONTRACT_ADDRESS> "MIN_BOUNTY_AMOUNT()(uint256)" --rpc-url $RPC_URL
# Check MIN_CONTRIBUTION
cast call <CONTRACT_ADDRESS> "MIN_CONTRIBUTION()(uint256)" --rpc-url $RPC_URL
# Check voting period
cast call <CONTRACT_ADDRESS> "votingPeriod()(uint256)" --rpc-url $RPC_URL3. Test Transactions
bash
# Test solo bounty creation
cast send <CONTRACT_ADDRESS> \
"createSoloBounty(string,string)(uint256)" \
"Test Bounty" "Test Description" \
--value 0.1ether \
--private-key $TEST_KEY \
--rpc-url $RPC_URL
# Test withdrawal
cast send <CONTRACT_ADDRESS> \
"withdraw()" \
--private-key $TEST_KEY \
--rpc-url $RPC_URL4. Monitor Contract
bash
# Watch events
cast logs --from-block <DEPLOYMENT_BLOCK> \
--address <CONTRACT_ADDRESS> \
--rpc-url $RPC_URL
# Check contract balance
cast balance <CONTRACT_ADDRESS> --rpc-url $RPC_URLConfiguration
Minimum Amounts
Ethereum Mainnet
- Minimum bounty: 0.001 ETH
- Minimum contribution: 0.00001 ETH
Base
- Minimum bounty: 0.001 ETH
- Minimum contribution: 0.00001 ETH
Arbitrum
- Minimum bounty: 0.001 ETH
- Minimum contribution: 0.00001 ETH
Voting Period
- Default: 2 days
- Adjustable by calling
resetVotingPeriod() - Recommended: 1–7 days depending on the use case
Fee Structure
- Protocol fee: 2.5% (250 BPS)
- Sent to the treasury upon claim acceptance
- Deducted from the bounty amount before payout
Deployment Addresses
Ethereum Mainnet
- Contract:
0xE731dFadBFf20542E10D09D26Fc71445C70d4232 - Explorer: https://etherscan.io/address/0xE731dFadBFf20542E10D09D26Fc71445C70d4232
- Deployed: May 13, 2026
Base
- Contract:
0x5555Fa783936C260f77385b4E153B9725feF1719 - Explorer: https://basescan.org/address/0x5555fa783936c260f77385b4e153b9725fef1719
- Deployed: Jan 19, 2026
Arbitrum
- Contract:
0x5555Fa783936C260f77385b4E153B9725feF1719 - Explorer: https://arbiscan.io/address/0x5555fa783936c260f77385b4e153b9725fef1719
- Deployed: Jan 19, 2026
DEGEN Chain
- Contract:
0x18E5585ca7cE31b90Bc8BB7aAf84152857cE243f - Explorer: https://explorer.degen.tips/address/0x18e5585ca7ce31b90bc8bb7aaf84152857ce243f
- Deployed: Jan 19, 2026
- Retired: Aug 31, 2026
Security Considerations
Treasury Configuration
- Use a multisig wallet.
- Consider a timelock for future fee changes.
- Document your fee distribution strategy.
Deployer Key
- Use a hardware wallet or secure KMS.
- Destroy deployment keys after use whenever possible.
- Document key custody procedures.
Immutable Parameters
The following values cannot be changed after deployment:
- Treasury address
MIN_BOUNTY_AMOUNTMIN_CONTRIBUTIONPoidhClaimNFTcontract
Monitoring
Key Metrics
Monitor:
- Total bounties created
- Total claims submitted
- Claim acceptance rate
- Average bounty size
- Total protocol fees collected
- Gas usage trends
Recommended Alerts
Configure alerts for:
- Unusually large bounties
- High rejection rates
- Failed transactions
- Large withdrawals
- Unexpected contract balance changes
Upgrade Path
The current deployment is immutable.
Future considerations include:
- Proxy-based upgradeability
- Migration strategy for active bounties
- Governance mechanisms for parameter changes
- Community signaling before upgrades
Troubleshooting
Deployment fails with "insufficient funds"
bash
cast balance $DEPLOYER_ADDRESS --rpc-url $RPC_URL
forge script script/Deploy.s.sol:Deploy --rpc-url $RPC_URLVerification fails
bash
cast chain-id --rpc-url $RPC_URL
cast abi-encode \
"constructor(address,uint256,uint256)" \
"$TREASURY" "$MIN_BOUNTY" "$MIN_CONTRIB"Transaction reverts with "Not issuer"
bash
cast call <CONTRACT_ADDRESS> \
"getBounty(uint256)((uint256,address,string,string,uint256,address,uint256,uint256))" \
<BOUNTY_ID> \
--rpc-url $RPC_URLSupport
If you encounter deployment issues:
- Review
docs/README.md - Read
docs/POIDH_V3_SECURITY_REPORT.md - Test on a testnet before deploying to mainnet
- Consult the team before any production deployment