-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
client/core,eth: Lock funds for refund #1479
Changes from all commits
e0d31a1
1219455
6c8fcc1
8549c5e
bdb6960
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -810,8 +810,10 @@ func (dc *dexConnection) reconcileTrades(srvOrderStatuses []*msgjson.OrderStatus | |
(!trade.isMarketBuy() || len(trade.matches) == 0) { | ||
if trade.isMarketBuy() { | ||
trade.unlockRedemptionFraction(1, 1) | ||
trade.unlockRefundFraction(1, 1) | ||
} else { | ||
trade.unlockRedemptionFraction(trade.Trade().Remaining(), trade.Trade().Quantity) | ||
trade.unlockRefundFraction(trade.Trade().Remaining(), trade.Trade().Quantity) | ||
} | ||
} | ||
// Now update the trade. | ||
|
@@ -4007,7 +4009,8 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
} | ||
fromWallet, toWallet := wallets.fromWallet, wallets.toWallet | ||
|
||
accountRedeemer, isAccountRedemption := toWallet.Wallet.(asset.AccountRedeemer) | ||
accountRedeemer, isAccountRedemption := toWallet.Wallet.(asset.AccountLocker) | ||
accountRefunder, isAccountRefund := fromWallet.Wallet.(asset.AccountLocker) | ||
|
||
prepareWallet := func(w *xcWallet) error { | ||
// NOTE: If the wallet is already internally unlocked (the decrypted | ||
|
@@ -4054,7 +4057,7 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
if form.IsLimit && !form.Sell { | ||
fundQty = calc.BaseToQuote(rate, fundQty) | ||
} | ||
redemptionLots := lots | ||
redemptionRefundLots := lots | ||
|
||
isImmediate := (!form.IsLimit || form.TifNow) | ||
|
||
|
@@ -4077,7 +4080,7 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
if err == nil { | ||
baseQty := calc.QuoteToBase(midGap, fundQty) | ||
lots = baseQty / lotSize | ||
redemptionLots = lots * marketBuyRedemptionSlippageBuffer | ||
redemptionRefundLots = lots * marketBuyRedemptionSlippageBuffer | ||
if lots == 0 { | ||
err = newError(orderParamsErr, | ||
"order quantity is too low for current market rates. "+ | ||
|
@@ -4192,7 +4195,7 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
// Everything is ready. Send the order. | ||
route, msgOrder, msgTrade := messageOrder(ord, msgCoins) | ||
|
||
// If the to asset is an AccountRedeemer, we need to lock up redemption | ||
// If the to asset is an AccountLocker, we need to lock up redemption | ||
// funds. | ||
var redemptionReserves uint64 | ||
if isAccountRedemption { | ||
|
@@ -4203,17 +4206,31 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
if len(pubKeys) == 0 || len(sigs) == 0 { | ||
return nil, 0, newError(signatureErr, "wrong number of pubkeys or signatures, %d & %d", len(pubKeys), len(sigs)) | ||
} | ||
redemptionReserves, err = accountRedeemer.ReserveN(redemptionLots, wallets.toAsset.MaxFeeRate, wallets.toAsset.Version) | ||
redemptionReserves, err = accountRedeemer.ReserveNRedemptions(redemptionRefundLots, wallets.toAsset.MaxFeeRate, wallets.toAsset.Version) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Works for me. Only additional thought about this matter is that the rate given to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the swap cannot be initiated, then it doesn't matter if too little is reserved for refunds and redemptions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The swap tx could still be mined with a gas fee cap less than what FeeRate would recommend. It would just be dicey for the refund (that happens in several hours). For the redeem, you're redeeming the other person's swap, so who knows what they used. |
||
if err != nil { | ||
return nil, 0, codedError(walletErr, fmt.Errorf("ReserveN error: %w", err)) | ||
return nil, 0, codedError(walletErr, fmt.Errorf("ReserveNRedemptions error: %w", err)) | ||
} | ||
msgTrade.RedeemSig = &msgjson.RedeemSig{ | ||
PubKey: pubKeys[0], | ||
Sig: sigs[0], | ||
} | ||
defer func() { | ||
if !success { | ||
accountRedeemer.UnlockReserves(redemptionReserves) | ||
accountRedeemer.UnlockRedemptionReserves(redemptionReserves) | ||
} | ||
}() | ||
} | ||
|
||
// If the from asset is an AccountLocker, we need to lock up refund funds. | ||
var refundReserves uint64 | ||
if isAccountRefund { | ||
refundReserves, err = accountRefunder.ReserveNRefunds(redemptionRefundLots, wallets.fromAsset.MaxFeeRate, wallets.fromAsset.Version) | ||
if err != nil { | ||
return nil, 0, codedError(walletErr, fmt.Errorf("ReserveNRefunds error: %w", err)) | ||
} | ||
defer func() { | ||
if !success { | ||
accountRefunder.UnlockRefundReserves(refundReserves) | ||
} | ||
}() | ||
} | ||
|
@@ -4259,9 +4276,10 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
// Store the order. | ||
dbOrder := &db.MetaOrder{ | ||
MetaData: &db.OrderMetaData{ | ||
Status: order.OrderStatusEpoch, | ||
Host: dc.acct.host, | ||
MaxFeeRate: wallets.fromAsset.MaxFeeRate, | ||
Status: order.OrderStatusEpoch, | ||
Host: dc.acct.host, | ||
MaxFeeRate: wallets.fromAsset.MaxFeeRate, | ||
RedeemMaxFeeRate: wallets.toAsset.MaxFeeRate, | ||
Proof: db.OrderProof{ | ||
DEXSig: result.Sig, | ||
Preimage: preImg[:], | ||
|
@@ -4282,9 +4300,10 @@ func (c *Core) prepareTrackedTrade(dc *dexConnection, form *TradeForm, crypter e | |
|
||
// Prepare and store the tracker and get the core.Order to return. | ||
tracker := newTrackedTrade(dbOrder, preImg, dc, dc.marketEpochDuration(mktID), c.lockTimeTaker, c.lockTimeMaker, | ||
c.db, c.latencyQ, wallets, coins, c.notify, c.formatDetails, form.Options, redemptionReserves) | ||
c.db, c.latencyQ, wallets, coins, c.notify, c.formatDetails, form.Options, redemptionReserves, refundReserves) | ||
|
||
tracker.redemptionLocked = tracker.redemptionReserves | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You've got another one of these three lines down. |
||
tracker.refundLocked = tracker.refundReserves | ||
|
||
if recoveryCoin != nil { | ||
tracker.change = recoveryCoin | ||
|
@@ -4897,7 +4916,7 @@ func (c *Core) dbTrackers(dc *dexConnection) (map[order.OrderID]*trackedTrade, e | |
copy(preImg[:], dbOrder.MetaData.Proof.Preimage) | ||
tracker := newTrackedTrade(dbOrder, preImg, dc, dc.marketEpochDuration(mktID), c.lockTimeTaker, | ||
c.lockTimeMaker, c.db, c.latencyQ, nil, nil, c.notify, c.formatDetails, | ||
dbOrder.MetaData.Options, dbOrder.MetaData.RedemptionReserves) | ||
dbOrder.MetaData.Options, dbOrder.MetaData.RedemptionReserves, dbOrder.MetaData.RefundReserves) | ||
trackers[dbOrder.Order.ID()] = tracker | ||
|
||
// Get matches. | ||
|
@@ -5106,6 +5125,14 @@ func (c *Core) resumeTrades(dc *dexConnection, trackers []*trackedTrade) assetMa | |
} | ||
} | ||
|
||
lockMatchRefund := func(match *matchTracker) { | ||
if tracker.isMarketBuy() { | ||
tracker.lockRefundFraction(1, uint64(len(tracker.matches))) | ||
} else { | ||
tracker.lockRefundFraction(match.Quantity, trade.Quantity) | ||
} | ||
} | ||
|
||
martonp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// If matches haven't redeemed, but the counter-swap has been received, | ||
// reload the audit info. | ||
isActive := tracker.metaData.Status == order.OrderStatusBooked || tracker.metaData.Status == order.OrderStatusEpoch | ||
|
@@ -5123,6 +5150,7 @@ func (c *Core) resumeTrades(dc *dexConnection, trackers []*trackedTrade) assetMa | |
} | ||
if match.Status < order.MakerRedeemed { | ||
lockMatchRedemption(match) | ||
lockMatchRefund(match) | ||
} | ||
} else { // Taker | ||
if match.Status < order.TakerSwapCast { | ||
|
@@ -5132,6 +5160,9 @@ func (c *Core) resumeTrades(dc *dexConnection, trackers []*trackedTrade) assetMa | |
needsAuditInfo = true // taker needs AuditInfo for maker's contract | ||
counterSwap = match.MetaData.Proof.MakerSwap | ||
} | ||
if match.Status < order.MakerRedeemed { | ||
lockMatchRefund(match) | ||
} | ||
if match.Status < order.MatchComplete { | ||
lockMatchRedemption(match) | ||
} | ||
|
@@ -5250,6 +5281,7 @@ func (c *Core) resumeTrades(dc *dexConnection, trackers []*trackedTrade) assetMa | |
|
||
if isActive { | ||
tracker.lockRedemptionFraction(trade.Remaining(), trade.Quantity) | ||
tracker.lockRefundFraction(trade.Remaining(), trade.Quantity) | ||
} | ||
|
||
// Balances should be updated for any orders with locked wallet coins, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method would be unneeded if we lock up the refund reserves in
FundOrder
.