Contract Deployment Guide
Overview
Contracts on Dong Chain can be deployed via:
- Foundry (recommended for new development)
- Hardhat (for teams migrating from Ethereum)
- Substrate RPC (direct, for advanced use)
Pre-Deployment Checklist
- [ ] Contract compiled with resolc to
.polkavm(for PVM) orsolc(for REVM) - [ ] All tests pass:
forge testwith 100% branch coverage - [ ] Fuzz tests run:
forge test --fuzz-runs 100000 - [ ] Security audit complete (for mainnet/any funds)
- [ ] resolc version pinned in repository
- [ ] Constructor arguments verified
- [ ] Non-upgradeability confirmed (for Depository/EntryPoint)
Foundry Deployment
Setup
bash
# foundry.toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.24"
[rpc_endpoints]
dongchain_local = "http://localhost:9944"
dongchain_testnet = "https://rpc.testnet.dongchain.io"
dongchain_mainnet = "https://rpc.mainnet.dongchain.io"
[etherscan]
dongchain_testnet = { key = "none", url = "https://explorer.testnet.dongchain.io/api" }Deployment Script
solidity
// script/Deploy.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "forge-std/Script.sol";
import "../src/DongChainDepository.sol";
import "../src/EntryPoint.sol";
import "../src/DongChainAccountFactory.sol";
import "../src/DongChainSponsorPaymaster.sol";
contract DeployDongChain is Script {
function run() external {
uint256 deployerKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address deployer = vm.addr(deployerKey);
address mpcAllocator = vm.envAddress("MPC_ALLOCATOR_ADDRESS");
console.log("Deployer:", deployer);
console.log("MPC Allocator:", mpcAllocator);
vm.startBroadcast(deployerKey);
// 1. Deploy EntryPoint (ERC-4337)
EntryPoint entryPoint = new EntryPoint();
console.log("EntryPoint:", address(entryPoint));
// 2. Deploy Account Factory
DongChainAccountFactory factory = new DongChainAccountFactory(address(entryPoint));
console.log("AccountFactory:", address(factory));
// 3. Deploy Paymaster
DongChainSponsorPaymaster paymaster = new DongChainSponsorPaymaster(entryPoint);
paymaster.deposit{value: 1 ether}(); // Fund paymaster
console.log("Paymaster:", address(paymaster));
// 4. Deploy Depository (non-upgradable)
DongChainDepository depository = new DongChainDepository(mpcAllocator);
console.log("Depository:", address(depository));
vm.stopBroadcast();
// Write deployment addresses
_saveDeployment(address(entryPoint), address(factory), address(paymaster), address(depository));
}
function _saveDeployment(
address entryPoint,
address factory,
address paymaster,
address depository
) internal {
string memory json = string.concat(
'{"entryPoint":"', vm.toString(entryPoint),
'","factory":"', vm.toString(factory),
'","paymaster":"', vm.toString(paymaster),
'","depository":"', vm.toString(depository), '"}'
);
vm.writeFile("./deployments/dongchain.json", json);
}
}bash
# Deploy to local node
forge script script/Deploy.s.sol \
--rpc-url dongchain_local \
--private-key $DEPLOYER_PRIVATE_KEY \
--broadcast \
-vvvv
# Deploy to testnet
forge script script/Deploy.s.sol \
--rpc-url dongchain_testnet \
--private-key $DEPLOYER_PRIVATE_KEY \
--broadcast \
--verify \
-vvvvVerify Deployment
bash
# Verify contract on block explorer
forge verify-contract \
--chain-id 9999 \
--etherscan-api-key none \
--verifier-url https://explorer.testnet.dongchain.io/api \
$CONTRACT_ADDRESS \
src/DongChainDepository.sol:DongChainDepository \
--constructor-args $(cast abi-encode "constructor(address)" $MPC_ALLOCATOR)Hardhat Deployment
javascript
// scripts/deploy.js
const { ethers } = require("hardhat");
const fs = require("fs");
async function main() {
const [deployer] = await ethers.getSigners();
console.log("Deployer:", deployer.address);
console.log("Balance:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)));
const MPC_ALLOCATOR = process.env.MPC_ALLOCATOR_ADDRESS;
// Deploy EntryPoint
const EntryPoint = await ethers.getContractFactory("EntryPoint");
const entryPoint = await EntryPoint.deploy();
await entryPoint.waitForDeployment();
console.log("EntryPoint:", await entryPoint.getAddress());
// Deploy Depository
const Depository = await ethers.getContractFactory("DongChainDepository");
const depository = await Depository.deploy(MPC_ALLOCATOR);
await depository.waitForDeployment();
console.log("Depository:", await depository.getAddress());
// Save addresses
const deployment = {
entryPoint: await entryPoint.getAddress(),
depository: await depository.getAddress(),
network: (await ethers.provider.getNetwork()).name,
block: await ethers.provider.getBlockNumber(),
};
fs.writeFileSync(
`./deployments/${deployment.network}.json`,
JSON.stringify(deployment, null, 2)
);
}
main().catch((err) => { console.error(err); process.exit(1); });bash
npx hardhat run scripts/deploy.js --network dongchain_testnetUsing Deployed Contracts
JavaScript/TypeScript
typescript
import { ethers } from "ethers";
import DepositoryABI from "./artifacts/DongChainDepository.abi.json";
import deployment from "./deployments/dongchain.json";
const provider = new ethers.JsonRpcProvider(process.env.DONGCHAIN_RPC_URL);
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const depository = new ethers.Contract(
deployment.depository,
DepositoryABI,
signer
);
// Deposit ERC-20
const tx = await depository.depositErc20(
depositorAddress,
tokenAddress,
ethers.parseEther("100"),
ethers.randomBytes(32) // orderId
);
await tx.wait();
console.log("Deposited:", tx.hash);Cast (Foundry CLI)
bash
# Read from contract
cast call $DEPOSITORY "MPC_ALLOCATOR()(address)" --rpc-url $DONGCHAIN_RPC
# Check if nonce used
cast call $DEPOSITORY "usedNonces(bytes32)(bool)" 0x$(openssl rand -hex 32) --rpc-url $DONGCHAIN_RPC
# Send transaction
cast send $DEPOSITORY \
"depositNative(address,bytes32)" \
$DEPOSITOR_ADDRESS \
0x$(openssl rand -hex 32) \
--value 1ether \
--rpc-url $DONGCHAIN_RPC \
--private-key $PRIVATE_KEYDeployment Addresses Registry
Track all deployments in deployments/:
deployments/
├── dongchain-local.json # Local development
├── dongchain-testnet.json # Public testnet
└── dongchain-mainnet.json # Mainnet (TBD)Format:
json
{
"network": "dongchain-testnet",
"chainId": 9999,
"deployedAt": "2026-03-27T00:00:00Z",
"block": 100000,
"deployer": "0x...",
"contracts": {
"EntryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"AccountFactory": "0x...",
"Paymaster": "0x...",
"Depository": "0x..."
}
}