DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

Denial Of Service

Summary

A user can intiate 0 amount or dust transaction calling bid::fjordAuction and unBid::fjordAuction functions causing delaying of transactions for other users.
https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L143
https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L159C1-L159C46

Vulnerability Details

The vulnerability arises from the ability of users to submit transactions with zero amounts or minimal amounts (dust transactions) to the bid and unBid functions in the FjordAuction contract. These transactions, while having no substantive impact on the auction's state, can cause significant delays and disruptions in the transaction processing for other users.espically when the auction _biddingTime is about to end

Attack Scenario (2 min and auction will end) :

  • TotalTokens = 1000

  • PRECISION_18 = 1e18

  1. Malicous Bidder bid (100 point )

  2. Malicous Bidder Intiate alot Spam 0 amount bidding transactions

  3. Another Bidder trying to bid (100 point)

  4. But he fails since the auctionEnded while processing the spam transactions

  5. The Malicous bidder get more auction Tokens

    1. AuctionTokens With 200 Point Bids ( Normal ) 100 + 100

      1. TotalBids = 200

        1. `multiplier`=TotalTokens*PRECISION_18/TotalBids => 1000 x 1e18 / 200 = 5e18

        2. claimaplePoints=userBids x`multiplier` / PRECISION_18 => 100 x 1e18 / 1e18 = 500 token

    2. userBidsAuctionTokens with 100 Point Bids ( Malicous ) 100 only

      1. `multiplier`=TotalTokens*PRECISION_18/TotalBids => 1000 x 1e18 / 100 = 10e18

      2. claimaplePoints=userBids x `multiplier` / PRECISION_18 => 100 x 10e18 / 1e18 = 1000 token

  • **A malicous Unbider can do the same thing in 'unstake::fjordPoints' function preventing a user from unstaking his points before auction ends **

  • Use this PoC in auction.t.sol

function testSimulationDustTransactionsBlockUserFromBidding() public {
//This test simulate that there is 2 min and auction ends
//@Note I set the biddingTime to 120 seconds for this test
// to simulate the auction ending in 2 minutes
address Malicousbidder = address(0x2);
address bidder = address(0x3);
uint256 bidAmount = 100 ether;
// Time simulation
uint256 startTime = block.timestamp;
uint256 timeIncrement = 10; // Skip in 10-second intervals for this demo
uint auctionRemainingTime = 120; // 2 minutes
deal(address(fjordPoints), bidder, bidAmount);
deal(address(fjordPoints), Malicousbidder, bidAmount);
vm.startPrank(Malicousbidder);
fjordPoints.approve(address(auction), bidAmount);
//RealBid
auction.bid(bidAmount);//he bid 100 ether
while (startTime <=auctionRemainingTime){
// Simulate passing time
skip(timeIncrement);
startTime += timeIncrement;
auction.bid(0);
//after exiting the loop there will be 1 second left
}
// 1 second skipped
skip(1);
//Transaction of another bidder is delayed and the acution is ended
vm.startPrank(bidder);
fjordPoints.approve(address(auction), bidAmount);
vm.expectRevert(FjordAuction.AuctionAlreadyEnded.selector);
auction.bid(bidAmount);
console.log(block.timestamp);
vm.stopPrank();
assertEq(fjordPoints.balanceOf(bidder), bidAmount);
assertEq(fjordPoints.balanceOf(Malicousbidder), 0);
assertEq(fjordPoints.balanceOf(address(auction)), bidAmount);
}

Impact

  1. Prevent A user from particpate in a an active auction => Lead to bigger amount of auction tokens for the malicous bidder

  2. Prevent A user from Unstake His Points before Auction ends => user fjordPoints is burnt

Tools Used

Manual Analysis (vsCode)

Recommendations

  • Enforcing a minimum transaction amount As following can prevent attackers from clogging the network with zero amount or dust transactions.

function bid(uint256 amount) external {
+ uint minAmount = 0.1 ether // put any value
if (block.timestamp > auctionEndTime) {
revert AuctionAlreadyEnded();
}
+ if (amount<minAmount){revert();}
bids[msg.sender] = bids[msg.sender].add(amount);
totalBids = totalBids.add(amount);
fjordPoints.transferFrom(msg.sender, address(this), amount);
emit BidAdded(msg.sender, amount);
}
function unbid(uint256 amount) external {
+ uint minAmount = 0.1 ether // put any value
if (block.timestamp > auctionEndTime) {
revert AuctionAlreadyEnded();
}
+ if (amount<minAmount){revert();}
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoBidsToWithdraw();
}
if (amount > userBids) {
revert InvalidUnbidAmount();
}
bids[msg.sender] = bids[msg.sender].sub(amount);
totalBids = totalBids.sub(amount);
fjordPoints.transfer(msg.sender, amount);
emit BidWithdrawn(msg.sender, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.