CertiK reviewed Lifty Gaming (Lifty) on 21 Apr 2023: 11 findings, 0 critical; 5 marked fixed, 5 acknowledged, 1 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 | 1 | 0 | 0 |
| Medium | 0 | 0 | 1 |
| Low | 0 | 5 | 4 |
The function `transferPaymentAndFees()` is checking if the royalties are set using the boolean `royaltiesApplied`. The `royaltiesApplied` boolean will be set to `true` if the condition `assets.length == 1` is met.\ This is likely during some calls to the function `buy()`. ```solidity=54 transferPaymentAndFees(from,to,payment[i],assets[0],assets.length == 1,amount); ``` In the case of the boolean `royaltiesApplied` is `true`, the contract `OrderFulfiller` will call the following statement: ```solidity=115 IERC165(collection).supportsInterface(INTERFACE_ID_FEES); ``` This will check if the `collection` support the interface `INTERFACE_ID_FEES`, but because the ERC20 standard does not have the `supportsInterface()` function, this will revert and can lead to a Denial of Service during the calls to the `buy()` function.
When changing the fees of a token, there is a check to ensure that the seller fee and the buyer fee are both less than 100%. ```solidity=148 function changeMarketplaceCollectionFee( address collection, uint16 buyerFee, uint16 sellerFee ) external onlyOwner { require( sellerFee < 10000 && buyerFee < 10000, "FeeProvider: wrong fee amount" ); ``` However, this check is insufficient as both seller and buyer fees are applied to an order amount, meaning that the sum of the fees should be less than 100%. ```solidity=92 uint256 buyerFee = calculateFee( payment.amount, marketplaceFee.buyerFee ); uint256 sellerFee = calculateFee( payment.amount, marketplaceFee.sellerFee ); fee = (buyerFee + sellerFee) * amount; ```
There is no explicit check that each order meant to be filled in a `buy()` call has not expired yet. The only check involving expiration is that an operator has signed the order hashes along with an `expiredAt` time that is in the future. ```solidity=73 require(expiredAt > block.timestamp, "Buy: the deal is expired."); require( verifyDealSign(expiredAt, dealSign, ordersHashes), "Buy: wrong deal signature" ); ``` Since this `expiredAt` time is not compared with an order's expiration time, an operator is able to approve a deal involving an already expired order.
Addresses should be checked before assignment or external call to make sure they are not zero addresses. ```solidity=142 feesBeneficiary = newFeesBeneficiary; ``` - `newFeesBeneficiary` is not zero-checked before being used.
The functions `ECDSA.recover` and `ECDSA.tryRecover` are vulnerable to a kind of signature malleability due to accepting EIP-2098 compact signatures in addition to the traditional 65-byte signature format. This is only an issue for the functions that take a single bytes argument, and not the functions that take `r, v, s` or `r, vs` as separate arguments. Reference: https://github.com/advisories/GHSA-4h98-2769-gh6h
| Address | Chain | Source code |
|---|---|---|
| 0xa4b7…a5290xa4b71b99eef99ea217adb7e3641cb3e779eaa529 | Chain: Ethereum | Source code: Verified source |
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