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 version

Confirm 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 init

This creates the standard layout:

my-tron-project/
├── contracts/        ← Solidity contracts
├── migrations/       ← deployment scripts
├── test/             ← test files
└── tronbox-config.js ← network and compiler config

You 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 fieldTronBox equivalent
gas (max gas per tx)feeLimit (in sun, capped at 15,000 TRX)
gasPricenot applicable — TVM uses energyPrice, set chain-wide
from (default sender)privateKey (controls the sender account directly)
host / portfullHost (single full URL including scheme)
🚧

Never commit your private key

Use the process.env.PRIVATE_KEY pattern shown above and set the value through a shell session or .env file with dotenv. 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:

FunctionTruffleTronBox
Inittruffle inittronbox init
Compiletruffle compiletronbox compile
Deploytruffle migratetronbox migrate
Testtruffle testtronbox test
Unboxtruffle unboxtronbox unbox
Consoletruffle consoletronbox 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: 0x prefix + 20-byte hex address.
  • TRON: Base58Check (T…) — the underlying bytes are 21 bytes (a 0x41 prefix plus the 20-byte address). TronWeb provides tronWeb.address.fromHex() and tronWeb.address.toHex() for round-tripping.

If you have hard-coded test addresses (0xAb…), replace them with TRON addresses (TXY…).

Native unit

  • Ethereum: wei is the smallest unit, 1 ETH = 10¹⁸ wei.
  • TRON: sun is 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() and deployer.deploy() work the same. If you have custom Energy or fee logic, replace gas / gasPrice with feeLimit and (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.jsTronWeb
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 shasta

If 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.
  • feeLimit errors — your transaction needs more Energy than the configured feeLimit allows. Re-estimate with wallet/triggerconstantcontract and increase feeLimit (max 15,000 TRX).

Best practices

  • Use .env files 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