BlockApex (Auditor) was contracted by Sonar(Client) for the purpose of conducting a Smart Contract Audit/Code Review. This document presents the findings of our analysis which took place on 8th September 2021.
Name: Sonar BSC-ETH bridge |
Auditor: Moazzam Arif | Kaif Ahmed |
Platform: Ethereum/Solidity |
Type of review: Bridge |
Methods: Architecture Review, Functional Testing, Manual Review |
Git repository: https://github.com/sonarplatform/eth_bridge/tree/4c086d33fb5cb7a04a2192d6566c7905ea3b1074 |
White paper/ Documentation: Not provided |
Document log: Initial Audit (08-09-2021) Final Audit (pending) |
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detect major issues/vulnerabilities. Some specific checks are as follows:
Code review | Functional review | |
Reentrancy | Unchecked external call | Business Logics Review |
Ownership Takeover | ERC20 API violation | Functionality Checks |
Timestamp Dependence | Unchecked math | Access Control & Authorization |
Gas Limit and Loops | Unsafe type inference | Escrow manipulation |
DoS with (Unexpected) Throw | Implicit visibility level | Token Supply manipulation |
DoS with Block Gas Limit | Deployment Consistency | Asset’s integrity |
Transaction-Ordering Dependence | Repository Consistency | User Balances manipulation |
Style guide violation | Data Consistency | Kill-Switch Mechanism |
Costly Loop | Operation Trails & Event Generation |
This is a POA bridge application that provides eth to bsc and bsc to eth bridging. It allows its native tokens to be accessed on both ETH and BSC blockchains.
Steps to burn and mint (BSC => ETH):
1. User calls the burn method on BSC bridge (BSC blockchain)
2. With the burn method, tokens are transferred to the admin account
3. Transfer event is emitted on successful burn
4. Relayer listens the event and call the mint method on ETH bridge
5. With the mint method, the tokens are transferred to the user on the ethereum blockchain
For ETH => BSC similar steps are followed.
No test cases were provided, we did our own simulations.
The analysis indicates that the contracts audited are insecure..
Our team performed a technique called “Filtered Audit”, where the contract was separately audited by two individuals. After a thorough and rigorous process of manual testing, all the flags raised were iteratively reviewed and tested.
# of issues | Severity of the risk |
2 | Critical Risk issue(s) |
0 | High Risk issue(s) |
1 | Medium Risk issue(s) |
1 | Low Risk issue(s) |
1 | Informatory issue(s) |
1. Anyone can lock funds of other users
If user1 wants to transfer tokens from BSC to ETH, user1 will first approve funds to the BSC bridge. Now that the user has approved his funds to the bridge contract, anyone else can call the burn method passing the address of user1, the funds of user1 have been locked by someone else.
Remedy:
Burn function contains following logic
token.transferFrom(to, address(this), AmountwithFees);
The parameter contains “to” but should contain “msg.sender”
2. Server API to mint the tokens
There is an api written in the server to mint tokens. It does not verify that the burn has been called or not. The users can mint without burning using that api.
Remedy:
User should submit proof of burn before calling the minting API
No high-risk issues were found.
1. Locking/Unlocking both side
The contract has locking and unlocking functionality on both sides. For minting it is assumed that the admin wallet should have enough token balance.
Attack scenario:
1. User 1 locks 1000 tokens on BSC bridge
2. There is not enough token balance equivalent to be given to user1 on ETH bridge
require( adminBal > amount, "insuffient funds in admin account.");
3. Now user1 can not unlock on ETH bridge
a. He will have to unlock his token again to get his funds back from BSC bridge (extra gas, because the function is not performing the intended behavior)
b. Unlocking of tokens on the same bridge is inconvenient from user’s perspective
Remedy:
Usually the lock/unlock strategy is used on one bridge and mint/burn strategy is used on the other bridge.
1. Centralization Risk
Admin wallet is a single wallet and there is high risk of centralization if the private key gets compromised.
require(admin == msg.sender, "only admin can call this");
Remedy:
Assignment of privileged roles to multi-signature wallets to prevent single point of failure due to the private key.
1. Lock pragma versions
Contracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively.
Remedy:
Lock the pragma version and also consider known bugs (https://github.com/ethereum/solidity/releases) for the compiler version that is chosen. Please refer to this doc for more details.
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
BlockApex (Auditor) was contracted by SONAR (Client) for the purpose of conducting a Smart Contract Audit/Code Review. This document presents the findings of our analysis which took place on 28th September 2021 .
Name: Sonar BSC-ETH bridge v2 | |
Auditor: Moazzam Arif | Kaif Ahmed | |
Platform: Ethereum/Solidity | |
Type of review: Bridge | |
Methods: Architecture Review, Functional Testing, Computer-Aided Verification, Manual Review | |
Git repository: https://github.com/XORD-one/sonar-bridge-contract/tree/17cb255444153945b66c5da8672f2ca06ec91efd | |
White paper/ Documentation: Not provided | |
Document log: Bridge v1 Audit (08-09-2021) | Bridge v2 Audit (28-09-2021)* |
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detect major issues/vulnerabilities. Some specific checks are as follows:
Code review | Functional review | |
Reentrancy | Unchecked external call | Business Logics Review |
Ownership Takeover | ERC20 API violation | Functionality Checks |
Timestamp Dependence | Unchecked math | Access Control & Authorization |
Gas Limit and Loops | Unsafe type inference | Escrow manipulation |
DoS with (Unexpected) Throw | Implicit visibility level | Token Supply manipulation |
DoS with Block Gas Limit | Deployment Consistency | Asset’s integrity |
Transaction-Ordering Dependence | Repository Consistency | User Balances manipulation |
Style guide violation | Data Consistency | Kill-Switch Mechanism |
Costly Loop | Operation Trails & Event Generation |
This is a POA bridge application that provides ETH to BSC and BSC to ETH bridging. It allows its native tokens to be accessed on both ETH and BSC blockchains.
Steps to burn and mint (BSC => ETH):
1. User calls the burn method on BSC bridge (BSC blockchain)
2. With the burn method, tokens are transferred to the admin account
3. Transfer event is emitted on successful burn
4. Relayer listens the event and call the mint method on ETH bridge
5. With the mint method, the tokens are transferred to the user on the ethereum blockchain
For ETH => BSC similar steps are followed.
Smart contract for the native token (PING) was provided. As $PING is similar to $RFI and $SAFEMOON. So the swapping and fee distributions were primarily focused during this security assessment (as they had already been audited by Certik). Only minting and burning functionality of $ePING (ethereum representation of $PING) was considered in scope. Manual Review and Static Analysis tools were used to produce this report.
The analysis indicates that some of the functionalities in the contracts audited are not working properly.
Our team performed a technique called “Filtered Audit”, where the contract was separately audited by two individuals. After their thorough and rigorous process of manual testing, an automated review was carried out using Mythril, MythX and Slither. All the flags raised were manually reviewed and re-tested.
# of issues | Severity of the risk |
0 | Critical Risk issue(s) |
1 | High Risk issue(s) |
0 | Medium Risk issue(s) |
1 | Low Risk issue(s) |
5 | Informatory issue(s) |
No issues were found
1. No Minting and Burning in ePING
File: ePING.sol
_tTotal represents the totalSupply. Initially on the second chain _tTotal is set to 0 in the constructor. _tTotal is used to calculate the currentRate and currentRate is used while transferring and burning. Setting _tTotal to zero gives math errors. While minting _rTotal is so high (~uint(0 => ~MAX value of uint256)). Adding any value to _rTotal will cause underflow.
NOTE: Please carefully set the _rTotal. Also while minting do not change the currentRate, as it will be reflected in other users’ balances
No issues were found.
1. GasFee Griefing Attack
Assuming that the relayer server (owned by the client) pays the gasFee to mint/unlock tokens on the alternate bridge. As there is no min_amount limit on bridging tokens. Consider the following Attack Scenario
Attack Scenario:
1. User deposits 0/1 wei amount of token on BscBridge.
2. Relayer server picks-up the deposit event and calls the mint function on etheremBridge.
3. User receives 0/1 wei tokens. And Relayer pays the gas.
4. As gas fees are high, we can deduce that 1 wei tokens < gasFee (paid by relayer).
Remedy:
1. Charge gas fee from the user. While bridging the tokens, mint amount - gasFeeEquivalent on alternate chain.
2. Put a minimum threshold on the amount of tokens to be bridged.
1. transactionID is used while depositing into the bridges. transactionID is not verified in the smart contracts. It is used when the deposit event is emitted. We advise you to validate transactionID at the backend (relayer servers).
2. Destination chainId should be used while depositing. This will improve user experience if multiple chains are supported for bridging in future.
3. Remove console.log from smart contract.
4. IToken.sol has a wrong implementation of interface. Use Openzeppelin’s ERC20 interface.
5. Fees are deducted on every transfer. Please make sure that the bridge addresses are excluded from the fees.
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
BlockApex (Auditor) was contracted by __PhoenixDAO__ (Client) for the purpose of conducting a Smart Contract Audit/Code Review. This document presents the findings of our analysis which took place on ___28th October 2021____.
Name: PhoenixDAO |
Auditor: Muhammad Jariruddin | Kaif Ahmed |
Platform: Ethereum/Solidity |
Type of review: LP staking | DAO |
Methods: Architecture Review, Functional Testing, Computer-Aided Verification, Manual Review |
Git repository: https://github.com/Musfirazia/PhoenixStaking/tree/3aec9851bd517e9e8da4d72193367cfa9f6cc863 |
White paper/ Documentation: Not provided |
Document log: Initial Audit published (4th October 2021) Final Audit published (3rd November 2021) |
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detect major issues/vulnerabilities. Some specific checks are as follows:
Code review | Functional review | |
Reentrancy | Unchecked external call | Business Logics Review |
Ownership Takeover | ERC20 API violation | Functionality Checks |
Timestamp Dependence | Unchecked math | Access Control & Authorization |
Gas Limit and Loops | Unsafe type inference | Escrow manipulation |
DoS with (Unexpected) Throw | Implicit visibility level | Token Supply manipulation |
DoS with Block Gas Limit | Deployment Consistency | Asset’s integrity |
Transaction-Ordering Dependence | Repository Consistency | User Balances manipulation |
Style guide violation | Data Consistency | Kill-Switch Mechanism |
Costly Loop | Operation Trails & Event Generation |
PhoenixDAO
File: DaoSmartContract.sol
DAO smart contracts used to maintain onchain proposals. Voting is maintained off-chain. To avoid spams, proposers must have to deposit collateral in $PHNX.
Steps to successful proposal:
1-User submits a proposal and add collateral (Note: collateral is not deducted at at this point)
2-Off-chain voting happens
3-Admins change the status of proposals to Upvote on smart contract.
4-Collateral amount is deducted from the proposer's account.
5-When the status reaches completed, proposer’s collateral is returned back.
Phoenix Spot Staking
File: DaoStakeContract.sol
Users can earn spot staking rewards by depositing $PHNX for set period of time. If a user unstakes before the set duration, his portion (according to a formula) of staking amount will be burnt. Regardless, the user will get the full rewards at the time of staking.
Phoenix LP staking
File: phxStake.sol
Users can earn rewards by staking their LP tokens. This staking style is similar to Pancakeswap’s MasterChef.
The final analysis indicates that the contracts audited are well-secured. Most of the issues reported in the initial review have been fixed by the client. The contracts were reviewed again in order to ensure maximum security.
Our team performed a technique called “Filtered Audit”, where the contract was separately audited by two individuals. After their thorough and rigorous process of manual testing, an automated review was carried out using Mythril, MythX and Slither.
Our team found:
# of issues | Severity of the risk |
2 | Critical Risk issue(s) |
0 | High Risk issue(s) |
2 | Medium Risk issue(s) |
0 | Low Risk issue(s) |
1 | Informatory issue(s) |
File: DaoSmartContract.sol
1. User can withdraw the amount even if the actual deposit didn’t happen
Attack Scenario:
User submit a proposal with collateral amount X. As the collateral is deducted when the proposal status is changed to UpVotes by admins. User can withdraw collateral amount of tokens(even if the tokens are not actually deducted). Only checks in place are:
require(!proposalList[proposalId].isClaimed, "Collateral Already Claimed");
require(proposalList[proposalId].proposer == sender, "Only Owner of Proposal can withdraw");
Though this function requires to be called by admins, we suggest that please verify at the backend that the user is eligible to withdraw or not.
Remedy:
Verify that the user has his collateral deducted by just adding a flag in proposal struct (collateralDeposited).
Dev’s response:
It is only possible when the user has a signature and the user cannot have a signature. Verified at the backend.
2. User can withdraw even if the collateral is returned when the status of proposal is completed
Attack Scenario:
When the admin changes the status of the proposal to completed, the contract automatically transfers the collateral back to the proposer. Still there are no checks placed and the collateral is returned back.
Remedy:
Add a flag (collateralReturned) in the proposal struct and verify the flag in withdraw.
Dev’s response:
It is only possible when the user has a signature and the user cannot have a signature. Verified at the backend.
No high-risk issues were found.
1. Possible DOS attack in unstake
File: DaoStakeContract.sol
When users deposit to earn spot staking rewards. StakerData holds the staking information. StakerData needs stakeId to find staking information. stakeId is generated as follows.
bytes32 stakeId = keccak256(abi.encode(_timestamp, _beneficiary, _altQuantity));
When the user unstakes, he has to provide stakeIds to unstake. Now the attacker can use the stakeIds of other users with the following constraint i.e., (sum of withdraw amount from all staking events should be less than attacker's staked amount). Attacker withdraws his amount, but now the original staker does not know his stakeIds.
stakerBalance[sender] = stakerBalance[sender].sub(withdrawAmount);
Note:
Although the attacker might have his stakes burnt, the other users will be unable to unstake (at least other users will a have hard time to find stakeIds).
Remedy:
We suggest verifying the stakeIds before processing.
Status:
Fixed.
2. LPTokens are transferred to $PHNX contract address
The Lp staking smart contract is similar to PCS MasterChef contract. When the user deposits LPs, updatePool method is called. This method transfers some of LP tokens to the $PHNX contract address. This will cause issues when the user tries to unstake their LPs because the contract wouldn’t have enough LPs.
Status:
Fixed.
No high-risk issues were found.
1. Pid(pool id) arg is never used when a user withdraws in LP staking. We suggest removing that.
File: PhxStake.sol
Status:
Fixed.
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
BlockApex (Auditor) was contracted by _Voirstudio__ (Client) for the purpose of conducting a Smart Contract Audit/Code Review. This document presents the findings of our analysis which took place from _19th August 2021__ .
Entry #1
Date: 11th October 2021
In the first week, we developed a deeper understanding of the protocol and its workings. We started by reviewing the five main contracts against common solidity flaws and did a static analysis using Slither. In the second week, we wrote unit-test cases to ensure that the functions are performing their intended behaviour. In the 3rd week, we began with the line-by-line manual code review.
Note: We haven’t fuzzed the end-to-end smart contracts behaviour in this auditing round. So this is the version of the report with the issues that were found in all the steps we performed before the above mentioned date. We are now engaged again by Unipilot to further test and fuzz properties. A detailed analysis will be shared later in an updated version of the report which will be published later.
Entry #2
Date: 1st November 2021
We were tasked with an additional review of the protocol by Voirstudio to verify the mathematics and economics of Unipilot. We fuzzed the smart contracts to test properties of the protocol and found some issues which are reported below. We have tested and discussed a few bullets in the grey area regarding the economics of the protocol and worked out contingency plans around it.
Note: We worked closely with the developers and the fixes were incrementally applied. The team was very supportive and was open to suggestions and discussion. They even provided a few pointers as to where we would find potential vulnerabilities.
Name: Unipilot |
Auditor: Moazzam Arif | Kaif Ahmed | Muhammad Jarir Uddin |
Platform: Ethereum/Solidity |
Type of review: Mathematics, Tokenomics, Liquidity Management, Index Fund |
Methods: Architecture Review, Functional Testing, Computer-Aided Verification, Manual Review |
Git repository: First review: https://github.com/VoirStudio/unipilot-protocol-contract-v2/tree/update-structure |
Git repository: Second review: https://github.com/VoirStudio/unipilot-protocol-contract-v2/tree/update-getSharesAndAmounts |
White paper/ Documentation: https://unipilot.medium.com/ |
Document log: 1st review: Initial Audit (19th August 2021) | Final Audit (11th October 2021) 2nd review: Initial Audit (20th October 2021) | Final Audit (26th October 2021) |
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detect major issues/vulnerabilities. Some specific checks are as follows:
Code review | Functional review | |
Reentrancy | Unchecked external call | Business Logics Review |
Ownership Takeover | ERC20 API violation | Functionality Checks |
Timestamp Dependence | Unchecked math | Access Control & Authorization |
Gas Limit and Loops | Unsafe type inference | Escrow manipulation |
DoS with (Unexpected) Throw | Implicit visibility level | Token Supply manipulation |
DoS with Block Gas Limit | Deployment Consistency | Asset’s integrity |
Transaction-Ordering Dependence | Repository Consistency | User Balances manipulation |
Style guide violation | Data Consistency | Kill-Switch Mechanism |
Costly Loop | Operation Trails & Event Generation |
Unipilot is an auto-liquidity management protocol built on top of Uniswap v3. It simplifies the liquidity management by rebasing the liquidity of the pool, when prices get out of range.
To readjust the liquidity of the pool, Captains (independent nodes) are compensated for the gas fee plus some bonus in $PILOT.
It also has a governing token i.e., $PILOT. When a protocol earns a fee from Uniswap v3, users have the option to claim a fee in equivalent $PILOT (price is fetched from $FEE_TOKEN/$WETH -> $PILOT/$WETH price oracles).
The protocol is built to support multiple dexes (decentralized exchanges) for liquidity management. Currently it supports only Uniswap v3’s liquidity. In future, the protocol will support other decentralized exchanges like Sushiswap (Trident). So the architecture is designed to keep in mind the future releases.
The protocol has 5 main smart contracts and their dependent libraries.
Unipilot.sol: The smart contact is the entry point in the protocol. It allows users to deposit, withdraw and collect fees on liquidity. It mints an NFT to it’s users representing their individual shares.
V3Oracle.sol: It is a wrapper around Uniswap oracles. It also has helper functions to calculate TWAP (time-weighted average price) and other prices relevant data.
UniswapLiquidityManager.sol: The heart of the protocol that allows users to add, withdraw, collectFee and readjust the liquidity on Uniswap v3. This smart contract interacts with Uniswap v3Pool and v3Factory to add and remove liquidity. It maintains 2 positions on Uniswap i.e., base position and range position (leftover tokens are added as range orders).
UniStrategy.sol: The smart contract to fetch and process ticks’ data from Uniswap. It also decides the bandwidth of the ticks to supply liquidity (on the basis of governance).
ULMState.sol: This smart contract fetches the updated prices and tick ranges from Uniswap’s v3 pools.
Steps to Add Liquidity:
1-User will give approval of both tokens to Unipilot.sol
2-User will call the deposit method of Unipilot.sol
3-Unipilot.sol’s deposit method will call the deposit method of UniswapLiquidityManager.sol and transfer both the tokens to UniswapLiquidityManager.sol
4-UniswapLiquditymanager.sol will add the liquidity on Uniswap. This will:
a. Mint an NFT denoting the user’s shares in the liquidity provided
b. 2-Alter the existing liquidity by increasing the user’s share
In our first iteration, we found 1 critical-risk issue, 4 high-risk issues, 1 medium-risk, 1 low-risk issue and 1 informatory issue. All these issues were refactored and fixes have been made. A detailed report on the first review can be found here.
The second iteration was performed recently, with the updated codebase. We found a few more issues that were promptly fixed by the team. Our analysis indicates that the contracts are now secure.
Our team found:
# of issues | Severity of the risk |
1 | Critical Risk issue(s) |
0 | High Risk issue(s) |
3 | Medium Risk issue(s) |
0 | Low Risk issue(s) |
2 | Informatory issue(s) |
1. Ether balance of contract can be withdrawn
File: PeripheryPayments.sol
Description:
Unipilot conducted a testnet bug bounty. In that some users reported they were unable to collect their fees. By investigating that with the dev team, they founded that ERC20/WETH pool was misbehaving due to the following code snippet:
if (balanceWETH9 > 0) { IWETH9(WETH).withdraw(balanceWETH9); // contract balance is transferred TransferHelper.safeTransferETH(recipient, balanceWETH9);}
Remedy:
The dev team suggested to remove this method and pass proper amount to be withdrawn
Status:
Fixed
No high-risk issues were found.
1. Math Precision issues
File: UniswapLiquidityManger.sol & ULMState.sol
Description:
Unipilot uses 1e18 precision for calculating the Liquidity shares and feeGrowth when adding liquidity and fees. This causes some small amounts to be locked forever in the UniswapLiquiditymanager.
See the following code snippet:
position.feeGrowthGlobal0 += FullMath.mulDiv(
collect0Base + collect0Range,
1e18, // precision
position.totalLiquidity
);
Remedy:
We suggest using FixedPoint128.Q128 from Uniswap. We fuzzed against this precision and we got more precise results
Status:
Fixed
2. Safe cast and Safe Math
Description:
There are many instances in the contract which use unsafe math operations. This might lead to overflow/underflow. The contract also uses unsafe type casting.
See the following code snippet of unsafe cast:
(int256 amount0Delta, int256 amount1Delta) = IUniswapV3Pool(b.poolAddress).swap( address(this), b.zeroForOne, int256(b.amountIn), // unsafe casting, use safeCast b.sqrtPriceLimitX96, abi.encode((SwapCallbackData({ token0: token0, token1: token1, fee: fee })));
Remedy:
We suggest to use safe math and safe cast libraries
Status:
Fixes in progress
3. Economic Attacks
a. Price Oracle manipulation
File: UniswapLiquidityManger.sol
Unipilot relies on TWAP when minting new $PILOT tokens, either in fees or in readjustment of the pool. Tokens are priced w.r.t to ether and then from etherAmount the pilotAmount is calculated.
Attack Scenario:
Consider users who want to get $PILOT in fees instead of underlying tokens. Users can create a pool with $WETH, do some swaps, and inflate the tokens against $WETH. Unipilot will get the etherAmount of tokens from the pool and convert ethers to pilot. Hence the user gets the $PILOT at a manipulated price.
Note:
To mitigate this attack, devs already have implemented whitelisting of pools when distributing fees. But they had not implemented whitelisting during readjustments.
Remedy:
Add whitelisting to readjustment
Status:
Fixed
b. Put a limit on tx.gasPrice
File: UniswapLiquidityManger.sol
Description:
When a user readjust the pool, his transaction fees is compensated plus a
Premium is given to the user in $PILOT.
b.gasUsed = tx.gasprice.mul(initialGas.sub(gasleft())); // tx.gasprice can be adjusted high enough to mint more $PILOT b.pilotAmount = IOracle(_oracle).ethToAsset(PILOT, 3000,b.gasUsed);
Remedy:
Add a limit to tx.gasprice
Status:
Fixed
c. Probable Slippage Attacks
While readjusting the pool, the Unipilot swaps X amount of tokens to make the pool in range. The swap percent (how much should be swapped) and the slippage is hardcoded. This incentivizes sandwich attacks.
Remedy:
The swap amount and slippage should be configurable according to favorable conditions
Status:
Fixed
No low-risk issues were found.
1. Contracts should be made pausable in case of a mishap.
2. Contracts should have rescue funds methods.
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
Name: Dafi bridge (Final Audit) |
Auditors: Moazzam Arif | Muhammad Jarir |
Platform: Ethereum/Solidity |
Type of review: ETH - BSC Bridge |
Methods: Architecture Review, Functional Testing, Computer-Aided Verification, Manual Review |
Git repository: https://github.com/DAFIProtocol/dBridge/tree/dafi-bridge-contracts |
White paper/ Documentation: Dafi Bridge Flow Document (1).pdf |
Document log: Initial Audit: 30th November 2021 Final Audit: 2nd December 2021 |
The git-repository shared was checked for common code violations along with vulnerability-specific probing to detect major issues/vulnerabilities. Some specific checks are as follows:
Code review | Functional review | |
Reentrancy | Unchecked external call | Business Logics Review |
Ownership Takeover | ERC20 API violation | Functionality Checks |
Timestamp Dependence | Unchecked math | Access Control & Authorization |
Gas Limit and Loops | Unsafe type inference | Escrow manipulation |
DoS with (Unexpected) Throw | Implicit visibility level | Token Supply manipulation |
DoS with Block Gas Limit | Deployment Consistency | Asset’s integrity |
Transaction-Ordering Dependence | Repository Consistency | User Balances manipulation |
Style guide violation | Data Consistency | Kill-Switch Mechanism |
Costly Loop | Operation Trails & Event Generation |
A detailed overview of the project can be found here:
https://blog.dafiprotocol.io/introducing-the-dbridge-testnet-c564f5b4eea2
Dafi’s “dbridge” enables users to bring their ERC-20 $DAFI tokens across from the Ethereum network to Binance Smart Chain, and vice versa, with aims of making $DAFI available on multiple high-speed and low-cost networks. As Dafi’s goal is to support every token on most chains, to launch their own dToken, it’s important that their protocol is cross-chain.
Dafi Bridge is an implementation of a generic POA Bridge. Authority is distributed among validators. Validators sign the proof-of-burn message and the user submits (to avoid gas griefing attacks) the signature on the alternate chain to claim tokens.
The codebase:
The system consists of 3 smart contracts (i.e ETH Bridge, BSC Bridge & a burnable/mintable ERC20 token representing Dafi on alternate chains)
Bridge contracts have onlyOwner modifier to set configurations (i.e adding/removing validators, minimum signers required(threshold)).
The analysis indicates that the contracts audited are working properly.
Our team performed a technique called “Filtered Audit”, where the contract was separately audited by two individuals. After their thorough and rigorous process of manual testing, no potential flags were raised.
Our team found:
# of issues | Severity of the risk |
0 | Critical Risk issue(s) |
0 | High Risk issue(s) |
1 | Medium Risk issue(s) |
1 | Low Risk issue(s) |
3 | Informatory issue(s) |
No critical-risk issues were found in the review.
No high-risk issues were found in the review.
1. If ETHToken is changed, tokens will be locked forever in the contract
File: ETHBridgeOptimized.sol
Description:
Owner(multisig) can change the underlying ETHToken address. If there are tokens locked in the smart contract and changeToken() is called, tokens will be locked forever in the contract.
Remedy:
Remove changeToken() method from the contract. If there is a need to change the token address, a new contract can be deployed.
Status:
Fixed.
1. Unnecessary allowance check in burn/lock tokens
File: ETHBridgeOptimized.sol, BinanceBridgeOptimized.sol
Description:
if (IERC20(BSCTOKEN).allowance(msg.sender, address(this)) < amount)
revert AllowanceInsufficient(
IERC20(BSCTOKEN).allowance(msg.sender, address(this)), amount);
When burning/locking tokens, the contract checks if the msg.sender has allowed the smart contract (address(this)) to burn/lock. This check will cost extra gas. Normally these checks are used with burnFrom. There is already check placed in the burn method of dafiToken.sol
Remedy:
Remove allowance checks
Status:
Fixed.
1. Misleading variable/function names
File: ETHBridgeOptimized.sol, BinanceBridgeOptimized.sol, dafiTokenBSC.sol function burnTokens(uint256 amount, address targetChain) external { function lockTokens(uint256 amount, address targetChain) external { function viewOwners(address checkAddress) external view returns (bool) //viewValidators function burn(uint256 _value, address _beneficiary) external onlyBridge { // burnFrom
Remedy:
Our suggestion is that
1. targetChain should be recipient
2. viewOwners should be ViewValidators
2. burn should be burnFrom in dafiToken
2. Gas cost optimization while incrementing nonce
File: ETHBridgeOptimized.sol, BinanceBridgeOptimized.sol
Description:
nonceIncrement() method is used to increment a state variable nonce. Calling a function instead of directly updating the state variable will save the gas cost. Calling a function introduce JUMP opcode which has a higher gas cost
Status:
Fixed.
3. Centralization risk on minting/burning on BSC Token
Description:
onlyBridge can burn/mint tokens. Bridge address can be changed by the owner (MultiSig). There are no potential risks as long as the signers of the multisig are honest.
The smart contracts provided by the client for audit purposes have been thoroughly analyzed in compliance with the global best practices till date w.r.t cybersecurity vulnerabilities and issues in smart contract code, the details of which are enclosed in this report.
This report is not an endorsement or indictment of the project or team, and they do not in any way guarantee the security of the particular object in context. This report is not considered, and should not be interpreted as an influence, on the potential economics of the token, its sale or any other aspect of the project.
Crypto assets/tokens are results of the emerging blockchain technology in the domain of decentralized finance and they carry with them high levels of technical risk and uncertainty. No report provides any warranty or representation to any third-Party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third-party should rely on the reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project.
Smart contracts are deployed and executed on a blockchain. The platform, its programming language, and other software related to the smart contract can have its vulnerabilities that can lead to hacks. The scope of our review is limited to a review of the Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks.
This audit cannot be considered as a sufficient assessment regarding the utility and safety of the code, bug-free status or any other statements of the contract. While we have done our best in conducting the analysis and producing this report, it is important to note that you should not rely on this report only - we recommend proceeding with several independent audits and a public bug bounty program to ensure security of smart contracts.
Drop your email to read the BlockApex newsletter and keep yourself updated around the clock.