MCPcopy
hub / github.com/canopy-network/canopy / HandleBatchWithdraw

Method HandleBatchWithdraw

fsm/dex.go:375–452  ·  view source on GitHub ↗

Two-chain LP accounting: - Mirror liquidity ledger on both chains for symmetry - Outbound deposits/withdraws: update ledger + move tokens - Inbound deposits/withdraws: update ledger but only token movement for withdraws HandleBatchWithdraw() handles local/remote liquidity withdraw requests. local=tr

(batch *lib.DexBatch, counterChainId uint64, x, y *uint64, local bool)

Source from the content-addressed store, hash-verified

373// HandleBatchWithdraw() handles local/remote liquidity withdraw requests.
374// local=true: x=local pool, y=counter mirror; local=false: x=counter mirror, y=local pool.
375func (s *StateMachine) HandleBatchWithdraw(batch *lib.DexBatch, counterChainId uint64, x, y *uint64, local bool) lib.ErrorI {
376 if len(batch.Withdrawals) == 0 {
377 return nil
378 }
379 // initialize vars
380 var totalPointsToRemove uint64
381 // get liquidity pool
382 p, err := s.GetPool(counterChainId + LiquidityPoolAddend)
383 if err != nil {
384 return err
385 }
386 // collect withdrawals
387 for _, w := range batch.Withdrawals {
388 initialPoints, e := p.GetPointsFor(w.Address)
389 if e != nil {
390 s.log.Errorf("an error occurred retrieving the pool points for: %x, %s", w.Address, e.Error())
391 continue // defensive
392 }
393 // update the total points to remove
394 totalPointsToRemove += lib.SafeMulDiv(initialPoints, w.Percent, 100)
395 }
396 if totalPointsToRemove == 0 || p.TotalPoolPoints == 0 {
397 return nil
398 }
399 // compute totals; actual paid amounts are tracked below to avoid burning rounding dust
400 // x = 1000 RONI; totalPoolPoints = 100 ; Pablo has 50 points
401 // y = 100 CNPY; totalPoolPoints = 100 ; Pablo has 50 points
402 // Both the X and Y pool should have the same a) pool holders b) pool points per holder c) totalPoolPoints
403 // Pablo has 50 pool points and Pablo withdrawals 50% = 25 points
404 // AmountCNPYToReceiveInWithdrawal = 100 x 25 / 100
405 // AmountRONIToReceiveInWithdrawal = 1000 x 25 / 100
406 totalYWithdrawal := lib.SafeMulDiv(*y, totalPointsToRemove, p.TotalPoolPoints)
407 totalXWithdraw := lib.SafeMulDiv(*x, totalPointsToRemove, p.TotalPoolPoints)
408 var paidY, paidX uint64
409 // distribute tokens
410 for _, w := range batch.Withdrawals {
411 initialPoints, e := p.GetPointsFor(w.Address)
412 if e != nil {
413 s.log.Warnf("an error occurred retrieving the pool points for: %x, %s", w.Address, e.Error())
414 continue // defensive
415 }
416 // calculate points from percent
417 points := lib.SafeMulDiv(initialPoints, w.Percent, 100)
418 // calculate share
419 yShare := lib.SafeMulDiv(totalYWithdrawal, points, totalPointsToRemove)
420 // calculate virtual share
421 xShare := lib.SafeMulDiv(totalXWithdraw, points, totalPointsToRemove)
422 // remove points from pool
423 if err = p.RemovePoints(w.Address, points); err != nil {
424 return err
425 }
426 payout, counter := yShare, xShare
427 if local {
428 payout, counter = xShare, yShare
429 }
430 paidY += yShare
431 paidX += xShare
432 // credit user and update pool balance

Calls 11

GetPoolMethod · 0.95
AccountAddMethod · 0.95
SetPoolMethod · 0.95
SafeMulDivFunction · 0.92
NewAddressFunction · 0.92
GetPointsForMethod · 0.80
RemovePointsMethod · 0.80
ErrorfMethod · 0.65
ErrorMethod · 0.65
WarnfMethod · 0.65

Tested by 1