GigaSwap

Smart Contract Audit Report

Audit Summary

GigaSwap Audit Report GigaSwap is building a new platform where users can create ERC-20 and ERC-721 transfer deals.

For this audit, we reviewed the GigaSwap, Erc20CountPointFactory, Erc721CountFactory, Erc721ItemFactory, EtherPointFactory, FeeSettings, Sale, PositionsController, Erc20AssetFactory, Erc20Asset, Erc721ItemAssetFactory and Erc721ItemAsset, ETHAssetFactory, and ETHAsset contracts provided to us by the project team.

Audit Findings

All Findings have been resolved.
Date: July 7th, 2022.
Updated: July 20th, 2022 to reflect the new contracts provided to us by the project team.

Finding #1 - Erc721CountPoint & Erc721ItemPoint - High (Resolved)

Description: The withdraw() function utilizes the ERC721Enumerable contract's tokenOfOwnerByIndex() function when transferring NFTs, however there is no prior check to ensure that the specified NFT address supports ERC721Enumerable functionality.
Risk/Impact: Any NFTs that are sent to the Erc721CountPoint & Erc721ItemPoint contracts that do not support ERC721Enumerable functionality will be locked.
Recommendation: The team should use the ERC165 supportsInterface() function and check that the token address specified by the user implements ERC721Enumerable functionality.
Resolution: The team has implemented the above recommendation for the Erc721CountPoint contract and removed the ERC721Enumerable logic in the Erc721ItemPoint contract.

Finding #2 - Erc20CountPoint - Low (Acknowledged)

Description: Although the withdraw() function contains the payable modifier, the withdraw fee is charged using the token address specified by the creator.
function withdraw() external payable {        
    address owner = isSwapped ? to : from;
    require(msg.sender == owner || msg.sender == router);  
    uint256 balance = token.balanceOf(address(this));     
    uint256 fee = (balance * feePercentil) / 1000;
    if (!isSwapped) fee = 0;    
    uint256 toTransfer = balance - fee;
    token.transfer(feeAddress, fee);
    token.transfer(owner, toTransfer);
}
Risk/Impact: Any ETH sent to the contract by use of the withdraw() function will be locked as the contract does not contain a function to withdraw the ETH.
Recommendation: The team should remove the payable modifier from the withdraw() function.
Resolution: This Finding has been acknowledged by the team.

Finding #3 - GigaSwap - Low (Resolved)

Description: Any user can initiate a withdraw transaction of any existing Deal at any time.
Risk/Impact: Any user can initiate a withdraw before a swap() is able to occur and return the tokens or ETH back to the "from" address.
Recommendation: The team should restrict access to the withdraw() function to only be called by the "from" or the "to address" associated with the point.
Resolution: The team has implemented the above recommendation.

Finding #4 - GigaSwap - Low (Resolved)

Description: Any user can add points to any existing Deal at any time.
Risk/Impact: Users can add a point to a Deal that can never be fulfilled which will ensure that the Deal will never be completed.
Recommendation: Upon creating a new point, the team should restrict access to each Deal ID to only be utilized by one of the owners of the Deal.
Resolution: The team has implemented the above recommendation.

Finding #5 - Erc721ItemPoint - Informational (Resolved)

Description: The withdraw() function uses a for loop to transfer the contract's full balance of the specified token address, however the isComplete() function only checks that the contract is the owner of a specific NFT via the Item ID.
Recommendation: The team could remove the for loop from the withdraw() function and only use the transferFrom() function to transfer the specific NFT to the owner address.
Resolution: The team has implemented the above recommendation.

Contracts Overview

GigaSwap Contract:
  • Any user can create a new Deal by specifying an address that will be added as the second owner of the Deal.
  • The default state value of a newly created Deal is 1.
  • Users can use any of the valid Factory contracts to add a "point" to any existing Deal when the current state of the specified Deal is 1.
  • The owner can add/remove addresses from the valid Factory list at any time.
  • The creator or co-owner of a Deal can increment the state value of the Deal to 2 at any time which will prevent any more additional points from being added.
  • Any user can initiate a swap transaction by specifying a valid Deal ID that contains at least 1 point and is currently in state 2.
  • Each point assigned to a Deal must be considered complete in order for a swap transaction to be successful.
  • In order for a point to be considered complete, the balance of the CountPoint contract created in the Factory must be greater than the desired amount of tokens (or ETH) set by the creator.

  • Either Deal owner can initiate a withdraw transaction by specifying a valid Deal ID that contains at least 1 point.
  • If a Deal has been successfully swapped, the full token or ETH balance of the Point contract will be sent to the "to" address.
  • If the point has not been successfully swapped, the full token or ETH balance of the Point contract will be sent to the "from" address.
  • A fee will be charged on withdraws that is allocated to the Fee address set by the project team if a swap has successfully occurred.
  • The owner can set the withdraw fee up to 1% and the ETH fee up to 0.035 ETH at any time.
  • The owner can set the Fee address to any address at any time.
Erc20CountPointFactory and Erc20CountPoint Contracts:
  • Any owner of an existing Deal can add a new point to their Deal by specifying the Deal ID, token address, desired amount of tokens, a "from" address, and a "to" address.
  • A new Erc20CountPoint contract is created each time a new point is added.
  • If a swap has not successfully occurred in this contract, the "from" address can initiate a withdraw transaction that will transfer all of the tokens in the contract to their wallet address.
  • If a swap has successfully occurred in this contract, the "to" address can initiate a withdraw transaction that will transfer all of the tokens in the contract to their wallet address.
  • A withdraw fee is collected that is allocated to the Fee address if a swap has successfully occurred.
Erc721CountFactory and Erc721CountPoint Contracts:
  • Any owner of an existing Deal can add a new point to their Deal by specifying the Deal ID, token address, desired amount of tokens, a "from" address, and a "to" address.
  • A new Erc721CountPoint contract is created each time a new point is added.
  • If a swap has not successfully occurred in this contract, the "from" address can initiate a withdraw transaction that will transfer all of the tokens in the contract to their wallet address.
  • If a swap has successfully occurred in this contract, the "to" address can initiate a withdraw transaction that will transfer all of the tokens in the contract to their wallet address.
  • A withdraw fee in ETH is collected that is allocated to the Fee address if a swap has successfully occurred.
Erc721ItemFactory and Erc721ItemPoint Contracts:
  • Any owner of an existing Deal can add a new point to their Deal by specifying the Deal ID, token address, Item ID, a "from" address, and a "to" address.
  • A new Erc721ItemPoint contract is created each time a new point is added.
  • If a swap has not successfully occurred in this contract, the "from" address can initiate a withdraw transaction that will transfer the NFT in the contract to their wallet address.
  • If a swap has successfully occurred in this contract, the "to" address can initiate a withdraw transaction that will transfer the NFT in the contract to their wallet address.
  • A withdraw fee in ETH is collected that is allocated to the Fee address if a swap has successfully occurred.
EtherPointFactory and EtherPoint Contracts:
  • Any owner of an existing Deal can add a new point to their Deal by specifying the Deal ID, desired ETH amount, a "from" address, and a "to" address.
  • A new EtherPoint contract is created each time a new point is added.
  • If a swap has not successfully occurred in this contract, the "from" address can initiate a withdraw transaction that will transfer all of the ETH in the contract to their wallet address.
  • If a swap has successfully occurred in this contract, the "to" address can initiate a withdraw transaction that will transfer all of the ETH in the contract to their wallet address.
  • A withdraw fee in ETH is collected that is allocated to the Fee address if a swap has successfully occurred.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control The team maintains control of the ownership features listed above. PASS
Compiler Issues N/A PASS
Delegate Call to Untrusted Contract N/A PASS
Dependence on Predictable Variables N/A PASS
Ether/Token Theft N/A PASS
Flash Loans N/A PASS
Front Running N/A PASS
Improper Events N/A PASS
Improper Authorization Scheme N/A PASS
Integer Over/Underflow N/A PASS
Logical Issues N/A PASS
Oracle Issues N/A PASS
Outdated Compiler Version N/A PASS
Race Conditions N/A PASS
Reentrancy N/A PASS
Signature Issues N/A PASS
Unbounded Loops N/A PASS
Unused Code N/A PASS
Overall Contract Safety   PASS

GigaSwap Contract

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IFeeSettings 
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 + [Int] ISwapper (IFeeSettings)
    - [Ext] addDealPoint #

 + [Int] IDealPoint 
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 + [Int] IDealPointFactory 

 +  Ownable 
    - [Pub]  #
    - [Ext] transferOwnership #
       - modifiers: onlyOwner

 +  Swapper (ISwapper, Ownable)
    - [Ext] makeDeal #
    - [Ext] addDealPoint #
    - [Pub] addFactory #
       - modifiers: onlyOwner
    - [Pub] removeFactory #
       - modifiers: onlyOwner
    - [Pub] setFactories #
       - modifiers: onlyOwner
    - [Pub] getDeal
    - [Pub] getDealIdByIndex
    - [Ext] getDealsPage
    - [Pub] isComplete
    - [Ext] swap #
    - [Ext] withdraw #
    - [Ext] stopEdit #
    - [Ext] getDealPoint
    - [Ext] getDealPoints

 +  FeeSettingsDecorator (IFeeSettings)
    - [Pub]  #
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 +  GigaSwap (Swapper, FeeSettingsDecorator)
    - [Pub]  #
       - modifiers: FeeSettingsDecorator

Erc20CountPointFactory Contract

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IDealPoint 
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 + [Int] IDealPointFactory 

 + [Int] IFeeSettings 
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 + [Int] ISwapper (IFeeSettings)
    - [Ext] addDealPoint #

 +  PointFactory (IDealPointFactory)
    - [Pub]  #
    - [Int] addPoint #

 +  DealPoint (IDealPoint)
    - [Pub]  #
    - [Ext] swap #
    - [Ext] isComplete

 + [Int] IERC20 
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] approve #
    - [Ext] transferFrom #

 +  Erc20CountPoint (DealPoint)
    - [Pub]  #
       - modifiers: DealPoint
    - [Ext] isComplete
    - [Ext] withdraw ($)

 +  Erc20CountPointFactory (PointFactory)
    - [Pub]  #
       - modifiers: PointFactory
    - [Pub] makePoint #

Erc721CountFactory Contract

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IDealPoint 
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 + [Int] IDealPointFactory 

 + [Int] IFeeSettings 
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 + [Int] ISwapper (IFeeSettings)
    - [Ext] addDealPoint #

 +  PointFactory (IDealPointFactory)
    - [Pub]  #
    - [Int] addPoint #

 +  DealPoint (IDealPoint)
    - [Pub]  #
    - [Ext] swap #
    - [Ext] isComplete

 + [Int] IERC721 
    - [Ext] balanceOf
    - [Ext] tokenOfOwnerByIndex
    - [Ext] tokenByIndex
    - [Ext] transferFrom #

 +  Erc721CountPoint (DealPoint)
    - [Pub]  #
       - modifiers: DealPoint
    - [Ext] isComplete
    - [Ext] withdraw ($)
    - [Ext] withdraw #

 +  Erc721CountFactory (PointFactory)
    - [Pub]  #
       - modifiers: PointFactory
    - [Pub] makePoint #

Erc721ItemFactory Contract

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IDealPoint 
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 + [Int] IDealPointFactory 

 + [Int] IFeeSettings 
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 + [Int] ISwapper (IFeeSettings)
    - [Ext] addDealPoint #

 +  PointFactory (IDealPointFactory)
    - [Pub]  #
    - [Int] addPoint #

 +  DealPoint (IDealPoint)
    - [Pub]  #
    - [Ext] swap #
    - [Ext] isComplete

 + [Int] IERC721 
    - [Ext] ownerOf
    - [Ext] balanceOf
    - [Ext] tokenOfOwnerByIndex
    - [Ext] tokenByIndex
    - [Ext] transferFrom #

 +  Erc721ItemPoint (DealPoint)
    - [Pub]  #
       - modifiers: DealPoint
    - [Ext] isComplete
    - [Ext] withdraw ($)

 +  Erc721ItemFactory (PointFactory)
    - [Pub]  #
       - modifiers: PointFactory
    - [Pub] makePoint #

EtherPointFactory Contract

Smart Contract Audit - Inheritance

Smart Contract Audit - Graph


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public
 
 + [Int] IDealPoint 
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 + [Int] IDealPointFactory 

 + [Int] IFeeSettings 
    - [Ext] feeAddress #
    - [Ext] feePercentil #
    - [Ext] feeEth #

 + [Int] ISwapper (IFeeSettings)
    - [Ext] addDealPoint #

 +  PointFactory (IDealPointFactory)
    - [Pub]  #
    - [Int] addPoint #

 +  DealPoint (IDealPoint)
    - [Pub]  #
    - [Ext] swap #
    - [Ext] isComplete

 + [Int] IERC20 
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] approve #
    - [Ext] transferFrom #

 +  EtherPoint (DealPoint)
    - [Pub]  #
       - modifiers: DealPoint
    - [Ext] isComplete
    - [Ext] swap #
    - [Ext] withdraw ($)

 +  EtherPointFactory (PointFactory)
    - [Pub]  #
       - modifiers: PointFactory
    - [Pub] makePoint #

About SourceHat

SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1300+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value across 1500 projects!.
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

Contact us today to get a free quote for a smart contract audit of your project!

What is a SourceHat Audit?

Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

How Do I Interpret the Findings?

Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

  • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
  • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
  • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
  • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.