OmniFusion - Smart Contract Audit Report

Summary

The Omnimorphs team is expanding the functionality of their Omnimorphs NFTs by allowing users to select features of their Omnimorphs and "fuse" them together to combine their traits.

For this audit, we reviewed the OmniFusion Contract at commit 2f3f9a18af446f8dba66d4be1781de58abe3f0c6 on the team's GitHub.

We previously reviewed the project's Omnimorphs NFT Contract here.

Notes on the Contract:
  • Any user is able to fuse any two Omnimorphs NFTs they own at any time, as long as fusion is enabled.
  • One Omnimorph NFT will remain with the combined traits, the other will be burned in the fusion process.
  • A fusion transaction uses input data in the form of a signed message from the off-chain backend of the platform. This message is then decoded into the necessary information for the fusion by the Contract.
  • To fuse two Omnimorphs, at least one Catalyst NFT is required. The Catalyst NFTs are burned during the fusion.
  • Each Catalyst corresponds to one trait being used in the fusion; a maximum of 6 Catalysts may be used during a single fusion corresponding to a maximum of 6 traits.
  • Once an Omnimorph has been fused, it cannot be fused again; a record of the fusion is stored in the Contract.
  • Users will receive a SoulShard NFT that represents the Omnimorph intended to be burned during the fusion, serving as proof of participation in the fusion.
  • Users may burn their Catalyst and SoulShard NFTs if desired.
  • NFT metadata that contains information about the NFTs is stored using an off-chain URI endpoint.
  • The owner may mint any number of Catalyst NFTs to any number of addresses at any time.
  • The owner may toggle the ability to fuse at any time.
  • The owner may lock fusion, permanently disabling it, at any time.
  • The owner may change the address used to verify the signature of a fusion call at any time.
  • The owner may change the URI endpoint at any time.
  • The Contract is ERC-1155 compliant; all standard functionality is present.
  • As the Contract is using Solidity 0.8.X, it is protected from overflows/underflows.
Audit Findings Summary
  • No external threats were identified.
  • Ensure trust in the team as they have significant control within the ecosystem.
  • Date: December 10th, 2021.

Audit Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Centralization of ControlSome off-chain logic is required.WARNING
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Flash LoansN/APASS
Integer Over/UnderflowN/APASS
Logical IssuesN/APASS
Multiple SendsN/APASS
OraclesN/APASS
SuicideN/APASS
State Change External CallsN/APASS
Unbounded LoopsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

OmniFusion Contract

smart_contract_audit_company

token_audit


 ($) = payable function
 # = non-constant function

    + [Int] IERC165 
    - [Ext] supportsInterface

 + [Int] IERC1155 (IERC165)
    - [Ext] balanceOf
    - [Ext] balanceOfBatch
    - [Ext] setApprovalForAll #
    - [Ext] isApprovedForAll
    - [Ext] safeTransferFrom #
    - [Ext] safeBatchTransferFrom #

 + [Int] IERC1155Receiver (IERC165)
    - [Ext] onERC1155Received #
    - [Ext] onERC1155BatchReceived #

 + [Int] IERC1155MetadataURI (IERC1155)
    - [Ext] uri

 + [Lib] Address 
    - [Int] isContract
    - [Int] sendValue #
    - [Int] functionCall #
    - [Int] functionCall #
    - [Int] functionCallWithValue #
    - [Int] functionCallWithValue #
    - [Int] functionStaticCall
    - [Int] functionStaticCall
    - [Int] functionDelegateCall #
    - [Int] functionDelegateCall #
    - [Int] verifyCallResult

 +  Context 
    - [Int] _msgSender
    - [Int] _msgData

 +  ERC165 (IERC165)
    - [Pub] supportsInterface

 +  ERC1155 (Context, ERC165, IERC1155, IERC1155MetadataURI)
    - [Pub] Constructor #
    - [Pub] supportsInterface
    - [Pub] uri
    - [Pub] balanceOf
    - [Pub] balanceOfBatch
    - [Pub] setApprovalForAll #
    - [Pub] isApprovedForAll
    - [Pub] safeTransferFrom #
    - [Pub] safeBatchTransferFrom #
    - [Int] _safeTransferFrom #
    - [Int] _safeBatchTransferFrom #
    - [Int] _setURI #
    - [Int] _mint #
    - [Int] _mintBatch #
    - [Int] _burn #
    - [Int] _burnBatch #
    - [Int] _setApprovalForAll #
    - [Int] _beforeTokenTransfer #
    - [Prv] _doSafeTransferAcceptanceCheck #
    - [Prv] _doSafeBatchTransferAcceptanceCheck #
    - [Prv] _asSingletonArray

 +  Ownable (Context)
    - [Pub] Constructor #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Int] _transferOwnership #

 + [Int] IERC721 (IERC165)
    - [Ext] balanceOf
    - [Ext] ownerOf
    - [Ext] safeTransferFrom #
    - [Ext] transferFrom #
    - [Ext] approve #
    - [Ext] getApproved
    - [Ext] setApprovalForAll #
    - [Ext] isApprovedForAll
    - [Ext] safeTransferFrom #

 + [Int] IERC721Receiver 
    - [Ext] onERC721Received #

 + [Int] IERC721Metadata (IERC721)
    - [Ext] name
    - [Ext] symbol
    - [Ext] tokenURI

 + [Lib] Strings 
    - [Int] toString
    - [Int] toHexString
    - [Int] toHexString

 +  ERC721 (Context, ERC165, IERC721, IERC721Metadata)
    - [Pub] Constructor #
    - [Pub] supportsInterface
    - [Pub] balanceOf
    - [Pub] ownerOf
    - [Pub] name
    - [Pub] symbol
    - [Pub] tokenURI
    - [Int] _baseURI
    - [Pub] approve #
    - [Pub] getApproved
    - [Pub] setApprovalForAll #
    - [Pub] isApprovedForAll
    - [Pub] transferFrom #
    - [Pub] safeTransferFrom #
    - [Pub] safeTransferFrom #
    - [Int] _safeTransfer #
    - [Int] _exists
    - [Int] _isApprovedOrOwner
    - [Int] _safeMint #
    - [Int] _safeMint #
    - [Int] _mint #
    - [Int] _burn #
    - [Int] _transfer #
    - [Int] _approve #
    - [Int] _setApprovalForAll #
    - [Prv] _checkOnERC721Received #
    - [Int] _beforeTokenTransfer #

 + [Lib] ECDSA 
    - [Prv] _throwError
    - [Int] tryRecover
    - [Int] recover
    - [Int] tryRecover
    - [Int] recover
    - [Int] tryRecover
    - [Int] recover
    - [Int] toEthSignedMessageHash
    - [Int] toEthSignedMessageHash
    - [Int] toTypedDataHash

 + [Int] IOmniFusion 
    - [Ext] fuseTokens #

 + [Int] IOmniFusionBurn 
    - [Ext] burn #

 +  OmniFusion (ERC1155, IOmniFusion, IOmniFusionBurn, Ownable)
    - [Pub] Constructor #
       - modifiers: ERC1155
    - [Pub] fuseTokens #
    - [Ext] getFusionReceiptIPFSHash
    - [Ext] burn #
    - [Ext] mintCatalysts #
       - modifiers: onlyOwner
    - [Ext] setIsFusionActive #
       - modifiers: onlyOwner
    - [Ext] lockFusion #
       - modifiers: onlyOwner
    - [Ext] setFusionSigner #
       - modifiers: onlyOwner
    - [Ext] setURI #
       - modifiers: onlyOwner
    - [Prv] _mintShard #
    - [Prv] _hashTransaction
    - [Prv] _matchAddressSigner
    - [Prv] _bytesToBytes32