This finding relates to front-running opportunities in Lender.sol and the associated increasing costs within this system.
In the absence of protective mechanisms, transactions that spot lucrative opportunities may be outpaced by others willing to pay higher gas prices, resulting in the original transaction's failure.
Such situations could arise in the borrow() function where two competing borrowers might inflate their gas prices to secure the same pool.
This elevates the gas costs associated with system usage.
The same problem arises during buyLoan() with multiple parties driving up gas prices for the same loan auction.
Similarly, in the giveLoan() function, multiple parties might compete to assign their loan to another lender's pool.
Front-running can substantially increase users' transaction costs, especially in competitive contracts with numerous users.
The issue might not directly risk funds in the traditional sense of theft or loss, but it poses a significant indirect risk. Users could be consistently outbid, leading to financial loss due to wasted transactions. As mentioned, in competitive environments, this could lead to substantial costs.
Consequently, consistent transaction failures or high fees could damage the system's reputation, causing users to rethink using the service.
Manual audit.
Despite the complexity they can add to the system, I recommend using:
Commitment-reveal schemes π‘
The added complexity is worth it when considering the potential discontent from clients and the competitive edge that a similar protocol could gain if they adopted such measures.
π Notice βΉοΈ: Commitment-reveal schemes can also solve some block validators' abuse the
Lender.solcontract has due to the use of block.timestamp. I've submitted the details in another finding.
π§ Note β οΈ: Commitment-reveal schemes are not straightforward. After their implementation, a subsequent audit is essential.
π Commit Phase:
Users send a hashed combination of their choice (function selector to call and the desired value of the inputs, for example) and a secret value (like a nonce or a random number) to the contract.
This hashed value represents their "commitment" and is stored without revealing the actual choice.
π΅οΈ Reveal Phase:
After all commitments are received, users are required to send their original choice and secret value during the reveal phase.
The contract then verifies the commitment by hashing the revealed data and comparing it with the stored hash.
π¬ Action Phase:
Once all relevant reveals are completed and verified, the desired function (like borrow(), buyLoan(), or giveLoan()) is executed based on the revealed choices.
π‘οΈ Guard Measures:
To prevent participants from not revealing after committing, consider implementing penalties or incentives.
Use time-bound mechanisms to transition between commit, reveal, and action phases.
β Integrity Checks:
Ensure that the contract logic accounts for cases where users send incorrect reveal data or fail to reveal within the allocated time.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.