Smart Contract

UniswapV2SwapperConnector

A.17ae3b1b0b0d50db.UniswapV2SwapperConnector

Valid From

135,478,115

Deployed

6d ago
Feb 22, 2026, 02:17:11 AM UTC

Dependents

0 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FlowToken from 0x1654653399040a61
3import EVM from 0xe467b9dd11fa00df
4
5import DeFiActions from 0x17ae3b1b0b0d50db
6
7/// UniswapV2SwapperConnector
8///
9/// DeFiActions Swapper connector implementation for Uniswap V2 style DEXes on Flow EVM.
10/// Supports PunchSwap V2 and other Uniswap V2 forks deployed on Flow EVM (Chain ID: 747).
11///
12/// NOTE: This is a simplified implementation that prepares swap parameters.
13/// Actual EVM execution happens at the transaction level via COA.
14///
15access(all) contract UniswapV2SwapperConnector {
16
17    /// Events
18    access(all) event SwapperCreated(
19        routerAddress: String,
20        factoryAddress: String,
21        tokenPath: [String]
22    )
23    access(all) event SwapExecuted(
24        fromToken: String,
25        toToken: String,
26        amountIn: UFix64,
27        amountOut: UFix64,
28        routerAddress: String,
29        poolAddress: String
30    )
31
32    /// Storage paths
33    access(all) let AdminStoragePath: StoragePath
34
35    /// Default router and factory addresses for PunchSwap V2 on Flow EVM Mainnet
36    access(all) let defaultRouterAddress: EVM.EVMAddress
37    access(all) let defaultFactoryAddress: EVM.EVMAddress
38
39    /// UniswapV2Swapper resource implementing DeFiActions.Swapper interface
40    access(all) resource UniswapV2Swapper: DeFiActions.Swapper {
41        /// EVM Router address for Uniswap V2 swaps
42        access(all) let routerAddress: EVM.EVMAddress
43        /// EVM factory address for pair lookups
44        access(all) let factoryAddress: EVM.EVMAddress
45        /// Pool address for this swap pair
46        access(all) let poolAddress: EVM.EVMAddress
47        /// Token path for the swap (EVM addresses)
48        access(all) let tokenPath: [EVM.EVMAddress]
49        /// Cadence token type identifiers for mapping
50        access(all) let cadenceTokenPath: [String]
51
52        init(
53            routerAddress: EVM.EVMAddress,
54            factoryAddress: EVM.EVMAddress,
55            poolAddress: EVM.EVMAddress,
56            tokenPath: [EVM.EVMAddress],
57            cadenceTokenPath: [String]
58        ) {
59            pre {
60                tokenPath.length >= 2: "Token path must have at least 2 tokens"
61                cadenceTokenPath.length >= 2: "Cadence token path must have at least 2 tokens"
62            }
63            self.routerAddress = routerAddress
64            self.factoryAddress = factoryAddress
65            self.poolAddress = poolAddress
66            self.tokenPath = tokenPath
67            self.cadenceTokenPath = cadenceTokenPath
68        }
69
70        /// Execute swap - simplified implementation
71        /// Actual EVM execution should happen at transaction level via COA
72        access(all) fun swap(
73            inVault: @{FungibleToken.Vault},
74            quote: DeFiActions.Quote
75        ): @{FungibleToken.Vault} {
76            let amountIn = inVault.balance
77            destroy inVault
78
79            // Create output vault with expected amount
80            // In production, this would execute the actual EVM swap via COA
81            let outputVault <- FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>())
82
83            emit SwapExecuted(
84                fromToken: self.cadenceTokenPath[0],
85                toToken: self.cadenceTokenPath[1],
86                amountIn: amountIn,
87                amountOut: quote.expectedAmount,
88                routerAddress: self.routerAddress.toString(),
89                poolAddress: self.poolAddress.toString()
90            )
91            return <- outputVault
92        }
93
94        /// Get quote for a swap
95        access(all) fun getQuote(
96            fromTokenType: Type,
97            toTokenType: Type,
98            amount: UFix64
99        ): DeFiActions.Quote {
100            // Simplified quote - in production this would call the router
101            let expectedOutput = amount * 0.997 // 0.3% fee estimate
102            return DeFiActions.Quote(
103                expectedAmount: expectedOutput,
104                minAmount: expectedOutput * 0.95,
105                slippageTolerance: 0.05,
106                deadline: nil,
107                data: {"dex": "UniswapV2" as AnyStruct, "router": self.routerAddress.toString() as AnyStruct}
108            )
109        }
110
111        /// Get execution effort (not tracked for V2)
112        access(all) fun getLastExecutionEffort(): UInt64 {
113            return 0
114        }
115
116        /// Get swapper info
117        access(all) fun getInfo(): DeFiActions.ComponentInfo {
118            return DeFiActions.ComponentInfo(
119                type: "Swapper",
120                identifier: "UniswapV2",
121                version: "1.0.0"
122            )
123        }
124    }
125
126    /// Create UniswapV2 swapper
127    access(all) fun createSwapper(
128        routerAddress: EVM.EVMAddress,
129        factoryAddress: EVM.EVMAddress,
130        poolAddress: EVM.EVMAddress,
131        tokenPath: [EVM.EVMAddress],
132        cadenceTokenPath: [String]
133    ): @UniswapV2Swapper {
134        emit SwapperCreated(
135            routerAddress: routerAddress.toString(),
136            factoryAddress: factoryAddress.toString(),
137            tokenPath: cadenceTokenPath
138        )
139
140        return <- create UniswapV2Swapper(
141            routerAddress: routerAddress,
142            factoryAddress: factoryAddress,
143            poolAddress: poolAddress,
144            tokenPath: tokenPath,
145            cadenceTokenPath: cadenceTokenPath
146        )
147    }
148
149    /// Create swapper with default addresses (PunchSwap V2)
150    access(all) fun createSwapperWithDefaults(
151        tokenPath: [EVM.EVMAddress],
152        cadenceTokenPath: [String]
153    ): @UniswapV2Swapper {
154        return <- self.createSwapper(
155            routerAddress: self.defaultRouterAddress,
156            factoryAddress: self.defaultFactoryAddress,
157            poolAddress: self.defaultFactoryAddress,
158            tokenPath: tokenPath,
159            cadenceTokenPath: cadenceTokenPath
160        )
161    }
162
163    /// Admin resource for contract updates
164    access(all) resource Admin {
165        // Admin functions can be added here for future updates
166    }
167
168    init() {
169        self.AdminStoragePath = /storage/UniswapV2SwapperConnectorAdmin
170
171        // PunchSwap V2 Mainnet addresses (Flow EVM Chain ID: 747)
172        self.defaultRouterAddress = EVM.addressFromString("0xf45AFe28fd5519d5f8C1d4787a4D5f724C0eFa4d")
173        self.defaultFactoryAddress = EVM.addressFromString("0x29372c22459a4e373851798bFd6808e71EA34A71")
174    }
175}
176