NettyWorth

Resonance Security6 addresses on Ethereum

Audit · firm’s term: audit report

Resonance Security reviewed NettyWorth on 25 Nov 2024: 20 findings, 3 critical; 19 marked fixed, 1 open.

3 critical findings, fixed
Open the reportOpen NettyWorth’s security record
Report stored on IPFS. Content hash Qmderke4rGECvjuGZwVb7Bm2zH7mnsk9vAayLJiDdChiLg

Trustblock does not review code.

Findings20

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical003
High002
Medium102
Low0012
CriticalCollateral NFTs Can Be Drained By Unauthorized UserFixed

After a loan is created, a NFT that is stored as collateral in the Vault can only be obtained by the lender or borrower after the loan is finished or liquidated.However, it is possible for an unauthorized user to obtain all the nft from the vault. This can be done because the safeBatchTransfer() function allows any user to call it as it is defined as public.

CriticalLoans Cannot Be Liquidated If Promissory Receipt Is TransferredFixed

PromissoryReceipt can be transferred using the transferPromissoryReceipt() function but this will cause a problem in the protocol as the updateLender() function from LoanManager does not update the _assetsHash neither _assets maps from the CryptoVault contract.This prevents liquidation of a loan whose promissory receipt has been transferred by using the correct transferPromissoryReceipt() function.

CriticalTransfer Receipts Not Using The Correct Functions Blocks Payback And Close LoansFixed

PromissoryReceipt and ObligationReceipt can be transferred using the basic functions for transferring NFTs such as safeTransferFrom() or transferFrom() but this will cause a problem in the protocol as it does not update the borrower or lender fields in the LoanManager contract.This prevents liquidation or repayment of a loan whose any of its receipts have been transferred by using any of the methods mentioned above.

HighDefault Loans Could Still Be Paid Back By BorrowersFixed

The protocol allows a loan that has been finalized to be repaid as long as it is not liquidated. This makes the interest and the fees incorrect.The borrower could wait until lender calls forCloseLoan() function to frontrun him and close the loan by calling payBackLoan() and obtain a loan for a longer period than initially stated.

HighExecution At Deadlines Should Be AllowedFixed

When a loan is created, both parties agree on the loan duration. The protocol implements mechanisms to avoid lenders to liquidate the loan before it ends but it is still possible for lenders to liquidate a loan in the last block of the loan period.The forCloseLoan() function should check if the block.timestamp is greater than loan.loanDuration instead of checking if it is greater or equal.This may result in borrowers potentially losing the collateral NFT at the last timestamp of the loan's duration.

MediumLoans With High APR Cannot Be Paid BackFixed

The createLoan() function allows the creation of a loan with an _aprBasisPoints higher than 100%.When a borrower tries to payback a loan with this huge rate, the require that checks the loan.aprBasisPoints in the getPayoffAmount() function will revert.

MediumUnsafe DowncastFixed

When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs.In this protocol, failures caused by collisions could lead to errors in loan creation.

Low++i/i++ Should Be unchecked{++i}/unchecked{i++}Fixed

When it is not possible for counters to overflow, as is the case when used in for and while-loops, they should be unchecked. The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop.

Lowabi.encodePacked() Should Not Be Used With Dynamic Types When Passing The Result To A Hash Function Such As keccak256()Fixed

Unless there is a compelling reason, abi.encode() should be preferred instead of abi.encodePacked().abi.encode() will pad parameters to 32 bytes, which will prevent hash collisions.For example, abi.encodePacked(0x123,0x456) returns 0x123456 which will collide with abi.encodePacked(0x1,0x23456). but abi.encode(0x123,0x456) will result in 0x0...1230...456If there is only one argument to abi.encodePacked() it can often be cast to bytes() or bytes32() instead.If all arguments are strings and or bytes, bytes.concat() should be used instead.It should be noted that the severity of this finding has been decreased since no dynamic types are being used inside the function abi.encodePacked().

LowadminFee Can Be Set To 100%Fixed

The updateAdminFee() function allows an owner to set a fee of 100% which may not be practical or could be considered predatory lending.

Show 9 more
LowConsider Disabling renounceOwnership()Fixed

As NettyWorth does not include eventually giving up all ownership control, consider overwriting OpenZeppelin's Ownable's renounceOwnership() function in order to disable it.This will prevent the protocol from being left unattended in the event that the owners renounce ownership.

LowCritical Changes Should Use Two-step ProcedureFixed

The critical procedures used to change proxies, fees or owners in this protocol should use a two step process in order to ensure the modification is indeed intended.

LowEvents That Mark Critical Parameter Changes Should Contain Both The Old And The New ValueFixed

UpdatedAdminWallet() and UpdatedAdminFee() events should emit the previous information and the new one to improve traceability.This should especially be done if the new value is not required to be different from the old value

LowIncorrect Calculation Of Array Sizes For Allowed/Blocked Collection And TokensFixed

When an owner wants to add/remove collections or allowed tokens, he calls the whitelistCollection contract functions with the array of addresses he wants to add/remove.In case this array has only one element, the calculation of the collection/tokens total will be wrong, since it subtracts 1 from the array size (which will be 1) and adds it to the total, meaning no increment or decrement.

LowNew Deployment Causes Loss Of Information About Used NoncesFixed

During loan creation, the protocol calls the SignatureUtils contract that manages and validates the signatures of the lender and borrower.The functions used for these validations use a nonce that is previously validated and stored in the _nonceUsedForUser mapping from the proxy, so it can only be used once per loan.In case that a new version of the contract is deployed, the _nonceUsedForUser mapping will be empty and the data in the old contract will not be accessible, allowing the reuse of nonces and the replay of signatures.

LowNon-external Function Names (Private Or Internal) Should Begin With An UnderscoreFixed

According to the Solidity Style Guide, non-external function names should begin with an underscore.

LowNon-external Variable (Private Or Internal) Should Begin With An UnderscoreFixed

According to the Solidity Style Guide, non-external variable names should begin with an underscore.

LowPossible Scenario For Signature Replay AttackFixed

The validateNftDepositSignature() function validates the deposit of an NFT. This function does not use any nonce, allowing a malicious user to replay the signature.This function is not currently used in the protocol, so exploitation is not possible. However, when it starts being used, this vulnerability would arise and negatively affect the protocol.

LowPotential Interest Calculation Precision IssuesFixed

In Solidity, dividing integers truncates the result to the nearest smallest integer, meaning that any fractional part of the result is discarded.The function getPayoffAmount() multiplies three values: loanAmount, aprBasisPoints, and loanDurationinSeconds and then, the result is divided by (BPS * SECONDS_IN_YEAR).This division might result in a loss of precision in cases where the product of (loanAmount * aprBasisPoints * loanDurationinSeconds) is not perfectly divisible by and is less than (BPS * SECONDS_IN_YEAR). This truncation could lead to small differences in the calculated interest, particularly for loans with:Short durationsSmall loan amountsLow APR values

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Part of NettyWorth’s security record

NettyWorth
Audits1 audit by 1 firmLast audit Nov 2024, by Resonance Security.
Critical findingsNo open critical findingsIn that report, 3 critical findings were reported. Each is marked fixed by the firm that reported it.
Open NettyWorth’s security record

Security firm

Resonance Security

18 projects reviewed · 25 reports · latest Aug 2025

See Resonance Security’s audits

Something 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