Migrating a Truffle project to TronBox
Project-level migration walkthrough — convert an existing Truffle project to TronBox: directory layout, network config, command equivalents, and test framework adjustments.
Prerequisites
TronBox is a TRON-specific fork of Truffle that provides contract compilation, deployment, and testing. If you have an existing Truffle (or Hardhat-via-Truffle-compatibility) project, this page walks through migrating it to TronBox project layout. For the Solidity-level changes that often accompany this migration, see Migrating Ethereum contracts to TRON.
Set up TronBox
npm install -g tronbox
tronbox versionConfirm the installation succeeded (any recent 4.x version is fine). For a TronBox-from-scratch walkthrough including writing your first contract, see Quickstart.
Initialize a fresh TronBox project as a target
mkdir my-tron-project && cd my-tron-project
tronbox initThis creates the standard layout:
my-tron-project/
├── contracts/ ← Solidity contracts
├── migrations/ ← deployment scripts
├── test/ ← test files
└── tronbox-config.js ← network and compiler configYou will copy your existing Truffle project's contracts/, migrations/, and test/ directories into this new project — see Step 4 below.
Step 1 — Rewrite the config file
Rename truffle-config.js to tronbox-config.js. Replace the contents with the TronBox-shape config below (adapt the compilers.solc.version and per-network feeLimit to your needs):
module.exports = {
networks: {
development: {
privateKey: process.env.PRIVATE_KEY,
userFeePercentage: 100,
feeLimit: 100 * 1e6, // 100 TRX, in sun
fullHost: 'http://127.0.0.1:9090',
network_id: '9'
},
shasta: {
privateKey: process.env.PRIVATE_KEY,
userFeePercentage: 50,
feeLimit: 100 * 1e6,
fullHost: 'https://api.shasta.trongrid.io',
network_id: '2'
},
mainnet: {
privateKey: process.env.PRIVATE_KEY,
userFeePercentage: 50,
feeLimit: 100 * 1e6,
fullHost: 'https://api.trongrid.io',
network_id: '1'
}
},
compilers: {
solc: {
version: '0.8.6'
}
}
};Key field mappings from truffle-config.js:
| Truffle field | TronBox equivalent |
|---|---|
gas (max gas per tx) | feeLimit (in sun, capped at 15,000 TRX) |
gasPrice | not applicable — TVM uses energyPrice, set chain-wide |
from (default sender) | privateKey (controls the sender account directly) |
host / port | fullHost (single full URL including scheme) |
Never commit your private keyUse the
process.env.PRIVATE_KEYpattern shown above and set the value through a shell session or.envfile withdotenv. Hard-coding a key in source has caused many compromised mainnet accounts.
Step 2 — Map Truffle commands to TronBox
The CLI surface is nearly identical:
| Function | Truffle | TronBox |
|---|---|---|
| Init | truffle init | tronbox init |
| Compile | truffle compile | tronbox compile |
| Deploy | truffle migrate | tronbox migrate |
| Test | truffle test | tronbox test |
| Unbox | truffle unbox | tronbox unbox |
| Console | truffle console | tronbox console |
The console prompt becomes tronbox(networkName)> (for example, tronbox(shasta)>) instead of Truffle's truffle(networkName)>.
Step 3 — Adapt addresses and units in scripts and tests
Two pervasive differences will affect your migration scripts and test code:
Address format
- Ethereum:
0xprefix + 20-byte hex address. - TRON: Base58Check (
T…) — the underlying bytes are 21 bytes (a0x41prefix plus the 20-byte address). TronWeb providestronWeb.address.fromHex()andtronWeb.address.toHex()for round-tripping.
If you have hard-coded test addresses (0xAb…), replace them with TRON addresses (TXY…).
Native unit
- Ethereum:
weiis the smallest unit, 1 ETH = 10¹⁸ wei. - TRON:
sunis the smallest unit, 1 TRX = 10⁶ sun.
Replace web3.utils.toWei('1', 'ether') (gives 10¹⁸) with tronWeb.toSun(1) (gives 10⁶) in test setup. Update any hard-coded constants to match the 6-decimal TRX scale.
Step 4 — Copy contracts, migrations, and tests
# From the Truffle project root, copy directories into the new TronBox project
cp -r contracts/* my-tron-project/contracts/
cp -r migrations/* my-tron-project/migrations/
cp -r test/* my-tron-project/test/The directory structures are identical, so most files copy over unchanged. Specific changes you'll likely need:
migrations/—artifacts.require()anddeployer.deploy()work the same. If you have custom Energy or fee logic, replacegas/gasPricewithfeeLimitand (optionally)userFeePercentage.test/— see Step 5.
Step 5 — Replace web3.js with TronWeb in tests
Truffle test environments inject a global web3 object. TronBox injects tronWeb instead. The API shapes differ — see TronWeb documentation for the full reference.
Common substitutions in tests:
| web3.js | TronWeb |
|---|---|
web3.eth.getBalance(address) | tronWeb.trx.getBalance(address) |
web3.eth.accounts[0] | tronWeb.defaultAddress.base58 |
web3.utils.toWei(amount, 'ether') | tronWeb.toSun(amount) |
web3.utils.fromWei(amount, 'ether') | tronWeb.fromSun(amount) |
contract.method.call() | contract.method().call() (note the parentheses) |
contract.method({ from, gas }) | contract.method().send({ feeLimit, from }) |
Many tests will need only mechanical changes; some (especially those that depend on the exact gas accounting of an EVM call) need to be rewritten in TRON terms.
Step 6 — Compile, deploy, test
export PRIVATE_KEY="your-private-key-without-0x-prefix"
tronbox compile
tronbox migrate --network shasta
tronbox test --network shastaIf anything fails, see Smart contract errors for diagnostic flows for OUT_OF_TIME, OUT_OF_ENERGY, and REVERT errors.
Common migration issues
- Deployment fails with
Insufficient balance— the deployer account doesn't have enough TRX. Get Shasta testnet TRX from the Shasta faucet. - Tests pass on Truffle but fail on TronBox — check unit conversions (wei → sun) and address format (
0x…→T…). The most common silent failure is a hard-coded value that is now off by 12 orders of magnitude. - Event listeners don't fire — TronWeb's event API is different from web3.js. See Event log and the TronWeb docs.
feeLimiterrors — your transaction needs more Energy than the configuredfeeLimitallows. Re-estimate withwallet/triggerconstantcontractand increasefeeLimit(max 15,000 TRX).
Best practices
- Use
.envfiles to manage private keys; commit only an.env.example. - Test on Shasta or Nile testnet first before deploying to Mainnet.
- Pin TronBox and TronWeb versions in
package.json. Updates are usually backward-compatible, but lock files prevent silent breakage. - Verify on TRONSCAN after Mainnet deployment so users can audit the contract — see Contract verification.
Related resources
- Migrating Ethereum contracts to TRON — Solidity-level migration (opcode differences, CREATE2, addresses)
- Quickstart — TronBox CLI walkthrough from scratch
- Smart contract errors — diagnostic flows for deployment errors
- Best practices — pre-deployment checklist
- Contract verification — verify on TRONSCAN after deployment
- TronBox documentation — full TronBox reference
- TronWeb documentation — full TronWeb reference
Updated 7 days ago