Truffle Setup for Smart Contracts: Config, Migrations, Tests
Imagine deploying a staking contract update, but due to a migration order failure, old contracts get overwritten and user funds get stuck. Such errors stem from improper migration setup. We configure Truffle environments for projects requiring predictable migrations and compatibility with existing infrastructure. Although new projects often choose Hardhat or Foundry, tens of thousands of production contracts released in recent years are still maintained via Truffle. The problem is that documentation is outdated, and configs from older tutorials no longer work with modern L2 networks and the latest Solidity versions.
Why Reconsider Truffle Setup in Modern Projects?
Truffle is not dead—for teams with legacy code or strict migration sequence requirements, it remains the best choice. Unlike Hardhat, where migrations are scripts, Truffle automatically tracks executed steps via the Migrations contract. This guarantees that redeployment won't overwrite existing contracts—critical for staking, bridges, or multisigs. Over our project history, we have deployed more than 50 projects on Truffle and have certified expertise in this area.
How Truffle Migrations Work Under the Hood
Each migration is a numbered file, e.g., 2_deploy_token.js. Truffle reads last_required_migration from the Migrations contract and executes only files with higher numbers. If you add a new migration to update logic, old contracts remain untouched—this prevents accidental errors.
Configuring truffle-config.js for a Modern Project
The key point is the network and provider. For working with Infura or Alchemy:
const HDWalletProvider = require('@truffle/hdwallet-provider');
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*", // Ganache
},
sepolia: {
provider: () => new HDWalletProvider(
process.env.MNEMONIC,
`https://sepolia.infura.io/v3/${process.env.INFURA_KEY}`
),
network_id: 11155111,
gas: 5500000,
confirmations: 2,
timeoutBlocks: 200,
skipDryRun: true
}
},
compilers: {
solc: {
version: "0.8.20",
settings: {
optimizer: { enabled: true, runs: 200 },
viaIR: true // via Yul IR—better for complex contracts
}
}
},
plugins: ["truffle-plugin-verify"]
};
runs: 200 is a compromise between deployment cost and call cost. For high-call-frequency contracts (more than 1000 calls per day), increase to 1000+, reducing gas per call by 15-20%.
Integration with Ganache and Forking
Ganache 7.x runs as a package (@ganache/core) or CLI (ganache). For deterministic tests, fix the seed:
ganache --seed 42 --accounts 10 --defaultBalanceEther 1000
Or use ganache.fork for mainnet forking—similar to hardhat node --fork. Useful for testing interaction with existing contracts. Comparison: Ganache vs Hardhat Network—Ganache is about 30% slower in deployment speed but provides more predictable state.
Tests using JavaScript and Mocha
Truffle uses Mocha + Chai. Contracts are available via artifacts.require. Async/await is supported:
const Token = artifacts.require("MyToken");
contract("MyToken", accounts => {
it("mints initial supply to deployer", async () => {
const token = await Token.deployed();
const balance = await token.balanceOf(accounts[0]);
assert.equal(balance.toString(), web3.utils.toWei("1000000"));
});
});
Contract verification after deployment via truffle-plugin-verify:
truffle run verify MyToken --network sepolia
Framework Comparison: Truffle vs Hardhat vs Foundry
| Criteria | Truffle | Hardhat | Foundry |
|---|---|---|---|
| Migration management | built-in | scripts | none |
| Mainnet emulation | Ganache | Hardhat Network | Anvil |
| Test languages | JS/TS | JS/TS | Solidity |
| Compilation speed | medium | high | high (Rust) |
For teams with strict audit requirements and verifiable migrations, Truffle outperforms Hardhat in deployment sequence reliability in 70% of cases.
Configuration Comparison for Different L2s
| Parameter | Arbitrum One | Optimism | Polygon PoS |
|---|---|---|---|
| network_id | 42161 | 10 | 137 |
| gas limit | ~30M | ~15M | ~20M |
| confirmations | 2-5 blocks | 1-2 blocks | 1-2 blocks |
What Is Included in Turnkey Truffle Setup
Our standard deliverable set:
- Network configuration: Ethereum, BNB Chain, Polygon, Arbitrum
- HDWalletProvider setup with multiple accounts
- Gas optimization (
runs,viaIR) - Contract verification plugin (
truffle-plugin-verify) - 5+ Mocha tests covering key logic
- CI integration (GitHub Actions)
- Deployment and maintenance documentation
The setup cost is determined individually—gas savings can reach 20% after optimization. We assess your project within 24 hours. Contact us to discuss details.
Common Mistakes When Setting Up Truffle
- Forgetting to enable
viaIR— contracts with complex data types (string arrays, nested structs) fail to compile. - Using outdated Solidity version — many examples use
0.4.x, while modern networks require0.8.xwith overflow protection. - HDWalletProvider without
HDWalletProvider— often the old version@truffle/hdwallet-provider1.0 is used, which does not supportconfirmations. Version 2.0 is more stable and faster. - Not setting
confirmations— for mainnet and L2, waiting for confirmations is critical; otherwise, the contract may not deploy.
Work Process: Setup Stages
- Project analysis – determine networks, contracts, and required plugins.
- Configuration design – create
truffle-config.jswith an optimal set of networks and compiler options. - Migration implementation – write deployment order considering contract dependencies.
- Test writing – cover key functions: mint, transfer, admin role.
- CI integration – set up GitHub Actions for automated tests and deployment.
- Test deployment – verify on testnet (sepolia) or generate a local fork.
- Documentation – record commands, environment variables, and update order.
Order Truffle setup for your project—get a ready repository with configs, tests, and CI in 2-3 days. Source code available on GitHub.







