Function: postFillOrder(address account, PostFillOrderArgs args)
This function allows to fill a buy and sell order for the account. It can be called by the account itself or an operator authorized for this account. Also, this function is designed to handle matching with existing orders. It provides the execution result to the CLOBManager contract for token settlement and applies fees. The postFillOrder function reverts if the type of the order is FILL_OR_KILL and the order was not fully filled during matching. If the fillOrderType is IMMEDIATE_OR_CANCEL, the order may be partially filled.
Inputs
accountControl: Full control.
Constraints: Should be
msg.senderitself or an approved operator for theaccount.Impact: The account on whose behalf the order is being filled.
argsControl: Full control.
Constraints:
args.priceLimit % tickSize == 0 && args.priceLimit != 0.Impact: Contains
amount,priceLimit,side,amountIsBase,fillOrderType, andsettlement.
Branches and code coverage
Intended branches
The order type is
FILL_OR_KILL, the order was fully filled, and theargs.amountIsBaseistrue.The order type is
FILL_OR_KILL, the order was fully filled, and theargs.amountIsBaseisfalse.The order type is
IMMEDIATE_OR_CANCEL, the order was partly filled, and theargs.amountIsBaseistrue.The order type is
IMMEDIATE_OR_CANCEL, the order was partly filled, and theargs.amountIsBaseisfalse.The order type is
IMMEDIATE_OR_CANCEL, the order was fully filled, and theargs.amountIsBaseistrue.The order type is
IMMEDIATE_OR_CANCEL, the order was fully filled, and theargs.amountIsBaseisfalse.The
takerFeeis equal to the expected amount.The multiple expired orders have been closed and fee was not charged from them.
There were multiple matches, and the maker fee is equal to the expected amount.
Negative behavior
The order type is
FILL_OR_KILL, the order was not fully filled, and theargs.amountIsBaseistrue.The order type is
FILL_OR_KILL, the order was not fully filled, and theargs.amountIsBaseisfalse.The caller is not an
accountoroperatorof the account.
Function call analysis
BookLib.assertLimitPriceInBounds(ds, args.priceLimit)What is controllable?
args.priceLimit.If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? Reverts if
priceLimitis zero orprice % tickSize != 0.
BookLib.incrementNextOrderId(ds)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the next order ID.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
OrderLib.toOrder(args, orderId, account)What is controllable?
args.side,args.amount, andargs.price.If the return value is controllable, how is it used and how can it go wrong? Returns the new
Orderobject.What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> BookLib.getBestAsk(ds)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the best minimum price
askTree.minimum().What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> OrderLib.isExpired(bestAskOrder)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns true when the
cancelTimestampis not null and is less than the currentblock.timestamp; otherwise, it returns false.What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._removeExpiredAsk(ds, bestAskOrder) -> TransientMakerData.addBaseToken(order.owner, baseTokenAmount)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here. The
baseAmountwill be saved for the owner of the expired order in theTransientMakerDatamemory.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._removeExpiredAsk(ds, bestAskOrder) -> BookLib.removeOrderFromBook(ds, order)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? The
metadata.quoteTokenOpenInterestandmetadata.baseTokenOpenInterestwill be decremented — depends on the side of the order, andorder.idwill be deleted from theorderslist. Also,bidTreeandaskTreewill be updated in addition toorders.nextOrderIdandorders.prevOrderId.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> FixedPointMathLib.min(matchedBase, incomingOrder.amount)What is controllable?
incomingOrder.amount.If the return value is controllable, how is it used and how can it go wrong? Returns the minimum value between
matchedBaseandincomingOrder.amount.What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> BookLib.getQuoteTokenAmount(ds, matchedPrice, matchData.baseDelta)What is controllable? If the provided
incomingOrder.amountis less thanmatchedBase, thematchData.baseDeltawill be equal to theincomingOrder.amountand fully controlled by the caller.If the return value is controllable, how is it used and how can it go wrong? Returns the quote-tokens amount calculated using the provided
matchedPriceandmatchData.baseDeltaamount. The result can be rounded down to zero ifmatchData.baseDelta * matchedPriceis less thanconfig.baseSize.What happens if it reverts, reenters or does other unusual control flow? Can revert as a result of overflow during
matchData.baseDelta * matchedPricecalculation ifmatchedPriceormatchData.baseDeltais too large.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> FixedPointMathLib.min(matchedBase, BookLib.getBaseTokenAmount(ds, matchedPrice, incomingOrder.amount))What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the minimum amount between the
matchedBaseand the result of thegetBaseTokenAmountfunction execution, which calculates the base-token amount using the provided-by-the-callerincomingOrder.amountand thematchedPrice.What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> BookLib.getBaseTokenAmount(ds, matchedPrice, incomingOrder.amount)What is controllable?
incomingOrder.amount.If the return value is controllable, how is it used and how can it go wrong? Returns the base-token amount, which is calculated using the provided-by-the-caller
incomingOrder.amountand thematchedPrice. Can return zero ifquoteAmount * self.config.baseSizeis less thanprice.What happens if it reverts, reenters or does other unusual control flow? Can revert as a result of overflow during
quoteAmount * self.config.baseSizecalculation ifquoteAmountis too large.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> BookLib.getQuoteTokenAmount(ds, matchedPrice, matchData.baseDelta)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the quote-tokens amount calculated using the provided
matchedPriceandmatchData.baseDeltaamount. The result can be rounded down to zero ifmatchData.baseDelta * matchedPriceis less thanconfig.baseSize.What happens if it reverts, reenters or does other unusual control flow? Can revert as a result of overflow during
matchData.baseDelta * matchedPricecalculation ifmatchedPriceormatchData.baseDeltais too large.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> TransientMakerData.addQuoteToken(matchedOrder.owner, matchData.quoteDelta)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here. The
matchData.quoteDeltawill be saved for the owner of the matched order in theTransientMakerDatamemory.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> TransientMakerData.addBaseToken(matchedOrder.owner, matchData.baseDelta)What is controllable?
matchData.baseDeltacan be controlled by the caller, if this amount is less than thematchedOrder.amount.If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here. The
matchData.baseDeltawill be saved for the owner of the matched order in theTransientMakerDatamemory.
this._processFillBidOrder(ds, account, newOrder, args) -> this._matchIncomingBid(ds, newOrder, args.amountIsBase) -> this._matchIncomingOrder(ds, bestAskOrder, incomingOrder, incomingOrder.amount, amountIsBase) -> BookLib.removeOrderFromBook(ds, matchedOrder)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? The
metadata.quoteTokenOpenInterestandmetadata.baseTokenOpenInterestwill be decremented — depends on the side of the order, andorder.idwill be deleted from theorderslist. Also,bidTreeandaskTreewill be updated in addition toorders.nextOrderIdandorders.prevOrderId.
this._processFillBidOrder(ds, account, newOrder, args) -> this._settleIncomingOrder(ds, account, Side.BUY, args.settlement, result.totalQuoteTokenSent, result.totalBaseTokenReceived) -> TransientMakerData.getMakerCreditsAndClearStorage()What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the current state of the maker's credits, including the expired orders and matched orders.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillBidOrder(ds, account, newOrder, args) -> this._settleIncomingOrder(ds, account, Side.BUY, args.settlement, result.totalQuoteTokenSent, result.totalBaseTokenReceived) -> factory.settleIncomingOrder(settleParams)What is controllable?
settleParams.taker,settleParams.side, andsettleParams.settlementare controlled by the caller.If the return value is controllable, how is it used and how can it go wrong? Returns the
takerFeeamount, which is used for events and as a part of the returnedPostFillOrderResult.What happens if it reverts, reenters or does other unusual control flow? If
settlementis set toINSTANT, the function might revert duringsafeTransferFromif the taker does not have enough balance or has not approved a sufficient allowance. Also, it reverts if the balance of the factory contract is not enough to transfer tokens to the taker. Ifsettlementis set toACCOUNT, the function might revert during thedebitAccountfunction call if the taker does not have enough internal token balance.
this._processFillAskOrder(ds, account, newOrder, args) -> this._matchIncomingAsk(ds, newOrder, args.amountIsBase) -> BookLib.getBestBid(ds)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the best maximum price
bidTree.minimum().What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillAskOrder(ds, account, newOrder, args) -> this._matchIncomingAsk(ds, newOrder, args.amountIsBase) -> OrderLib.isExpired(bestBidOrder)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns true when the
cancelTimestampis not null and is less than the currentblock.timestamp; otherwise, it returns false.What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillAskOrder(ds, account, newOrder, args) -> this._matchIncomingAsk(ds, newOrder, args.amountIsBase) -> this._removeExpiredBid(ds, bestBidOrder) -> BookLib.getQuoteTokenAmount(ds, order.price, order.amount)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? Returns the quote-tokens amount calculated using the expired
order.priceandorder.amount. The result can be rounded down to zero iforder.amount * order.priceis less thanconfig.baseSize.What happens if it reverts, reenters or does other unusual control flow? Can revert as a result of overflow during
order.amount * order.pricecalculation iforder.priceororder.amountis too large.
this._processFillAskOrder(ds, account, newOrder, args) -> this._matchIncomingAsk(ds, newOrder, args.amountIsBase) -> this._removeExpiredBid(ds, bestBidOrder) -> TransientMakerData.addQuoteToken(order.owner, quoteTokenAmount)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? There are no problems here.
this._processFillAskOrder(ds, account, newOrder, args) -> this._matchIncomingAsk(ds, newOrder, args.amountIsBase) -> this._removeExpiredBid(ds, bestBidOrder) -> BookLib.removeOrderFromBook(ds, order)What is controllable? N/A.
If the return value is controllable, how is it used and how can it go wrong? This function does not return a value.
What happens if it reverts, reenters or does other unusual control flow? The
metadata.quoteTokenOpenInterestandmetadata.baseTokenOpenInterestwill be decremented — depends on the side of the order, andorder.idwill be deleted from theorderslist. Also,bidTreeandaskTreewill be updated in addition toorders.nextOrderIdandorders.prevOrderId.