Smart Contract

AgentManager2

A.79f5b5b0f95a160b.AgentManager2

Valid From

128,903,063

Deployed

1w ago
Feb 20, 2026, 08:53:51 AM UTC

Dependents

1 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FlowToken from 0x1654653399040a61
3import stFlowToken from 0xd6f80565193ad727
4import EVM from 0xe467b9dd11fa00df
5import VaultCore from 0x79f5b5b0f95a160b
6import IncrementStakingStrategy from 0x79f5b5b0f95a160b
7import IncrementLoopingStrategy from 0x79f5b5b0f95a160b
8import IncrementLendingStrategy from 0x79f5b5b0f95a160b
9import IncrementFarmingStrategy from 0x79f5b5b0f95a160b
10import SwapStrategy from 0x79f5b5b0f95a160b
11
12access(all) contract AgentManager2 {
13    
14    access(all) let AgentStoragePath: StoragePath
15    access(all) let AgentPublicPath: PublicPath
16    access(all) let EVM_VAULT_CORE: String
17    access(all) let EVM_STRATEGY_MANAGER: String
18    
19    access(all) event StrategyExecuted(strategy: String, amount: UFix64, result: String)
20    access(all) event FundsBridgedToEVM(amount: UFix64, evmAddress: String)
21    access(all) event FundsBridgedFromEVM(amount: UFix64)
22    access(all) event YieldHarvested(strategy: String, amount: UFix64)
23    
24    access(self) var totalBridgedToEVM: UFix64
25    access(self) var totalBridgedFromEVM: UFix64
26    
27    access(all) resource Agent {
28        access(self) let vaultRef: &VaultCore.Vault
29        access(self) let coa: auth(EVM.Call, EVM.Withdraw) &EVM.CadenceOwnedAccount
30        access(self) var stakingStrategy: @IncrementStakingStrategy.Strategy
31        access(self) var loopingStrategy: @IncrementLoopingStrategy.Strategy
32        access(self) var lendingStrategy: @IncrementLendingStrategy.Strategy
33        access(self) var farmingStrategy: @IncrementFarmingStrategy.Strategy
34        access(self) var swapStrategy: @SwapStrategy.Strategy
35        
36        init(vaultRef: &VaultCore.Vault, coa: auth(EVM.Call, EVM.Withdraw) &EVM.CadenceOwnedAccount) {
37            self.vaultRef = vaultRef
38            self.coa = coa
39            self.stakingStrategy <- IncrementStakingStrategy.createStrategy()
40            self.loopingStrategy <- IncrementLoopingStrategy.createStrategy()
41            self.lendingStrategy <- IncrementLendingStrategy.createStrategy()
42            self.farmingStrategy <- IncrementFarmingStrategy.createStrategy()
43            self.swapStrategy <- SwapStrategy.createStrategy()
44        }
45        
46        access(all) fun executeStaking(amount: UFix64): UFix64 {
47            let strategyRef = &self.stakingStrategy as &IncrementStakingStrategy.Strategy
48            let flowVault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.flow, amount: amount) as! @FlowToken.Vault
49            let stFlowVault <- strategyRef.executeStrategy(from: <-flowVault)
50            let received = stFlowVault.balance
51            self.vaultRef.depositFromStrategy(assetType: VaultCore.AssetType.stflow, from: <-stFlowVault)
52            emit StrategyExecuted(strategy: "Staking", amount: amount, result: received.toString())
53            return received
54        }
55        
56        access(all) fun executeLooping(amount: UFix64, numLoops: UInt8): UFix64 {
57            let strategyRef = &self.loopingStrategy as &IncrementLoopingStrategy.Strategy
58            let flowVault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.flow, amount: amount) as! @FlowToken.Vault
59            let stFlowVault <- strategyRef.executeStrategy(from: <-flowVault, numLoops: numLoops)
60            let received = stFlowVault.balance
61            self.vaultRef.depositFromStrategy(assetType: VaultCore.AssetType.stflow, from: <-stFlowVault)
62            emit StrategyExecuted(strategy: "Looping", amount: amount, result: received.toString())
63            return received
64        }
65        
66        access(all) fun supplyToLending(asset: String, amount: UFix64) {
67            let lendingRef = &self.lendingStrategy as &IncrementLendingStrategy.Strategy
68            if asset == "FLOW" {
69                let vault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.flow, amount: amount) as! @FlowToken.Vault
70                lendingRef.depositFlow(vault: <-vault)
71                lendingRef.supplyFlow(amount: amount)
72            } else if asset == "stFLOW" {
73                let vault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.stflow, amount: amount) as! @stFlowToken.Vault
74                lendingRef.depositStFlow(vault: <-vault)
75                lendingRef.supplyStFlow(amount: amount)
76            }
77            emit StrategyExecuted(strategy: "Lending-Supply", amount: amount, result: "Success")
78        }
79        
80        access(all) fun stakeInFarm(poolId: UInt64, amount: UFix64, tokenType: String) {
81            let farmingRef = &self.farmingStrategy as &IncrementFarmingStrategy.Strategy
82            if tokenType == "FLOW" {
83                let vault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.flow, amount: amount) as! @FlowToken.Vault
84                let success = farmingRef.executeStrategy(poolId: poolId, from: <-vault)
85                emit StrategyExecuted(strategy: "Farming", amount: amount, result: success ? "true" : "false")
86            } else if tokenType == "stFLOW" {
87                let vault <- self.vaultRef.withdrawForStrategy(assetType: VaultCore.AssetType.stflow, amount: amount) as! @stFlowToken.Vault
88                let success = farmingRef.executeStrategy(poolId: poolId, from: <-vault)
89                emit StrategyExecuted(strategy: "Farming", amount: amount, result: success ? "true" : "false")
90            }
91        }
92        
93        access(all) fun harvestFarmingRewards(poolId: UInt64) {
94            let farmingRef = &self.farmingStrategy as &IncrementFarmingStrategy.Strategy
95            let rewards <- farmingRef.harvestPool(poolId: poolId)
96            var totalHarvested: UFix64 = 0.0
97            for tokenKey in rewards.keys {
98                let rewardVault <- rewards.remove(key: tokenKey)!
99                totalHarvested = totalHarvested + rewardVault.balance
100                if tokenKey.slice(from: tokenKey.length - 9, upTo: tokenKey.length) == "FlowToken" {
101                    self.vaultRef.depositFromStrategy(assetType: VaultCore.AssetType.flow, from: <-rewardVault)
102                } else if tokenKey.slice(from: tokenKey.length - 11, upTo: tokenKey.length) == "stFlowToken" {
103                    self.vaultRef.depositFromStrategy(assetType: VaultCore.AssetType.stflow, from: <-rewardVault)
104                } else {
105                    destroy rewardVault
106                }
107            }
108            destroy rewards
109            self.vaultRef.recordYieldHarvest(assetType: VaultCore.AssetType.flow, amount: totalHarvested)
110            emit YieldHarvested(strategy: "Farming", amount: totalHarvested)
111        }
112        
113        access(all) fun bridgeToEVM(amount: UFix64): Bool {
114            let flowVault <- self.vaultRef.withdrawForEVMBridge(assetType: VaultCore.AssetType.flow, amount: amount) as! @FlowToken.Vault
115            self.coa.deposit(from: <-flowVault)
116            AgentManager2.totalBridgedToEVM = AgentManager2.totalBridgedToEVM + amount
117            emit FundsBridgedToEVM(amount: amount, evmAddress: self.coa.address().toString())
118            return true
119        }
120        
121        access(all) fun bridgeFromEVM(amount: UFix64): Bool {
122            let scaledAmount = amount * 1000000000.0
123            let amountUInt = UInt(scaledAmount) * 1000000000
124            let balance = EVM.Balance(attoflow: amountUInt)
125            let flowVault <- self.coa.withdraw(balance: balance) as! @FlowToken.Vault
126            let actualAmount = flowVault.balance
127            self.vaultRef.depositFromEVMBridge(from: <-flowVault)
128            AgentManager2.totalBridgedFromEVM = AgentManager2.totalBridgedFromEVM + actualAmount
129            emit FundsBridgedFromEVM(amount: actualAmount)
130            return true
131        }
132        
133        access(all) fun executeEVMStrategy(contractAddress: String, calldata: [UInt8], value: UFix64): EVM.Result {
134            let scaledValue = value * 1000000000.0
135            let amountUInt = UInt(scaledValue) * 1000000000
136            let balance = EVM.Balance(attoflow: amountUInt)
137            let addressBytes = contractAddress.decodeHex()
138            assert(addressBytes.length == 20, message: "Invalid EVM address")
139            let fixedBytes: [UInt8; 20] = [addressBytes[0], addressBytes[1], addressBytes[2], addressBytes[3], addressBytes[4], addressBytes[5], addressBytes[6], addressBytes[7], addressBytes[8], addressBytes[9], addressBytes[10], addressBytes[11], addressBytes[12], addressBytes[13], addressBytes[14], addressBytes[15], addressBytes[16], addressBytes[17], addressBytes[18], addressBytes[19]]
140            let evmAddress = EVM.EVMAddress(bytes: fixedBytes)
141            return self.coa.call(to: evmAddress, data: calldata, gasLimit: 10_000_000, value: balance)
142        }
143        
144        access(all) fun getStrategyBalances(): {String: {String: UFix64}} {
145            return {"staking": self.stakingStrategy.getBalances(), "looping": self.loopingStrategy.getBalances(), "lending": self.lendingStrategy.getBalances(), "farming": self.farmingStrategy.getBalances(), "swap": self.swapStrategy.getBalances()}
146        }
147        
148        access(all) fun getFarmingPositions(): {UInt64: {String: UFix64}} {
149            return self.farmingStrategy.getPositions()
150        }
151        
152        access(all) fun getLendingPosition(): IncrementLendingStrategy.UserPosition {
153            return self.lendingStrategy.getPositions()
154        }
155        
156        access(all) fun getLoopingHealth(): {String: UFix64} {
157            return self.loopingStrategy.getHealthMetrics()
158        }
159        
160        access(all) fun getCOAAddress(): String {
161            return self.coa.address().toString()
162        }
163        
164        access(all) fun getCOABalance(): UFix64 {
165            let balanceAttoflow = self.coa.balance().attoflow
166            let scaledDown = UFix64(balanceAttoflow / 1000000000)
167            return scaledDown / 1000000000.0
168        }
169    }
170    
171    access(all) fun createAgent(vaultRef: &VaultCore.Vault, coa: auth(EVM.Call, EVM.Withdraw) &EVM.CadenceOwnedAccount): @Agent {
172        return <- create Agent(vaultRef: vaultRef, coa: coa)
173    }
174    
175    access(all) fun getMetrics(): {String: UFix64} {
176        return {"totalBridgedToEVM": self.totalBridgedToEVM, "totalBridgedFromEVM": self.totalBridgedFromEVM}
177    }
178    
179    init() {
180        self.AgentStoragePath = /storage/AgentManager2
181        self.AgentPublicPath = /public/AgentManager2
182        self.EVM_VAULT_CORE = "0xc0F67510F9E8974345f7fE8b8981C780F94BFbf9"
183        self.EVM_STRATEGY_MANAGER = "0x915537401B7BC088d54a58e55b488B821508A55f"
184        self.totalBridgedToEVM = 0.0
185        self.totalBridgedFromEVM = 0.0
186    }
187}