Smart Contract

MockDexSwapper

A.b1d63873c3cc9f79.MockDexSwapper

Valid From

142,666,965

Deployed

1w ago
Feb 18, 2026, 10:20:15 PM UTC

Dependents

1 imports
1import Burner from 0xf233dcee88fe0abe
2import FungibleToken from 0xf233dcee88fe0abe
3
4import DeFiActions from 0x6d888f175c158410
5import DeFiActionsUtils from 0x6d888f175c158410
6
7/// TEST-ONLY mock swapper that withdraws output from a user-provided Vault capability.
8/// Do NOT use in production.
9access(all) contract MockDexSwapper {
10
11    /// Holds the set of available swappers which will be provided to users of SwapperProvider.
12    /// inType -> outType -> Swapper
13    access(self) let swappers: {Type: {Type: Swapper}}
14
15    init() {
16        self.swappers = {}
17    }
18
19    access(all) fun getSwapper(inType: Type, outType: Type): Swapper? {
20        if let swappersForInType = self.swappers[inType] {
21            return swappersForInType[outType]
22        }
23        return nil
24    }
25
26    /// Used by testing code to configure the DEX with swappers for a specific token pair.
27    ///
28    /// IMPORTANT: This function will overwrite any existing swapper for the same token pair.
29    /// This is intended to be used in cases where we want to change the price only, without
30    /// needing to remove and re-add the swapper.
31    ///
32    /// @param swapper: The swapper to set for the token pair
33    access(all) fun setMockDEXSwapperForPair(swapper: Swapper) {
34        let inType = swapper.inType()
35        let outType = swapper.outType()
36        let swappersRef = &self.swappers as auth(Mutate) &{Type: {Type: Swapper}}
37        if swappersRef[inType] == nil {
38            swappersRef[inType] = { outType: swapper }
39        } else {
40            let swappersForInTypeRef = &self.swappers[inType]! as auth(Mutate) &{Type: Swapper}
41            swappersForInTypeRef[outType] = swapper
42        }
43    }
44
45    /// Used by testing code to remove a swapper for the given token pair.
46    /// Panics if no swapper for the given pair exists.
47    access(all) fun removeMockDEXSwapperForPair(inType: Type, outType: Type) {
48        let swappersForInTypeRef = &self.swappers[inType]! as auth(Mutate) &{Type: Swapper}
49        swappersForInTypeRef.remove(key: outType)
50    }
51
52    access(all) struct BasicQuote : DeFiActions.Quote {
53        access(all) let inType: Type
54        access(all) let outType: Type
55        access(all) let inAmount: UFix64
56        access(all) let outAmount: UFix64
57        init(inType: Type, outType: Type, inAmount: UFix64, outAmount: UFix64) {
58            self.inType = inType
59            self.outType = outType
60            self.inAmount = inAmount
61            self.outAmount = outAmount
62        }
63    }
64
65    /// NOTE: reverse swaps are unsupported.
66    access(all) struct Swapper : DeFiActions.Swapper {
67        access(self) let inVault: Type
68        access(self) let outVault: Type
69        /// source for output tokens only (reverse swaps unsupported)
70        access(self) let vaultSource: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>
71        access(self) let priceRatio: UFix64 // out per unit in
72        access(contract) var uniqueID: DeFiActions.UniqueIdentifier?
73
74        init(inVault: Type, outVault: Type, vaultSource: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>, priceRatio: UFix64, uniqueID: DeFiActions.UniqueIdentifier?) {
75            pre {
76                inVault.isSubtype(of: Type<@{FungibleToken.Vault}>()): "inVault must be a FungibleToken Vault"
77                outVault.isSubtype(of: Type<@{FungibleToken.Vault}>()): "outVault must be a FungibleToken Vault"
78                vaultSource.check(): "Invalid vaultSource capability"
79                priceRatio > 0.0: "Invalid price ratio"
80            }
81            self.inVault = inVault
82            self.outVault = outVault
83            self.vaultSource = vaultSource
84            self.priceRatio = priceRatio
85            self.uniqueID = uniqueID
86        }
87
88        access(all) view fun inType(): Type { return self.inVault }
89        access(all) view fun outType(): Type { return self.outVault }
90
91        access(all) fun quoteIn(forDesired: UFix64, reverse: Bool): {DeFiActions.Quote} {
92            let inAmt = reverse ? forDesired * self.priceRatio : forDesired / self.priceRatio
93            return BasicQuote(
94                inType: reverse ? self.outType() : self.inType(),
95                outType: reverse ? self.inType() : self.outType(),
96                inAmount: inAmt,
97                outAmount: forDesired
98            )
99        }
100
101        access(all) fun quoteOut(forProvided: UFix64, reverse: Bool): {DeFiActions.Quote} {
102            let outAmt = reverse ? forProvided / self.priceRatio : forProvided * self.priceRatio
103            return BasicQuote(
104                inType: reverse ? self.outType() : self.inType(),
105                outType: reverse ? self.inType() : self.outType(),
106                inAmount: forProvided,
107                outAmount: outAmt
108            )
109        }
110
111        access(all) fun swap(quote: {DeFiActions.Quote}?, inVault: @{FungibleToken.Vault}): @{FungibleToken.Vault} {
112            pre { inVault.getType() == self.inType(): "Wrong in type" }
113            let outAmt = (quote?.outAmount) ?? (inVault.balance * self.priceRatio)
114            // burn seized input and withdraw from the provided source
115            Burner.burn(<-inVault)
116            let src = self.vaultSource.borrow() ?? panic("Invalid borrowed vault source")
117            return <- src.withdraw(amount: outAmt)
118        }
119
120        access(all) fun swapBack(quote: {DeFiActions.Quote}?, residual: @{FungibleToken.Vault}): @{FungibleToken.Vault} {
121            // Not needed in tests; burn residual and panic to surface misuse
122            Burner.burn(<-residual)
123            panic("MockSwapper.swapBack() not implemented")
124        }
125
126        access(all) fun getComponentInfo(): DeFiActions.ComponentInfo {
127            return DeFiActions.ComponentInfo(type: self.getType(), id: self.id(), innerComponents: [])
128        }
129        access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? { return self.uniqueID }
130        access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) { self.uniqueID = id }
131    }
132
133    access(all) struct SwapperProvider : DeFiActions.SwapperProvider {
134        access(all) fun getSwapper(inType: Type, outType: Type): Swapper? {
135            return MockDexSwapper.getSwapper(inType: inType, outType: outType)
136        }
137    }
138}
139