Anime Metaverse
Smart Contract Audit Report
Audit Summary
Anime Metaverse is a new collection of ERC-1155 NFTs that users can attempt to win in random lottery drawings.
For this audit, we reviewed the project team's AnimeMetaverseReward contract at 0xD5043026510451c2faf21B9596FEa42ce741386A and GachaDraw contract at 0x62427Bb87fbf68522453d10919F326c58181f40F on the Görli Testnet.
Audit Findings
All findings have been resolved, though some centralized aspects are present.
Date: September 21st, 2022.
Updated: October 3rd, 2022 with resolution and acknowledgement.Finding #1 - AnimeMetaverseReward - High (Resolved)
Description: The claimMerchandise() function allows users to provide their own value parameter.
Risk/Impact: Malicious users can provide a value of 0. This allows them to bypass the _burn() function while still minting themselves a Digital Merch NFT.
Recommendation: The team should remove the value parameter function and instead use the SUPPLY_PER_TOKENID variable.
Resolution: The team has implemented the above recommendation.
Finding #2 - GachaDraw - Medium (Acknowledged)
Description: The getRandomNumber() function uses on-chain data to generate random numbers.
Risk/Impact: Malicious users could create contracts that use the same random number generation as the getRandomNumber() function and revert until a desired result is achieved. The same can be done manually but with less efficiency. Validators are also capable of predicting the outcome of getRandomNumber() to acheive a desirable result.
Recommendation: The industry standard solution is to use ChainLink for off-chain verifiably random data. The team should at minimum prevent contracts from calling the function to mitigate the probability for manipulation.
Resolution: The team has chosen not to implement the above recommendation as all players using the lottery system win some form of reward and the potential for influencing outcomes would not have any tangible benefit to the user.
Contracts Overview
AnimeMetaverseReward Contract:
- As the contracts are implemented with Solidity v0.8.15, they are safe from any possible overflows/underflows.
GachaDraw Contract:
- This contract is an ERC-1155 implementation of various types of NFTs within the AnimeMetaverse platform.
- There are a total of 6 NFT types:
- Merch Tokens
- Gift Box Tokens
- AnimeMetaverse Item Tokens
- Component Tokens
- Booster Tokens
- Digital Merch Tokens
- Each NFT type has a max supply of 100,000.
- A valid Minter address may mint any amount of any NFT, up to the current airdrop limit and maximum supply, to any address at any time with the exception of Digital Merch NFTs.
- A valid Burner address may burn any NFT from any user at any time.
- Users may choose to redeem one of their Merch Token NFTs for a Digital Merchandise NFT when "claim merchandise" is enabled.
- This will burn the user's Merch Token NFT and mint them a new Digital Merchandise NFT.
- The owner may set the airdrop limit to any value between 1 and 10,000 at any time.
- The owner may toggle any address as a valid Minter at any time.
- The owner may toggle any address as a Burner for an NFT type at any time.
- The owner may toggle the ability to claim merchandise at any time.
- This contract allows users to redeem AnimeMetaverseTickets on various Activities for a chance at an AnimeMetaverseReward NFT.
- The AnimeMetaverseTickets contract was out of scope for this audit so we can not give an assessment in regard to security.
- Each Activity has an associated activity type, start time, end time, and max supply of each AnimeMetaverseReward NFT with the exception Digital Merchandise NFTs.
- Users may redeem their tickets by performing a "draw" on an active Activity between the start and end time. Each ticket redeemed will be burned from the user.
- Users must burn at least 1 ticket to draw.
- The maximum amount of tickets a user may burn is equal to the number of remaining NFTS in the Activity.
- A random number will be generated for each ticket burned. This random number is generated through on-chain values and is thus open to potential manipulation.
- Each NFT type within the Activity will be iterated through in order.
- The "index count" will be incremented by the number of remaining NFTs each iteration.
- The user will win the current NFT type if the maximum supply for the Activity has not been reached and the current index count is greater than the randomly generated number.
- The user will be minted the NFT type they won, if applicable.
- The owner may create a new Activity at any time.
- The owner may mark an Activity as active or inactive at any time.
- The owner may update the start and end times for an activity at any time.
- The owner may update the max supply of Gift Box NFTs for any Activity at any time.
- The owner may update the Ticket contract and Rewards contract addresses at any time.
Audit Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Jump/Storage Write | N/A | PASS |
Centralization of Control |
|
WARNING |
Compiler Issues | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | The GachaDraw getRandomNumber() function relies on predictable variables for randomness. | WARNING |
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 |
AnimeMetaverseReward Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [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 #
- [Int] _afterTokenTransfer #
- [Prv] _doSafeTransferAcceptanceCheck #
- [Prv] _doSafeBatchTransferAcceptanceCheck #
- [Prv] _asSingletonArray
+ Ownable (Context)
- [Pub] Constructor #
- [Pub] owner
- [Int] _checkOwner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Int] _transferOwnership #
+ ERC1155Burnable (ERC1155)
- [Pub] burn #
- [Pub] burnBatch #
+ AmvUtils
- [Int] intToString
- [Int] singletonArray
+ [Int] IAnimeMetaverseReward
- [Ext] mintBatch #
- [Ext] forceBurn #
+ AnimeMetaverseReward (ERC1155, Ownable, AmvUtils, IAnimeMetaverseReward)
- [Pub] Constructor #
- modifiers: ERC1155
- [Prv] setTokenInfo #
- [Ext] setMaxAirdropLimit #
- modifiers: onlyOwner
- [Ext] setMinterAddress #
- modifiers: onlyOwner,validAddress
- [Ext] toggleMerchandiseClaim #
- modifiers: onlyOwner
- [Ext] setBurnerAddress #
- modifiers: onlyOwner,validAddress,validTokenType
- [Ext] mintBatch #
- modifiers: onlyMinter,validAddress,validTokenType,validAirdropAmount
- [Int] mintDigitalMerch #
- [Ext] claimMerchandise #
- modifiers: validAddress
- [Ext] forceBurn #
- modifiers: validAddress,onlyBurner
- [Pub] isValidBurner
- [Pub] getTokenType
- [Ext] setURI #
- modifiers: onlyOwner
- [Pub] uri
- [Ext] maxSupply
- modifiers: validTokenType
- [Ext] totalSupply
- modifiers: validTokenType
- [Ext] startIndex
- modifiers: validTokenType
GachaDraw Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Pub] Constructor #
- [Pub] owner
- [Int] _checkOwner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
- [Int] _transferOwnership #
+ [Int] IAnimeMetaverseTicket
- [Ext] burn #
+ [Int] IAnimeMetaverseReward
- [Ext] mintBatch #
- [Ext] forceBurn #
+ GachaDraw (Ownable)
- [Pub] Constructor #
- [Ext] setTicketContract #
- modifiers: onlyOwner,validAddress
- [Ext] setRewardContract #
- modifiers: onlyOwner,validAddress
- [Ext] createActivity #
- modifiers: onlyOwner,validActivityType,validTimestamp
- [Ext] setActivityStatus #
- modifiers: onlyOwner,validActivity
- [Ext] setActivityTimestamp #
- modifiers: onlyOwner,validActivity,validTimestamp
- [Ext] updateGiftBoxSupply #
- modifiers: onlyOwner,validActivity
- [Ext] drawTicket #
- modifiers: validActivity
- [Int] getRandomNumber
- [Ext] getTotalRewardSupply
- [Ext] getMaximumRewardSupply
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.