CertiK reviewed RealFevr (RealFevr - bridge) on 1 Mar 2024: 29 findings, 0 critical; 13 marked fixed, 3 acknowledged, 13 open.
Report hosted on skynet.certik.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 | 3 | 0 |
| Medium | 3 | 0 | 2 |
| Low | 10 | 0 | 11 |
Function `safeMint()` mints NFT tokens based upon the current value of `lastMintedId`, and increments the value afterward. Function `safeMintTo()` allows the privileged account to specify any `tokenId` but still increments `lastMintedId`. 1. The use of function `safeMintTo()` will cause an issue with function `safeMint()` where, when `lastMintedId` reaches the lowest value used as input `tokenId` in `safeMintTo()`, the function will revert because the tokenId has already been minted. Function `safeMint()` cannot be called again until `safeMintTo()` is called enough times to increment `lastMintedId` to a value that has not been used as an NFT's token Id yet. 2. The increment of `lastMintedId` in function `safeMintTo()` means that `safeMint()` may skip some values rather than minting incrementally. 3. If function `safeMint()` is used to mint a `tokenId`, this may prevent the `ERC721BridgeImpl` contract from successfully minting as needed with function `mintERC721()`. Further, contract `base_erc721` is ownable, meaning that while the `ERC721BridgeImpl` is the `owner`, function `safeMint()` will not be used.
Function `mintERC721()` uses `safeMintTo()` to mint ERC721 tokens to a specified `to` address. This function makes a call to `onERC721Received()` if the `to` address is a contract. If the `to` address is a malicious contract, they may use the call to make extra, unintended calls, before function `setMarketplaceDistributions()` is subsequently called. As a result, the associated marketplace distributions information will not yet be set before the `to` address has an opportunity to use the token in other parts of the protocol. If there are other parts of the protocol that rely on the marketplace distributions information to operate correctly, this may result in an exploit.
Whenever possible, upgradeable versions of OpenZeppelin contracts can be used as inheritances for upgradeable contracts in case the formatting is needed in future upgrades.
Function `takeFees()` is only called in function `depositSingleERC721()`, where the `quantity` parameter is hardcoded as 1. If the quantity is always supposed to be 1, it is unnecessary to include a parameter for it, and `bridgeCost` can be replaced with the `fees` parameter everywhere in the `takeFees()` function.
Please confirm it is intended that `burnToken()` does not include validation and tracking of a `uniqueKey` string like `withdrawERC20()` and `mintToken()`.
The contracts cited are upgradeable. The comment `// impl v2 storage` is noted above state variable `_multiDeposit`, appended after event declaration. Please clarify whether the source code provided is for an upgrade of an existing deployment, or whether this contract is to be deployed for the first time. This information is needed in order to determine whether storage collisions and other inconsistencies during upgrades should be considered.
It is best practice to check input satisfies restrictions before using it to update a corresponding state variable.
### ERC20BridgeImpl - The comment above `setFeeStatus()` misspells the word "status" as "statys." - The comment above `setFeeStatus()` includes the wrong comments for the `active` parameter. - The comment in `createNewToken()` above the `hasRole` checks inaccurately says that only the `DEFAULT_ADMIN_ROLE` or the `BRIDGE` can call the function, but it is only the `DEFAULT_ADMIN_ROLE` or the `OPERATOR` that can call the function. ### ERC721BridgeImpl - The comment above `setFeeStatus()` misspells the word "status" as "statys." - The comment above `setFeeStatus()` includes the wrong comments for the `active` parameter. - The comment in `depositSingleERC721()` above the `ownerOf()` check should be removed before the contract is deployed. - The event `NFTDetailsSet` emitted in function `createERC721()` implies that the use of the created contract is immediately active with the bridge through the `true` bool. Instead, the event should use a `false` bool.
Contract `ERC721BridgeImpl` records the address that deposits each NFT in mapping `nftListPerContract` but this information is never checked in any function before updates to the value in functions `depositSingleERC721()` and `withdrawSingleERC721()`. Contract `ERC20BridgeImpl` records the total running sum of each token a user has deposited into the bridge through mapping `userData`, but this value is never checked within the contract and is not updated further through withdrawals.
Functions `airdrop()` and `airdropD()` do not override the behavior of `_update()`; each function can directly reference this function instead of using the `super` keyword.
The cited errors and events are never used within the contract codebase.
- Variable `maxNFTsPerTx` is never used within the core logic of the contract. - Variable `permittedNFTs[address].feeWithdrawAmount` is never used within the core logic of the contract.
The use of `transferFrom()` allows NFTs to be sent to contracts, even if they do not implement `onERC721Received()`. If an NFT is sent to a contract that cannot manage the NFT sent, it may become stuck in the contract.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (4)
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’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