TNT

CertiKFiles named in the report

CertiK reviewed TNT on 17 Feb 2023: 11 findings, 0 critical; 9 marked fixed, 1 acknowledged, 1 open.

No open critical findings
Open the reportOpen TNT’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings11

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High011
Medium000
Low108
HighDivision Truncation AttackFixed

The function `buyClaimToken()` permits a user to buy a portion of vesting. ```solidity=129 function buyClaimToken(uint256 _amount) public { require(!salePaused, "Public Sale paused"); require(blockTimeAtListing == 0, "Listed already"); // uint256 sourceAmount = _amount / (10 ** 18) * SOURCE_PER_CLAIM / DECIMAL_CORRECT_VALUE * (10 ** SOURCE_DECIMALS); uint256 sourceAmount = _amount * SOURCE_PER_CLAIM * (10 ** SOURCE_DECIMALS) / DECIMAL_CORRECT_VALUE / (10 ** 18); sourceToken.safeTransferFrom(msg.sender, sourceReceiptor, sourceAmount); _updateClaimable(msg.sender, _amount); emit Buy(msg.sender, _amount); } ``` The design of the function permits a user to get **1** TNT for **$\frac{SOURCE\_PER\_CLAIM}{1000}$** USDC. However, the math logic implemented is vulnerable to a Math truncation attack. The truncation will occur when `_amount * SOURCE_PER_CLAIM * (10 ** SOURCE_DECIMALS) / DECIMAL_CORRECT_VALUE` < `1e18`. Assuming the value of `SOURCE_PER_CLAIM` is very small, an attacker can manipulate the parameter `_amount` value to have the correct value to truncate. Therefore, this vulnerability can cause the attacker to update his claimable TNT amount without actually paying the source tokens, thus gaining TNT tokens without paying the necessary USDC tokens. Additionally, the attacker can **repeat** the above transaction in a batch to drain TNT tokens from the contract with less gas cost.

LowDiscussion on `ClaimTokenAmount`Fixed

The claim token amount in contract `Advisor`, `PrivateSale` and `Team` contracts are using `10**16` to convert input amount to the real amount with decimal. Since the decimal for `TNT` token is 18 instead of 16, which may lead to incompatible issues for the off-chain program, for example, 100 `_claimTokenAmount` refers to 1 `remainedToken`.

LowDiscussion on the `Sale` after ListingFixed

The `PublicSale` contract allows the purchase of `claimToken` through the `buyClaimToken()` function. The sale may continue even after listing, which can lead to the following scenarios: 1. The user can purchase the token when the cliff time passed and unlock tokens immediately. 2. The user may not unlock the full `percentageAtListing` amount if they purchase tokens after the claim. For example, if `claimTokenPercentageAtListing` is set at 20%, a user who buys 100 tokens before the listing and starts claiming when the cliff time has been reached then buys another 100 tokens at the same time. He/She will only be able to unlock 20% of the first 100 tokens (100 * 20% = 20) instead of the full 200 tokens (200 * 20% = 40) immediately. Because the `lastClaimTime` will be larger than 0 for the second purchase and the `claimTokenPercentageAtListing` will not be applied.

LowDuplicate SatementFixed

The value `claimable.lastClaimTime` updated twice with the same value `blockTimeAtListing` for the first time claim.

LowIncompatible With USDCFixed

The `PublicSale` contract allows users to purchase the `claimToken` using `sourceToken` through the `buyClaimToken()` function. As indicated in the comment, the `sourceToken` will be USDC, and the claimToken will be the `TNT` token. However, since USDC uses 6 decimals, it may not be compatible with the existing token sales logic. ```solidity=99 uint256 sourceTokenAmount = _claimTokenAmount * srcPerClaimToken * 10 ** 16; ``` Reference: [Etherscan - USDC](https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48)

Lowinsufficient Validation on Exist UserFixed

In function `_addClaimable` and `updateUserAddress` will validate the new user exists or not before adding to the `claimableMap` via `remainedToken`. For example, ```solidity=43 require(claimableMap[_user].remainedToken == 0, "Advisor: User already exists"); ``` The concern is that the aforementioned validation is not sufficient, because if user already claimed all remained amount it will be considered as non-existence user.

LowMissing Zero Address ValidationFixed

Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=39 srcTokenReceiveWallet = _srcTokenReceiveWallet; ``` - `_srcTokenReceiveWallet` is not zero-checked before being used. --- ```solidity=130 srcTokenReceiveWallet = _srcTokenReceiveWallet; ``` - `_srcTokenReceiveWallet` is not zero-checked before being used.

LowUnchecked ERC-20 `transfer()`/`transferFrom()` CaFixed

The return value of the transfer()/transferFrom() call is not checked. ```solidity=105 claimToken.transfer(owner(), claimToken.balanceOf(address(this))); ``` --- ```solidity=111 claimToken.transfer(owner(), claimToken.balanceOf(address(this))); ``` --- ```solidity=134 claimToken.transfer(owner(), claimToken.balanceOf(address(this))); ``` --- ```solidity=111 claimToken.transfer(owner(), claimToken.balanceOf(address(this))); ```

LowVariables That Could Be Declared as ImmutableFixed

The linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (3)

  • contracts/PassiveSale.sol
  • contracts/TNT.sol
  • contracts/ActiveSale.sol

Part of TNT’s security record

TNT
Audits1 audit by 1 firmLast audit Feb 2023, by CertiK.
Critical findingsNo open critical findingsIn 1 report.
Open TNT’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us