Smart Contract
BridgeConfigV2
A.79f5b5b0f95a160b.BridgeConfigV2
1import EVM from 0xe467b9dd11fa00df
2import FlowToken from 0x1654653399040a61
3import VaultCore from 0x79f5b5b0f95a160b
4
5/// BridgeConfigV2 - Complete bridge solution with public interface
6access(all) contract BridgeConfigV2 {
7
8 // ====================================================================
9 // PATHS
10 // ====================================================================
11 access(all) let BridgeStoragePath: StoragePath
12 access(all) let BridgePublicPath: PublicPath
13 access(all) let AdminStoragePath: StoragePath
14
15 // ====================================================================
16 // STATE
17 // ====================================================================
18 access(self) var evmVaultAddress: EVM.EVMAddress?
19 access(self) var totalBridgedToEVM: UFix64
20 access(self) var totalBridgedFromEVM: UFix64
21
22 // ====================================================================
23 // EVENTS
24 // ====================================================================
25 access(all) event BridgeCOACreated(coaAddress: String)
26 access(all) event UserBridgedToEVM(user: Address, amount: UFix64, evmRecipient: String)
27 access(all) event ReceivedFromEVM(user: Address, amount: UFix64)
28 access(all) event EVMVaultAddressSet(address: String)
29
30 // ====================================================================
31 // PUBLIC INTERFACE
32 // ====================================================================
33 access(all) resource interface BridgePublic {
34 access(all) fun getCOAAddress(): String?
35 access(all) fun bridgeUserFunds(
36 user: Address,
37 amount: UFix64,
38 evmRecipient: String
39 )
40 }
41
42 // ====================================================================
43 // BRIDGE RESOURCE
44 // ====================================================================
45 access(all) resource Bridge: BridgePublic {
46 access(self) var bridgeCOA: @EVM.CadenceOwnedAccount?
47
48 init() {
49 self.bridgeCOA <- nil
50 }
51
52 access(all) fun setupCOA() {
53 pre {
54 self.bridgeCOA == nil: "COA already exists"
55 }
56
57 self.bridgeCOA <-! EVM.createCadenceOwnedAccount()
58
59 let coaAddress = self.bridgeCOA?.address()?.toString() ?? "unknown"
60 emit BridgeCOACreated(coaAddress: coaAddress)
61 }
62
63 access(all) fun getCOAAddress(): String? {
64 return self.bridgeCOA?.address()?.toString()
65 }
66
67 /// Public function users can call to bridge their funds
68 access(all) fun bridgeUserFunds(
69 user: Address,
70 amount: UFix64,
71 evmRecipient: String
72 ) {
73 pre {
74 self.bridgeCOA != nil: "COA not set up"
75 BridgeConfigV2.evmVaultAddress != nil: "EVM vault not set"
76 }
77
78 // Get vault reference
79 let vaultOwner = getAccount(0x79f5b5b0f95a160b)
80 let vaultCap = vaultOwner.capabilities.get<&VaultCore.Vault>(VaultCore.VaultPublicPath)
81 let vaultRef = vaultCap.borrow() ?? panic("Could not borrow vault")
82
83 // Withdraw from VaultCore
84 let flowVault <- vaultRef.withdrawForEVMBridge(
85 assetType: VaultCore.AssetType.flow,
86 amount: amount
87 ) as! @FlowToken.Vault
88
89 // Deposit to COA
90 let coaRef = (&self.bridgeCOA as auth(EVM.Call) &EVM.CadenceOwnedAccount?)!
91 coaRef.deposit(from: <-flowVault)
92
93 // Call EVM vault
94 let calldata = self.encodeDepositFromCadence(
95 userAddress: user.toString(),
96 amount: amount
97 )
98
99 let attoflowAmount = amount * 100000000.0
100 let attoflowUInt = UInt(attoflowAmount) * 10000000000
101
102 let result = coaRef.call(
103 to: BridgeConfigV2.evmVaultAddress!,
104 data: calldata,
105 gasLimit: 500000,
106 value: EVM.Balance(attoflow: attoflowUInt)
107 )
108
109 assert(result.status == EVM.Status.successful,
110 message: "Bridge failed")
111
112 BridgeConfigV2.totalBridgedToEVM = BridgeConfigV2.totalBridgedToEVM + amount
113
114 emit UserBridgedToEVM(
115 user: user,
116 amount: amount,
117 evmRecipient: evmRecipient
118 )
119 }
120
121 access(all) fun receiveFromEVM(
122 from: @FlowToken.Vault,
123 user: Address
124 ) {
125 let amount = from.balance
126
127 // Get vault reference
128 let vaultOwner = getAccount(0x79f5b5b0f95a160b)
129 let vaultCap = vaultOwner.capabilities.get<&VaultCore.Vault>(VaultCore.VaultPublicPath)
130 let vaultRef = vaultCap.borrow() ?? panic("Could not borrow vault")
131
132 vaultRef.depositFromEVMBridge(from: <-from)
133
134 BridgeConfigV2.totalBridgedFromEVM = BridgeConfigV2.totalBridgedFromEVM + amount
135
136 emit ReceivedFromEVM(user: user, amount: amount)
137 }
138
139 access(self) fun encodeDepositFromCadence(
140 userAddress: String,
141 amount: UFix64
142 ): [UInt8] {
143 // TODO: Implement proper ABI encoding in production
144 // For now, placeholder selector
145 return [0x12, 0x34, 0x56, 0x78]
146 }
147 }
148
149 // ====================================================================
150 // ADMIN RESOURCE
151 // ====================================================================
152 access(all) resource Admin {
153 access(all) fun setEVMVaultAddress(address: String) {
154 BridgeConfigV2.evmVaultAddress = EVM.addressFromString(address)
155 emit EVMVaultAddressSet(address: address)
156 }
157 }
158
159 // ====================================================================
160 // PUBLIC FUNCTIONS
161 // ====================================================================
162 access(all) fun createBridge(): @Bridge {
163 return <- create Bridge()
164 }
165
166 access(all) fun getEVMVaultAddress(): String? {
167 return BridgeConfigV2.evmVaultAddress?.toString()
168 }
169
170 access(all) fun getBridgeMetrics(): {String: UFix64} {
171 return {
172 "totalBridgedToEVM": self.totalBridgedToEVM,
173 "totalBridgedFromEVM": self.totalBridgedFromEVM
174 }
175 }
176
177 // ====================================================================
178 // INIT
179 // ====================================================================
180 init() {
181 self.BridgeStoragePath = /storage/VaultCoreBridgeV2
182 self.BridgePublicPath = /public/VaultCoreBridgeV2
183 self.AdminStoragePath = /storage/BridgeConfigV2Admin
184
185 self.evmVaultAddress = nil
186 self.totalBridgedToEVM = 0.0
187 self.totalBridgedFromEVM = 0.0
188
189 self.account.storage.save(<-create Admin(), to: self.AdminStoragePath)
190 }
191}