Quantstamp reviewed Petaverse on 3 Mar 2023: 19 findings, 0 critical; 12 marked fixed, 6 acknowledged, 1 open.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 1 |
| Medium | 0 | 0 | 1 |
| Low | 1 | 6 | 10 |
Currently, the team describes that cloned Pets are transferred back to a holding contract if the original Pet is burned. Although these clones may be held by the team instead of individual accounts, they still exist on-chain and can have their clone status modified to be an original, therefore recreating a Pet that was already burned.
Currently, `Voucher.redeemVoucherTo()` does not support the redemption of Vouchers, as nothing is ensuring that the token for the specified `_voucherTokenId` is held by the contract before burning it. Therefore, calls to `redeemVoucherTo()` will fail if the token is not held by the contract.
In `Pet.multiMintTo()`, the mint function does not take into account the previous custodial status of the accounts being minted tokens to, allowing for it to be possible to overwrite the custodial status of a `to` address that has been previously assigned to be a custodian, as a result of some oversight.
The Admin role that belongs to the multisig wallet, as stated in the docs, can mark any address to be custodial. This means the address with the Custodial role, which is also the Admin address, can freely transfer the assets of Custodial wallets. Aside from possible exploits in the case of multisig compromise, this structure can damage the public view and reputation of the protocol, as it is highly centralized. The Cloner role also has full control over changing the clone status of an asset. This means that even though an asset is marked as a clone on one chain, it can be marked as original through the `setClone()` function by the Cloner role. changing from original to clone is also possible. This can cause more confusion for the admins and the end users, and affect the overall integrity of the protocol. Specifically, here is the full list of privileged roles: The Pet contract has a DEFAULT_ADMIN_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole()</li> <li>Grant/Revoke roles</li> <li>setBaseURI(..)</li> <li>setCustodial(..)</li> <li>setOperatorFilterRegistry(..)</li> <li>setRoyaltyInfo(..)</li> <li>setIMX(..)</li> </ul> a MINTER_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole()</li> <li>mintTo(..), multiMintTo(..)</li> <li>mintToContract(..), multiMintToContract(..))</li> <li>Approve addresses to transfer contract-owned Pets.</li> <li>Transfer contract owned Pets.</li> <li>Sign messages for Voucher minting.</li> </ul> a CLONER_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole()</li> <li>setClone(..)</li> <li>Approve addresses to transfer any cloned Pet.</li> <li>Transfer any cloned Pet..</li> </ul> a CUSTODIAL_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole().</li> <li>Approve addresses to transfer Pets from custodial accounts.</li> <li>Transfer any Pets from custodial accounts.</li> </ul> The Voucher contract has a DEFAULT_ADMIN_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole().</li> <li>setBaseURI(..)</li> <li>setOperatorFilterRegistry(..)</li> <li>setRoyaltyInfo(..)</li> <li>Withdraw native tokens from the contract.</li> </ul> a REDEEMER_ROLE who can: <ul> <li>Renounce their role and disable all of the following listed actions by calling renounceRole().</li> <li>redeemVoucherTo(..)</li> </ul>
If the `DEFAULT_ADMIN_ROLE` is renounced without assigning a new admin, all the contracts will be left without an admin. Consequently, any function guarded by the `getRoleAdmin()`function will no longer be able to be executed.
It is possible for the same TokenId to be minted simultaneously cross-chain. Preventing the withdrawal of the newly minted L2 token to L1, due to the tokenId already existing. Note that this case is concerned with minting through ImmutableX L2.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (4)
236 projects reviewed · 333 reports · latest Oct 2026
See Quantstamp’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us