Smart Contract
UniswapV2SwapperConnector
A.17ae3b1b0b0d50db.UniswapV2SwapperConnector
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