CertiK reviewed DIN on 14 Jan 2025: 19 findings, 0 critical; 4 marked fixed, 4 acknowledged, 11 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 3 | 1 |
| Medium | 0 | 1 | 1 |
| Low | 11 | 0 | 2 |
When calculating rewards for a specific `tokenId` in the `NFTAirdrop` contract, its corresponding `powerLevel` is determined based on the `tokenId`. Each level has unique reward release methods. If multiple `tokenIds` share the same `powerLevel`, this could lead to rewards being incorrectly calculated, potentially causing claims to exceed the intended allocation for that `powerLevel`.
Initializer functions invoked separately from contract creation, such as in minimal proxies, may be reentered if they make an untrusted non-view external call. This reentrancy can lead to unexpected behaviors, breaking the expectation of a single execution.
The `stake()` functions attempt to ensure the successful transfer of ERC20 tokens by checking the return value of the `transfer()`/`transferFrom()` function. It assumes that `transfer()`/`transferFrom()` returns a `bool` indicating success or failure. However, some non-standard ERC20 tokens, such as [OMG](https://etherscan.io/address/0xd26114cd6ee289accf82350c8d8487fedb8a0c07#code#L97) and [USDT](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#code#L340), do not return a `bool` for the `transfer()`/`transferFrom()` function. This discrepancy can cause the function to fail, leading to tokens being locked within the contract.
In contracts `NodeStakingConvertor` and `xDINConverting`, users can claim native tokens, however, the comments and related function names, such as in the following code, refer to `DIN` token. ```solidity // How much xDIN in exchange for // return how much DIN function depositXDIN(uint256 xDINAmount) public returns (uint256) { uint256 DINRewardAmount = estiamteExchangeDINAmount(xDINAmount); IERC20(xDINAddress).transferFrom(_msgSender(), address(this), xDINAmount); IERC20Authorized(xDINAddress).burn(xDINAmount); // mint DIN reward addClaim(_msgSender(), DINRewardAmount, nextClaimId); nextClaimId += 1; return DINRewardAmount; } ```
The `stake` function in the **CurveStaking** contract is responsible for allowing users to deposit a specific `amount` of tokens for staking. However, if the `amount` is not properly validated, it can lead to two potential issues: If a user stakes an extremely small `amount`, the resulting weight (`amount * time`) may become negligible due to the limitations of integer precision in Solidity (e.g., if the result rounds down to `0`).This can cause the user's shares of staking weight to be effectively `0`, making them ineligible to receive any rewards. Additionally, if a user stakes an extremely large `amount`, the calculation of `amount * time` (used to compute the user's staking weight) may exceed the maximum value that can be stored in a `uint256` variable, potentially causing an integer overflow or preventing more users to stake.
There should always be events emitted in the sensitive functions that are controlled by centralization roles.
The `requestClaim()` function in the `NodeStakingConvertor` contract does not validate the length of the provided `nftIds`. Even if the `nftIds` array is empty, the function will still create a `ClaimSchedule` for `msg.sender` and allocate the `nextClaimId`, leading to unnecessary gas consumption.
In the `depositXDIN()` function of `xDINConverting` contract, user rewards are calculated based on the provided `xDIN` amount, followed by burning the transferred tokens. However, due to the absence of `DINRewardAmount` verification, the function burns the user's tokens even when the calculated `DINRewardAmount` is zero.
The cited address input is missing a check that it is not `address(0)`.
The change of `owner` by function `transferOwnership()` overrides the previously set `owner` with the new one without guaranteeing the new `owner` has the ability to actuate transactions on-chain.
The `CurveStaking` logic contract does not protect the initializer. An attacker can front-run the `initialize` call and assume ownership of the logic contract. Once in control, the attacker can perform privileged operations, misleading users into believing that they are interacting with the legitimate owner of the upgradeable contract.
| Address | Chain | Source code |
|---|---|---|
| 0x3ab1…da4e0x3ab1a5f76e12202d1ad1548a08a799501581da4e | Chain: BNB Chain | Source code: Verified source |
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething 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