Reading audit reports can increase your security knowledge and help you avoid new types of bugs in your protocol. Here is a great example of how the same signature check can cause trouble. Take a look at two code snippets:
function refinanceFull(
RenegotiationOffer calldata _renegotiationOffer,
Loan memory _loan,
bytes calldata _renegotiationOfferSignature
) external nonReentrant returns (uint256, Loan memory) {
...
if (lenderInitiated) {
if (_isLoanLocked(_loan.startTime, _loan.startTime + _loan.duration)) {
revert LoanLockedError();
}
...
} else if (msg.sender != _loan.borrower) {
revert InvalidCallerError();
} else {
/// @notice Borrowers clears interest
@> _checkSignature(_renegotiationOffer.lender, _renegotiationOffer.hash(), _renegotiationOfferSignature);
netNewLender -= totalAccruedInterest;
totalAccruedInterest = 0;
}
and the second one:
function addNewTranche(
RenegotiationOffer calldata _renegotiationOffer,
Loan memory _loan,
bytes calldata _renegotiationOfferSignature
) external nonReentrant returns (uint256, Loan memory) {
...
uint256 loanId = _renegotiationOffer.loanId;
_baseLoanChecks(loanId, _loan);
_baseRenegotiationChecks(_renegotiationOffer, _loan);
@> _checkSignature(_renegotiationOffer.lender, _renegotiationOffer.hash(), _renegotiationOfferSignature);
if (_loan.tranche.length == getMaxTranches) {
revert TooManyTranchesError();
}
So when lender signs RenegotiationOffer, it is meant to replace tranche, i.e. execute refinanceFull(). But a malicious user can use this sign and front-run execute addNewTranche().
addNewTranche() doesn’t limit the RenegotiationOffer too much. The newly generated Loan will be approximately twice the total amount borrowed, and the risk of borrowing against the lender will increase dramatically.
As a simple bug fix you can add a type field to differentiate between signatures.
Read the full report here:
#signature
#maliability
Completely free courses
Learn more about the blockchain world
Free education videos
by RareSkills
by Jeiwan
by RareSkills
by RareSkills
by Andreas M. Antonopoulos, Gavin Wood
by Micah Dameron
Compare execution layer differences between chains
Dive deep into the storage of any contract