This guide covers how to deploy and configure the Swarm Storage Incentive contracts on various networks.
- Hardhat development environment
- Node.js and yarn/npm
- Access to network (mainnet requires real ETH)
The contracts must be deployed in this specific order due to dependencies:
1. Token (external or TestToken for testnets)
2. PostageStamp (depends on Token)
3. PriceOracle (depends on PostageStamp)
4. StakeRegistry (depends on Token and PriceOracle)
5. Redistribution (depends on StakeRegistry, PostageStamp, PriceOracle)
6. Role Setup (connects contracts together)
- Chain ID: 1
- Swarm Network ID: 1
- Block Confirmations: 6
- Token: Must use deployed BZZ token
- Multisig:
0xD5C070FEb5EA883063c183eDFF10BA6836cf9816
- Chain ID: 11155111
- Swarm Network ID: 10
- Block Confirmations: 6
- Token: Uses TestToken with minting
- Multisig:
0xb1C7F17Ed88189Abf269Bf68A3B2Ed83C5276aAe
- Chain ID: TBD
- Swarm Network ID: 5
- Block Confirmations: 6
- Token: Uses TestToken
- Multisig:
0xb1C7F17Ed88189Abf269Bf68A3B2Ed83C5276aAe
- Swarm Network ID: 1
- Block Confirmations: 1
- Used for: Testing deployments
File: deploy/main/000_deploy_token.ts
For mainnet:
# Expects Token to already exist
# Will error if not foundFor testnets:
# Deploys TestToken with 16 decimals
# Mints initial supply to deployerFile: deploy/main/001_deploy_postage.ts
Constructor:
[token.address, 16] // minimumBucketDepth = 16Deployment:
npx hardhat deploy --network mainnet --tags postageStampFile: deploy/main/002_deploy_oracle.ts
Constructor:
[postageStamp.address]Special Handling:
- If oracle exists, preserves old price
- Re-applies old price after redeployment
Deployment:
npx hardhat deploy --network mainnet --tags oracleFile: deploy/main/003_deploy_staking.ts
Constructor:
[token.address, swarmNetworkId, priceOracle.address]Network IDs (from helper-hardhat-config.ts):
- Mainnet: 1
- Testnet: 10
- Testnet Light: 5
- Tenderly: 1
Deployment:
npx hardhat deploy --network mainnet --tags stakingFile: deploy/main/004_deploy_redistribution.ts
Constructor:
[stakeRegistry.address, postageStamp.address, priceOracle.address]Deployment:
npx hardhat deploy --network mainnet --tags redistributionFile: deploy/main/005_deploy_roles_postage.ts
Grants:
PRICE_ORACLE_ROLE→ PriceOracle contractREDISTRIBUTOR_ROLE→ Redistribution contract
File: deploy/main/006_deploy_roles_redistribution.ts
Currently no roles need to be set (constructor handles it).
File: deploy/main/007_deploy_roles_staking.ts
Grants:
REDISTRIBUTOR_ROLE→ Redistribution contract
File: deploy/main/008_deploy_roles_oracle.ts
Grants:
PRICE_UPDATER_ROLE→ Redistribution contract
Deployment:
npx hardhat deploy --network mainnet --tags rolesDeploy all contracts in order:
# Deploy all contracts
npx hardhat deploy --network mainnet
# Deploy only contracts (no roles)
npx hardhat deploy --network mainnet --tags contracts
# Deploy only roles
npx hardhat deploy --network mainnet --tags rolesNetwork: Ethereum Mainnet
Chain ID: 1
Token: 0x... (BZZ token)
PostageStamp: 0x...
PriceOracle: 0x...
StakeRegistry: 0x...
Redistribution: 0x...
See mainnet_deployed.json for current addresses.
Network: Sepolia Testnet
Chain ID: 11155111
See testnet_deployed.json for current addresses.
After deployment, verify contracts using Hardhat:
npx hardhat verify --network mainnet \
<CONTRACT_ADDRESS> \
<CONSTRUCTOR_ARG1> <CONSTRUCTOR_ARG2> ...Configuration is stored in helper-hardhat-config.ts:
export const networkConfig: networkConfigInfo = {
mainnet: {
blockConfirmations: 6,
swarmNetworkId: 1,
multisig: '0xD5C070FEb5EA883063c183eDFF10BA6836cf9816',
},
testnet: {
blockConfirmations: 6,
swarmNetworkId: 10,
multisig: '0xb1C7F17Ed88189Abf269Bf68A3B2Ed83C5276aAe',
},
// ... other networks
};# Example: Grant PRICE_ORACLE_ROLE to an address
npx hardhat send-tx --network mainnet \
--contract PostageStamp \
--method grantRole \
--args ROLE_HASH ADDRESS# Renounce admin roles to make contracts immutable
npx hardhat send-tx --network mainnet \
--contract PostageStamp \
--method renounceRole \
--args ROLE_HASH ADDRESSAfter oracle deployment:
npx hardhat send-tx --network mainnet \
--contract PriceOracle \
--method setPrice \
--args 24000This sets the initial price to 24000 (downscaled).
Set minimum batch validity (24h default):
npx hardhat send-tx --network mainnet \
--contract PostageStamp \
--method setMinimumValidityBlocks \
--args 17280 # 24 * 60 * 60 / 5If migrating from old contract:
const oldBatches = await getOldBatches();
await PostageStamp.copyBatchBulk(oldBatches);Check contract status:
npx hardhat status --target mainnetThis shows:
- Contract pause status
- Admin roles
- Role assignments
- Connection status
Error: "Token not available"
Solution: For mainnet, token must be deployed first. For testnets, ensure TestToken deployment runs.
Error: "Deployer needs to have admin role"
Solution: Grant admin role to deployer or execute transactions manually from admin account.
Error: Transaction reverted
Solution: Use copyBatchBulk() for batch migrations (processes 60-90 batches per tx).
Warning: StampPriceUpdateFailed event
Cause: PostageStamp not responding to price update
Solution: Check PostageStamp status, ensure not paused
Since contracts are NOT upgradeable, upgrades require:
- Deploy new contracts
- Use
copyBatch()to migrate batches (admin only) - Allow stake migration via
migrateStake()when paused - Transfer admin roles to multisig
- Renounce old admin/pauser roles
- All admin roles granted to multisig
- Pauser roles granted to multisig
- Initial price set on oracle
- Minimum validity configured
- All contracts verified on Etherscan
- Role setup verified
- Test initial deposit and withdrawal
- Test pause/unpause functionality
-
Deploy Token (if not exists)
npx hardhat deploy --network mainnet --tags token
-
Deploy Contracts
npx hardhat deploy --network mainnet --tags contracts
-
Setup Roles
npx hardhat deploy --network mainnet --tags roles
-
Set Initial Price
npx hardhat send-tx --network mainnet \ --contract PriceOracle \ --method setPrice \ --args 24000
-
Grant Additional Admins (e.g., multisig)
npx hardhat grant-role --network mainnet \ --contract PostageStamp \ --role DEFAULT_ADMIN_ROLE \ --to 0xD5C070FEb5EA883063c183eDFF10BA6836cf9816
-
Verify Contracts
npx hardhat verify --network mainnet --all
-
Check Status
npx hardhat status --target mainnet
-
Test End-to-End
- Create test batch
- Stake tokens
- Participate in redistribution game
Configures:
- Compiler version (Sol ≥ 0.8.19)
- Networks (mainnet, testnet, etc.)
- Etherscan verification
- Gas optimization
Defines:
- Network IDs
- Block confirmations
- Multisig addresses
- Swarm network IDs
Stores:
- Deployment artifacts
- Addresses and ABIs
- Constructor arguments
- Verification data
# Deploy all
npx hardhat deploy --network mainnet
# Deploy specific tag
npx hardhat deploy --network mainnet --tags postageStamp
# Run scripts
npx hardhat run scripts/cluster/changePrice.ts --network mainnet
# Check status
npx hardhat status --target mainnet
# Verify contracts
npx hardhat verify --network mainnet CONTRACT_ADDRESS ...
# Get contract info
npx hardhat contracts --target main# Deploy to local hardhat network
npx hardhat deploy --network localhost
# Run tests
npx hardhat test# Deploy to testnet
npx hardhat deploy --network testnet
# Verify on Etherscan
npx hardhat verify --network testnet --all# Estimate deployment gas
npx hardhat deploy --network mainnet --dry-runUse the status task to monitor contract health:
npx hardhat status --target mainnetMonitor for:
- Contract pause status
- Admin role assignments
- Role configuration
- Connection issues
For issues or questions:
- Check deployment logs in
deployments/directory - Review error messages in transaction receipts
- Check contract status using
statustask - Verify role setup using events