Track 4: Advanced smart contract developer

Start with reproducible builds and TVM semantics, then turn a timed-payment contract into a testable, assessable release candidate that can be accepted on Shasta.

This track is a starting point for moving from ordinary contract development to an engineering release process. It is intended for developers who can already write, test, and deploy Solidity contracts and want a deeper understanding of TVM execution, resource costs, security checks, and release acceptance.

What you will learn

The track starts with reproducible builds, then covers TVM and resource semantics, contract-logic review, positive and negative testing, Energy and security assessment, and deployment and release records on Shasta.

A timed-payment contract is used throughout. A payer deposits test TRX and specifies a recipient and release time; after that time, only the designated recipient can claim the funds. Each stage uses the same source and test records to turn a working contract into a reviewable, reproducible release candidate.

To follow along, add the timed-payment contract example to an existing Solidity contract project, such as a TronBox project, then add the build configuration, tests, cost baseline, and deployment records stage by stage. You can also apply the same process to your own contract by replacing the create-payment and claim paths with that contract's main execution paths. Here, “release candidate” means that the contract has an explicit version and acceptance record. It does not mean the contract has completed the independent security audit required for production.

You do not need to understand every detail of TVM and the resource model before starting. First use the overview below to understand each stage, then review the current contract while working through the linked documentation. Return to the recommended reading when an execution, Energy, or deployment question arises.

Track overview

StageMain focusTimed-payment contract task
1. Establish a reproducible build baselinePin the source, dependencies, compiler, and optimizer configurationPreserve a reproducible ABI, creation bytecode, and runtime bytecode
2. Calibrate execution and resource semanticsUnderstand TVM, Energy, the Dynamic Energy Model, exception accounting, and EVM differencesRecord the execution and resource characteristics of the create-payment and claim paths
3. Review the contract logicCheck state, permissions, time, fund transfers, ABI, and eventsDefine the contract's state constraints and security invariants
4. Complete the testsCover the normal flow, boundary conditions, and failure pathsTest creation, release-time claims, and the main invalid operations
5. Assess cost and securityEstablish an Energy baseline, a fee_limit policy, and a security-check recordMeasure deployment and the main calls, then check fund and permission risks
6. Complete deployment and the release recordDeploy, verify the source, check behavior, and preserve version evidenceRelease on Shasta and record the contract address, transactions, and verification result

Before you begin

You should already have experience writing, testing, and deploying ordinary Solidity contracts, and understand accounts, transactions, resources, and the Shasta testnet. If you have not yet completed the compile-deploy-call flow, first work from Smart contract quickstart — Step 1: Install TronBox through “Call the contract from the console.” The exercises also require a contract project managed by TronBox or a comparable tool and a Shasta deployment account holding test TRX. If you have not yet prepared a project, complete the quickstart setup first, then add the contract source from the accompanying recipe.

This track organizes the knowledge and acceptance chain from contract source to a release candidate. For the concrete compile and deployment flow, begin with Creating and compiling — Compile and Deploying — Preparation, then use the stage-specific reading below as needed.

All public-testnet exercises use Shasta. Automated tests can run on an isolated local test network. Use test source, test accounts, and test TRX throughout. Provide a private key only to a local deployment tool or controlled signing environment; never put it in source code, configuration files, logs, or version control.

Track stages

1. Establish a reproducible build baseline

A contract compiling successfully does not mean every environment will produce the same artifacts. The exact compiler version, optimizer settings and runs, dependency versions, source paths, and linked-library configuration can all change the ABI, creation bytecode, or runtime bytecode. Pin these inputs before release so testing, deployment, and source verification do not use different artifacts.

A reproducible build also needs to identify the source commit and configuration for the current candidate. Generate the ABI and bytecode through the build process rather than editing them by hand. Preserve the dependency lockfile, compiler warnings, and build command as part of the record. All later tests, Energy measurements, and the Shasta deployment should continue to use this baseline.

Recommended reading

  1. Solidity on TRON — Compiler version support

    Continue through “Differences from upstream Solidity” to confirm the target Solidity version and relevant TRON extensions. You can skip TRC-10, staking, and voting extensions the current contract does not use.

  2. Creating and compiling — Compile and View the compiled artifacts

    Use these sections to confirm the compiler and optimizer settings and where to obtain the ABI and bytecode. The page primarily demonstrates TronIDE; the project configuration must still pin versions and support a clean build.

  3. Smart contract quickstart — Step 5: Compile

    Use this section to confirm the TronBox compile command. If necessary, revisit Configure the Shasta network; leave deployment until stage 6.

Stage exercise

First prepare the contract project that the remaining stages will share. To use the through-line example, add the timed-payment contract example to the project. To use your own contract, first identify the main execution paths that the later stages will review. Then pin the source commit, dependency lockfile, and exact Solidity compiler version. Explicitly record whether the optimizer is enabled in the project configuration and, when it is enabled, pin the runs value. Clean the existing build output, compile again, and save the ABI, creation bytecode, runtime bytecode, compiler warnings, and build command.

Build again with the same configuration in a clean working directory or CI environment and compare the artifacts. If they differ, identify the environment, dependency, or configuration difference before continuing to testing and deployment. Compare the ABI, creation bytecode, and runtime bytecode separately; do not compare only a tool artifact that may contain paths or timestamps.

Before calibrating execution semantics: Confirm that the same source and configuration reproduce the same ABI and bytecode, and record the corresponding source commit and build environment. The next stage uses these artifacts to analyze TVM execution and resource cost.

2. Calibrate execution and resource semantics

TRON smart contracts execute in the TVM. TVM is broadly compatible with EVM bytecode and Solidity, but Energy metering, address handling, execution-time limits, some opcodes, and on-chain context differ. Prior Ethereum experience does not replace checking these boundaries.

Contract deployment and state-changing calls consume Energy. Actual cost depends on the execution path, storage access, and call parameters. Popular contracts may also be affected by the Dynamic Energy Model, so one test result is not automatically a permanent cost. When resources are insufficient or execution fails, use the receipt to determine whether state was rolled back, how Energy was recorded, and what cost the caller paid.

For the timed-payment contract, creating a payment writes the payer, recipient, amount, and release time. Claiming checks the permission and time condition, updates the claimed state, and transfers TRX. The two paths have different storage and external-transfer behavior and should be understood and measured separately.

Also distinguish the two paths for transferring TRX to a contract. Carrying callValue into a payable method executes the contract; an ordinary TransferContract sent directly to a contract address does not invoke receive() or fallback(). A contract that maintains internal payment records must not use only address(this).balance as its business ledger.

Recommended reading

  1. TRON Virtual Machine — Transactions and TVM vs EVM — Energy model in place of gas

    On the TVM page, continue through “Execution context,” “Halting, exceptions, and protocol limits,” and “Energy metering.” On the comparison page, read through “TRX transfer paths.” Skip proprietary opcodes and precompiled contracts the current project does not use.

  2. Bandwidth and Energy — Energy and Paying for resources — Charging order

    Use these sections to distinguish caller resources, deployer sharing, and burned TRX. Leave the Dynamic Energy Model and the fee_limit strategy until stage 5.

  3. VM exception handling — Runtime exceptions that exhaust the Energy allowance and REVERT

    Compare the rollback and resource outcomes of REVERT, OUT_OF_ENERGY, and OUT_OF_TIME. Read about other exceptions only if they occur in the current contract.

Stage exercise

Using the current ABI and source, diagram the create-payment and claim execution paths. Mark the state each path reads and changes, the events it emits, and any external transfer it can make. For every failure condition, record the expected rollback and receipt result.

In an isolated local test environment, execute one successful creation, one successful claim, and one intentional revert. Save each transaction receipt and its Energy data. At this point, focus on confirming the actual semantics; do not set the final fee_limit yet.

Before reviewing contract logic: Confirm that you can explain the state and resource effects of creation and claiming and how the main exceptions appear in a receipt. The next stage checks the business rules and security invariants behind these paths.

3. Review the contract logic

The timed-payment contract needs a set of rules that always hold: the payment amount and recipient address are valid, and the release time follows the product rules; the contract holds the funds until they can be claimed; only the specified recipient can claim after the release time; and a payment cannot be claimed twice.

Review state changes, permission checks, time conditions, and fund transfers together along each execution path. Before an external transfer, complete the necessary checks and state updates and define what happens if the transfer fails. block.timestamp can enforce a time condition, but boundary values and acceptable timing variance must be documented and tested.

The ABI and events must express the same business semantics. Confirm each public method's parameters, visibility, and payable status. The creation event should record the payment ID, payer, recipient, amount, and release time. The claim event should include the payment ID, recipient, and amount needed to reconcile the claim. Both events should emit only after the corresponding state change succeeds.

If the recipient may be a contract, include rejected TRX transfers and reentrancy in the threat model. When choosing transfer, send, or call, assess the failure semantics, return-value handling, and checks-effects-interactions ordering together. Replacing only the transfer method is not a complete security treatment.

Recommended reading

  1. Smart contract security — Reentrancy and Sending TRX to a contract that rejects it

    Use these sections to review access control, checks-effects-interactions, reentrancy, denial of service, and locked-fund risks. Whether the integer-overflow section is relevant depends on the compiler version.

  2. TRX transfers in smart contracts — Three transfer methods

    Compare the failure semantics of transfer, send, and call. Assess any choice together with the recipient type, return-value checks, and reentrancy protection.

  3. Event logs — Defining and emitting events

    Confirm event arguments, indexed fields, and emission points. Consuming events off chain is not a prerequisite for this stage.

  4. Parameter encoding and decoding — ABI encoding specification

    Continue to function selectors and argument decoding only if you need to construct call data manually or build an off-chain decoder. An ordinary contract project should prefer the compiler-generated ABI.

Stage exercise

Create a logic checklist for the timed-payment contract. For every item, record the state variables, creation conditions, claim conditions, fund destination, external calls, events, and failure result. Express every business rule as an invariant that a test can verify instead of relying only on code review.

Perform an independent code review and confirm that the source, ABI, and event definitions describe the same business rules. If the logic changes, update the source and tests first, then regenerate the stage 1 artifacts.

Before completing the tests: Confirm that state, permissions, time, fund transfers, ABI, and events remain consistent across the create and claim paths, and that the main rules are recorded as testable invariants. The next stage validates them with successful and failing scenarios.

4. Complete the tests

A normal flow shows only that the contract works for one set of ideal inputs. A release candidate also needs boundary and failure-path coverage and evidence that a failure leaves no partial state, incorrect event, or exploitable fund state.

The successful timed-payment tests must include payment creation and a claim after the release time. Failure tests should cover creating a payment with a zero amount, a zero-address recipient, or a release time no later than the current block time; claiming a nonexistent or not-yet-released payment; claiming from the wrong account; and claiming the same payment twice. Each test should verify not only that the call fails but also that balances, state, and events remain correct.

Run time-related tests on an isolated local network. The TRON block API returns block_header.raw_data.timestamp in milliseconds, whereas the contract's block.timestamp and releaseTime use seconds. After reading the current block, convert the value with Math.floor(block.block_header.raw_data.timestamp / 1000), then add a short interval to obtain releaseTime. When using TRE, wait slightly longer than that interval, then call tronWrap.send('tre_mine', [{ blocks: 1 }]) to create a new block. Confirm that the new block timestamp has reached releaseTime before testing the claim. Before each test, restore the same initial state and keep the test accounts, amount, and relative time interval fixed. Use Shasta to validate real network, resource, and solidification behavior; it does not replace local automated tests.

Recommended reading

  1. TronBox and Testing contracts with TRE

    Use these pages to verify the test configuration, how to run tronbox test locally and on Shasta, and how to call tre_mine for time-dependent tests.

  2. Smart contract errors — REVERT

    Use the diagnostic flow to confirm a business-rule rollback. Continue to OUT_OF_ENERGY or OUT_OF_TIME only if those conditions occur.

  3. Smart contract security — Common attack patterns

    Add rejection and reentrancy tests according to the contract's fund, permission, and external-call risks; the current contract does not need a test for every attack described on the page.

Stage exercise

Add the following tests to the timed-payment contract:

  1. Create a payment with a valid amount, recipient, and future release time.
  2. After the release time, claim as the specified recipient and verify balances, state, and events.
  3. Reject a payment created with a zero amount.
  4. Reject a payment created with the zero address as its recipient.
  5. Reject a payment whose releaseTime equals or precedes the current block time.
  6. Reject a call to claim() with a paymentId that does not exist.
  7. Reject a claim before the release time.
  8. Reject a claim from an account other than the specified recipient.
  9. Reject a second claim for an already claimed payment.

For every failure, assert that no unexpected state change occurred, no funds moved incorrectly, and no success event was emitted. Record the actual error result, then run the complete suite in a clean environment or CI.

If the claim path can transfer to a contract address, add negative cases for a recipient that rejects the transfer and one that attempts reentrancy. If the product permits direct TRX transfers to the contract, confirm that such balances do not automatically create a payment record or change an existing payment's claimable amount.

Before assessing cost and security: Confirm that normal creation and claiming pass consistently, every required failure path stops as expected, and the balance, state, and event assertions are complete. The next stage uses these fixed scenarios to establish cost and security baselines.

5. Assess cost and security

An Energy assessment must use real execution paths rather than a single average. Deployment, payment creation, and claiming have different storage patterns, and the first write, later updates, success paths, and failure paths may have different costs. Each measurement should record its input, pre-state, result, and query time so differences can be explained.

fee_limit caps the caller-side Energy budget for one contract execution. It is not a fixed fee or a contract-security guarantee. Base the policy on measured Energy, the Dynamic Energy Model, chain parameters, and the effect of failure, and estimate again or retain a reasonable margin before a call. Historical measurements are a baseline, not a permanent substitute for a current estimate.

Security checks should continue to cover permissions, time, reentrancy, external-transfer failure, unexpected TRX, unclaimable funds, and administrative capabilities. Static analyzers can assist, but they may not fully understand TVM-specific behavior and cannot replace human review proportionate to the funds at risk.

Recommended reading

  1. FeeLimit and Energy cost — What fee_limit actually does and Estimating Energy before broadcasting

    Use these sections to understand the caller budget, Dynamic Energy, and estimation fallback. Read only the configuration for the tool the current project uses.

  2. Paying for resources — Charging order and Dynamic Energy Model

    Confirm resource sources, TRX cost, deployer sharing, and Dynamic Energy effects. The account-creation special case is not relevant to this stage.

  3. Smart contract security — A solid development process and Best practices — Design for Energy from day one

    Use these sections for pre-release peer review, automated tests, static analysis, and resource-design checks. Leave upgrade and operations guidance until after completing the track.

Stage exercise

On Shasta, measure contract deployment, payment creation, a release-time claim, and the main failure paths separately. Record the transaction type, inputs, pre-state, estimate, Energy and Bandwidth from the solidified receipt, execution result, and fee_limit used.

Use the measurements to define an Energy baseline and fee_limit policy, including the estimate source, safety margin, re-estimation trigger, and failure handling. Complete a security checklist that records the method, result, unresolved issue, and release-blocking status for every risk.

Before deployment and release: Confirm that the main calls have an explainable Energy baseline and fee_limit policy and that no unresolved release blocker remains in the security checklist. The next stage uses the same source and configuration for Shasta acceptance.

6. Complete deployment and the release record

Build the release candidate directly from the source, dependencies, and compiler configuration already tested. Before deploying, recheck the source commit, artifacts, target network, deployment account, constructor arguments, and available resources so a last-minute change cannot bypass testing and cost assessment.

After the deployment transaction is broadcast, check the execution result, preserve the contract address, and run basic read and write checks. Broadcast acceptance is not execution success; preserve the original txID and wait for a solidified receipt before judging the deployment result. Source verification must use exactly the deployed source, compiler, and optimizer settings. A match proves that the published source corresponds to the on-chain bytecode; it does not prove the contract has passed a security audit.

A complete release record should trace the on-chain contract back to source and test evidence. Include the version or commit, build configuration, ABI and bytecode, test results, Energy baseline, security review, deployment txID, contract address, source-verification status, and known limitations.

Recommended reading

  1. Deploying — Preparation and Confirming a successful deployment

    Confirm the deployment account, Shasta network, resource preparation, and deployment result. If you use TronBox, reuse the fields and acceptance semantics rather than copying the TronIDE procedure.

  2. Transaction signature and broadcast flow — Step 4: Confirm the transaction result

    Query the transaction body, execution receipt, and solidified result. Keep every example endpoint on Shasta.

  3. Contract verification — Step-by-step verification

    Submit the source and build settings that match the on-chain bytecode. Switch TRONSCAN to Shasta first, and consult the relevant troubleshooting section only if verification fails.

  4. Smart contract interaction — Querying a contract's ABI and bytecode

    Confirm the on-chain ABI and runtime bytecode. For the read and write examples, use only the method implemented by the current acceptance script.

Stage exercise

Rebuild the contract from the source commit that completed testing and security review, then deploy it to Shasta. Save the deployment account, target network, constructor arguments, deployment txID, contract address, solidified receipt, and resource use. At that address, complete one payment creation and one release-time claim.

Verify the contract source with the source and build configuration pinned in stage 1. Finally, assemble one candidate record containing the source version, artifacts, tests, Energy baseline, security review, deployment evidence, verification result, and known limitations.

Validate the release result: The Shasta contract completes a normal creation and claim and rejects the main invalid operations as expected. Its address can be traced to the corresponding source, build configuration, tests, security review, cost baseline, and source-verification record.

Next steps and extensions

After this track, you should have a reproducible timed-payment contract project, positive and negative tests, an Energy baseline, a security checklist, a Shasta contract address, and a source-verification record. Together, these show that the current version is ready for further review; they do not replace an independent security audit or a production-release decision.

If the contract needs upgrades, long-term operations, or multiple managed versions, continue with Upgrading smart contracts — Trade-offs of introducing upgradeability and Best practices — After deployment. Add plans for upgrade permissions, migration, monitoring, and emergency response.

If you complete only part of the track, preserve the current source commit, artifacts, test results, and measurements, then resume at the relevant stage. Any source or configuration change should rerun the affected build, test, cost, and release checks.

If you are still blocked at any stage, share track feedback and include “Track 4,” the current stage, tool versions, Shasta endpoint, completed steps, and the actual error. Do not submit private keys, seed phrases, API keys, undisclosed vulnerability details, or production-account information.