As of 3 Nov 2026, The Dtec World has 2 audit reports by 1 security firm on Trustblock; the latest is by CertiK, dated 24 Jul 2024. Those reports list no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| Dtec - Audit 2 | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
| Dtec Audit | Security firm: CertiK | Date: | Scope: Files named in the report | No open critical findings | Open · skynet.certik.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 2 | 1 | 1 |
| Medium | 0 | 1 | 3 |
| Low | 3 | 1 | 14 |
In the contract `PublicSaleLock`, users can call `claim()` function to claim the `DTEC` tokens they purchased earlier in the `DTECPublicSale` contract after a certain period. However, it is noted that in the `getClaimable()` function, the contract uses the code below to calculate the claimable amount of `DTEC`, and the value of `numerator` is always less than **10000**, which means 10% of `info.totalAmount` will be stuck in the current contract. ```solidity=70 uint256 numerator = getReleaseNumerator(periodsPassed); uint256 totalClaimableSoFar = info.totalAmount * numerator / 10000; if (totalClaimableSoFar > info.totalAmount) { totalClaimableSoFar = info.totalAmount; } return totalClaimableSoFar - info.totalClaimed; ```
Open the reportThe function `migrateOldUsers` is intended to facilitate the migration of tokens from an old contract to a new one. It requires that each user's bought amount in the new contract be zero before allowing migration. ```solidity function migrateOldUsers (address[] calldata users ) external onlyOwner nonReentrant { //... for (uint256 i = 0; i < users.length; i++) { require(addressToBoughtAmt[users[i]] == 0, "User should only migrate once, no duplicate amount"); //... require(oldSaleContract.amountSold() == totalMigratedTokenAmount , "All bought amounts should be migrated"); emit MigrationMade(users, block.timestamp, totalMigratedTokenAmount); } ``` This may bring a potential DoS attack and no token can be migrated from an old contract to a new contract.
Open the reportIn the `migrateOldUsers()` function, the contract calculates the value of `allocation` via `addressToBoughtAmt`. However, it is noted that `addressToBoughtAmt` is possibly inconsistent with `allocation` in the old contract due to the `claimAllocation()` function. If a user has called `claimAllocation()` in the old contract, the `allocation` of this user is zero. But the migration incorrectly updates `allocation` to the corresponding bought amount, which causes a user can claim more tokens than bought.
Open the reportIn the contract `DTECTokenSale`, the `_owner` can transfer `_amt` amount of `DTEC` tokens away. It is noted that this function misses a sanity check for `_amt`, as a result, the allocated tokens of users may be also transferred, causing calling to `claimAllocation()` failed.
Open the reportThe `PrivateSaleLock2` contract is designed with two primary methods, `releaseFunds()` and `claim()`, to facilitate users in claiming tokens. Specifically, the `releaseFunds()` method reads the quantity of tokens purchased by the user from the `DTECPrivateSale` contract and directly releases a certain amount of tokens to the user based on the `immediateReleaseRate` set in the `DTECPrivateSale` contract. The `claim()` method calculates the total amount of tokens released to the current user through the `PrivateSaleLock` contract, subtracts the amount already claimed by the user, and transfers the currently claimable tokens to the user. The underlying design intent here is that the total number of tokens released through `releaseFunds()`, combined with the total released through the `claim()` method, equals the number of tokens purchased by the user via the `DTECPrivateSale` contract. Additionally, since users can obtain their purchased tokens through both the original `DTECPrivateSale` contract and the `PrivateSaleLock` contract, and can also receive the same amount of tokens through the `PrivateSaleLock2` contract, they ultimately have the opportunity to receive double the amount of tokens.
Open the reportThe associated variables have been given fixed values through hard coding, which cannot be modified. Additionally, the token decimal appears to be hardcoded to 18.
Open the reportThe `lockStartTime` state variable in the `CommunityIncentives` and `TgeVestingBase` contracts signifies the commencement time for the release of the vested amount. It is designated as immutable, indicating that its value is assigned only once. For the vesting service to operate accurately, `lockStartTime` must not be initialized to zero. Consequently, evaluating whether `lockStartTime` equals zero is redundant. ```solidity if (info.totalClaimed == info.totalAmount || lockStartTime == 0 || block.timestamp < lockStartTime) { return 0; } ``` ```solidity if (info.totalClaimed == info.totalAmount || lockStartTime == 0 ) { return 0; } ```
Open the reportThe contract is serving as the underlying entity to interact with one or more third party protocols. The scope of the audit treats third party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity DTECPrivateSale public constant privSale1 = DTECPrivateSale(0x6d158bb60FfF3a66F0290BF3F156B9d355163e50); PrivateSaleLock public constant privSale1Lock = PrivateSaleLock(0x47D5c7599991F121A817C289B8E62Dd2015D5Eb3); IERC20 public constant dtecToken = IERC20(0xd87aF7B418d64FF2cdE48d890285bA64fc6E115F); ``` ```solidity address public immutable dtecTokenAddress; ```
Open the reportThe linked statements do not affect the functionality of the codebase and appear to be either remnants of test code or older functionality.
Open the reportThe provided codebase cannot be compiled. Additionally, suppose the contracts are within the same folder. There will be inconsistency in the imports of the `ITokenLock.sol` interface between the different files. Specifically, the discrepancy lies in the paths used to import this interface: - In the file `DTECTokenSale.sol`, it is imported as ```solidity import {ITokenLock} from "./interfaces/ITokenLock.sol"; ``` - In the file `PublicSaleLock.sol` and `LinearLock.sol`, it is imported as ```solidity import {ITokenLock} from "../interfaces/ITokenLock.sol"; ```
Open the reportThe `_owner` can modify the `period` of the contract. However, there is no validation to prevent the `period` from being set to zero. If `period` is set to zero, the lock contract will encounter a revert error when users attempt to claim their tokens. The variable `releaseRate` is also lacking the same sanity check.
Open the reportThere should always be events emitted in the sensitive functions that are controlled by centralization roles.
Open the reportThe cited address input is missing a check that it is not `address(0)`.
Open the reportState variables that never change should be declared as `constant` to save gas. ```solidity=7 uint256 public MAX_SUPPLY = 900000000 * 10 ** 18; ``` - `MAX_SUPPLY` should be declared `constant`.
Open the reportIn the contract `DTECPrivateSale`, only whitelisted users can buy `DTEC` via this contract. It is noted that the contract misses a functionality that remove users from whitelist.
Open the reportThe function `getReleaseNumerator` is used to calculate the released amount. ```solidity function getReleaseNumerator(uint256 _periods) internal pure returns (uint256) { if (_periods == 0) { return 0; } else if (_periods == 1) { return 2000; } else if (_periods == 2) { return 5000; } return 9000; } ``` However, if the calculated `periodsPassed` is zero, getClaimable() will be returned directly at L67 without reaching the first if branch(L50) in the function `getReleaseNumerator()`.
Open the reportThe function `getClaimable()` is used to calculate claimable tokens. ```solidity function getClaimable(address _user) public view returns (uint256) { LockInfo memory info = userToLockInfo[_user]; if (info.totalClaimed == info.totalAmount || lockStartTime == 0 || block.timestamp < lockStartTime) { return 0; } //... } ``` However, since the visit level of functions `setReleaseInfo()` and `setPeriod()` are internal, which could not be called by the owner, thus `lockStartTime` and `releaseRate` will always be zero. The function `getClaimable()` will reach condition in L46 and always return zero, no one can claim any tokens.
Open the reportThe 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.
Open the reportThe reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="dtec-blockchain"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
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