Omniscia Seen Haus Audit
AuctionRunnerFacet Manual Review Findings
AuctionRunnerFacet Manual Review Findings
ARF-01M: Ineffectual Protection & Bid Refund Re-Entrancy
| Type | Severity | Location |
|---|---|---|
| Logical Fault | Major | AuctionRunnerFacet.sol:L116, L128 |
Description:
The bid code refunds the previous buyer's bid before replacing the bid data with the new one. This permits a re-entrancy attack to unfold whereby the current buyer of an auction is informed of the action. As a result, a complex attack can unfold whereby a secondary auction can steal user funds by creating an auction and a corresponding bid, waiting for a victim's outbid and then during the re-entrancy cancelling the auction thereby refunding the bid to the malicious attacker twice while causing the victim's funds to be permanently lost in the contract. We should note that the attack vector is possible due to the fact that the isContract safe-guard is ineffectual and can be bypassed by the constructor of a contract given that it will yield false for a contract in-creation.
Example:
115// Make sure we can accept the caller's bid116require(!AddressUpgradeable.isContract(msg.sender), "Contracts may not bid");117require(block.timestamp >= auction.start, "Auction hasn't started");118if ((auction.state != State.Pending) || (auction.clock != Clock.Trigger)) {119 require(block.timestamp <= endTime, "Auction timer has elapsed");120}121require(msg.value >= auction.reserve, "Bid below reserve price");122
123// If a standing bid exists:124// - Be sure new bid outbids previous125// - Give back the previous bidder's money126if (auction.bid > 0) {127 require(msg.value >= (auction.bid + getPercentageOf(auction.bid, getMarketController().getOutBidPercentage())), "Bid too small");128 auction.buyer.transfer(auction.bid);129 emit BidReturned(consignment.id, auction.buyer, auction.bid);130}131
132// Record the new bid133auction.bid = msg.value;134auction.buyer = payable(msg.sender);135getMarketController().setConsignmentPendingPayout(consignment.id, msg.value);Recommendation:
We advise the Checks-Effects-Interactions (CEI) pattern to be conformed to by applying a pull pattern to bid refunds. If refunds are disbursed immediately, the buyer will be able to outbid the current bidder and generally cause the bid system to be rigged.
Alleviation:
Although the statements were re-ordered to conform to the CEI pattern, the code still performs a regular refund at the end of execution. This allows a smart-contract based bidder to automatically re-bid in the auction. We assume the support of "smart" bidders is intended and as such consider this exhibit dealt with.
ARF-02M: Deprecated Native Asset Transfer
| Type | Severity | Location |
|---|---|---|
| Language Specific | Minor | AuctionRunnerFacet.sol:L128 |
Description:
The transfer member exposed by payable address types has been deprecated as it does not reliably execute and can fail in future updates of the EVM as it forwards a fixed gas stipend which is not compatible with gas cost EIP upgrades such as EIP-2929.
Example:
128auction.buyer.transfer(auction.bid);Recommendation:
We advise a safe wrapper library to be utilized instead such as the sendValue function of the Address library by OpenZeppelin which is guaranteed to execute under all circumstances.
Alleviation:
The codebase was updated to utilize an internal sendValueOrCreditAccount function that attempts to send the native asset to the recipient address and in case the action fails for any reason, the user is given a redeemable credit of their native asset portion. This change has alleviated this exhibit in full.