-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Alert Bronze Donkey
Medium
User can set extremely short deadlines leading to failed transactions
Summary
The lack of minimum deadline validation in PinlinkShop.sol
will cause transaction failures for buyers as sellers can set deadlines just seconds ahead, making it impossible to execute purchases in high network activity.
Root Cause
In PinlinkShop.sol:_list()
the deadline validation only checks if it's greater than current timestamp:
require(deadline > block.timestamp, DeadlineHasExpiredAlready());
This allows deadlines to be set just seconds into the future.
Internal Pre-conditions
- Seller needs to call
list()
with a deadline just seconds ahead ofblock.timestamp
- Number of concurrent buyers in the market to be at least 1
- The listing must have a reasonable price to attract buyers
External Pre-conditions
- Network must have normal or high congestion (>10 second block times)
- Gas price fluctuations causing transaction delays
Attack Path
- Malicious seller creates a listing with attractive price and deadline =
block.timestamp + 5 seconds
- Legitimate buyers attempt to purchase but transactions fail with
ListingDeadlineExpired()
- Seller repeats this pattern to:
- Discourage buyers
- Create false impression of market activity
- Manipulate price discovery
Impact
The protocol suffers from market manipulation and reduced usability. Buyers waste gas on failed transactions. The attacker can control market price discovery through artificial scarcity.
PoC
PoC
function testShortDeadlineGriefing() public {
// Setup
uint256 listAmount = 100;
uint256 pricePerToken = 10e18; // 10 USD per token
vm.startPrank(alice);
// Create listing with extremely short deadline
bytes32 listingId = pshop.list(
address(fractions),
tokenId,
listAmount,
pricePerToken,
block.timestamp + 5 // 5 second deadline
);
vm.stopPrank();
// Bob attempts to buy
vm.startPrank(bob);
uint256 buyAmount = 50;
uint256 pinAmount = pshop.getQuoteInTokens(listingId, buyAmount);
PIN.approve(address(pshop), pinAmount);
// Simulate network congestion
vm.warp(block.timestamp + 6);
// Purchase fails due to expired deadline
vm.expectRevert(PinlinkShop.ListingDeadlineExpired.selector);
pshop.purchase(listingId, buyAmount, pinAmount);
vm.stopPrank();
}
Recommendation
Implement a minimum deadline duration of 15 minutes to:
- Allow sufficient time for transactions to execute
- Account for network congestion
- Prevent market manipulation through short deadlines
- Improve user experience by reducing failed transactions
Mitigation
Add minimum deadline duration check in _list()
:
function _list(
address fractionalAssets,
uint256 tokenId,
uint256 amount,
uint256 usdPricePerFraction,
uint256 deadline
) internal returns (bytes32 listingId) {
require(deadline >= block.timestamp + 15 minutes, "Deadline too short");
require(deadline > block.timestamp, DeadlineHasExpiredAlready());
// ... rest of function
}
Metadata
Metadata
Assignees
Labels
No labels