CertiK reviewed ACENT (ACENT Mainnet) on 15 Nov 2022: 47 findings, 1 critical; 9 marked fixed, 38 open.
The original report was removed from its address (seen 17 Oct 2026).
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 1 |
| High | 12 | 0 | 0 |
| Medium | 0 | 0 | 1 |
| Low | 26 | 0 | 7 |
File: ADEVault.sol The linked statement transfers the withdrawal/performance fee valued in the `ADE` token to the `treasury`. As a result, over time the `treasury` will accumulate a significant portion of `ADE` tokens. If the `treasury` is an EOA (Externally Owned Account), mishandling its private key can have devastating consequences for the project as a whole.
In the contract `AcentFactory` the role `feeToSetter` has authority over the functions shown in the diagram below. Any compromise to the `feeToSetter` account may allow the hacker to take advantage of this authority. 
In the contract `AcentPair` the role `factory` has authority over the functions shown in the diagram below. Any compromise to the `factory` account may allow the hacker to take advantage of this authority. 
In the contract `ADEInitMintable` 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. 
In the contract `ADEToken` 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. 
In the contract `ADEVault` 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.  In the contract `ADEVault` the role `admin` has authority over the functions shown in the diagram below. Any compromise to the `admin` account may allow the hacker to take advantage of this authority. 
In the contract `FundDistributor` the role `admin` has authority over the functions shown in the diagram below. Any compromise to the `admin` account may allow the hacker to take advantage of this authority. 
In the contract `Spica` 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. 
In the contract `Supercluster` 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. 
In the contract `Timelock` the role `admin` has authority over the functions shown in the diagram below. Any compromise to the `admin` account may allow the hacker to take advantage of this authority.  In the contract `Timelock` the role `pendingAdmin` has authority over the functions shown in the diagram below. Any compromise to the `pendingAdmin` account may allow the hacker to take advantage of this authority. 
In the contract `Virgo` 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.  In the contract `Virgo` the role `devaddr` has authority over the functions shown in the diagram below. Any compromise to the `devaddr` account may allow the hacker to take advantage of this authority. 
In the contract `VirgoAdmin` 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. 
File: Virgo.sol When the same LP token is added into a pool more than once in the function `add()`, the total amount of reward in the function `updatePool()` will be incorrectly calculated. The current implementation is relying on the operation correctness to avoid repeatedly adding the same LP token to the pool, as the function will only be called by the owner.
File: ADEVault.sol The order of external call/transfer and storage manipulation must follow the check-effect-interaction pattern in the following functions: - `withdraw()`
File: Virgo.sol The order of external call/transfer and storage manipulation must follow the check-effect-interaction pattern in the following functions: - `deposit()` - `withdraw()` - `enterStaking()` - `leaveStaking()` - `emergencyWithdraw()`
File: WACE.sol Any invocation of `transfer(recipient, amount)` must fail if it causes the balance of the `recipient` address to overflow.
File: WACE.sol Any invocation of `transfer(recipient, amount)` must fail if it causes the balance of the `recipient` address to overflow.
File: WACE.sol Any call of the form `transfer(recipient, amount)` must fail if the recipient address is the zero address.
File: WACE.sol Any call of the form `transfer(recipient, amount)` must fail if the recipient address is the zero address.
File: WACE.sol All calls of the form `transferFrom(from, dest, amount)` where the `from` address is zero, must fail.
File: WACE.sol All calls of the form `transferFrom(from, dest, amount)` where the `from` address is zero, must fail.
File: WACE.sol All calls of the form `transferFrom(from, dest, amount)` where the `dest` address is zero, must fail.
File: WACE.sol All calls of the form `transferFrom(from, dest, amount)` where the `dest` address is zero, must fail.
File: WACE.sol Any call of `transferFrom(from, dest, amount)` with a value in `amount` whose transfer would cause an overflow of the balance of address `dest` must fail.
File: WACE.sol Any call of `transferFrom(from, dest, amount)` with a value in `amount` whose transfer would cause an overflow of the balance of address `dest` must fail.
`public` functions that are never called by the contract could be declared as `external`. `external` functions are more efficient than `public` functions.
File: ADERouter.sol When users add or remove LP tokens into the router, and the `mint` and `burn` operations are performed. When transferring standard ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged transaction fee. As a result, the amount inconsistency will occur and the transaction may fail due to the validation checks.
File: Virgo.sol The contract `MasterChef` operates as the main entry for interaction with staking users. The staking users deposit LP tokens into the `AcentSwap` pool and in return get a proportionate share of the pool’s rewards. Later on, the staking users can withdraw their own assets from the pool. In this procedure, the functions `deposit()` and `withdraw()` are involved in transferring users’ assets into (or out of) the `AcentSwap` protocol. When transferring standard ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged (and burned) transaction fee. As a result, this may not meet the assumption behind these low-level asset-transferring routines and will bring unexpected balance inconsistencies.
The linked statement at L135 will cause data copy operation from `memory` to `storage` space and need more gas fee to execute, however, it is unnecessarily executed if the values of `preAllocPoint` and `_allocPoint` are the same.
File: Virgo.sol There's no sanity check to validate if a pool exists.
File: Supercluster.sol The given input is missing the check for the array size.
Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=18 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapExactTokensForTokens.selector, amountIn, amountOutMin, path, to, deadline )); ``` - `router` is not zero-checked before being used. --- ```solidity=28 feeToSetter = _feeToSetter; ``` - `_feeToSetter` is not zero-checked before being used. --- ```solidity=33 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapTokensForExactTokens.selector, amountOut, amountInMax, path, to, deadline )); ``` - `router` is not zero-checked before being used. --- ```solidity=47 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapExactETHForTokens.selector, amountOutMin, path, to, deadline )); ``` - `router` is not zero-checked before being used. --- ```solidity=48 disliked = _validator; ``` - `_validator` is not zero-checked before being used. --- ```solidity=54 feeTo = _feeTo; ``` - `_feeTo` is not zero-checked before being used. --- ```solidity=59 feeToSetter = _feeToSetter; ``` - `_feeToSetter` is not zero-checked before being used. --- ```solidity=62 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapTokensForExactETH.selector, amountOut, amountInMax, path, to, deadline )); ``` - `router` is not zero-checked before being used. --- ```solidity=77 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapExactTokensForETH.selector, amountIn, amountOutMin, path, to, deadline )); ``` - `router` is not zero-checked before being used. --- ```solidity=78 token0 = _token0; ``` - `_token0` is not zero-checked before being used. --- ```solidity=79 token1 = _token1; ``` - `_token1` is not zero-checked before being used. --- ```solidity=91 (bool success, bytes memory returnData) = router.delegatecall(abi.encodeWithSelector( IADERouter01(router).swapETHForExactTokens.selector, amountOut, path, to, deadline )); ``` - `router` is not zero-checked before being used.
The linked variables are assigned only once, either during their contract-level declaration or during the `constructor`'s execution.
The linked variables are assigned only once, either during their contract-level declaration or during the `constructor`'s execution.
File: Multicall2.sol Anyone can call the two functions `aggregate()` and `tryAggregate()` because they don't have access limitations. The attackers may successfully access such the `onlyOwner/onlyAdmin` functions of the target contract with the malicious `callData` if the `Muticall2` contract is set to be the `owner/admin` of the `target` contract. In this case, the contract is attacked.
File: Virgo.sol The `owner` can set the `migrator` to any contract that implements the `IMigratorChef` interface via the function `setMigrator()`. Therefore, calling `migrator.migrate()` in the function `migrate()` may have dangerous implications, since it is unknown to the user. However, if `setMigrator()` and `migrate()` are removed, the project may lose the ability to upgrade and migrate.
The contract has unlocked compiler version. An unlocked compiler version in the source code of the contract permits the user to compile it at or above a particular version. This, in turn, leads to differences in the generated bytecode between compilations due to differing compiler version numbers. This can lead to an ambiguity when debugging as compiler specific bugs may occur in the codebase that would be hard to identify over a span of multiple compiler versions rather than a specific one.
File: Virgo.sol The linked state variable is never used within the `Virgo` contract.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (40)
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