CertiK reviewed AIDOGE (ArbDoge AI) on 20 Jul 2023: 22 findings, 1 critical; 9 marked fixed, 13 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 | 1 |
| High | 2 | 0 | 2 |
| Medium | 0 | 0 | 0 |
| Low | 11 | 0 | 6 |
```solidity=305 function emergencyRewardWithdraw(uint256 _amount) public onlyOwner { require(_amount <= rewardToken.balanceOf(address(this)), 'DogeBonusPool: not enough token'); rewardToken.safeTransfer(address(msg.sender), _amount); } ``` The `emergencyRewardWithdraw()` function allows the contract owner to withdraw reward tokens. In the [deployed `DogeBonusPool` contract](https://arbiscan.io/address/0x5845696f6031bfd57b32e6ce2ddea19a486fa5e5#readContract), AIDOGE tokens are used as both deposit tokens and reward tokens. If the owner's account is compromised by a hacker, the hacker could potentially withdraw all user deposits using this function.
In the contract `AIDoge` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and update critical state variables to damage the tokenomics. 
The contract `DogeBonusPool` is used for users to stake pool tokens in order to earn `rewardToken`. As of April 23, 2023 8:30:15 PM (GMT + 0), the [deployed `DogeBonusPool`](https://arbiscan.io/address/0x5845696f6031bfd57b32e6ce2ddea19a486fa5e5#readContract) allows users to stake AIDOGE tokens and earn `rewardToken` which is also AIDOGE token. The expected rewards can be calculated as the product of the pool's `RewardsPerSecond` and the total reward period, which equals 6992930980883225239092 Wei or approximately 7000 Ether. However, the actual rewards, calculated by deducting the total deposit from `DogeBonusPool`'s balance of AIDOGE token, amount to 4384909523570706133135 Wei or approximately 4400 Ether. The discrepancy between these two values indicates that a portion of the rewards (about 2600 Ether of AIDOGE) is paid from other users' deposits.
Reading, initializing, and modifying storage variables cost more gas than operating local variables, and this gas cost can significantly increase when these operations are performed inside a loop. Reference: https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack ```solidity=127 totalRewards = totalRewards.add(epochReward); ```
In the `add()` and `set()` functions, the flag '_withUpdate' determines if all the pools will be updated. This reliance might lead to significant loss of the reward.
```solidity=125 function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { if (_withUpdate) { massUpdatePools(); } totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); poolInfo[_pid].allocPoint = _allocPoint; } ``` The `set()` function allows the owner to update a pool's `allocPoint`, which determines the proportion of total rewards the pool receives. However, the function does not check if the pool has been added. If `_pid` is equal to or greater than the number of valid pools, an invalid pool with `_pid` may be allocated rewards, causing other pools to lose rewards.
```solidity=191 require(_amount.add(user.amount) <= maxStakingPerUser, 'DogeBonusPool: exceed max stake'); ``` The `deposit()` function in the contract is used for users to deposit tokens. `_amount` represents the tokens that the user is transferring from their wallet, and `user.amount` represents the amount of tokens a user has already deposited. The check in the code requires the sum of `_amount` and `user.amount` to be smaller or equal to `maxStakingPerUser`, which represents the maximum amount of tokens that a user can deposit. However, if the token is deflationary, the contract may receive fewer tokens than the specified `_amount`. This can lead to deposit failures that should have been successful, as the total deposit does not exceed the `maxStakingPerUser` limit.
The return values of the `transfer()` calls in the smart contract are not checked. Some ERC-20 tokens' transfer functions return no values, while others return a bool value, they should be handled with care. If a function returns `false` instead of reverting upon failure, an unchecked failed transfer could be mistakenly considered successful in the contract. ```solidity=212 backToken.transfer(gov1Wallet, amountBackTokenGov1); ``` --- ```solidity=213 backToken.transfer(gov2Wallet, amountBackTokenGov2); ``` --- ```solidity=214 backToken.transfer(address(jackpotWallet), amountBackTokenJackpot); ``` --- ```solidity=215 backToken.transfer(devWallet, amountBackTokenDev); ``` --- ```solidity=304 backToken.transfer(_msgSender(), backToken.balanceOf(address(this))); ```
The contract has a `startTime` state variable, which is intended to represent the start time for users to burn tokens. However, users are able to call the `burn()` function to burn tokens before the startTime has been reached and share rewards.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (5)
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