Closed JayWelsh closed 2 years ago
claimPendingPayout
isn't a method anywhere in the codebase. Not sure what it's referencing.disburseFunds
is called) would revert before doing any damage because sale.state
was called to State.Ended
prior to calling disburseFunds
in the first pass: // Mark sale as settled
sale.state = State.Ended;
sale.outcome = Outcome.Closed;
// Distribute the funds (handles royalties, staking, multisig, and seller)
disburseFunds(_consignmentId, consignment.pendingPayout);
require(sale.state != State.Ended, "Sale has already been settled");
// Distribute the funds (handles royalties, staking, multisig, and seller)
getMarketController().setConsignmentPendingPayout(consignment.id, 0);
disburseFunds(_consignmentId, consignment.pendingPayout);
Addressed by https://github.com/seen-haus/seen-contracts/pull/55
Also makes CEI adjustment to cancelAuction
& cancelAuction
of AuctionEnderFacet.sol
SEF-01M: Double Payout Vulnerability
Description:
The sale system suffers from a double payout vulnerability as the
disburseFunds
function is re-entrant. In detail, a sale canclaimPendingPayout
with the final unit available and during thedisburseFunds
hook in that function purchase the last unit and then callcloseSale
before thesetConsignmentPendingPayout
has been zeroed out. This will lead to the attacker acquiring double the payout at the expense of the system. The same attack vector albeit simplified is applicable for the cancellation of a sale.Example:
Recommendation:
We advise the Checks-Effects-Interactions (CEI) pattern to be conformed to by first nullifying the pending payout and then distributing it to ensure that no such re-entrancy can unfold.