As of 3 Nov 2026, Ordify has 1 audit report on Trustblock, by CertiK, dated 22 Mar 2024. That report lists no open critical findings.
Record last updated . It holds audits, findings and contracts up to Nov 2026, and incidents up to Oct 2026. Trustblock does not review code.
Newest first
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 2 | 0 |
| Medium | 1 | 0 | 2 |
| Low | 10 | 0 | 14 |
The `createVestings` function can be invoked by the contract owner to create a vesting plan for a specific user, and when `depositCheck` is enabled, the contract will ensure there is enough token allocated in the contract. ```solidity=161 uint256 totalTokenAvailable = totalDepositedAmount + totalAmountClaimed - totalAmountAllocated; ``` The user is allowed to drop vesting via `requestRefund`, as a result, the vesting amount will be added to the ```solidity=226 totalAmountRefundRequested += vesting.amount; ``` However, the `requestRefund` will not update the `totalAmountAllocated`, once the contract owner `withdrawRequestRefundToken` from the contract. There might not be enough tokens for new vesting, because the canceled vesting is still part of the `totalAmountAllocated`, and the contract balance needs to cover it.
Open the reportAfter the event finished, there are two conditions that user can refund: 1. User has a valid signature from `verifyingAddressECDSA`. 2. `globalRefundEnabled` is set with `true`. AAlso, the actual refund sum is calculated with two phases contributions and `refundPercentage`: ```solidity=160 uint256 userContributed = userDetailsRecord.contributedRound1 + userDetailsRecord.contributedRound2; uint256 refundCalculationDividend = userContributed * refundPercentage; userRefoundAmount = refundCalculationDividend / (BASIS_POINT_RATE_CONVERTER); ``` The `refundPercentage` can be set with: - `setRefundPercentage` - `prepareForGlobalRefund` However, the `prepareForGlobalRefund` will avoid the `refundPercentage` to be 0, but `setRefundPercentage` can set 0 `refundPercentage`, which is inconsistent on design that ``refundPercentage` > 0`. And if `refundPercentage` is 0 user cannot get any refund.
Open the reportIn the latest version of the code, a new function called `emergencyWithdrawWithoutReward` has been introduced. This function is designed to prevent the user's deposited assets from being locked up in the event that the pool lacks sufficient rewards. However, this update has led to some concerns: 1. The validation check for `prematureWithdrawEnabled` within the `withdraw` function can be circumvented by users through a combination of `claim` and `emergencyWithdrawWithoutReward` calls. This means that even if `prematureWithdrawEnabled` is set to false, indicating that early withdrawal is not allowed, users can still withdraw their stakes prematurely. We would like to check with the team if such scenario is considered. 2. When using the `emergencyWithdrawWithoutReward` function, the system does not record any reward information for the stake. As a result, any rewards that might be allocated to the user in the future will be permanently lost, as there is no record of these rewards being associated with the user's stake.
Open the reportAccording to the code, whenever a claim is made, the contract will transfer token to the user and accumulate `claimableAmount` to `totalAmountClaimed`. However, in the function `createVesting()`, when `airdroptedAtStart` is true, `totalAmountClaimed` will be directly modified without transferring money to the user.\
Open the reportBased on the updated codebase, the `round2Multiplier` is no longer used for round2 allowance calculation, and no other logic is attached to it. As a result, the `round2Multiplier` and corresponding setup logic are redundant.
Open the reportThe `Helper` function will store tiers configuration to classify users' staking status. When deploying the contract, the following code snippets are implemented to update the `tiers` and `tiersMap`: ```solidity Tier memory noneTier = Tier("NONE", 0, 0); tiers.push(noneTier); tiersMap["NONE"] = noneTier; Tier memory prevTier = tiers[0]; for (uint256 i = 0; i < _tiers.length; i++) { require(prevTier.amountNeeded < _tiers[i].amountNeeded, "Tiers must be oredered amount needed"); tiers.push(_tiers[i]); tiersMap[_tiers[i].name] = _tiers[i]; prevTier = _tiers[i]; } ``` However, there is no validation if `_tiers[i].name` is already filled, as a result, duplicate records may exist with the same name and previous data stored in the given name will be overwritten.
Open the reportBased on the function `withdrawRefundForAll()`, it can be inferred that this function is intended to execute the withdrawal of refund assets only when the refund mode is enabled. Therefore, when refundMode is true, "refund mode is on"; conversely, when refundMode is false, "refund mode" is off.
Open the reportThe following function is mainly used to withdraw penalty refund, however, the function should be `10000 - refundPercentage` based on the implementation: ```solidity=278 /** * @dev method used to refund stable token after refund is activated. Only part of refund is available. 1000 - refundPercentage */ function withdrawStableRefund() external onlyOwner { ```
Open the reportWhen deploying the contract, it was checked whether the values of `withdrawFeePercentage` and `rate` were within the valid range, but the lack of a check here may cause the setting to be outside the expected or valid range. ```solidity=175 require(_stakingDefinition.withdrawFeePercentage <= 100, "withdraw perct too big"); require(_stakingDefinition.rate <= 1000, "rate too big"); ```
Open the reportThe cited address(`treasury`) input is missing a check that it is not `address(0)`.
Open the reportSigned messages do not include the current chain ID, thus allowing attackers to perform replay attacks across chains when the launchpad are deployed on the other chains with the same address. ```solidity=121 bytes32 signedMessageHash = keccak256(abi.encode(address(this), user)).toEthSignedMessageHash(); ``` ```solidity=473 bytes32 signedMessageHash = keccak256(abi.encode(address(this), user, whitelistedAmount)).toEthSignedMessageHash(); ```
Open the reportThe `createVestings` function is being used to create vesting for the user. And the user reserves the grace period to request the refund via `requestRefund` function. ```solidity=223 require(block.timestamp <= (startDateAt + refundGracePeriodDuration), "refund period passed"); ``` However, since there is no time restriction on `createVestings`, the user may not always allow refunding the vesting.
Open the reportBased on the comments in Helper contract, the weights for tiers are for IDO snapshot purposes (which is not in the current scope). And based on the test, the weight for the previous tier should always be less than the following tiers, similar to the `amountNeeded` value. However, such validation is not implemented in the current codebase.
Open the reportIn the withdraw function, it is already checked whether the `rewardBalance` of the contract is greater than the user reward. ```solidity=431 require(rewardBalance >= reward, "rewardBalance is too low"); ``` ```solidity=439 require(rewardBalance >= reward, "rewardBalance less than reward"); ```
Open the reportThe new mapping `tiersInitialization` is adding in the Helper contract in the updated codebase. However, this mapping is never used.
Open the reportIn the function `_buy()`, the `stablecoin.safeTransferFrom` is performed before updates to contract states. In the function `stake()`, the `tokenAddress.safeTransferFrom` is performed before updates to state(user deposit). In the function `addReward()`, the `tokenAddress.safeTransferFrom` is is performed before updates to state(reward balance).
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="ordify"></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