Collar Quest Battle And Breeding

Smart Contract Audit Report

Audit Summary

CollarQuestBattleAndBreeding Audit Report Collar Quest is building a new platform in which users can 'Breed' their NFTs. In addition, authorized users can execute 'Battles'.

For this audit, we reviewed Collar Quest's Breeding contract at 0xc9b47dcb7f55175e03483dc626158a37e7a73516 on the Ethereum Mainnet, and Battle contract at 0x6f289537e5ac198f43a9399861f0864f6708ede8 on the Goerli Testnet.

We previously reviewed the project team's SPARCE contracts here.

Audit Findings

All findings have been resolved, though some centralized aspects are present.
Date: September 27th, 2022.
Updated: September 28th, 2022 to reflect response from the project team.
Updated: November 22nd, 2022 to reflect changes to the Battle contract from 0x9c04d75924fd2e06c5d8fa986e4de1bd11342735 to 0x6f289537e5ac198f43a9399861f0864f6708ede8 on the Goerli Testnet.

Finding #1 - Breeding & Battle - Low (Resolved)

Description: A deadline is included in the message hash of passed signatures, but there is no check to see if the deadline has passed.
Risk/Impact: Signatures can still be used after their specified deadlines.
Recommendation: The project team should require that the current timestamp does not exceed the deadline if they wish to enforce it.
Update: Signatures must now be used before their deadline has passed.

Contracts Overview

  • As the contracts are implemented with Solidity v0.8.x, they are safe from any possible overflows/underflows.
Breeding Contract:
  • This contract allows users to breed matrons and sires of different SPARC-E ID's.
  • When breeding, the token IDs, gene count, deadline, and signature are all specified.
  • These values are verified to have originated from a signed message from a Breed Manager address.
  • A user can use a single signature to breed multiple times.
  • The user must own both tokens in order to breed.
  • Each parent's breed count is incremented after a breed. A sire or matron cannot breed if it results in either of their breed counts exceeding the maximum breed count.
  • A TAG fee and a GeM fee are both taken from the user upon breeding.
  • The TAG fee is a flat specified amount, and the GeM fee is calculated using the sum of the specified fee corresponding to the birthcount of each parent.
  • The TAG fee is transferred to the Treasury address; the GeM fee is burned.
  • A new Breed is then created with attributes consisting of its parents, gene count, breed time, and hatched status.
  • Any user can hatch a Breed once the hatch time has passed from the time of its creation.
  • Neither parent can breed again until their current Breed has hatched.
  • When a Breed is hatched, a new SPARC-E is minted to the original breeder with its assigned gene count.
  • The deployer is granted the Admin Role upon creation.
  • The Admin Role can grant or revoke the Breed Manager Role from any address at any time.
  • The Admin Role can update the SPARC-E, Treasury, TAG, and GeM addresses at any time.
  • The Admin Role can update the GeM fee for any birthcount at any time.
  • The Admin Role can update the maximum breed count, hatch time, and TAG fee at any time.
Battle Contract:
  • A battle can be executed by an Admin or a Battle Manager at any time.
  • Two signatures along with a reward amount and deadline must be passed. These signatures are verified to have originated from addresses with the Battle Manager One and Battle Manager Two roles, respectively.
  • A signature can only be used by a manager address once.
  • A signature cannot be used if its deadline has passed.
  • The caller of the battle will then have their claimable reward amount incremented by the specified reward amount.
  • If the user has not claimed before, their last claim time is set to the current timestamp.
  • A user can claim rewards once the claim wait duration has passed since their last claim time.
  • A user cannot claim more than the maximum claim limit at once.
  • A user cannot claim if they have been added to the Blacklist.
  • The claimed reward amount is transferred to the user in the form of GeM tokens.
  • The team must ensure that the contract holds a sufficient GeM balance in order to allow claims.
  • The Admin should not grant the Battle Manager One Role to any user other than the contract's first manager, and should not grant the Battle Manager Two Role to any user other than the contract's second manager. If this does occur, it may become possible for a signature to be reused.
  • The deployer is granted the Admin Role upon creation.
  • The Admin Role can grant or revoke the Battle Manager One or Battle Manager Two Role from any address at any time.
  • The Admin can update the GeM address at any time.
  • The Admin can update the maximum claim limit and claim wait duration at any time.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control
  • The mentioned roles have the permissions described above.
  • The Admin can update Breeding fees to any amounts at any time.
  • The Admin can update the claim wait duration and maximum claim limit to any values at any time.
  • WARNING
    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

    Breeding Contract

    Smart Contract Audit - Inheritance

    Smart Contract Audit - Graph

    
     ($) = payable function
     # = non-constant function
     
     + [Int] IAccessControl 
        - [Ext] hasRole
        - [Ext] getRoleAdmin
        - [Ext] grantRole #
        - [Ext] revokeRole #
        - [Ext] renounceRole #
    
     + [Int] IERC165 
        - [Ext] supportsInterface
    
     + [Int] IERC721 (IERC165)
        - [Ext] balanceOf
        - [Ext] ownerOf
        - [Ext] safeTransferFrom #
        - [Ext] transferFrom #
        - [Ext] approve #
        - [Ext] getApproved
        - [Ext] setApprovalForAll #
        - [Ext] isApprovedForAll
        - [Ext] safeTransferFrom #
    
     + [Int] ICollarQuest (IERC721)
        - [Ext] spawnSparce #
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] decimals
        - [Ext] symbol
        - [Ext] name
        - [Ext] getOwner
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
        - [Ext] burn #
        - [Ext] burnFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  Validator 
        - [Pub]  #
        - [Pub] validateSig
    
     + [Lib] ECDSA 
        - [Int] recover
        - [Int] toSignedMessageHash
    
     + [Lib] Strings 
        - [Int] toString
        - [Int] toHexString
        - [Int] toHexString
    
     +  AccessControl (Context, IAccessControl)
        - [Pub] hasRole
        - [Int] _checkRole
        - [Pub] getRoleAdmin
        - [Pub] grantRole #
           - modifiers: onlyRole
        - [Pub] revokeRole #
           - modifiers: onlyRole
        - [Pub] renounceRole #
        - [Int] _setupRole #
        - [Int] _setRoleAdmin #
        - [Prv] _grantRole #
        - [Prv] _revokeRole #
    
     +  BreedingCore (AccessControl, Validator)
        - [Int] payBreedFee #
    
     +  Breeding (BreedingCore)
        - [Pub]  #
        - [Ext] setCollarQuest #
           - modifiers: onlyRole
        - [Ext] setTotalBreedCount #
           - modifiers: onlyRole
        - [Ext] setHatchTime #
           - modifiers: onlyRole
        - [Ext] setTreasury #
           - modifiers: onlyRole
        - [Ext] setTag #
           - modifiers: onlyRole
        - [Ext] setGeM #
           - modifiers: onlyRole
        - [Ext] setTagFee #
           - modifiers: onlyRole
        - [Ext] setGeMFee #
           - modifiers: onlyRole
        - [Ext] breed #
           - modifiers: notBreedWhen
        - [Ext] eggsHatch #
    
    
    

    Battle Contract

    Smart Contract Audit - Inheritance

    Smart Contract Audit - Graph

    
     ($) = payable function
     # = non-constant function
     
     + [Int] IAccessControl 
        - [Ext] hasRole
        - [Ext] getRoleAdmin
        - [Ext] grantRole #
        - [Ext] revokeRole #
        - [Ext] renounceRole #
    
     + [Int] IERC20 
        - [Ext] totalSupply
        - [Ext] balanceOf
        - [Ext] transfer #
        - [Ext] allowance
        - [Ext] approve #
        - [Ext] transferFrom #
        - [Ext] mint #
    
     + [Int] IERC721 
        - [Ext] balanceOf
        - [Ext] ownerOf
        - [Ext] safeTransferFrom #
        - [Ext] transferFrom #
        - [Ext] approve #
        - [Ext] getApproved
        - [Ext] setApprovalForAll #
        - [Ext] isApprovedForAll
        - [Ext] safeTransferFrom #
    
     +  Context 
        - [Int] _msgSender
        - [Int] _msgData
    
     +  AccessControl (Context, IAccessControl)
        - [Pub] hasRole
        - [Int] _checkRole
        - [Pub] getRoleAdmin
        - [Pub] grantRole #
           - modifiers: onlyRole
        - [Pub] revokeRole #
           - modifiers: onlyRole
        - [Pub] renounceRole #
        - [Int] _setupRole #
        - [Int] _setRoleAdmin #
        - [Prv] _grantRole #
        - [Prv] _revokeRole #
    
     +  Validator 
        - [Pub]  #
        - [Pub] validateSig
    
     + [Lib] ECDSA 
        - [Int] recover
        - [Int] toSignedMessageHash
    
     + [Lib] Strings 
        - [Int] toString
        - [Int] toHexString
        - [Int] toHexString
    
     +  Battle (AccessControl, Validator)
        - [Pub]  #
        - [Ext] setSPARCE #
           - modifiers: onlyRole
        - [Ext] setGeM #
           - modifiers: onlyRole
        - [Ext] setMaxClaimLimit #
           - modifiers: onlyRole
        - [Ext] setClaimTimeStamp #
           - modifiers: onlyRole
        - [Ext] battleReward #
        - [Ext] claim #
        - [Ext] getNonce
        - [Ext] isSigned
    
    
    

    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 1800+ 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!
    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.