Search Apps Documentation Source Content File Folder Download Copy Actions Download

swap_callback.gno

2.40 Kb ยท 85 lines
 1package v1
 2
 3import (
 4	"chain/runtime"
 5
 6	prbac "gno.land/p/gnoswap/rbac"
 7	u256 "gno.land/p/gnoswap/uint256"
 8
 9	"gno.land/r/gnoswap/access"
10	"gno.land/r/gnoswap/common"
11	"gno.land/r/gnoswap/halt"
12)
13
14// SwapCallback implements the pool's SwapCallback interface.
15// This is called by the pool after it has sent output tokens to the recipient.
16// The router must transfer the required input tokens to the pool.
17//
18// This callback pattern enables:
19// 1. Flash swaps (receive tokens before paying)
20// 2. Just-in-time token transfers
21// 3. Complex multi-hop swaps without intermediate transfers
22//
23// Parameters:
24//   - token0Path, token1Path: Pool token paths
25//   - amount0Delta, amount1Delta: Token deltas (positive = owe, negative = received)
26//   - payer: Address that will pay for the swap
27//
28// Access:
29//   - Only callable by Router v1 address (self-callback from pool)
30//
31// Returns:
32//   - error: nil on success, error if transfer fails
33//
34// Delta convention (Uniswap V3):
35//   - Positive delta: tokens the pool must receive (input token)
36//   - Negative delta: tokens the pool has sent (output token)
37func (r *routerV1) SwapCallback(
38	token0Path, token1Path string,
39	amount0Delta, amount1Delta int64,
40	payer address,
41) error {
42	halt.AssertIsNotHaltedRouter()
43
44	caller := runtime.PreviousRealm().Address()
45	assertIsRouterV1(caller)
46
47	var tokenToPay string
48	var amountToPay int64
49
50	// amount0Delta > 0 means pool wants token0
51	// amount1Delta > 0 means pool wants token1
52	if amount0Delta > 0 {
53		amountToPay = amount0Delta
54		tokenToPay = token0Path
55	} else if amount1Delta > 0 {
56		amountToPay = amount1Delta
57		tokenToPay = token1Path
58	} else {
59		return nil
60	}
61
62	// Transfer tokens from router to pool
63	// The router should already have the tokens from the user
64	r.transferToPool(tokenToPay, u256.NewUintFromInt64(amountToPay), payer)
65
66	return nil
67}
68
69// transferToPool transfers tokens from router to pool
70func (r *routerV1) transferToPool(token string, amount *u256.Uint, payer address) {
71	balance := common.BalanceOf(token, payer)
72
73	if u256.NewUintFromInt64(balance).Lt(amount) {
74		panic("insufficient balance in router for callback")
75	}
76
77	poolAddr := access.MustGetAddress(prbac.ROLE_POOL.String())
78	routerAddr := access.MustGetAddress(prbac.ROLE_ROUTER.String())
79
80	if payer == routerAddr {
81		common.SafeGRC20Transfer(cross, token, poolAddr, amount.Int64())
82	} else {
83		common.SafeGRC20TransferFrom(cross, token, payer, poolAddr, amount.Int64())
84	}
85}