Hyperswap Smart Contract Audit
Hyperswap Smart Contract Audit
Hyperswap
Smart Contract Security Audit
Description 16
Code Location 16
Risk Level 17
Recommendation 17
Remediation Plan 17
Description 18
Code Location 18
Risk Level 22
Recommendation 22
Remediation Plan 22
Description 23
1
Code Location 23
Risk Level 23
Recommendation 24
Remediation Plan 24
Description 25
Code Location 25
Risk Level 25
Recommendation 26
Remediation Plan 26
Description 27
Code Location 27
Recommendations 28
Remediation Plan 28
Description 29
Code Location 29
Risk Level 30
Recommendation 30
Remediation Plan 30
Description 31
Code Location 31
Risk Level 33
2
Recommendation 33
Reference 33
Remediation Plan 33
Description 34
Code Location 34
Risk Level 35
Recommendation 35
Remediation Plan 35
Description 36
Code Location 36
Risk Level 38
Recommendation 38
Remediation Plan 38
Description 39
Code Location 39
Risk Level 41
Recommendation 41
Remediation Plan 42
Description 43
Code Location 43
3
Risk Level 43
Recommendations 43
Remediation Plan 44
Description 45
Code Location 45
Risk Level 46
Recommendation 46
References 46
Remediation Plan 46
Description 47
Code Location 47
Risk Level 47
Recommendations 48
Remediation Plan 48
Description 49
Code Location 49
Risk Level 49
Recommendations 50
Remediation Plan 50
Description 51
Code Location 51
Risk Level 52
4
Recommendations 52
Remediation Plan 52
Description 53
Code Location 53
Risk Level 54
Recommendation 54
Remediation Plan 54
Description 55
Code Location 55
Risk Level 55
Recommendations 56
Remediation Plan 56
Description 57
Code Location 57
Risk Level 57
Recommendations 57
Remediation Plan 57
Description 58
Code Location 58
Risk Level 59
Recommendation 59
5
Remediation Plan 59
4 AUTOMATED TESTING 60
4.1 STATIC ANALYSIS REPORT 61
Description 61
Results 61
4.2 AUTOMATED SECURITY SCAN 65
Description 65
Results 65
6
DOCUMENT REVISION HISTORY
CONTACTS
7
EXECUTIVE OVERVIEW
8
1.1 INTRODUCTION
Spherium engaged Halborn to conduct a security assessment on their Hyper-
swap smart contracts beginning on September 16th, 2021 and ending October
1st, 2021. This security assessment was scoped to the Hyperswap smart
contracts code in Solidity.
9
flaws in logic, process,and implementation; automated testing techniques
help enhance coverage of the Spherium contract solidity code and can
quickly identify items that do not follow security best practices. The
following phases and associated tools were used throughout the term of
the audit:
RISK METHODOLOGY:
10
2 - Low probability of an incident occurring.
1 - Very unlikely issue will cause an incident.
The risk level is then calculated using a sum of these two values, creating
a value of 10 to 1 with 10 being the highest level of security risk.
10 - CRITICAL
9 - 8 - HIGH
7 - 6 - MEDIUM
5 - 4 - LOW
3 - 1 - VERY LOW AND INFORMATIONAL
EXECUTIVE OVERVIEW
11
1.4 SCOPE
IN-SCOPE : Hyperswap github repository
The security assessment was scoped to the following smart contract:
Listing 1: Hyperswap-Contract
1 core - bsc / contracts /
2 periphery - bsc / contracts /
3 governance / contracts /
4 rewards / contracts /
12
2. ASSESSMENT SUMMARY & FINDINGS
OVERVIEW
0 0 1 13 5
LIKELIHOOD
(HAL-02)
(HAL-03)
(HAL-01)
(HAL-04)
(HAL-06)
IMPACT
(HAL-05)
(HAL-07)
(HAL-11) (HAL-09)
EXECUTIVE OVERVIEW
(HAL-10)
(HAL-12)
(HAL-15)
(HAL-13)
(HAL-16) (HAL-08)
(HAL-14)
(HAL-17)
(HAL-18)
(HAL-19)
13
SECURITY ANALYSIS RISK LEVEL REMEDIATION DATE
14
FINDINGS & TECH
DETAILS
15
3.1 (HAL-01) UNCHECKED TRANSFER -
MEDIUM
Description:
Code Location:
16
118 address tokenB ,
119 uint liquidity ,
120 uint amountAMin ,
121 uint amountBMin ,
122 address to ,
123 uint deadline
124 ) public virtual override ensure ( deadline ) returns ( uint
amountA , uint amountB ) {
125 address pair = SpheriumLibrary . pairFor ( factory , tokenA ,
tokenB );
126 ISpheriumPair ( pair ). transferFrom ( msg . sender , pair ,
liquidity ) ; // send liquidity to pair
127 ( uint amount0 , uint amount1 ) = ISpheriumPair ( pair ). burn ( to
);
Risk Level:
Likelihood - 2
Impact - 4
Recommendation:
FINDINGS & TECH DETAILS
Remediation Plan:
17
3.2 (HAL-02) MANIPULATION OF
INITIAL TOKEN ADDRESSES - LOW
Description:
Code Location:
64 }
65
66 // called once by the factory at time of deployment
67 function initialize ( address _token0 , address _token1 ) external
{
68 require ( msg . sender == factory , ' Spherium : FORBIDDEN '); //
sufficient check
69 token0 = _token0 ;
70 token1 = _token1 ;
71 }
18
112 ( uint112 _reserve0 , uint112 _reserve1 ,) = getReserves () ;
// gas savings
113 uint balance0 = IERC20 ( token0 ). balanceOf ( address ( this ) ) ;
114 uint balance1 = IERC20 ( token1 ). balanceOf ( address ( this ) ) ;
115 uint amount0 = balance0 . sub ( _reserve0 ) ;
116 uint amount1 = balance1 . sub ( _reserve1 ) ;
117
118 bool feeOn = _mintFee ( _reserve0 , _reserve1 ) ;
119 uint _totalSupply = totalSupply ; // gas savings , must be
defined here since totalSupply can update in _mintFee
120 if ( _totalSupply == 0) {
121 liquidity = Math . sqrt ( amount0 . mul ( amount1 ) ) . sub (
MINIMUM_LIQUIDITY );
122 _mint ( address (0) , MINIMUM_LIQUIDITY ); // permanently
lock the first MINIMUM_LIQUIDITY tokens
123 } else {
124 liquidity = Math . min ( amount0 . mul ( _totalSupply ) /
_reserve0 , amount1 . mul ( _totalSupply ) / _reserve1 );
125 }
126 require ( liquidity > 0 , ' Spherium :
INSUFFICIENT_LIQUIDITY_MINTED ');
127 _mint ( to , liquidity ) ;
128
129 _update ( balance0 , balance1 , _reserve0 , _reserve1 ) ;
FINDINGS & TECH DETAILS
19
144 uint _totalSupply = totalSupply ; // gas savings , must be
defined here since totalSupply can update in _mintFee
145 amount0 = liquidity . mul ( balance0 ) / _totalSupply ; // using
balances ensures pro - rata distribution
146 amount1 = liquidity . mul ( balance1 ) / _totalSupply ; // using
balances ensures pro - rata distribution
147 require ( amount0 > 0 && amount1 > 0 , ' Spherium :
INSUFFICIENT_LIQUIDITY_BURNED ');
148 _burn ( address ( this ) , liquidity ) ;
149 _safeTransfer ( _token0 , to , amount0 ) ;
150 _safeTransfer ( _token1 , to , amount1 ) ;
151 balance0 = IERC20 ( _token0 ) . balanceOf ( address ( this )) ;
152 balance1 = IERC20 ( _token1 ) . balanceOf ( address ( this )) ;
153
154 _update ( balance0 , balance1 , _reserve0 , _reserve1 ) ;
155 if ( feeOn ) kLast = uint ( reserve0 ). mul ( reserve1 ); //
reserve0 and reserve1 are up - to - date
156 emit Burn ( msg . sender , amount0 , amount1 , to ) ;
157 }
158
159 // this low - level function should be called from a contract
which performs important safety checks
160 function swap ( uint amount0Out , uint amount1Out , address to ,
bytes calldata data ) external lock {
FINDINGS & TECH DETAILS
20
174 balance0 = IERC20 ( _token0 ) . balanceOf ( address ( this )) ;
175 balance1 = IERC20 ( _token1 ) . balanceOf ( address ( this )) ;
176 }
177 uint amount0In = balance0 > _reserve0 - amount0Out ?
balance0 - ( _reserve0 - amount0Out ) : 0;
178 uint amount1In = balance1 > _reserve1 - amount1Out ?
balance1 - ( _reserve1 - amount1Out ) : 0;
179 require ( amount0In > 0 || amount1In > 0 , ' Spherium :
INSUFFICIENT_INPUT_AMOUNT ') ;
180 { // scope for reserve {0 ,1} Adjusted , avoids stack too deep
errors
181 uint balance0Adjusted = balance0 . mul (1000) . sub ( amount0In .
mul (3) ) ;
182 uint balance1Adjusted = balance1 . mul (1000) . sub ( amount1In .
mul (3) ) ;
183 require ( balance0Adjusted . mul ( balance1Adjusted ) >= uint (
_reserve0 ) . mul ( _reserve1 ). mul (1000**2) , ' Spherium : K ');
184 }
185
186 _update ( balance0 , balance1 , _reserve0 , _reserve1 ) ;
187 emit Swap ( msg . sender , amount0In , amount1In , amount0Out ,
amount1Out , to ) ;
188 }
189
FINDINGS & TECH DETAILS
21
Risk Level:
Likelihood - 1
Impact - 4
Recommendation:
Remediation Plan:
NOT APPLICABLE: The Spherium team claims that factory contract can
initialize the token0 and token1, but it cannot change the token0 and
token1 variables for the second time.
FINDINGS & TECH DETAILS
22
3.3 (HAL-03) MISSING RE-ENTRANCY
PROTECTION - LOW
Description:
Code Location:
Risk Level:
Likelihood - 1
Impact - 4
23
Recommendation:
Remediation Plan:
NOT APPLICABLE: The Spherium team claims that due to their use of lock
modifier in pair contract suffice reentrancy protection.
FINDINGS & TECH DETAILS
24
3.4 (HAL-04) MULTIPLE CALLS MAY
LEADS TO DENIAL OF SERVICE(DOS) -
LOW
Description:
Code Location:
Risk Level:
Likelihood - 1
Impact - 4
25
Recommendation:
If possible, refactoring the code such that each transaction only executes
one external calls or make sure that all calls can be trusted (i.e. they’re
part of your own codebase).
Remediation Plan:
26
3.5 (HAL-05) INCOMPATIBILITY WITH
INFLATIONARY TOKENS - LOW
Description:
Code Location:
Listing 8: periphery-bsc/contracts/SpheriumRouter01.sol
1 TransferHelper . safeTransferFrom ( tokenA , msg . sender , pair , amountA )
;
2 TransferHelper . safeTransferFrom ( tokenB , msg . sender , pair , amountB )
;
3 TransferHelper . safeTransferFrom ( token , msg . sender , pair ,
amountToken );
4 TransferHelper . safeTransferFrom ( path [0] , msg . sender ,
SpheriumLibrary . pairFor ( factory , path [0] , path [1]) , amounts [0])
;
5 TransferHelper . safeTransfer ( token , to , amountToken ) ;
Listing 9: periphery-bsc/contracts/SpheriumRouter02.sol
1 TransferHelper . safeTransferFrom ( tokenA , msg . sender , pair , amountA )
;
27
2 TransferHelper . safeTransferFrom ( tokenB , msg . sender , pair , amountB )
;
3 TransferHelper . safeTransferFrom ( token , msg . sender , pair ,
amountToken );
4 TransferHelper . safeTransferFrom ( path [0] , msg . sender ,
SpheriumLibrary . pairFor ( factory , path [0] , path [1]) , amounts [0])
;
5 TransferHelper . safeTransferFrom ( path [0] , msg . sender ,
SpheriumLibrary . pairFor ( factory , path [0] , path [1]) , amountIn );
6 TransferHelper . safeTransfer ( token , to , amountToken ) ;
7 TransferHelper . safeTransfer ( token , to , IERC20 ( token ). balanceOf (
address ( this ) )) ;
Recommendations:
Remediation Plan:
FINDINGS & TECH DETAILS
28
3.6 (HAL-06) WEAK PSEUDO-RANDOM
NUMBER GENERATOR - LOW
Description:
Code Location:
29
Risk Level:
Likelihood - 1
Impact - 4
Recommendation:
Remediation Plan:
30
3.7 (HAL-07) EXTERNAL FUNCTION
CALLS WITHIN LOOP - LOW
Description:
Code Location:
output );
172 uint amountOut = amounts [ i + 1];
173 ( uint amount0Out , uint amount1Out ) = input == token0 ?
( uint (0) , amountOut ) : ( amountOut , uint (0) ) ;
174 address to = i < path . length - 2 ? SpheriumLibrary .
pairFor ( factory , output , path [i + 2]) : _to ;
175 ISpheriumPair ( SpheriumLibrary . pairFor ( factory , input ,
output )) . swap ( amount0Out , amount1Out , to , new bytes
(0) );
176 }
177 }
31
227 ( address input , address output ) = ( path [i ] , path [i +
1]) ;
228 ( address token0 ,) = SpheriumLibrary . sortTokens ( input ,
output );
229 uint amountOut = amounts [ i + 1];
230 ( uint amount0Out , uint amount1Out ) = input == token0 ?
( uint (0) , amountOut ) : ( amountOut , uint (0) ) ;
231 address to = i < path . length - 2 ? SpheriumLibrary .
pairFor ( factory , output , path [i + 2]) : _to ;
232 ISpheriumPair ( SpheriumLibrary . pairFor ( factory , input ,
output )) . swap (
233 amount0Out , amount1Out , to , new bytes (0)
234 );
235 }
32
356 pair . swap ( amount0Out , amount1Out , to , new bytes (0) ) ;
357 }
358 }
Risk Level:
Likelihood - 2
Impact - 3
Recommendation:
Reference:
Remediation Plan:
FINDINGS & TECH DETAILS
33
3.8 (HAL-08) IGNORE RETURN VALUES -
LOW
Description:
Code Location:
30 address tokenA ,
31 address tokenB ,
32 uint amountADesired ,
33 uint amountBDesired ,
34 uint amountAMin ,
35 uint amountBMin
36 ) private returns ( uint amountA , uint amountB ) {
37 // create the pair if it doesn 't exist yet
38 if ( ISpheriumFactory ( factory ) . getPair ( tokenA , tokenB ) ==
address (0) ) {
39 ISpheriumFactory ( factory ) . createPair ( tokenA , tokenB );
40 }
34
51 uint amountAMin ,
52 uint amountBMin
53 ) internal virtual returns ( uint amountA , uint amountB ) {
54 // create the pair if it doesn 't exist yet
55 if ( ISpheriumFactory ( factory ) . getPair ( tokenA , tokenB ) ==
address (0) ) {
56 ISpheriumFactory ( factory ) . createPair ( tokenA , tokenB );
57 }
Risk Level:
Likelihood - 3
Impact - 2
Recommendation:
Add return value check to avoid unexpected crash of the contract. Return
value check will help in handling the exceptions better way.
FINDINGS & TECH DETAILS
Remediation Plan:
35
3.9 (HAL-09) MISSING ZERO-ADDRESS
CHECK - LOW
Description:
Code Location:
36
51 feeToSetter = _feeToSetter ;
52 }
37
Risk Level:
Likelihood - 2
Impact - 3
Recommendation:
Remediation Plan:
38
3.10 (HAL-10) USAGE OF
BLOCK-TIMESTAMP - LOW
Description:
Code Location:
39
81 price1CumulativeLast += uint ( UQ112x112 . encode (
_reserve0 ). uqdiv ( _reserve1 )) * timeElapsed ;
82 }
40
491 _lgeTimestamp = block . timestamp ;
492
493 if ( sender == _lgePairAddress && recipient !=
_lgePairAddress ) {
494 // buying
495
496 ( uint256 wlRoundNumber , , , , , ) =
getLGEWhitelistRound () ;
497
498 if ( wlRoundNumber > 0) {
499 WhitelistRound storage wlRound =
_lgeWhitelistRounds [ wlRoundNumber - 1];
Risk Level:
Likelihood - 2
Impact - 3
Recommendation:
41
Remediation Plan:
42
3.11 (HAL-11) FLOATING PRAGMA - LOW
Description:
Code Location:
Risk Level:
Likelihood - 1
Impact - 3
Recommendations:
Consider locking the pragma version with known bugs for the compiler
version. When possible, do not use floating pragma in the final live
deployment. Specifying a fixed compiler version ensures that the bytecode
produced does not vary between builds. This is especially important if
you rely on bytecode-level verification of the code.
43
Remediation Plan:
44
3.12 (HAL-12) OUTDATED
DEPENDENCIES - LOW
Description:
Code Location:
45
21 " dotenv " : " ^8.2.0 "
22 },
Risk Level:
Likelihood - 2
Impact - 3
Recommendation:
References:
Remediation Plan:
46
3.13 (HAL-13) PRAGMA VERSION
DEPRECATED - LOW
Description:
Code Location:
Listing 34
1 pragma solidity =0.6.6 ( contracts / SpheriumRouter01 . sol #1)
2 pragma solidity =0.6.6 ( contracts / interfaces / IERC20 . sol #1)
3 pragma solidity =0.6.6 ( contracts / interfaces / ISpheriumFactory .
sol #1)
4 pragma solidity =0.6.6 ( contracts / interfaces / ISpheriumPair . sol
FINDINGS & TECH DETAILS
#1)
5 pragma solidity =0.6.6 ( contracts / interfaces / ISpheriumRouter01
. sol #1)
6 pragma solidity =0.6.6 ( contracts / interfaces / IWETH . sol #1)
7 pragma solidity =0.6.6 ( contracts / libraries / SafeMath . sol #1)
8 pragma solidity =0.6.6 ( contracts / libraries / SpheriumLibrary .
sol #1)
9 pragma solidity >=0.6.0 ( contracts / libraries / TransferHelper .
sol #3)
Risk Level:
Likelihood - 2
Impact - 2
47
Recommendations:
If possible, consider using the latest stable pragma version that has
been thoroughly tested to prevent potential undiscovered vulnerabilities
such as pragma between 0.6.12 - 0.7.6.
Remediation Plan:
48
3.14 (HAL-14) MULTIPLE PRAGMA
DEFINITION - LOW
Description:
Code Location:
Risk Level:
Likelihood - 2
Impact - 2
49
Recommendations:
Consider lock and use single pragma version known bugs for the compiler
version.
Remediation Plan:
50
3.15 (HAL-15) USAGE OF
STRICT-EQUALITIES - INFORMATIONAL
Description:
Avoid checking for strict equality, use of strict equalities can be easily
manipulated by an attacker via selfdestruct() or by mining.
Code Location:
51
244 uint32 nCheckpoints ,
245 uint256 oldVotes ,
246 uint256 newVotes
247 )
248 internal
249 {
250 uint32 blockNumber = safe32 ( block . number , " SPHRI ::
_writeCheckpoint : block number exceeds 32 bits " );
251
252 if ( nCheckpoints > 0 && checkpoints [ delegatee ][
nCheckpoints - 1]. fromBlock == blockNumber ) {
253 checkpoints [ delegatee ][ nCheckpoints - 1]. votes =
newVotes ;
Risk Level:
Likelihood - 1
Impact - 2
Recommendations:
FINDINGS & TECH DETAILS
While these sections of code use it for totalSupply, and time validation.
Don’t use strict equality to determine if an account has enough Ether or
tokens.
Remediation Plan:
52
3.16 (HAL-16) USE OF INLINE
ASSEMBLY - INFORMATIONAL
Description:
Code Location:
33 assembly {
34 pair := create2 (0 , add ( bytecode , 32) , mload ( bytecode ) ,
salt )
35 }
53
Risk Level:
Likelihood - 1
Impact - 2
Recommendation:
Remediation Plan:
54
3.17 (HAL-17) PRAGMA TOO RECENT -
INFORMATIONAL
Description:
Reference: https://github.com/ethereum/solidity/releases
In the Solitidy Github repository, there is a json file where are all
bugs finding in the different compiler versions. It should be noted that
pragma 0.6.12 and 0.7.6 are widely used by Solidity developers and have
been extensively tested in many security audits.
Reference: https://github.com/ethereum/solidity/blob/develop/docs/bugs_-
FINDINGS & TECH DETAILS
by_version.json
Code Location:
Risk Level:
Likelihood - 1
55
Impact - 2
Recommendations:
If possible, consider using the latest stable pragma version that has
been thoroughly tested to prevent potential undiscovered vulnerabilities
such as pragma between 0.6.12 - 0.7.6.
Remediation Plan:
56
3.18 (HAL-18) REDUNDANT BOOLEAN
COMPARISON - INFORMATIONAL
Description:
Code Location:
Risk Level:
Likelihood - 1
Impact - 1
Recommendations:
Remediation Plan:
57
3.19 (HAL-19) POSSIBLE MISUSE OF
PUBLIC FUNCTIONS - INFORMATIONAL
Description:
Code Location:
"periphery-bsc/contracts/SpheriumRouter01.sol:
getAmountIn(uint256,uint256,uint256) getAmountOut(uint256,uint256,uint256)
getAmountsIn(uint256,address[]) getAmountsOut(uint256,address[])
quote(uint256,uint256,uint256)
"periphery-bsc/contracts/SpheriumRouter02.sol:
getAmountIn(uint256,uint256,uint256) getAmountOut(uint256,uint256,uint256)
getAmountsIn(uint256,address[]) getAmountsOut(uint256,address[])
quote(uint256,uint256,uint256) setSpheriumTraderRewards(address)
governance/contracts/SpheriumToken-TGE.sol:
renounceOwnership() transferOwnership(address)
governance/contracts/spheriumToken.sol:
mint(address,uint256)
rewards/contracts/TraderRewards.sol:
recordTrade(address) setDivisor(uint256) setRewardTokensRemaining(uint256)
58
setRouter(address) setSphToken(address) withdrawRewardTokens()
Risk Level:
Likelihood - 1
Impact - 1
Recommendation:
Remediation Plan:
59
AUTOMATED TESTING
60
4.1 STATIC ANALYSIS REPORT
Description:
Results:
AUTOMATED TESTING
61
AUTOMATED TESTING
62
AUTOMATED TESTING
63
AUTOMATED TESTING
According to the test results, some of the findings found by these tools
were considered as false positives while some of these findings were real
security concerns. All relevant findings were reviewed by the auditors
and relevant findings addressed on the report as security concerns.
64
4.2 AUTOMATED SECURITY SCAN
Description:
Results:
SpheriumPair.sol, SpheriumERC20.sol
AUTOMATED TESTING
SpheriumToken.sol, SpheriumToken-TGE.sol
All relevant valid findings were founded in the manual code review.
65
THANK YOU FOR CHOOSING