Smart Contract
DCATransactionHandlerEVMSimple
A.ca7ee55e4fc3251a.DCATransactionHandlerEVMSimple
1import FlowTransactionScheduler from 0xe467b9dd11fa00df
2import DCAControllerUnified from 0xca7ee55e4fc3251a
3import DCAPlanUnified from 0xca7ee55e4fc3251a
4import FungibleToken from 0xf233dcee88fe0abe
5import FlowToken from 0x1654653399040a61
6import EVM from 0xe467b9dd11fa00df
7
8/// DCATransactionHandlerEVMSimple: Minimal EVM handler (~100 lines)
9/// Tests if scheduler can execute EVM swaps at all
10/// NO autonomous rescheduling - just executes FLOW → USDF via COA
11access(all) contract DCATransactionHandlerEVMSimple {
12
13 access(all) struct SimpleData {
14 access(all) let planId: UInt64
15 init(planId: UInt64) { self.planId = planId }
16 }
17
18 access(all) event Started(transactionId: UInt64, planId: UInt64)
19 access(all) event Completed(transactionId: UInt64, planId: UInt64, amountIn: UFix64)
20 access(all) event Failed(transactionId: UInt64, planId: UInt64, reason: String)
21
22 access(all) resource Handler: FlowTransactionScheduler.TransactionHandler {
23 access(self) let controllerCap: Capability<auth(DCAControllerUnified.Owner) &DCAControllerUnified.Controller>
24
25 init(controllerCap: Capability<auth(DCAControllerUnified.Owner) &DCAControllerUnified.Controller>) {
26 pre { controllerCap.check(): "Invalid controller" }
27 self.controllerCap = controllerCap
28 }
29
30 access(FlowTransactionScheduler.Execute) fun executeTransaction(id: UInt64, data: AnyStruct?) {
31 let txData = data as! SimpleData? ?? panic("SimpleData required")
32 emit Started(transactionId: id, planId: txData.planId)
33
34 let controller = self.controllerCap.borrow() ?? panic("No controller")
35 let plan = controller.borrowPlan(id: txData.planId) ?? panic("No plan")
36
37 // Get COA
38 let coaCap = controller.getCOACapability()
39 if coaCap == nil || !coaCap!.check() {
40 emit Failed(transactionId: id, planId: txData.planId, reason: "No COA")
41 return
42 }
43 let coa = coaCap!.borrow()!
44
45 // Get source vault and check balance
46 let sourceVaultCap = controller.getSourceVaultCapability()
47 ?? panic("No source vault")
48 let sourceVault = sourceVaultCap.borrow()
49 ?? panic("Cannot borrow source")
50
51 let amountIn = plan.amountPerInterval
52 if sourceVault.balance < amountIn {
53 emit Failed(transactionId: id, planId: txData.planId, reason: "Insufficient balance")
54 return
55 }
56
57 // Withdraw FLOW and deposit to COA
58 let flowToSwap <- sourceVault.withdraw(amount: amountIn) as! @FlowToken.Vault
59 coa.deposit(from: <-flowToSwap)
60
61 // Simple test: just deposit to COA and emit success
62 // In production, would call UniswapV3 router here
63
64 // Record execution
65 plan.recordExecution(amountIn: amountIn, amountOut: 0.0)
66
67 emit Completed(transactionId: id, planId: txData.planId, amountIn: amountIn)
68 }
69
70 access(all) view fun getViews(): [Type] {
71 return [Type<StoragePath>()]
72 }
73
74 access(all) fun resolveView(_ view: Type): AnyStruct? {
75 return /storage/DCATransactionHandlerEVMSimple
76 }
77 }
78
79 access(all) fun createHandler(
80 controllerCap: Capability<auth(DCAControllerUnified.Owner) &DCAControllerUnified.Controller>
81 ): @Handler {
82 return <- create Handler(controllerCap: controllerCap)
83 }
84
85 access(all) fun createData(planId: UInt64): SimpleData {
86 return SimpleData(planId: planId)
87 }
88}
89