Biconomy Hyphen 2.0 contest - saian's results

Next-Gen Multichain Relayer Protocol.

General Information

Platform: Code4rena

Start Date: 10/03/2022

Pot Size: $75,000 USDT

Total HM: 25

Participants: 54

Period: 7 days

Judge: pauliax

Total Solo HM: 10

Id: 97

League: ETH

Biconomy

Findings Distribution

Researcher Performance

Rank: 32/54

Findings: 2

Award: $263.70

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

123.2529 USDT - $123.25

Labels

bug
QA (Quality Assurance)

External Links

QA Report

Non-critical findings

1. abicoder v2 pragma in 0.8.0

abicoder v2 is used by default in solidity version 0.8.0, so it can be removed

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L4

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/LPToken.sol#L3

refer : https://blog.soliditylang.org/2020/12/16/solidity-v0.8.0-release-announcement/

2. Lack of zero address check

Lack of zero address checks in

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/TokenManager.sol#L44

function changeFee( address tokenAddress, uint256 _equilibriumFee, uint256 _maxFee ) external override onlyOwner whenNotPaused { require(_equilibriumFee != 0, "Equilibrium Fee cannot be 0"); require(_maxFee != 0, "Max Fee cannot be 0"); tokensInfo[tokenAddress].equilibriumFee = _equilibriumFee; tokensInfo[tokenAddress].maxFee = _maxFee; emit FeeChanged(tokenAddress, tokensInfo[tokenAddress].equilibriumFee, tokensInfo[tokenAddress].maxFee); }

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L78

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/WhitelistPeriodManager.sol#L60

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/LPToken.sol#L36

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityFarming.sol#L78

3. Unused imports

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/WhitelistPeriodManager.sol#L6-L7

Mitigation

Remove unused import statements

4. comments missing or incomplete

Some functions in the contracts lack comments, or comments are incomplete, some use natspec comments and some use regular comments

Example :

function initialize( address _executorManagerAddress, address _pauser, address _trustedForwarder, address _tokenManager, address _liquidityProviders ) public initializer {
/** * @dev Function to allow LPs to remove their liquidity from an existing NFT * Also automatically redeems any earned fee */ function removeLiquidity(uint256 _nftId, uint256 _amount) external nonReentrant onlyValidLpToken(_nftId, _msgSender()) whenNotPaused {
/** * @dev Returns the maximum amount a single community LP has provided */ function getMaxCommunityLpPositon(address _token) external view returns (uint256) {
/** * @dev Function used to deposit native token into pool to initiate a cross chain token transfer. * @param receiver Address on toChainId where tokens needs to be transfered * @param toChainId Chain id where funds needs to be transfered */ function depositNative( address receiver, uint256 toChainId, string memory tag ) external payable whenNotPaused nonReentrant {
Mitigation

Add comments to all function

5. Improper event declaration

In event EthReceived address is not indexed, indexing parameters eases filtering for specific data

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L68

same event is declared in LiquidityProviders.sol

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L38

6. Code structure

Some contracts does not follow solidity contract layout order described in

https://docs.soliditylang.org/en/develop/style-guide.html#order-of-layout

In contract TokenManager.sol modifier and event is placed between mappings, in Lptoken.sol modifier is placed after function

Mitigation

Reorder the contract

Awards

140.4459 USDT - $140.45

Labels

bug
G (Gas Optimization)

External Links

Gas Optimization

1. Storage variable can be cached to save gas

Impact

Storage variables that are read multiple times can be cached to save gas on SLOAD that costs ~100 gas (excluding first call)

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L156

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L247

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L273

tokenManager.getTokensInfo(tokenAddress).equilibriumFee can be cached and re-used

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L316

currentLiquidity[tokenAddress] can be cached and re-used

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L137

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L142

totalSharesMinted[_baseToken] can be replaced by variable supply

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L183

totalReserve[token] can be cached and re-used

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L288-L291

perTokenTotalCap[_token] can re-used to save gas

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/WhitelistPeriodManager.sol#L92

svgHelpers[tokenAddress] can re-used

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/LPToken.sol#L120-L122

tokenMetadata[tokenId].suppliedLiquidity and ILiquidityProviders(liquidityProvidersAddress).totalReserve(tokenAddress) can re-used

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/LPToken.sol#L124-L137

Mitigation

The storage variable can be cached and reused

2. Funtion arguments can used instead of storage read to save gas

Impact

In function changeFee in TokenManager.sol function arguments can be used in the event instead of storage read to save gas.

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/TokenManager.sol#L44

emit FeeChanged(tokenAddress, tokensInfo[tokenAddress].equilibriumFee, tokensInfo[tokenAddress].maxFee);

can be changed to

emit FeeChanged(tokenAddress, _equilibriumFee, _maxFee);

3. In getTokensInfo result of storage read can be returned directly

In function getTokensInfo seperate storage reads is done for each value in the struct, the value can be returned directly

function getTokensInfo(address tokenAddress) public view override returns (TokenInfo memory) { TokenInfo memory tokenInfo = TokenInfo( tokensInfo[tokenAddress].transferOverhead, tokensInfo[tokenAddress].supportedToken, tokensInfo[tokenAddress].equilibriumFee, tokensInfo[tokenAddress].maxFee, transferConfig[tokenAddress] ); return tokenInfo; }

can be changed to

function getTokensInfo(address tokenAddress) public view override returns (TokenInfo memory) { return tokensInfo[tokenAddress]; }

4. _msgSender() return value can be cached to save gas

Impact

return value of _msgSender can be cached and re-used to save gas

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L336

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L375-L380

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L384-L391

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L270-273

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L283-309

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L356

5. Adding unchecked can save gas

Impact

Using unchecked keyword, arithmetic underflow/overflow check can be avoided where underflow/overflow cannot happen which will save gas

Proof of concept

In function getRewardAmount in LiquidityPool liquidityDifference calculation can be placed inside unchecked

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L179

In function depositErc20 reward amount subtraction since reward <= incentives

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L167

In for loops increment statement can be placed inside a unchecked block since i cannot overflow

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/token/TokenManager.sol#L78

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/ExecutorManager.sol#L31

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/ExecutorManager.sol#L47

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityFarming.sol#L233

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/WhitelistPeriodManager.sol#L180

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/WhitelistPeriodManager.sol#L248

Mitigation

Add unchecked block to the statements

6. Reorder statements to save gas on revert

Impact

Statements can be ordered in the order of gas consumption so that it can reduce gas consumption in the case of revert

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L87-L105

_Pausable_init(_pauser) can be placed after the require statements to save gas if _pauser is address(0)

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L156-L162

require( tokenManager.getDepositConfig(toChainId, tokenAddress).min <= amount && tokenManager.getDepositConfig(toChainId, tokenAddress).max >= amount, "Deposit amount not in Cap limit" ); require(receiver != address(0), "Receiver address cannot be 0"); require(amount != 0, "Amount cannot be 0");

can be changed to

require(amount != 0, "Amount cannot be 0"); require(receiver != address(0), "Receiver address cannot be 0"); require( tokenManager.getDepositConfig(toChainId, tokenAddress).min <= amount && tokenManager.getDepositConfig(toChainId, tokenAddress).max >= amount, "Deposit amount not in Cap limit" );

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L247-253

require( tokenManager.getDepositConfig(toChainId, NATIVE).min <= msg.value && tokenManager.getDepositConfig(toChainId, NATIVE).max >= msg.value, "Deposit amount not in Cap limit" ); require(receiver != address(0), "Receiver address cannot be 0"); require(msg.value != 0, "Amount cannot be 0");

can be changed to

require(msg.value != 0, "Amount cannot be 0"); require(receiver != address(0), "Receiver address cannot be 0"); require( tokenManager.getDepositConfig(toChainId, NATIVE).min <= msg.value && tokenManager.getDepositConfig(toChainId, NATIVE).max >= msg.value, "Deposit amount not in Cap limit" );

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityPool.sol#L263

require( tokenManager.getTransferConfig(tokenAddress).min <= amount && tokenManager.getTransferConfig(tokenAddress).max >= amount, "Withdraw amnt not in Cap limits" ); require(receiver != address(0), "Bad receiver address");

can be changed to

require(receiver != address(0), "Bad receiver address"); require( tokenManager.getTransferConfig(tokenAddress).min <= amount && tokenManager.getTransferConfig(tokenAddress).max >= amount, "Withdraw amnt not in Cap limits" );

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L84-L89

In initializeRewardPool _baseToken and _rewardToken checks can be done before state variable read to save gas on revert

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityFarming.sol#L101-103

7. Revert string greater than 32 bytes

Impact

revert strings can be <= 32 bytes so that it can be placed in a single slot of memory and require statement will cost less gas

refer: https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#consider-having-short-revert-strings

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/ExecutorManager.sol#L17

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L56

Mitigation

Shorten the revert string or use error codes and explanation in docs

8. removing using for can save gas

library function SafeERC20Upgradeable.safeTransferFrom is used directly in contract LiquidityProvider.sol In LiquidityFarming.sol library function safeTransferFrom can be called directly

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L24

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityFarming.sol#L24

Mitigation

remove statement using for

9. amount and msg.value can be validated to save gas

In function increaseTokenLiquidity and increaseNativeLiquidity amount and msg.value can be validated for 0 value in the primary function to prevent gas consumption if call fails in _increaseLiquidty

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L238

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L326

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L338

Mitigation

place require(amount > 0) in the functions

10. != costs less compared to >

!= costs less gas when compared to > for unsigned int in require statements

Proof of concept

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L239

https://github.com/code-423n4/2022-03-biconomy/blob/04751283f85c9fc94fb644ff2b489ec339cd9ffc/contracts/hyphen/LiquidityProviders.sol#L283

Mitigation

replace > with !=

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter