CertiK reviewed OpenWorld (Open World) on 16 May 2023: 30 findings, 0 critical; 14 marked fixed, 6 acknowledged, 10 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 | 4 | 0 |
| Medium | 0 | 2 | 1 |
| Low | 10 | 0 | 13 |
In `OpenWorld.sol`, the contract inherits `ERC20PausableUpgradeable` and uses extensively the `whenNotPaused` modifier to prevent many functions from being called if the contract is paused. \ However, the contract does not implement any function allowing to set `_paused` as true. Therefore the contract is not pausable.
In `OpenWorld.sol`, the function `burn()` is the only function allowing any user to modify the state of the contract `OPEN` (under specific conditions) that is not pausable.
In `RewardRouterV2.sol`, the function `_unstakeOpen()` computes a `reductionAmount` to burn as follow: ```solidity=695 uint256 reductionAmount = stakedBnOpen.mul(_amount).div( balance ); ``` if `stakedBnOpen.mul(_amount) < balance` then the burnt amount will be zero.
In `OpenWorld.sol`, the state variable `stakerAddress` is defined and can be set to any address, however, it is never used.
Boolean constants can be used directly and do not need to be compared to true or false. --- ```solidity=45 require( tokenBlacklist[msg.sender] == false && tokenBlacklist[_to] == false, "Blacklist address cannot transfer" ); ``` --- ```solidity=50 require( isContractTransferBlock(msg.sender, _to) == false, "This address cannot send to ContractBlacklist Address" ); ``` --- ```solidity=54 require( isContractTransferBlock(_to, msg.sender) == false, "This address cannot receive from ContractBlacklist Address" ); ``` --- ```solidity=81 require( tokenBlacklist[_from] == false && tokenBlacklist[_to] == false, "Blacklist address cannot transfer" ); ``` --- ```solidity=86 require( tokenBlacklist[msg.sender] == false, "Blacklist address cannot transfer" ); ``` --- ```solidity=91 require( isContractTransferBlock(_from, _to) == false, "This address cannot send to ContractBlacklist Address" ); ``` --- ```solidity=95 require( isContractTransferBlock(_to, _from) == false, "This address cannot receive from ContractBlacklist Address" ); ```
In `OpenWorld.sol`, the function `transferFrom()` performs two checks returning the same error message: ```solidity=81 require( tokenBlacklist[_from] == false && tokenBlacklist[_to] == false, "Blacklist address cannot transfer" ); require( tokenBlacklist[msg.sender] == false, "Blacklist address cannot transfer" ); ```
In `OpenWorld.sol`, the function `initialize()` takes an address as a parameter named `owner_`. This parameter will be used to set the `feeAddress` and will receive all the `INITIAL_SUPPLY`. \ `OwnableUpgradeable.__Ownable_init();` will set the initializer address as the `owner` of the contract. The name `owner_` could lead one to think that the address provided will be the owner of the contract when it is not the case.
In `OpenWorld.sol`, There are no upper boundaries for `setSellFeeRate()`, it is possible to set `sellFeeRate` up to any arbitrary amount. \ However, if `sellFeeRate > 1000` then `getValuesWithSellRate()` might fail unexpectedly, preventing `transfer()` and `transferFrom()` to work correctly. ----- In `OpenStaking.sol`, there are no upper boundaries for `setUnstakingThreshold()`, it is possible to set `unstakingThreshold` up to any arbitrary value. \ If `unstakingThreshold` is set to a very high value then `unstake()` will fail before the threshold is passed, preventing users from unstaking their tokens.
In `RewardRouterV2.sol`, the function `batchStakeOpenForAccount()` does not check that `_accounts` and `_amounts` have the same length.
The **require** can be used to check for conditions and throw an exception if the condition is not met. It is better to provide a string message containing details about the error that will be passed back to the caller.
In `OapRouter.sol`, the function `swapAndStake()` does not require any type of whitelisting for `tokenIn`. A malicious contract could be given as input. Moreover, some legit contracts could interfere with the logic of the functions, for example, deflationary tokens will not work well with `swapExactTokensForTokens()`.
The mathematical expression does not check arithmetic overflow. Such unsafe math operations may cause unexpected behavior if unusual parameters are given. Here `depositToken` is set when deploying the contract, hence it is not possible to guarantee the logic of the ERC20 will interact safely with `OpenStaking`.
```solidity=24 event Mint(address indexed from, address indexed to, uint256 value); ``` - `Mint` is declared in `OPEN` but never emitted. --- ```solidity=25 event Burn(address indexed burner, uint256 value); ``` - `Burn` is declared in `OPEN` but never emitted.
In `OpenWorld.sol`, the mapping `_nextClaimTime` is private and never used in the contract `OPEN`. ```solidity=15 mapping(address => uint256) private _nextClaimTime; ```
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (6)
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