Quantstamp reviewed Voyager (Voyager Token) on 12 Feb 2021: 10 findings, 0 critical; 6 marked fixed, 2 acknowledged, 2 open.
Report hosted on certificate.quantstamp.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 | 0 | 2 |
| Medium | 0 | 0 | 2 |
| Low | 2 | 2 | 2 |
According to the ERC20 standard the `transfer` and `transferFrom` functions return `true` if the transfer was successful and `false` otherwise. These functions do not need to revert if the transfer is not successful. However, `TokenSwap.swap(uint256)` ignores return value by `fromToken.transferFrom(msg.sender,burnAddress,fromAmount)` on L54. Since `fromToken` is an arbitrary IERC20 (which was not in the scope of this audit), one cannot assume anything about how that token may fail.
The logic in `_stake`, `_unstake`, `_accrueInterest` and `_calculateAccruedInterest` is not properly documented. The specification does not mention anything related to accrued interest; hence, there is no reference to match against the implemented code. Moreover, the mathematical relations for computing the total amount of shares when staking and unstaking is not documented. As a consequence, one cannot tell if the implementation is indeed correct and fulfils the intended behavior. This may have a significant impact on end-users.
Integer overflow/underflow occur when an integer hits its bit-size limit. Every integer has a set range; when that range is passed, the value loops back around. A clock is a good analogy: at 11:59, the minute hand goes to 0, not 60, because 59 is the largest possible minute. <br><br> The addition on L64 of `StakingToken` may overflow since there is no hard cap on the total token supply: ``` return totalSupply() + _stakingContract.totalUnmintedInterest(); ```
The following functions are missing input parameter validations: 1. `StakeToken.init` does not check if its input parameters of type `address` are different from `address(0)`. 2. `StakeToken.mint` does not check if its input parameter of type `address` is different from `address(0)`. It also does not check if the value of `amount` is higher than `0`. 3. `Staking.constructor` does not check if its input parameter of type `address` is different from `address(0)`. It also does not check if the values of its `uint256` parameters are higher than `0`. Also the timestamp parameter is not checked and could be in the past. 4. `Staking.stake` does not check if its `amount` is higher than `0`. 5. `Staking.stakeFor` does not check if its `user` is different than `address(0)` and does not check if `amount` is higher than `0`. 6. `Staking.setInterestRate` does not check if its `newInterestRate` is higher than `0`. 8. `TokenSwap.constructor` does not check if its input parameters of type `address` are different from `address(0)`. It also does not check if the values of its `uint256` parameters are higher than `0`. 9. `TokenSwap.swap` does not check if the value of `fromAmount` is higher than `0`.
Presently, the `init` function in the `StakeToken` contract does not require the `minterAddresses` array to have a length greater than zero. If it has a length of zero, `StakeToken` will be deemed initialized, but will prevent minting from ever occurring, which defeats the purpose of the contract.
Every Solidity file specifies in the header a version number of the format `pragma solidity (^)0.7.*`. The caret (`^`) before the version number implies an unlocked pragma, meaning that the compiler will use the specified version _and above_, hence the term "unlocked".
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (8)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’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