HandleBatchDeposit() handles local/remote liquidity deposits. local=true: x=local pool (actual token movement), y=counter mirror. local=false: x=counter mirror, y=local pool.
(batch *lib.DexBatch, chainId uint64, x, y *uint64, local bool)
| 454 | // HandleBatchDeposit() handles local/remote liquidity deposits. |
| 455 | // local=true: x=local pool (actual token movement), y=counter mirror. local=false: x=counter mirror, y=local pool. |
| 456 | func (s *StateMachine) HandleBatchDeposit(batch *lib.DexBatch, chainId uint64, x, y *uint64, local bool) lib.ErrorI { |
| 457 | if len(batch.Deposits) == 0 { |
| 458 | return nil |
| 459 | } |
| 460 | // get the liquidity pool |
| 461 | p, err := s.GetPool(chainId + LiquidityPoolAddend) |
| 462 | if err != nil { |
| 463 | return err |
| 464 | } |
| 465 | // define variables |
| 466 | var totalDeposit, distributed uint64 |
| 467 | // x = the initial 'deposit' pool balance |
| 468 | // y = the 'counter' pool balance |
| 469 | // L = initial pool points |
| 470 | L := p.TotalPoolPoints |
| 471 | // sum all deposits |
| 472 | for _, deposit := range batch.Deposits { |
| 473 | totalDeposit += deposit.Amount |
| 474 | } |
| 475 | // nothing to add or failed invariant check |
| 476 | if totalDeposit == 0 || *x == 0 || *y == 0 { |
| 477 | return nil |
| 478 | } |
| 479 | // if no liq points yet assigned - initialize to 'dead' address |
| 480 | if L == 0 { |
| 481 | // calculate the initial pool points using L = √( x * y ) |
| 482 | L = lib.SqrtProductUint64(*x, *y) |
| 483 | // add points to the dead address |
| 484 | p.AddPoints(deadAddr.Bytes(), L) |
| 485 | } |
| 486 | // using integer math and geometric mean of reserves: |
| 487 | // deltaPoolPoints = L * ( √((x + totalDeposit) * y) - √(x * y) ) / √(x * y) or simplified as: |
| 488 | // deltaPoolPoints = L * (newK - oldK) / oldK (in a 1 sided deposit scenario dY=0 thus this formula) |
| 489 | oldK := lib.SqrtProductUint64(*x, *y) |
| 490 | if oldK == 0 { |
| 491 | return ErrInvalidLiquidityPool() |
| 492 | } |
| 493 | newK := lib.SqrtProductUint64(*x+totalDeposit, *y) |
| 494 | // totalDL is calculated as if all deposits is just 1 big deposit |
| 495 | totalDL := lib.SafeMulDiv(L, newK-oldK, oldK) |
| 496 | // distribute the points |
| 497 | for _, deposit := range batch.Deposits { |
| 498 | // calculate pro-rate share for this particular deposit |
| 499 | share := lib.SafeMulDiv(totalDL, deposit.Amount, totalDeposit) |
| 500 | // update the distributed counter |
| 501 | distributed += share |
| 502 | // add points to pool |
| 503 | p.AddPoints(deposit.Address, share) |
| 504 | // if 'local' request - (actually move from holding pool to liquidity pool, don't *just* update the ledger) |
| 505 | if local { |
| 506 | if err = s.PoolSub(chainId+HoldingPoolAddend, deposit.Amount); err != nil { |
| 507 | return err |
| 508 | } |
| 509 | p.Amount += deposit.Amount |
| 510 | } |
| 511 | // update the reserve |
| 512 | *x += deposit.Amount |
| 513 | // emit a deposit event |