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

Temporal Manipulation of Auction End Time

Summary

The FjordAuction contract is susceptible to timestamp manipulation due to its reliance on block.timestamp for determining the auction end time. This vulnerability allows miners to slightly adjust the auction duration, potentially providing an unfair advantage to certain participants.

auctionEndTime = block.timestamp.add(_biddingTime);

Vulnerability Details

https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L120-L137

1.Timestamp Dependency:

  • The contract's constructor sets auctionEndTime using block.timestamp + _biddingTime.

  • This makes the auction duration dependent on the block's timestamp at the time of deployment.

2.Miner Manipulation:

  • Miners can adjust block.timestamp (up to 15 seconds forward or backward).

  • By mining the block in which the auction is deployed, a miner can manipulate the timestamp to extend or shorten the auction duration.

3.Proof of Concept:

  • Deploy the FjordAuction contract with a specified biddingTime.

  • Use a testing framework to simulate a miner setting block.timestamp slightly ahead.

  • Verify that auctionEndTime is extended beyond the intended duration.

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity =0.8.21;
import "forge-std/Test.sol";
import "../src/FjordAuction.sol";
import { ERC20, ERC20Burnable } from "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol";
// Mock ERC20Burnable contract
contract MockERC20Burnable is ERC20Burnable {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract FjordAuctionTest is Test {
FjordAuction auction;
MockERC20Burnable fjordPoints;
MockERC20Burnable auctionToken;
address miner = address(0x1337);
uint256 biddingTime = 3600; // 1 hour
uint256 totalTokens = 1000 * 1e18;
function setUp() public {
fjordPoints = new MockERC20Burnable("Fjord Points", "FJP");
auctionToken = new MockERC20Burnable("Auction Token", "AUC");
fjordPoints.mint(miner, 1000 * 1e18);
auctionToken.mint(miner, totalTokens);
}
function testTimestampManipulation() public {
// Simulate miner setting block.timestamp slightly ahead
uint256 manipulatedTimestamp = block.timestamp + 15;
vm.warp(manipulatedTimestamp);
// Deploy the auction contract with manipulated timestamp
vm.startPrank(miner);
auction = new FjordAuction(address(fjordPoints), address(auctionToken), biddingTime, totalTokens);
vm.stopPrank();
// Check if auctionEndTime is extended
uint256 expectedEndTime = manipulatedTimestamp + biddingTime;
assertEq(auction.auctionEndTime(), expectedEndTime, "Auction end time should be extended due to timestamp manipulation");
// If the assertion passes, the test will show [PASS]
}
}
forge test --match-path test/FjordAuctionTest.t.sol -vvvv
[⠊] Compiling...
[⠒] Compiling 1 files with Solc 0.8.21
[⠢] Solc 0.8.21 finished in 1.92s
Compiler run successful!
Ran 1 test for test/FjordAuctionTest.t.sol:FjordAuctionTest
[PASS] testTimestampManipulation() (gas: 750384)
Traces:
[750384] FjordAuctionTest::testTimestampManipulation()
├─ [0] VM::warp(16)
│ └─ ← [Return]
├─ [0] VM::startPrank(0x0000000000000000000000000000000000001337)
│ └─ ← [Return]
├─ [696022] → new FjordAuction@0x03F1B4380995Fbf41652F75a38c9F74aD8aD73F5
│ └─ ← [Return] 2921 bytes of code
├─ [0] VM::stopPrank()
│ └─ ← [Return]
├─ [318] FjordAuction::auctionEndTime() [staticcall]
│ └─ ← [Return] 3616
├─ [0] VM::assertEq(3616, 3616, "Auction end time should be extended due to timestamp manipulation") [staticcall]
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.29ms (1.37ms CPU time)
Ran 1 test suite in 1.18s (5.29ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

Impact

  • Miners who participate in the auction can manipulate the end time to gain more time for placing bids or to cut off other participants early.

  • The integrity of the auction process is compromised, as participants cannot rely on a fixed auction duration.

  • Participants may have their bidding strategies disrupted due to unexpected changes in auction timing.

Tools Used

  • Manual review

  • Foundry

Recommendations

  • Instead of relying on block.timestamp, consider using block.number to determine the auction end. Calculate the end block based on an estimated average block time.

  • Introduce a buffer period to mitigate minor timestamp manipulations, ensuring that small adjustments by miners do not significantly impact the auction outcome.

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.