From 63dcad8189413fa200acefc506a09bde85aed279 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:32:11 -0500 Subject: [PATCH 01/13] pyusd strategy --- .../FlowYieldVaultsStrategiesV1_1.cdc | 86 +++++++++++++++++-- 1 file changed, 79 insertions(+), 7 deletions(-) diff --git a/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc b/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc index 7cfe055..231f9a5 100644 --- a/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc @@ -131,6 +131,65 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } } + access(all) resource FUSDEVStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { + /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- + /// specific Identifier to associated connectors on construction + access(contract) var uniqueID: DeFiActions.UniqueIdentifier? + access(self) let position: FlowCreditMarket.Position + access(self) var sink: {DeFiActions.Sink} + access(self) var source: {DeFiActions.Source} + + init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: FlowCreditMarket.Position) { + self.uniqueID = id + self.position = position + self.sink = position.createSink(type: collateralType) + self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) + } + + // Inherited from FlowYieldVaults.Strategy default implementation + // access(all) view fun isSupportedCollateralType(_ type: Type): Bool + + access(all) view fun getSupportedCollateralTypes(): {Type: Bool} { + return { self.sink.getSinkType(): true } + } + /// Returns the amount available for withdrawal via the inner Source + access(all) fun availableBalance(ofToken: Type): UFix64 { + return ofToken == self.source.getSourceType() ? self.source.minimumAvailable() : 0.0 + } + /// Deposits up to the inner Sink's capacity from the provided authorized Vault reference + access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) { + self.sink.depositCapacity(from: from) + } + /// Withdraws up to the max amount, returning the withdrawn Vault. If the requested token type is unsupported, + /// an empty Vault is returned. + access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} { + if ofToken != self.source.getSourceType() { + return <- DeFiActionsUtils.getEmptyVault(ofToken) + } + return <- self.source.withdrawAvailable(maxAmount: maxAmount) + } + /// Executed when a Strategy is burned, cleaning up the Strategy's stored AutoBalancer + access(contract) fun burnCallback() { + FlowYieldVaultsAutoBalancers._cleanupAutoBalancer(id: self.id()!) + } + access(all) fun getComponentInfo(): DeFiActions.ComponentInfo { + return DeFiActions.ComponentInfo( + type: self.getType(), + id: self.id(), + innerComponents: [ + self.sink.getComponentInfo(), + self.source.getComponentInfo() + ] + ) + } + access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? { + return self.uniqueID + } + access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) { + self.uniqueID = id + } + } + access(all) struct TokenBundle { access(all) let moetTokenType: Type access(all) let moetTokenEVMAddress: EVM.EVMAddress @@ -306,11 +365,22 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { // Set AutoBalancer sink for overflow -> recollateralize balancerIO.autoBalancer.setSink(positionSwapSink, updateSinkID: true) - return <-create FlowYieldVaultsStrategiesV1_1.mUSDFStrategy( - id: uniqueID, - collateralType: collateralType, - position: position - ) + switch type { + case Type<@mUSDFStrategy>(): + return <-create mUSDFStrategy( + id: uniqueID, + collateralType: collateralType, + position: position + ) + case Type<@FUSDEVStrategy>(): + return <-create FUSDEVStrategy( + id: uniqueID, + collateralType: collateralType, + position: position + ) + default: + panic("Unsupported strategy type \(type.identifier)") + } } /* =========================== @@ -671,7 +741,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { access(Configure) fun purgeConfig() { self.configs = { Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} + Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}, + Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} } } } @@ -757,7 +828,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { let configs = { Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): ({} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}) + Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}, + Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} } } self.account.storage.save(<-create StrategyComposerIssuer(configs: configs), to: self.IssuerStoragePath) From dc00223c8846c0981731d37c3347df41e2a72a28 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:09:46 -0500 Subject: [PATCH 02/13] config transaction scripts --- .../admin/upsert_musdf_config.cdc | 9 +++- local/setup_mainnet.sh | 41 +++++++++++++++++ local/setup_testnet.sh | 45 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc b/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc index 80f2244..1a5414c 100644 --- a/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc +++ b/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc @@ -8,7 +8,13 @@ import "FlowYieldVaultsStrategiesV1_1" /// - Must be signed by the account that deployed FlowYieldVaultsStrategies /// - You can omit some collaterals by passing empty arrays and guarding in prepare{} transaction( + // e.g. "A.0x...FlowYieldVaultsStrategiesV1_1.mUSDFStrategy" + strategyTypeIdentifier: String, + + // collateral vault type (e.g. "A.0x...FlowToken.Vault") tokenTypeIdentifier: String, + + // yield token (EVM) address yieldTokenEVMAddress: String, // collateral path/fees: [YIELD, ..., ] @@ -17,6 +23,8 @@ transaction( ) { prepare(acct: auth(Storage, Capabilities, BorrowValue) &Account) { + let strategyType = CompositeType(strategyTypeIdentifier) + ?? panic("Invalid strategyTypeIdentifier \(strategyTypeIdentifier)") let tokenType = CompositeType(tokenTypeIdentifier) ?? panic("Invalid tokenTypeIdentifier \(tokenTypeIdentifier)") // This tx must run on the same account that stores the issuer @@ -38,7 +46,6 @@ transaction( } let composerType = Type<@FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer>() - let strategyType = Type<@FlowYieldVaultsStrategiesV1_1.mUSDFStrategy>() if swapPath.length > 0 { issuer.addOrUpdateCollateralConfig( diff --git a/local/setup_mainnet.sh b/local/setup_mainnet.sh index 5982c6d..4de0b4f 100755 --- a/local/setup_mainnet.sh +++ b/local/setup_mainnet.sh @@ -118,6 +118,7 @@ flow transactions send ./lib/FlowCreditMarket/FlowActions/cadence/transactions/f # Setup UniV3 path tauUSDFv -> USDF -> WFLOW flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.1654653399040a61.FlowToken.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -128,6 +129,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path tauUSDFv -> USDF -> WBTC flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ @@ -137,6 +139,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path tauUSDFv -> USDF -> WETH flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ @@ -144,6 +147,37 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus --network mainnet \ --signer mainnet-admin + +# Setup UniV3 path FUSDEV -> PYUSD0 -> WFLOW +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.1654653399040a61.FlowToken.Vault' \ + "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ + '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ + '[100,3000]' \ + --network mainnet \ + --signer mainnet-admin + + +# Setup UniV3 path FUSDEV -> PYUSD0 -> WBTC +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ + "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ + '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ + '[100,3000]' \ + --network mainnet \ + --signer mainnet-admin + +# Setup UniV3 path FUSDEV -> PYUSD0 -> WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ + "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ + '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ + '[100,3000]' \ + --network mainnet \ + --signer mainnet-admin # # add mUSDFStrategy as supported Strategy with the ability to initialize when new YieldVaults are created flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ @@ -153,6 +187,13 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate --network mainnet \ --signer mainnet-admin +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ + /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xb1d63873c3cc9f79 \ + --network mainnet \ + --signer mainnet-admin + # configure PMStrategies strategy configs flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc \ 'A.b1d63873c3cc9f79.PMStrategiesV1.syWFLOWvStrategy' \ diff --git a/local/setup_testnet.sh b/local/setup_testnet.sh index c8cfb0f..aeec38e 100755 --- a/local/setup_testnet.sh +++ b/local/setup_testnet.sh @@ -89,6 +89,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate --signer testnet-admin flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.7e60df042a9c0868.FlowToken.Vault' \ "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95", "0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -98,6 +99,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # WETH univ3 path and fees flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c", "0x059A77239daFa770977DD9f1E98632C3E4559848"]' \ @@ -107,6 +109,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # WBTC univ3 path and fees flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c","0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6"]' \ @@ -114,6 +117,41 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus --network testnet \ --signer testnet-admin + +## PYUSD0 Vault +# WFLOW univ3 path and fees +# path: FUSDEV - WFLOW +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.7e60df042a9c0868.FlowToken.Vault' \ + "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ + '["0x61b44D19486EE492449E83C1201581C754e9e1E1", "0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ + '[3000]' \ + --network testnet \ + --signer testnet-admin + +# WETH univ3 path and fees +# path: FUSDEV - MOET - WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ + "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ + '["0x61b44D19486EE492449E83C1201581C754e9e1E1","0x02d3575e2516a515E9B91a52b294Edc80DC7987c", "0x059A77239daFa770977DD9f1E98632C3E4559848"]' \ + '[3000,3000]' \ + --network testnet \ + --signer testnet-admin + +# WBTC univ3 path and fees +# path: FUSDEV - MOET - WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ + "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ + '["0x61b44D19486EE492449E83C1201581C754e9e1E1","0x02d3575e2516a515E9B91a52b294Edc80DC7987c","0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6"]' \ + '[3000,3000]' \ + --network testnet \ + --signer testnet-admin + flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ @@ -121,6 +159,13 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate --network testnet \ --signer testnet-admin +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ + /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xd2580caf2ef07c2f \ + --network testnet \ + --signer testnet-admin + # PYUSD0 Vault flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc \ 'A.d2580caf2ef07c2f.PMStrategiesV1.FUSDEVStrategy' \ From 4dc9664bbb8fdbe443b14962a51f2e20686c3680 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 22 Jan 2026 21:23:58 -0500 Subject: [PATCH 03/13] mainnet setup script fixes --- local/setup_mainnet.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/local/setup_mainnet.sh b/local/setup_mainnet.sh index 4de0b4f..6ffffc8 100755 --- a/local/setup_mainnet.sh +++ b/local/setup_mainnet.sh @@ -118,7 +118,7 @@ flow transactions send ./lib/FlowCreditMarket/FlowActions/cadence/transactions/f # Setup UniV3 path tauUSDFv -> USDF -> WFLOW flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ 'A.1654653399040a61.FlowToken.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -129,7 +129,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path tauUSDFv -> USDF -> WBTC flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ @@ -139,7 +139,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path tauUSDFv -> USDF -> WETH flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ @@ -150,7 +150,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path FUSDEV -> PYUSD0 -> WFLOW flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ 'A.1654653399040a61.FlowToken.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -161,7 +161,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path FUSDEV -> PYUSD0 -> WBTC flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ @@ -171,7 +171,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path FUSDEV -> PYUSD0 -> WETH flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ @@ -264,7 +264,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # test FlowYieldVault strategy # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategies.mUSDCStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ # A.1654653399040a61.FlowToken.Vault \ # 1.0 \ # --compute-limit 9999 \ @@ -274,7 +274,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # # WBTC (BTCf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ # A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault \ # 0.0000001 \ # --compute-limit 9999 \ @@ -283,7 +283,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # # WETH (ETHf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ # A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault \ # 0.00001 \ # --compute-limit 9999 \ From f8859573da7bcfb3bf1ef4090a66991b57f63f69 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Fri, 23 Jan 2026 12:04:48 -0500 Subject: [PATCH 04/13] add readme addresses --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b98d7a2..1fa311a 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,14 @@ Mock FungibleToken implementations representing: | FlowActions | 0xd27920b6384e2a78 | DeFiActions | TBD | | FlowCreditMarket | 0xd27920b6384e2a78 | FlowALP | TBD | | FlowYieldVaults | 0xd27920b6384e2a78 | FlowYieldVaults | TBD | -| FlowYieldVaultsStrategies | 0xd27920b6384e2a78 | FlowYieldVaultsStrategies | TBD | +| FlowYieldVaultsStrategiesV1_1 | 0xd27920b6384e2a78 | FlowYieldVaultsStrategiesV1_1 | TBD | +| PMStrategiesV1 | 0xd27920b6384e2a78 | PMStrategiesV1 | TBD | | MOET | 0xd27920b6384e2a78 | MOET | 0x51f5cc5f50afb81e8f23c926080fa38c3024b238 | | USDC | 0xdfc20aee650fcbdf | EVMVMBridgedToken_d431955d55a99ef69beb96ba34718d0f9fbc91b1 | 0xd431955D55a99EF69BEb96BA34718d0f9fBc91b1 | +| PYUSD0 | 0xdfc20aee650fcbdf | EVMVMBridgedToken_d7d43ab7b365f0d0789ae83f4385fa710ffdc98f | 0xd7d43ab7b365f0d0789aE83F4385fA710FfdC98F | | wBTC | 0xdfc20aee650fcbdf | EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6 | 0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6 | | wETH | 0xdfc20aee650fcbdf | EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848 | 0x059A77239daFa770977DD9f1E98632C3E4559848 | -| mUSDC (ERC4626) | 0xdfc20aee650fcbdf | EVMVMBridgedToken_4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95 | 0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95 | +| FUSDEV (ERC4626) | 0xdfc20aee650fcbdf | EVMVMBridgedToken_61b44d19486ee492449e83c1201581c754e9e1e1 | 0x61b44D19486EE492449E83C1201581C754e9e1E1 | #### Mainnet | Asset Name | Cadence Address | Cadence Contract Name | EVM | @@ -78,13 +80,15 @@ Mock FungibleToken implementations representing: | FlowActions | 0x6d888f175c158410 | DeFiActions | TBD | | FlowCreditMarket | 0x6b00ff876c299c61 | FlowALP | TBD | | FlowYieldVaults | 0xb1d63873c3cc9f79 | FlowYieldVaults | TBD | -| FlowYieldVaultsStrategies | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategies | TBD | +| FlowYieldVaultsStrategiesV1_1 | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategiesV1_1 | TBD | +| PMStrategiesV1 | 0xb1d63873c3cc9f79 | PMStrategiesV1 | TBD | | MOET | 0x6b00ff876c299c61 | MOET | 0x213979bB8A9A86966999b3AA797C1fcf3B967ae2 | | USDC | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_f1815bd50389c46847f0bda824ec8da914045d14 | 0xF1815bd50389c46847f0Bda824eC8da914045D14 | | USDF | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_2aabea2058b5ac2d339b163c6ab6f2b6d53aabed | 0x2aabea2058b5ac2d339b163c6ab6f2b6d53aabed | +| PYUSD0 | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_99af3eea856556646c98c8b9b2548fe815240750 | 0x99aF3EeA856556646C98c8B9b2548Fe815240750 | | cbBTC | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_a0197b2044d28b08be34d98b23c9312158ea9a18 | 0xA0197b2044D28b08Be34d98b23c9312158Ea9A18 | | wETH | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590 | 0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590 | -| tauUSDF (ERC4626) | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_c52E820d2D6207D18667a97e2c6Ac22eB26E803c | 0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c | +| FUSDEV (ERC4626) | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_d069d989e2f44b70c65347d1853c0c67e10a9f8d | 0xd069d989e2F44B70c65347d1853C0c67e10a9F8D | ## How the System Works From 98141020a60662a729f46de7a6c45e686f0d82d6 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:47:46 -0500 Subject: [PATCH 05/13] add morpho swapper to PMStrategiesV1 --- cadence/contracts/PMStrategiesV1.cdc | 40 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/cadence/contracts/PMStrategiesV1.cdc b/cadence/contracts/PMStrategiesV1.cdc index ba0ff9e..2709708 100644 --- a/cadence/contracts/PMStrategiesV1.cdc +++ b/cadence/contracts/PMStrategiesV1.cdc @@ -8,7 +8,7 @@ import "SwapConnectors" import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" -import "ERC4626SwapConnectors" +import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // FlowYieldVaults platform import "FlowYieldVaults" @@ -346,24 +346,32 @@ access(all) contract PMStrategiesV1 { uniqueID: uniqueID ) // Swap Collateral -> YieldToken via ERC4626 Vault - let collateralTo4626Swapper = ERC4626SwapConnectors.Swapper( + let collateralToYieldMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swapper( asset: collateralType, vault: yieldTokenEVMAddress, coa: PMStrategiesV1._getCOACapability(), feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), - uniqueID: uniqueID + uniqueID: uniqueID, + isReversed: false ) // Finally, add the two Collateral -> YieldToken swappers into an aggregate MultiSwapper let collateralToYieldSwapper = SwapConnectors.MultiSwapper( inVault: collateralType, outVault: yieldTokenType, - swappers: [collateralToYieldAMMSwapper, collateralTo4626Swapper], + swappers: [collateralToYieldAMMSwapper, collateralToYieldMorphoERC4626Swapper], uniqueID: uniqueID ) - // YieldToken -> Collateral - // - Targets the Collateral <-> YieldToken pool as the only route since withdraws from the ERC4626 Vault are async - let yieldToCollateralSwapper = UniswapV3SwapConnectors.Swapper( + // create YieldToken <-> Collateral swappers + // + // YieldToken -> Collateral - can swap via two primary routes: + // - via AMM swap pairing YieldToken <-> Collateral + // - via ERC4626 vault deposit + // YieldToken -> Collateral high-level Swapper contains: + // - MultiSwapper aggregates across two sub-swappers + // - YieldToken -> Collateral (UniV3 Swapper) + // - YieldToken -> Collateral (ERC4626 Swapper) + let yieldToCollateralAMMSwapper = UniswapV3SwapConnectors.Swapper( factoryAddress: PMStrategiesV1.univ3FactoryEVMAddress, routerAddress: PMStrategiesV1.univ3RouterEVMAddress, quoterAddress: PMStrategiesV1.univ3QuoterEVMAddress, @@ -375,6 +383,24 @@ access(all) contract PMStrategiesV1 { uniqueID: uniqueID ) + // Swap (redeem) YieldToken -> Collateral via MorphoERC4626 Vault + let yieldToCollateralMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swaper( + asset: collateralType, + vault: yieldTokenEVMAddress, + coa: PMStrategiesV1._getCOACapability(), + feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: true + ) + + // Finally, add the two YieldToken <-> Collateral swappers into an aggregate MultiSwapper + let yieldToCollateralSwapper = SwapConnectors.MultiSwapper( + inVault: yieldTokenType, + outVault: collateralType, + swappers: [yieldToCollateralAMMSwapper, yieldToCollateralMorphoERC4626Swapper], + uniqueID: uniqueID + ) + // init SwapSink directing swapped funds to AutoBalancer // // Swaps provided Collateral to YieldToken & deposits to the AutoBalancer From f29da304b903f9a5f387786233c94cd72a7cc879 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:57:11 -0500 Subject: [PATCH 06/13] FYVStrategy v2 --- README.md | 4 +- ..._1.cdc => FlowYieldVaultsStrategiesV2.cdc} | 212 +++++------ cadence/contracts/PMStrategies.cdc | 358 ++++++++++++++++++ cadence/contracts/PMStrategiesV1.cdc | 6 +- cadence/tests/test_helpers.cdc | 4 +- ..._config.cdc => upsert_strategy_config.cdc} | 12 +- flow.json | 10 +- local/setup_emulator.sh | 4 +- local/setup_mainnet.sh | 64 +--- local/setup_testnet.sh | 63 +-- 10 files changed, 495 insertions(+), 242 deletions(-) rename cadence/contracts/{FlowYieldVaultsStrategiesV1_1.cdc => FlowYieldVaultsStrategiesV2.cdc} (83%) create mode 100644 cadence/contracts/PMStrategies.cdc rename cadence/transactions/flow-yield-vaults/admin/{upsert_musdf_config.cdc => upsert_strategy_config.cdc} (80%) diff --git a/README.md b/README.md index 1fa311a..37328b2 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Mock FungibleToken implementations representing: | FlowActions | 0xd27920b6384e2a78 | DeFiActions | TBD | | FlowCreditMarket | 0xd27920b6384e2a78 | FlowALP | TBD | | FlowYieldVaults | 0xd27920b6384e2a78 | FlowYieldVaults | TBD | -| FlowYieldVaultsStrategiesV1_1 | 0xd27920b6384e2a78 | FlowYieldVaultsStrategiesV1_1 | TBD | +| FlowYieldVaultsStrategiesV2 | 0xd27920b6384e2a78 | FlowYieldVaultsStrategiesV2 | TBD | | PMStrategiesV1 | 0xd27920b6384e2a78 | PMStrategiesV1 | TBD | | MOET | 0xd27920b6384e2a78 | MOET | 0x51f5cc5f50afb81e8f23c926080fa38c3024b238 | | USDC | 0xdfc20aee650fcbdf | EVMVMBridgedToken_d431955d55a99ef69beb96ba34718d0f9fbc91b1 | 0xd431955D55a99EF69BEb96BA34718d0f9fBc91b1 | @@ -80,7 +80,7 @@ Mock FungibleToken implementations representing: | FlowActions | 0x6d888f175c158410 | DeFiActions | TBD | | FlowCreditMarket | 0x6b00ff876c299c61 | FlowALP | TBD | | FlowYieldVaults | 0xb1d63873c3cc9f79 | FlowYieldVaults | TBD | -| FlowYieldVaultsStrategiesV1_1 | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategiesV1_1 | TBD | +| FlowYieldVaultsStrategiesV2 | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategiesV2 | TBD | | PMStrategiesV1 | 0xb1d63873c3cc9f79 | PMStrategiesV1 | TBD | | MOET | 0x6b00ff876c299c61 | MOET | 0x213979bB8A9A86966999b3AA797C1fcf3B967ae2 | | USDC | 0x1e4aa0b87d10b141 | EVMVMBridgedToken_f1815bd50389c46847f0bda824ec8da914045d14 | 0xF1815bd50389c46847f0Bda824eC8da914045D14 | diff --git a/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc similarity index 83% rename from cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc rename to cadence/contracts/FlowYieldVaultsStrategiesV2.cdc index 231f9a5..b752d3f 100644 --- a/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc @@ -8,7 +8,7 @@ import "SwapConnectors" import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" -import "ERC4626SwapConnectors" +import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // Lending protocol import "FlowCreditMarket" @@ -24,7 +24,7 @@ import "FlowEVMBridgeConfig" // live oracles import "ERC4626PriceOracles" -/// FlowYieldVaultsStrategiesV1_1 +/// FlowYieldVaultsStrategiesV2 /// /// This contract defines Strategies used in the FlowYieldVaults platform. /// @@ -35,7 +35,7 @@ import "ERC4626PriceOracles" /// A StrategyComposer is tasked with the creation of a supported Strategy. It's within the stacking of DeFiActions /// connectors that the true power of the components lies. /// -access(all) contract FlowYieldVaultsStrategiesV1_1 { +access(all) contract FlowYieldVaultsStrategiesV2 { access(all) let univ3FactoryEVMAddress: EVM.EVMAddress access(all) let univ3RouterEVMAddress: EVM.EVMAddress @@ -71,66 +71,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } } - /// This strategy uses mUSDF vaults - access(all) resource mUSDFStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { - /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- - /// specific Identifier to associated connectors on construction - access(contract) var uniqueID: DeFiActions.UniqueIdentifier? - access(self) let position: FlowCreditMarket.Position - access(self) var sink: {DeFiActions.Sink} - access(self) var source: {DeFiActions.Source} - - init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: FlowCreditMarket.Position) { - self.uniqueID = id - self.position = position - self.sink = position.createSink(type: collateralType) - self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) - } - - // Inherited from FlowYieldVaults.Strategy default implementation - // access(all) view fun isSupportedCollateralType(_ type: Type): Bool - - access(all) view fun getSupportedCollateralTypes(): {Type: Bool} { - return { self.sink.getSinkType(): true } - } - /// Returns the amount available for withdrawal via the inner Source - access(all) fun availableBalance(ofToken: Type): UFix64 { - return ofToken == self.source.getSourceType() ? self.source.minimumAvailable() : 0.0 - } - /// Deposits up to the inner Sink's capacity from the provided authorized Vault reference - access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) { - self.sink.depositCapacity(from: from) - } - /// Withdraws up to the max amount, returning the withdrawn Vault. If the requested token type is unsupported, - /// an empty Vault is returned. - access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} { - if ofToken != self.source.getSourceType() { - return <- DeFiActionsUtils.getEmptyVault(ofToken) - } - return <- self.source.withdrawAvailable(maxAmount: maxAmount) - } - /// Executed when a Strategy is burned, cleaning up the Strategy's stored AutoBalancer - access(contract) fun burnCallback() { - FlowYieldVaultsAutoBalancers._cleanupAutoBalancer(id: self.id()!) - } - access(all) fun getComponentInfo(): DeFiActions.ComponentInfo { - return DeFiActions.ComponentInfo( - type: self.getType(), - id: self.id(), - innerComponents: [ - self.sink.getComponentInfo(), - self.source.getComponentInfo() - ] - ) - } - access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? { - return self.uniqueID - } - access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) { - self.uniqueID = id - } - } - + /// This strategy uses FUSDEV vault access(all) resource FUSDEVStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- /// specific Identifier to associated connectors on construction @@ -237,12 +178,12 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } } - /// This StrategyComposer builds a mUSDFStrategy - access(all) resource mUSDFStrategyComposer : FlowYieldVaults.StrategyComposer { - /// { Strategy Type: { Collateral Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig } } - access(self) let config: {Type: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}} + /// This StrategyComposer builds a Strategy that uses MorphoERC4626 vault + access(all) resource MorphoERC4626StrategyComposer : FlowYieldVaults.StrategyComposer { + /// { Strategy Type: { Collateral Type: FlowYieldVaultsStrategiesV2.CollateralConfig } } + access(self) let config: {Type: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig}} - init(_ config: {Type: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}}) { + init(_ config: {Type: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig}}) { self.config = config } @@ -258,7 +199,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { /// Returns the Vault types which can be used to initialize a given Strategy access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} { let supported: {Type: Bool} = {} - if let strategyConfig = &self.config[forStrategy] as &{Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}? { + if let strategyConfig = &self.config[forStrategy] as &{Type: FlowYieldVaultsStrategiesV2.CollateralConfig}? { for collateralType in strategyConfig.keys { supported[collateralType] = true } @@ -287,6 +228,9 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { uniqueID: DeFiActions.UniqueIdentifier, withFunds: @{FungibleToken.Vault} ): @{FlowYieldVaults.Strategy} { + pre { + self.config[type] != nil: "Unsupported strategy type \(type.identifier)" + } let collateralType = withFunds.getType() let collateralConfig = self._getCollateralConfig( @@ -304,7 +248,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { ) // Create recurring config for automatic rebalancing - let recurringConfig = FlowYieldVaultsStrategiesV1_1._createRecurringConfig(withID: uniqueID) + let recurringConfig = FlowYieldVaultsStrategiesV2._createRecurringConfig(withID: uniqueID) // Create/store/publish/register AutoBalancer (returns authorized ref) let balancerIO = self._initAutoBalancerAndIO( @@ -317,13 +261,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { // Swappers: MOET <-> YIELD (YIELD is ERC4626 vault token) let moetToYieldSwapper = self._createMoetToYieldSwapper(tokens: tokens, uniqueID: uniqueID) - let yieldToMoetSwapper = self._createUniV3Swapper( - tokenPath: [tokens.yieldTokenEVMAddress, tokens.moetTokenEVMAddress], - feePath: [100], - inVault: tokens.yieldTokenType, - outVault: tokens.moetTokenType, - uniqueID: uniqueID - ) + let yieldToMoetSwapper = self._createYieldToMoetSwapper(tokens: tokens, uniqueID: uniqueID) // AutoBalancer-directed swap IO let abaSwapSink = SwapConnectors.SwapSink( @@ -366,12 +304,6 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { balancerIO.autoBalancer.setSink(positionSwapSink, updateSinkID: true) switch type { - case Type<@mUSDFStrategy>(): - return <-create mUSDFStrategy( - id: uniqueID, - collateralType: collateralType, - position: position - ) case Type<@FUSDEVStrategy>(): return <-create FUSDEVStrategy( id: uniqueID, @@ -390,7 +322,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { access(self) fun _getCollateralConfig( strategyType: Type, collateralType: Type - ): FlowYieldVaultsStrategiesV1_1.CollateralConfig { + ): FlowYieldVaultsStrategiesV2.CollateralConfig { let strategyConfig = self.config[strategyType] ?? panic( "Could not find a config for Strategy \(strategyType.identifier) initialized with \(collateralType.identifier)" @@ -403,8 +335,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } access(self) fun _resolveTokenBundle( - collateralConfig: FlowYieldVaultsStrategiesV1_1.CollateralConfig - ): FlowYieldVaultsStrategiesV1_1.TokenBundle { + collateralConfig: FlowYieldVaultsStrategiesV2.CollateralConfig + ): FlowYieldVaultsStrategiesV2.TokenBundle { // MOET let moetTokenType = Type<@MOET.Vault>() let moetTokenEVMAddress = FlowEVMBridgeConfig.getEVMAddressAssociated(with: moetTokenType) @@ -427,7 +359,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { "Could not retrieve the VM Bridge associated Type for the ERC4626 underlying asset \(underlying4626AssetEVMAddress.toString())" ) - return FlowYieldVaultsStrategiesV1_1.TokenBundle( + return FlowYieldVaultsStrategiesV2.TokenBundle( moetTokenType: moetTokenType, moetTokenEVMAddress: moetTokenEVMAddress, yieldTokenType: yieldTokenType, @@ -457,20 +389,20 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { uniqueID: DeFiActions.UniqueIdentifier ): UniswapV3SwapConnectors.Swapper { return UniswapV3SwapConnectors.Swapper( - factoryAddress: FlowYieldVaultsStrategiesV1_1.univ3FactoryEVMAddress, - routerAddress: FlowYieldVaultsStrategiesV1_1.univ3RouterEVMAddress, - quoterAddress: FlowYieldVaultsStrategiesV1_1.univ3QuoterEVMAddress, + factoryAddress: FlowYieldVaultsStrategiesV2.univ3FactoryEVMAddress, + routerAddress: FlowYieldVaultsStrategiesV2.univ3RouterEVMAddress, + quoterAddress: FlowYieldVaultsStrategiesV2.univ3QuoterEVMAddress, tokenPath: tokenPath, feePath: feePath, inVault: inVault, outVault: outVault, - coaCapability: FlowYieldVaultsStrategiesV1_1._getCOACapability(), + coaCapability: FlowYieldVaultsStrategiesV2._getCOACapability(), uniqueID: uniqueID ) } access(self) fun _createMoetToYieldSwapper( - tokens: FlowYieldVaultsStrategiesV1_1.TokenBundle, + tokens: FlowYieldVaultsStrategiesV2.TokenBundle, uniqueID: DeFiActions.UniqueIdentifier ): SwapConnectors.MultiSwapper { // Direct MOET -> YIELD via AMM @@ -492,12 +424,12 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { ) // UNDERLYING -> YIELD via ERC4626 vault - let underlyingTo4626 = ERC4626SwapConnectors.Swapper( - asset: tokens.underlying4626AssetType, - vault: tokens.yieldTokenEVMAddress, - coa: FlowYieldVaultsStrategiesV1_1._getCOACapability(), - feeSource: FlowYieldVaultsStrategiesV1_1._createFeeSource(withID: uniqueID), - uniqueID: uniqueID + let underlyingTo4626 = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: tokens.yieldTokenEVMAddress, + coa: FlowYieldVaultsStrategiesV2._getCOACapability(), + feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: false ) let seq = SwapConnectors.SequentialSwapper( @@ -513,12 +445,56 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { ) } + access(self) fun _createYieldToMoetSwapper( + tokens: FlowYieldVaultsStrategiesV2.TokenBundle, + uniqueID: DeFiActions.UniqueIdentifier + ): SwapConnectors.MultiSwapper { + // Direct YIELD -> MOET via AMM + let yieldToMoetAMM = self._createUniV3Swapper( + tokenPath: [tokens.yieldTokenEVMAddress, tokens.moetTokenEVMAddress], + feePath: [100], + inVault: tokens.yieldTokenType, + outVault: tokens.moetTokenType, + uniqueID: uniqueID + ) + + // YIELD -> UNDERLYING redeem via MorphoERC4626 vault + let yieldToUnderlying = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: tokens.yieldTokenEVMAddress, + coa: FlowYieldVaultsStrategiesV2._getCOACapability(), + feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: true + ) + // UNDERLYING -> MOET via AMM + let underlyingToMoet = self._createUniV3Swapper( + tokenPath: [tokens.underlying4626AssetEVMAddress, tokens.moetTokenEVMAddress], + feePath: [100], + inVault: tokens.underlying4626AssetType, + outVault: tokens.moetTokenType, + uniqueID: uniqueID + ) + + + let seq = SwapConnectors.SequentialSwapper( + swappers: [yieldToUnderlying, underlyingToMoet], + uniqueID: uniqueID + ) + + return SwapConnectors.MultiSwapper( + inVault: tokens.yieldTokenType, + outVault: tokens.moetTokenType, + swappers: [yieldToMoetAMM, seq], + uniqueID: uniqueID + ) + } + access(self) fun _initAutoBalancerAndIO( oracle: {DeFiActions.PriceOracle}, yieldTokenType: Type, recurringConfig: DeFiActions.AutoBalancerRecurringConfig?, uniqueID: DeFiActions.UniqueIdentifier - ): FlowYieldVaultsStrategiesV1_1.AutoBalancerIO { + ): FlowYieldVaultsStrategiesV2.AutoBalancerIO { // NOTE: This stores the AutoBalancer in FlowYieldVaultsAutoBalancers storage and returns an authorized ref. let autoBalancerRef = FlowYieldVaultsAutoBalancers._initNewAutoBalancer( @@ -537,7 +513,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { let source = autoBalancerRef.createBalancerSource() ?? panic("Could not retrieve Source from AutoBalancer with id \(uniqueID.id)") - return FlowYieldVaultsStrategiesV1_1.AutoBalancerIO( + return FlowYieldVaultsStrategiesV2.AutoBalancerIO( autoBalancer: autoBalancerRef, sink: sink, source: source @@ -549,7 +525,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { issuanceSink: {DeFiActions.Sink}, repaymentSource: {DeFiActions.Source} ): FlowCreditMarket.Position { - let poolCap = FlowYieldVaultsStrategiesV1_1.account.storage.copy< + let poolCap = FlowYieldVaultsStrategiesV2.account.storage.copy< Capability >(from: FlowCreditMarket.PoolCapStoragePath) ?? panic("Missing or invalid pool capability") @@ -567,7 +543,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } access(self) fun _createYieldToCollateralSwapper( - collateralConfig: FlowYieldVaultsStrategiesV1_1.CollateralConfig, + collateralConfig: FlowYieldVaultsStrategiesV2.CollateralConfig, yieldTokenEVMAddress: EVM.EVMAddress, yieldTokenType: Type, collateralType: Type, @@ -623,10 +599,10 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { /// may utilize resource consumption (i.e. account storage). Since Strategy creation consumes account storage /// via configured AutoBalancers access(all) resource StrategyComposerIssuer : FlowYieldVaults.StrategyComposerIssuer { - /// { StrategyComposer Type: { Strategy Type: { Collateral Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig } } } - access(all) var configs: {Type: {Type: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}}} + /// { StrategyComposer Type: { Strategy Type: { Collateral Type: FlowYieldVaultsStrategiesV2.CollateralConfig } } } + access(all) var configs: {Type: {Type: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig}}} - init(configs: {Type: {Type: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}}}) { + init(configs: {Type: {Type: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig}}}) { self.configs = configs } @@ -645,12 +621,12 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { access(all) view fun getSupportedComposers(): {Type: Bool} { return { - Type<@mUSDFStrategyComposer>(): true + Type<@MorphoERC4626StrategyComposer>(): true } } access(self) view fun isSupportedComposer(_ type: Type): Bool { - return type == Type<@mUSDFStrategyComposer>() + return type == Type<@MorphoERC4626StrategyComposer>() } access(all) fun issueComposer(_ type: Type): @{FlowYieldVaults.StrategyComposer} { pre { @@ -660,8 +636,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { "Could not find config for StrategyComposer \(type.identifier)" } switch type { - case Type<@mUSDFStrategyComposer>(): - return <- create mUSDFStrategyComposer(self.configs[type]!) + case Type<@MorphoERC4626StrategyComposer>(): + return <- create MorphoERC4626StrategyComposer(self.configs[type]!) default: panic("Unsupported StrategyComposer \(type.identifier) requested") } @@ -670,7 +646,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { access(Configure) fun upsertConfigFor( composer: Type, - config: {Type: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}} + config: {Type: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig}} ) { pre { self.isSupportedComposer(composer) == true: @@ -694,7 +670,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { for stratType in config.keys { let newPerCollateral = config[stratType]! let existingPerCollateral = mergedComposerConfig[stratType] ?? {} - var mergedPerCollateral: {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} = existingPerCollateral + var mergedPerCollateral: {Type: FlowYieldVaultsStrategiesV2.CollateralConfig} = existingPerCollateral for collateralType in newPerCollateral.keys { mergedPerCollateral[collateralType] = newPerCollateral[collateralType]! @@ -723,7 +699,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } // Base struct with shared addresses - var base = FlowYieldVaultsStrategiesV1_1.makeCollateralConfig( + var base = FlowYieldVaultsStrategiesV2.makeCollateralConfig( yieldTokenEVMAddress: yieldTokenEVMAddress, yieldToCollateralAddressPath: yieldToCollateralAddressPath, yieldToCollateralFeePath: yieldToCollateralFeePath @@ -740,9 +716,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } access(Configure) fun purgeConfig() { self.configs = { - Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}, - Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} + Type<@MorphoERC4626StrategyComposer>(): { + Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV2.CollateralConfig} } } } @@ -818,7 +793,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { self.univ3FactoryEVMAddress = EVM.addressFromString(univ3FactoryEVMAddress) self.univ3RouterEVMAddress = EVM.addressFromString(univ3RouterEVMAddress) self.univ3QuoterEVMAddress = EVM.addressFromString(univ3QuoterEVMAddress) - self.IssuerStoragePath = StoragePath(identifier: "FlowYieldVaultsStrategyV1_1ComposerIssuer_\(self.account.address)")! + self.IssuerStoragePath = StoragePath(identifier: "FlowYieldVaultsStrategyV2ComposerIssuer_\(self.account.address)")! self.config = {} let moetType = Type<@MOET.Vault>() @@ -827,9 +802,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } let configs = { - Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig}, - Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} + Type<@MorphoERC4626StrategyComposer>(): { + Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV2.CollateralConfig} } } self.account.storage.save(<-create StrategyComposerIssuer(configs: configs), to: self.IssuerStoragePath) diff --git a/cadence/contracts/PMStrategies.cdc b/cadence/contracts/PMStrategies.cdc new file mode 100644 index 0000000..817c413 --- /dev/null +++ b/cadence/contracts/PMStrategies.cdc @@ -0,0 +1,358 @@ +// standards +import "FungibleToken" +import "FlowToken" +import "EVM" +// DeFiActions +import "DeFiActionsUtils" +import "DeFiActions" +import "SwapConnectors" +import "FungibleTokenConnectors" +// amm integration +import "UniswapV3SwapConnectors" +import "ERC4626SwapConnectors" +import "ERC4626Utils" +// FlowYieldVaults platform +import "FlowYieldVaults" +import "FlowYieldVaultsAutoBalancers" +// vm bridge +import "FlowEVMBridgeConfig" +import "FlowEVMBridgeUtils" +import "FlowEVMBridge" +// live oracles +import "ERC4626PriceOracles" + +/// PMStrategies +/// +/// This contract defines Strategies used in the FlowYieldVaults platform. +/// +/// A Strategy instance can be thought of as objects wrapping a stack of DeFiActions connectors wired together to +/// (optimally) generate some yield on initial deposits. Strategies can be simple such as swapping into a yield-bearing +/// asset (such as stFLOW) or more complex DeFiActions stacks. +/// +/// A StrategyComposer is tasked with the creation of a supported Strategy. It's within the stacking of DeFiActions +/// connectors that the true power of the components lies. +/// +access(all) contract PMStrategies { + + access(all) var univ3FactoryEVMAddress: EVM.EVMAddress + access(all) var univ3RouterEVMAddress: EVM.EVMAddress + access(all) var univ3QuoterEVMAddress: EVM.EVMAddress + + access(all) var yieldTokenEVMAddress: EVM.EVMAddress + access(all) var swapFeeTier: UInt32 + + /// Canonical StoragePath where the StrategyComposerIssuer should be stored + access(all) let IssuerStoragePath: StoragePath + + /// This strategy uses syWFLOWv vaults + access(all) resource syWFLOWvStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { + /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- + /// specific Identifier to associated connectors on construction + access(contract) var uniqueID: DeFiActions.UniqueIdentifier? + + /// User-facing deposit connector + access(self) var sink: {DeFiActions.Sink} + /// User-facing withdrawal connector + access(self) var source: {DeFiActions.Source} + + init( + id: DeFiActions.UniqueIdentifier, + sink: {DeFiActions.Sink}, + source: {DeFiActions.Source} + ) { + self.uniqueID = id + self.sink = sink + self.source = source + } + + // Inherited from FlowYieldVaults.Strategy default implementation + // access(all) view fun isSupportedCollateralType(_ type: Type): Bool + + access(all) view fun getSupportedCollateralTypes(): {Type: Bool} { + return { self.sink.getSinkType(): true } + } + /// Returns the amount available for withdrawal via the inner Source + access(all) fun availableBalance(ofToken: Type): UFix64 { + return ofToken == self.source.getSourceType() ? self.source.minimumAvailable() : 0.0 + } + /// Deposits up to the inner Sink's capacity from the provided authorized Vault reference + access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) { + self.sink.depositCapacity(from: from) + } + /// Withdraws up to the max amount, returning the withdrawn Vault. If the requested token type is unsupported, + /// an empty Vault is returned. + access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} { + if ofToken != self.source.getSourceType() { + return <- DeFiActionsUtils.getEmptyVault(ofToken) + } + return <- self.source.withdrawAvailable(maxAmount: maxAmount) + } + /// Executed when a Strategy is burned, cleaning up the Strategy's stored AutoBalancer + access(contract) fun burnCallback() { + FlowYieldVaultsAutoBalancers._cleanupAutoBalancer(id: self.id()!) + } + access(all) fun getComponentInfo(): DeFiActions.ComponentInfo { + return DeFiActions.ComponentInfo( + type: self.getType(), + id: self.id(), + innerComponents: [ + self.sink.getComponentInfo(), + self.source.getComponentInfo() + ] + ) + } + access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? { + return self.uniqueID + } + access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) { + self.uniqueID = id + } + } + + /// This StrategyComposer builds a syWFLOWvStrategy + access(all) resource syWFLOWvStrategyComposer : FlowYieldVaults.StrategyComposer { + init() {} + + /// Returns the Types of Strategies composed by this StrategyComposer + access(all) view fun getComposedStrategyTypes(): {Type: Bool} { + return { + Type<@syWFLOWvStrategy>(): true + } + } + + /// Returns the Vault types which can be used to initialize a given Strategy + access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} { + return { Type<@FlowToken.Vault>(): true } + } + + /// Returns the Vault types which can be deposited to a given Strategy instance if it was initialized with the + /// provided Vault type + access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool} { + let supportedInitVaults = self.getSupportedInitializationVaults(forStrategy: forStrategy) + if supportedInitVaults[initializedWith] == true { + return { initializedWith: true } + } + return {} + } + + /// Composes a Strategy of the given type with the provided funds + access(all) fun createStrategy( + _ type: Type, + uniqueID: DeFiActions.UniqueIdentifier, + withFunds: @{FungibleToken.Vault} + ): @{FlowYieldVaults.Strategy} { + let flowTokenType = Type<@FlowToken.Vault>() + + // assign token types & associated EVM Addresses + let wflowTokenEVMAddress = FlowEVMBridgeConfig.getEVMAddressAssociated(with: flowTokenType) + ?? panic("Token Vault type \(flowTokenType.identifier) has not yet been registered with the VMbridge") + let yieldTokenType = FlowEVMBridgeConfig.getTypeAssociated(with: PMStrategies.yieldTokenEVMAddress) + ?? panic("Could not retrieve the VM Bridge associated Type for the yield token address \(PMStrategies.yieldTokenEVMAddress.toString())") + + // create the oracle for the assets to be held in the AutoBalancer retrieving the NAV of the 4626 vault + let yieldTokenOracle = ERC4626PriceOracles.PriceOracle( + vault: PMStrategies.yieldTokenEVMAddress, + asset: flowTokenType, + uniqueID: uniqueID + ) + + // configure and AutoBalancer for this stack + let autoBalancer = FlowYieldVaultsAutoBalancers._initNewAutoBalancer( + oracle: yieldTokenOracle, // used to determine value of deposits & when to rebalance + vaultType: yieldTokenType, // the type of Vault held by the AutoBalancer + lowerThreshold: 0.95, // set AutoBalancer to pull from rebalanceSource when balance is 5% below value of deposits + upperThreshold: 1.05, // set AutoBalancer to push to rebalanceSink when balance is 5% below value of deposits + rebalanceSink: nil, // nil on init - will be set once a PositionSink is available + rebalanceSource: nil, // nil on init - not set for Strategy + recurringConfig: nil, // disables native AutoBalancer self-scheduling, no rebalancing required after init + uniqueID: uniqueID // identifies AutoBalancer as part of this Strategy + ) + // enables deposits of YieldToken to the AutoBalancer + let abaSink = autoBalancer.createBalancerSink() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)") + // enables withdrawals of YieldToken from the AutoBalancer + let abaSource = autoBalancer.createBalancerSource() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)") + + // create WFLOW <-> YIELD swappers + // + // WFLOW -> YIELD - WFLOW can swap to YieldToken via two primary routes + // - via AMM swap pairing WFLOW <-> YIELD + // - via 4626 vault, swapping first to underlying asset then depositing to the 4626 vault + // WFLOW -> YIELD high-level Swapper then contains + // - MultiSwapper aggregates across two sub-swappers + // - WFLOW -> YIELD (UniV3 Swapper) + let wflowToYieldAMMSwapper = UniswapV3SwapConnectors.Swapper( + factoryAddress: PMStrategies.univ3FactoryEVMAddress, + routerAddress: PMStrategies.univ3RouterEVMAddress, + quoterAddress: PMStrategies.univ3QuoterEVMAddress, + tokenPath: [wflowTokenEVMAddress, PMStrategies.yieldTokenEVMAddress], + feePath: [PMStrategies.swapFeeTier], + inVault: flowTokenType, + outVault: yieldTokenType, + coaCapability: PMStrategies._getCOACapability(), + uniqueID: uniqueID + ) + // Swap UNDERLYING -> YIELD via ERC4626 Vault + let wflowTo4626Swapper = ERC4626SwapConnectors.Swapper( + asset: flowTokenType, + vault: PMStrategies.yieldTokenEVMAddress, + coa: PMStrategies._getCOACapability(), + feeSource: PMStrategies._createFeeSource(withID: uniqueID), + uniqueID: uniqueID + ) + // Finally, add the two WFLOW -> YIELD swappers into an aggregate MultiSwapper + let wflowToYieldSwapper = SwapConnectors.MultiSwapper( + inVault: flowTokenType, + outVault: yieldTokenType, + swappers: [wflowToYieldAMMSwapper, wflowTo4626Swapper], + uniqueID: uniqueID + ) + + // YIELD -> WFLOW + // - Targets the WFLOW <-> YIELD pool as the only route since withdraws from the ERC4626 Vault are async + let yieldToWFLOWSwapper = UniswapV3SwapConnectors.Swapper( + factoryAddress: PMStrategies.univ3FactoryEVMAddress, + routerAddress: PMStrategies.univ3RouterEVMAddress, + quoterAddress: PMStrategies.univ3QuoterEVMAddress, + tokenPath: [PMStrategies.yieldTokenEVMAddress, wflowTokenEVMAddress], + feePath: [PMStrategies.swapFeeTier], + inVault: yieldTokenType, + outVault: flowTokenType, + coaCapability: PMStrategies._getCOACapability(), + uniqueID: uniqueID + ) + + // init SwapSink directing swapped funds to AutoBalancer + // + // Swaps provided WFLOW to YIELD & deposits to the AutoBalancer + let abaSwapSink = SwapConnectors.SwapSink(swapper: wflowToYieldSwapper, sink: abaSink, uniqueID: uniqueID) + // Swaps YIELD & provides swapped WFLOW, sourcing YIELD from the AutoBalancer + let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToWFLOWSwapper, source: abaSource, uniqueID: uniqueID) + + abaSwapSink.depositCapacity(from: &withFunds as auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) + + assert(withFunds.balance == 0.0, message: "Vault should be empty after depositing") + destroy withFunds + + // Use the same uniqueID passed to createStrategy so Strategy.burnCallback + // calls _cleanupAutoBalancer with the correct ID + return <-create syWFLOWvStrategy( + id: uniqueID, + sink: abaSwapSink, + source: abaSwapSource + ) + } + } + + access(all) entitlement Configure + + /// This resource enables the issuance of StrategyComposers, thus safeguarding the issuance of Strategies which + /// may utilize resource consumption (i.e. account storage). Since Strategy creation consumes account storage + /// via configured AutoBalancers + access(all) resource StrategyComposerIssuer : FlowYieldVaults.StrategyComposerIssuer { + init() {} + + access(all) view fun getSupportedComposers(): {Type: Bool} { + return { + Type<@syWFLOWvStrategyComposer>(): true + } + } + access(all) fun issueComposer(_ type: Type): @{FlowYieldVaults.StrategyComposer} { + pre { + self.getSupportedComposers()[type] == true: + "Unsupported StrategyComposer \(type.identifier) requested" + } + switch type { + case Type<@syWFLOWvStrategyComposer>(): + return <- create syWFLOWvStrategyComposer() + default: + panic("Unsupported StrategyComposer \(type.identifier) requested") + } + } + access(Configure) + fun updateEVMAddresses( + factory: String, + router: String, + quoter: String, + yieldToken: String, + swapFeeTier: UInt32 + ) { + PMStrategies.univ3FactoryEVMAddress = EVM.addressFromString(factory) + PMStrategies.univ3RouterEVMAddress = EVM.addressFromString(router) + PMStrategies.univ3QuoterEVMAddress = EVM.addressFromString(quoter) + PMStrategies.yieldTokenEVMAddress = EVM.addressFromString(yieldToken) + PMStrategies.swapFeeTier = swapFeeTier + } + } + + /// Returns the COA capability for this account + /// TODO: this is temporary until we have a better way to pass user's COAs to inner connectors + access(self) + fun _getCOACapability(): Capability { + let coaCap = self.account.capabilities.storage.issue(/storage/evm) + assert(coaCap.check(), message: "Could not issue COA capability") + return coaCap + } + + /// Returns a FungibleTokenConnectors.VaultSinkAndSource used to subsidize cross VM token movement in contract- + /// defined strategies. + access(self) + fun _createFeeSource(withID: DeFiActions.UniqueIdentifier?): {DeFiActions.Sink, DeFiActions.Source} { + let capPath = /storage/strategiesFeeSource + if self.account.storage.type(at: capPath) == nil { + let cap = self.account.capabilities.storage.issue(/storage/flowTokenVault) + self.account.storage.save(cap, to: capPath) + } + let vaultCap = self.account.storage.copy>(from: capPath) + ?? panic("Could not find fee source Capability at \(capPath)") + return FungibleTokenConnectors.VaultSinkAndSource( + min: nil, + max: nil, + vault: vaultCap, + uniqueID: withID + ) + } + + /// Creates a Sink+Source for the AutoBalancer to use for scheduling fees + access(self) + fun _createTxnFunder(withID: DeFiActions.UniqueIdentifier?): {DeFiActions.Sink, DeFiActions.Source} { + let capPath = /storage/autoBalancerTxnFunder + if self.account.storage.type(at: capPath) == nil { + let cap = self.account.capabilities.storage.issue(/storage/flowTokenVault) + self.account.storage.save(cap, to: capPath) + } + let vaultCap = self.account.storage.copy>(from: capPath) + ?? panic("Could not find txnFunder Capability at \(capPath)") + return FungibleTokenConnectors.VaultSinkAndSource( + min: nil, + max: nil, + vault: vaultCap, + uniqueID: withID + ) + } + + init( + univ3FactoryEVMAddress: String, + univ3RouterEVMAddress: String, + univ3QuoterEVMAddress: String, + yieldTokenEVMAddress: String, + swapFeeTier: UInt32 + ) { + self.univ3FactoryEVMAddress = EVM.addressFromString(univ3FactoryEVMAddress) + self.univ3RouterEVMAddress = EVM.addressFromString(univ3RouterEVMAddress) + self.univ3QuoterEVMAddress = EVM.addressFromString(univ3QuoterEVMAddress) + self.yieldTokenEVMAddress = EVM.addressFromString(yieldTokenEVMAddress) + self.swapFeeTier = swapFeeTier + + self.IssuerStoragePath = StoragePath(identifier: "PMStrategiesComposerIssuer_\(self.account.address)")! + + self.account.storage.save(<-create StrategyComposerIssuer(), to: self.IssuerStoragePath) + + // TODO: this is temporary until we have a better way to pass user's COAs to inner connectors + // create a COA in this account + if self.account.storage.type(at: /storage/evm) == nil { + self.account.storage.save(<-EVM.createCadenceOwnedAccount(), to: /storage/evm) + let cap = self.account.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(/storage/evm) + self.account.capabilities.publish(cap, at: /public/evm) + } + } +} diff --git a/cadence/contracts/PMStrategiesV1.cdc b/cadence/contracts/PMStrategiesV1.cdc index 2709708..0d0b061 100644 --- a/cadence/contracts/PMStrategiesV1.cdc +++ b/cadence/contracts/PMStrategiesV1.cdc @@ -347,8 +347,7 @@ access(all) contract PMStrategiesV1 { ) // Swap Collateral -> YieldToken via ERC4626 Vault let collateralToYieldMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swapper( - asset: collateralType, - vault: yieldTokenEVMAddress, + vaultEVMAddress: yieldTokenEVMAddress, coa: PMStrategiesV1._getCOACapability(), feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), uniqueID: uniqueID, @@ -385,8 +384,7 @@ access(all) contract PMStrategiesV1 { // Swap (redeem) YieldToken -> Collateral via MorphoERC4626 Vault let yieldToCollateralMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swaper( - asset: collateralType, - vault: yieldTokenEVMAddress, + vaultEVMAddress: yieldTokenEVMAddress, coa: PMStrategiesV1._getCOACapability(), feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), uniqueID: uniqueID, diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index 1155e84..c4f4695 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -330,8 +330,8 @@ access(all) fun deployContracts() { Test.expect(err, Test.beNil()) err = Test.deployContract( - name: "FlowYieldVaultsStrategiesV1_1", - path: "../contracts/FlowYieldVaultsStrategiesV1_1.cdc", + name: "FlowYieldVaultsStrategiesV2", + path: "../contracts/FlowYieldVaultsStrategiesV2.cdc", arguments: [ "0x986Cb42b0557159431d48fE0A40073296414d410", "0x92657b195e22b69E4779BBD09Fa3CD46F0CF8e39", diff --git a/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc b/cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc similarity index 80% rename from cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc rename to cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc index 1a5414c..792c703 100644 --- a/cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc +++ b/cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc @@ -1,14 +1,14 @@ import "FungibleToken" import "EVM" -import "FlowYieldVaultsStrategiesV1_1" +import "FlowYieldVaultsStrategiesV2" -/// Admin tx to (re)configure Uniswap paths for the mUSDFStrategy +/// Admin tx to (re)configure Uniswap paths for strategies from FlowYieldVaultsStrategiesV2 /// /// NOTE: /// - Must be signed by the account that deployed FlowYieldVaultsStrategies /// - You can omit some collaterals by passing empty arrays and guarding in prepare{} transaction( - // e.g. "A.0x...FlowYieldVaultsStrategiesV1_1.mUSDFStrategy" + // e.g. "A.0x...FlowYieldVaultsStrategiesV2.FUSDEVStrategy" strategyTypeIdentifier: String, // collateral vault type (e.g. "A.0x...FlowToken.Vault") @@ -30,8 +30,8 @@ transaction( // This tx must run on the same account that stores the issuer // otherwise this borrow will fail. let issuer = acct.storage.borrow< - auth(FlowYieldVaultsStrategiesV1_1.Configure) &FlowYieldVaultsStrategiesV1_1.StrategyComposerIssuer - >(from: FlowYieldVaultsStrategiesV1_1.IssuerStoragePath) + auth(FlowYieldVaultsStrategiesV2.Configure) &FlowYieldVaultsStrategiesV2.StrategyComposerIssuer + >(from: FlowYieldVaultsStrategiesV2.IssuerStoragePath) ?? panic("Missing StrategyComposerIssuer at IssuerStoragePath") let yieldEVM = EVM.addressFromString(yieldTokenEVMAddress) @@ -45,7 +45,7 @@ transaction( return out } - let composerType = Type<@FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer>() + let composerType = Type<@FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer>() if swapPath.length > 0 { issuer.addOrUpdateCollateralConfig( diff --git a/flow.json b/flow.json index 0914fc3..e65a9ba 100644 --- a/flow.json +++ b/flow.json @@ -161,8 +161,8 @@ "testnet": "d2580caf2ef07c2f" } }, - "FlowYieldVaultsStrategiesV1_1": { - "source": "cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc", + "FlowYieldVaultsStrategiesV2": { + "source": "cadence/contracts/FlowYieldVaultsStrategiesV2.cdc", "aliases": { "emulator": "045a1763c93006ca", "mainnet": "b1d63873c3cc9f79", @@ -873,7 +873,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0x986Cb42b0557159431d48fE0A40073296414d410", @@ -1001,7 +1001,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0xca6d7Bb03334bBf135902e1d919a5feccb461632", @@ -1106,7 +1106,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0x92657b195e22b69E4779BBD09Fa3CD46F0CF8e39", diff --git a/local/setup_emulator.sh b/local/setup_emulator.sh index c726fb5..6110c5f 100755 --- a/local/setup_emulator.sh +++ b/local/setup_emulator.sh @@ -51,8 +51,8 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ - 'A.045a1763c93006ca.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.045a1763c93006ca.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ + 'A.045a1763c93006ca.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ + 'A.045a1763c93006ca.FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer' \ /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0x045a1763c93006ca \ --signer emulator-flow-yield-vaults diff --git a/local/setup_mainnet.sh b/local/setup_mainnet.sh index 6ffffc8..3794db1 100755 --- a/local/setup_mainnet.sh +++ b/local/setup_mainnet.sh @@ -115,42 +115,9 @@ flow transactions send ./lib/FlowCreditMarket/FlowActions/cadence/transactions/f # flow transactions send ./cadence/transactions/mocks/swapper/set_liquidity_connector.cdc /storage/EVMVMBridgedToken_4154d5b0e2931a0a1e5b733f19161aa7d2fc4b95Vault --network mainnet --signer mainnet-admin # - -# Setup UniV3 path tauUSDFv -> USDF -> WFLOW -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.1654653399040a61.FlowToken.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ - '[100,3000]' \ - --network mainnet \ - --signer mainnet-admin - - -# Setup UniV3 path tauUSDFv -> USDF -> WBTC -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ - '[100,3000]' \ - --network mainnet \ - --signer mainnet-admin - -# Setup UniV3 path tauUSDFv -> USDF -> WETH -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ - '[100,3000]' \ - --network mainnet \ - --signer mainnet-admin - - # Setup UniV3 path FUSDEV -> PYUSD0 -> WFLOW -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1654653399040a61.FlowToken.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -160,8 +127,8 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # Setup UniV3 path FUSDEV -> PYUSD0 -> WBTC -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ @@ -170,8 +137,8 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus --signer mainnet-admin # Setup UniV3 path FUSDEV -> PYUSD0 -> WETH -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ @@ -179,18 +146,11 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus --network mainnet \ --signer mainnet-admin # -# add mUSDFStrategy as supported Strategy with the ability to initialize when new YieldVaults are created -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ - /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xb1d63873c3cc9f79 \ - --network mainnet \ - --signer mainnet-admin flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ - /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xb1d63873c3cc9f79 \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer' \ + /storage/FlowYieldVaultsStrategyV2ComposerIssuer_0xb1d63873c3cc9f79 \ --network mainnet \ --signer mainnet-admin @@ -264,7 +224,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # test FlowYieldVault strategy # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.1654653399040a61.FlowToken.Vault \ # 1.0 \ # --compute-limit 9999 \ @@ -274,7 +234,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # # WBTC (BTCf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault \ # 0.0000001 \ # --compute-limit 9999 \ @@ -283,7 +243,7 @@ flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-cr # # WETH (ETHf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault \ # 0.00001 \ # --compute-limit 9999 \ diff --git a/local/setup_testnet.sh b/local/setup_testnet.sh index aeec38e..a1d90e1 100755 --- a/local/setup_testnet.sh +++ b/local/setup_testnet.sh @@ -6,7 +6,7 @@ flow project deploy --network testnet --update # set mocked prices in the MockOracle contract, initialized with MOET as unitOfAccount flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.7e60df042a9c0868.FlowToken.Vault' 0.5 --network testnet --signer testnet-admin -#flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.d2580caf2ef07c2f.YieldToken.Vault' 1.0 --network testnet --signer testnet-admin +flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.d2580caf2ef07c2f.YieldToken.Vault' 1.0 --network testnet --signer testnet-admin flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.dfc20aee650fcbdf.EVMVMBridgedToken_4154d5b0e2931a0a1e5b733f19161aa7d2fc4b95.Vault' 1.0 --network testnet --signer testnet-admin echo "bridge MOET to EVM" @@ -88,41 +88,11 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate --network testnet \ --signer testnet-admin -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' - 'A.7e60df042a9c0868.FlowToken.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95", "0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ - '[3000]' \ - --network testnet \ - --signer testnet-admin - -# WETH univ3 path and fees -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' - 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c", "0x059A77239daFa770977DD9f1E98632C3E4559848"]' \ - '[3000,3000]' \ - --network testnet \ - --signer testnet-admin - -# WBTC univ3 path and fees -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' - 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c","0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6"]' \ - '[3000,3000]' \ - --network testnet \ - --signer testnet-admin - - ## PYUSD0 Vault # WFLOW univ3 path and fees # path: FUSDEV - WFLOW -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.7e60df042a9c0868.FlowToken.Vault' \ "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ '["0x61b44D19486EE492449E83C1201581C754e9e1E1", "0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ @@ -132,8 +102,8 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # WETH univ3 path and fees # path: FUSDEV - MOET - WETH -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ '["0x61b44D19486EE492449E83C1201581C754e9e1E1","0x02d3575e2516a515E9B91a52b294Edc80DC7987c", "0x059A77239daFa770977DD9f1E98632C3E4559848"]' \ @@ -143,8 +113,8 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus # WBTC univ3 path and fees # path: FUSDEV - MOET - WETH -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_musdf_config.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ '["0x61b44D19486EE492449E83C1201581C754e9e1E1","0x02d3575e2516a515E9B91a52b294Edc80DC7987c","0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6"]' \ @@ -153,16 +123,9 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_mus --signer testnet-admin flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ - /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xd2580caf2ef07c2f \ - --network testnet \ - --signer testnet-admin - -flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strategy_composer.cdc \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.FUSDEVStrategy' \ - 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer' \ - /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xd2580caf2ef07c2f \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer' \ + /storage/FlowYieldVaultsStrategyV2ComposerIssuer_0xd2580caf2ef07c2f \ --network testnet \ --signer testnet-admin @@ -203,7 +166,7 @@ flow transactions send ./lib/flow-evm-bridge/cadence/transactions/flow-token/tra # # Flow # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy \ +# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.7e60df042a9c0868.FlowToken.Vault \ # 100.0 \ # --signer \ @@ -213,7 +176,7 @@ flow transactions send ./lib/flow-evm-bridge/cadence/transactions/flow-token/tra # # WBTC (BTCf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy \ +# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault \ # 0.00001 \ # --compute-limit 9999 \ @@ -222,7 +185,7 @@ flow transactions send ./lib/flow-evm-bridge/cadence/transactions/flow-token/tra # # WETH (ETHf) # flow transactions send ./cadence/transactions/flow-yield-vaults/create_yield_vault.cdc \ -# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy \ +# A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault \ # 0.001 \ # --compute-limit 9999 \ From 428ba29731078a45301c05230e47e6d7f626f1f1 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 5 Feb 2026 17:59:29 -0500 Subject: [PATCH 07/13] remove old PMStrategies --- cadence/contracts/PMStrategies.cdc | 358 ----------------------------- 1 file changed, 358 deletions(-) delete mode 100644 cadence/contracts/PMStrategies.cdc diff --git a/cadence/contracts/PMStrategies.cdc b/cadence/contracts/PMStrategies.cdc deleted file mode 100644 index 817c413..0000000 --- a/cadence/contracts/PMStrategies.cdc +++ /dev/null @@ -1,358 +0,0 @@ -// standards -import "FungibleToken" -import "FlowToken" -import "EVM" -// DeFiActions -import "DeFiActionsUtils" -import "DeFiActions" -import "SwapConnectors" -import "FungibleTokenConnectors" -// amm integration -import "UniswapV3SwapConnectors" -import "ERC4626SwapConnectors" -import "ERC4626Utils" -// FlowYieldVaults platform -import "FlowYieldVaults" -import "FlowYieldVaultsAutoBalancers" -// vm bridge -import "FlowEVMBridgeConfig" -import "FlowEVMBridgeUtils" -import "FlowEVMBridge" -// live oracles -import "ERC4626PriceOracles" - -/// PMStrategies -/// -/// This contract defines Strategies used in the FlowYieldVaults platform. -/// -/// A Strategy instance can be thought of as objects wrapping a stack of DeFiActions connectors wired together to -/// (optimally) generate some yield on initial deposits. Strategies can be simple such as swapping into a yield-bearing -/// asset (such as stFLOW) or more complex DeFiActions stacks. -/// -/// A StrategyComposer is tasked with the creation of a supported Strategy. It's within the stacking of DeFiActions -/// connectors that the true power of the components lies. -/// -access(all) contract PMStrategies { - - access(all) var univ3FactoryEVMAddress: EVM.EVMAddress - access(all) var univ3RouterEVMAddress: EVM.EVMAddress - access(all) var univ3QuoterEVMAddress: EVM.EVMAddress - - access(all) var yieldTokenEVMAddress: EVM.EVMAddress - access(all) var swapFeeTier: UInt32 - - /// Canonical StoragePath where the StrategyComposerIssuer should be stored - access(all) let IssuerStoragePath: StoragePath - - /// This strategy uses syWFLOWv vaults - access(all) resource syWFLOWvStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { - /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- - /// specific Identifier to associated connectors on construction - access(contract) var uniqueID: DeFiActions.UniqueIdentifier? - - /// User-facing deposit connector - access(self) var sink: {DeFiActions.Sink} - /// User-facing withdrawal connector - access(self) var source: {DeFiActions.Source} - - init( - id: DeFiActions.UniqueIdentifier, - sink: {DeFiActions.Sink}, - source: {DeFiActions.Source} - ) { - self.uniqueID = id - self.sink = sink - self.source = source - } - - // Inherited from FlowYieldVaults.Strategy default implementation - // access(all) view fun isSupportedCollateralType(_ type: Type): Bool - - access(all) view fun getSupportedCollateralTypes(): {Type: Bool} { - return { self.sink.getSinkType(): true } - } - /// Returns the amount available for withdrawal via the inner Source - access(all) fun availableBalance(ofToken: Type): UFix64 { - return ofToken == self.source.getSourceType() ? self.source.minimumAvailable() : 0.0 - } - /// Deposits up to the inner Sink's capacity from the provided authorized Vault reference - access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) { - self.sink.depositCapacity(from: from) - } - /// Withdraws up to the max amount, returning the withdrawn Vault. If the requested token type is unsupported, - /// an empty Vault is returned. - access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} { - if ofToken != self.source.getSourceType() { - return <- DeFiActionsUtils.getEmptyVault(ofToken) - } - return <- self.source.withdrawAvailable(maxAmount: maxAmount) - } - /// Executed when a Strategy is burned, cleaning up the Strategy's stored AutoBalancer - access(contract) fun burnCallback() { - FlowYieldVaultsAutoBalancers._cleanupAutoBalancer(id: self.id()!) - } - access(all) fun getComponentInfo(): DeFiActions.ComponentInfo { - return DeFiActions.ComponentInfo( - type: self.getType(), - id: self.id(), - innerComponents: [ - self.sink.getComponentInfo(), - self.source.getComponentInfo() - ] - ) - } - access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? { - return self.uniqueID - } - access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) { - self.uniqueID = id - } - } - - /// This StrategyComposer builds a syWFLOWvStrategy - access(all) resource syWFLOWvStrategyComposer : FlowYieldVaults.StrategyComposer { - init() {} - - /// Returns the Types of Strategies composed by this StrategyComposer - access(all) view fun getComposedStrategyTypes(): {Type: Bool} { - return { - Type<@syWFLOWvStrategy>(): true - } - } - - /// Returns the Vault types which can be used to initialize a given Strategy - access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} { - return { Type<@FlowToken.Vault>(): true } - } - - /// Returns the Vault types which can be deposited to a given Strategy instance if it was initialized with the - /// provided Vault type - access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool} { - let supportedInitVaults = self.getSupportedInitializationVaults(forStrategy: forStrategy) - if supportedInitVaults[initializedWith] == true { - return { initializedWith: true } - } - return {} - } - - /// Composes a Strategy of the given type with the provided funds - access(all) fun createStrategy( - _ type: Type, - uniqueID: DeFiActions.UniqueIdentifier, - withFunds: @{FungibleToken.Vault} - ): @{FlowYieldVaults.Strategy} { - let flowTokenType = Type<@FlowToken.Vault>() - - // assign token types & associated EVM Addresses - let wflowTokenEVMAddress = FlowEVMBridgeConfig.getEVMAddressAssociated(with: flowTokenType) - ?? panic("Token Vault type \(flowTokenType.identifier) has not yet been registered with the VMbridge") - let yieldTokenType = FlowEVMBridgeConfig.getTypeAssociated(with: PMStrategies.yieldTokenEVMAddress) - ?? panic("Could not retrieve the VM Bridge associated Type for the yield token address \(PMStrategies.yieldTokenEVMAddress.toString())") - - // create the oracle for the assets to be held in the AutoBalancer retrieving the NAV of the 4626 vault - let yieldTokenOracle = ERC4626PriceOracles.PriceOracle( - vault: PMStrategies.yieldTokenEVMAddress, - asset: flowTokenType, - uniqueID: uniqueID - ) - - // configure and AutoBalancer for this stack - let autoBalancer = FlowYieldVaultsAutoBalancers._initNewAutoBalancer( - oracle: yieldTokenOracle, // used to determine value of deposits & when to rebalance - vaultType: yieldTokenType, // the type of Vault held by the AutoBalancer - lowerThreshold: 0.95, // set AutoBalancer to pull from rebalanceSource when balance is 5% below value of deposits - upperThreshold: 1.05, // set AutoBalancer to push to rebalanceSink when balance is 5% below value of deposits - rebalanceSink: nil, // nil on init - will be set once a PositionSink is available - rebalanceSource: nil, // nil on init - not set for Strategy - recurringConfig: nil, // disables native AutoBalancer self-scheduling, no rebalancing required after init - uniqueID: uniqueID // identifies AutoBalancer as part of this Strategy - ) - // enables deposits of YieldToken to the AutoBalancer - let abaSink = autoBalancer.createBalancerSink() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)") - // enables withdrawals of YieldToken from the AutoBalancer - let abaSource = autoBalancer.createBalancerSource() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)") - - // create WFLOW <-> YIELD swappers - // - // WFLOW -> YIELD - WFLOW can swap to YieldToken via two primary routes - // - via AMM swap pairing WFLOW <-> YIELD - // - via 4626 vault, swapping first to underlying asset then depositing to the 4626 vault - // WFLOW -> YIELD high-level Swapper then contains - // - MultiSwapper aggregates across two sub-swappers - // - WFLOW -> YIELD (UniV3 Swapper) - let wflowToYieldAMMSwapper = UniswapV3SwapConnectors.Swapper( - factoryAddress: PMStrategies.univ3FactoryEVMAddress, - routerAddress: PMStrategies.univ3RouterEVMAddress, - quoterAddress: PMStrategies.univ3QuoterEVMAddress, - tokenPath: [wflowTokenEVMAddress, PMStrategies.yieldTokenEVMAddress], - feePath: [PMStrategies.swapFeeTier], - inVault: flowTokenType, - outVault: yieldTokenType, - coaCapability: PMStrategies._getCOACapability(), - uniqueID: uniqueID - ) - // Swap UNDERLYING -> YIELD via ERC4626 Vault - let wflowTo4626Swapper = ERC4626SwapConnectors.Swapper( - asset: flowTokenType, - vault: PMStrategies.yieldTokenEVMAddress, - coa: PMStrategies._getCOACapability(), - feeSource: PMStrategies._createFeeSource(withID: uniqueID), - uniqueID: uniqueID - ) - // Finally, add the two WFLOW -> YIELD swappers into an aggregate MultiSwapper - let wflowToYieldSwapper = SwapConnectors.MultiSwapper( - inVault: flowTokenType, - outVault: yieldTokenType, - swappers: [wflowToYieldAMMSwapper, wflowTo4626Swapper], - uniqueID: uniqueID - ) - - // YIELD -> WFLOW - // - Targets the WFLOW <-> YIELD pool as the only route since withdraws from the ERC4626 Vault are async - let yieldToWFLOWSwapper = UniswapV3SwapConnectors.Swapper( - factoryAddress: PMStrategies.univ3FactoryEVMAddress, - routerAddress: PMStrategies.univ3RouterEVMAddress, - quoterAddress: PMStrategies.univ3QuoterEVMAddress, - tokenPath: [PMStrategies.yieldTokenEVMAddress, wflowTokenEVMAddress], - feePath: [PMStrategies.swapFeeTier], - inVault: yieldTokenType, - outVault: flowTokenType, - coaCapability: PMStrategies._getCOACapability(), - uniqueID: uniqueID - ) - - // init SwapSink directing swapped funds to AutoBalancer - // - // Swaps provided WFLOW to YIELD & deposits to the AutoBalancer - let abaSwapSink = SwapConnectors.SwapSink(swapper: wflowToYieldSwapper, sink: abaSink, uniqueID: uniqueID) - // Swaps YIELD & provides swapped WFLOW, sourcing YIELD from the AutoBalancer - let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToWFLOWSwapper, source: abaSource, uniqueID: uniqueID) - - abaSwapSink.depositCapacity(from: &withFunds as auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) - - assert(withFunds.balance == 0.0, message: "Vault should be empty after depositing") - destroy withFunds - - // Use the same uniqueID passed to createStrategy so Strategy.burnCallback - // calls _cleanupAutoBalancer with the correct ID - return <-create syWFLOWvStrategy( - id: uniqueID, - sink: abaSwapSink, - source: abaSwapSource - ) - } - } - - access(all) entitlement Configure - - /// This resource enables the issuance of StrategyComposers, thus safeguarding the issuance of Strategies which - /// may utilize resource consumption (i.e. account storage). Since Strategy creation consumes account storage - /// via configured AutoBalancers - access(all) resource StrategyComposerIssuer : FlowYieldVaults.StrategyComposerIssuer { - init() {} - - access(all) view fun getSupportedComposers(): {Type: Bool} { - return { - Type<@syWFLOWvStrategyComposer>(): true - } - } - access(all) fun issueComposer(_ type: Type): @{FlowYieldVaults.StrategyComposer} { - pre { - self.getSupportedComposers()[type] == true: - "Unsupported StrategyComposer \(type.identifier) requested" - } - switch type { - case Type<@syWFLOWvStrategyComposer>(): - return <- create syWFLOWvStrategyComposer() - default: - panic("Unsupported StrategyComposer \(type.identifier) requested") - } - } - access(Configure) - fun updateEVMAddresses( - factory: String, - router: String, - quoter: String, - yieldToken: String, - swapFeeTier: UInt32 - ) { - PMStrategies.univ3FactoryEVMAddress = EVM.addressFromString(factory) - PMStrategies.univ3RouterEVMAddress = EVM.addressFromString(router) - PMStrategies.univ3QuoterEVMAddress = EVM.addressFromString(quoter) - PMStrategies.yieldTokenEVMAddress = EVM.addressFromString(yieldToken) - PMStrategies.swapFeeTier = swapFeeTier - } - } - - /// Returns the COA capability for this account - /// TODO: this is temporary until we have a better way to pass user's COAs to inner connectors - access(self) - fun _getCOACapability(): Capability { - let coaCap = self.account.capabilities.storage.issue(/storage/evm) - assert(coaCap.check(), message: "Could not issue COA capability") - return coaCap - } - - /// Returns a FungibleTokenConnectors.VaultSinkAndSource used to subsidize cross VM token movement in contract- - /// defined strategies. - access(self) - fun _createFeeSource(withID: DeFiActions.UniqueIdentifier?): {DeFiActions.Sink, DeFiActions.Source} { - let capPath = /storage/strategiesFeeSource - if self.account.storage.type(at: capPath) == nil { - let cap = self.account.capabilities.storage.issue(/storage/flowTokenVault) - self.account.storage.save(cap, to: capPath) - } - let vaultCap = self.account.storage.copy>(from: capPath) - ?? panic("Could not find fee source Capability at \(capPath)") - return FungibleTokenConnectors.VaultSinkAndSource( - min: nil, - max: nil, - vault: vaultCap, - uniqueID: withID - ) - } - - /// Creates a Sink+Source for the AutoBalancer to use for scheduling fees - access(self) - fun _createTxnFunder(withID: DeFiActions.UniqueIdentifier?): {DeFiActions.Sink, DeFiActions.Source} { - let capPath = /storage/autoBalancerTxnFunder - if self.account.storage.type(at: capPath) == nil { - let cap = self.account.capabilities.storage.issue(/storage/flowTokenVault) - self.account.storage.save(cap, to: capPath) - } - let vaultCap = self.account.storage.copy>(from: capPath) - ?? panic("Could not find txnFunder Capability at \(capPath)") - return FungibleTokenConnectors.VaultSinkAndSource( - min: nil, - max: nil, - vault: vaultCap, - uniqueID: withID - ) - } - - init( - univ3FactoryEVMAddress: String, - univ3RouterEVMAddress: String, - univ3QuoterEVMAddress: String, - yieldTokenEVMAddress: String, - swapFeeTier: UInt32 - ) { - self.univ3FactoryEVMAddress = EVM.addressFromString(univ3FactoryEVMAddress) - self.univ3RouterEVMAddress = EVM.addressFromString(univ3RouterEVMAddress) - self.univ3QuoterEVMAddress = EVM.addressFromString(univ3QuoterEVMAddress) - self.yieldTokenEVMAddress = EVM.addressFromString(yieldTokenEVMAddress) - self.swapFeeTier = swapFeeTier - - self.IssuerStoragePath = StoragePath(identifier: "PMStrategiesComposerIssuer_\(self.account.address)")! - - self.account.storage.save(<-create StrategyComposerIssuer(), to: self.IssuerStoragePath) - - // TODO: this is temporary until we have a better way to pass user's COAs to inner connectors - // create a COA in this account - if self.account.storage.type(at: /storage/evm) == nil { - self.account.storage.save(<-EVM.createCadenceOwnedAccount(), to: /storage/evm) - let cap = self.account.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(/storage/evm) - self.account.capabilities.publish(cap, at: /public/evm) - } - } -} From 2168f686bc2791b2c1db2af234be4cfded2ba4fd Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:41:21 -0500 Subject: [PATCH 08/13] tests --- cadence/contracts/FlowYieldVaults.cdc | 2 +- .../contracts/FlowYieldVaultsStrategiesV2.cdc | 99 +++-- cadence/contracts/PMStrategiesV1.cdc | 92 +++-- cadence/tests/PMStrategiesV1_test.cdc | 364 ++++++++++++++++++ cadence/tests/test_helpers.cdc | 20 + .../transactions/swap_flow_to_pyusd0.cdc | 159 ++++++++ flow.json | 28 ++ 7 files changed, 694 insertions(+), 70 deletions(-) create mode 100644 cadence/tests/PMStrategiesV1_test.cdc create mode 100644 cadence/tests/transactions/swap_flow_to_pyusd0.cdc diff --git a/cadence/contracts/FlowYieldVaults.cdc b/cadence/contracts/FlowYieldVaults.cdc index ccf618e..8449f99 100644 --- a/cadence/contracts/FlowYieldVaults.cdc +++ b/cadence/contracts/FlowYieldVaults.cdc @@ -317,7 +317,7 @@ access(all) contract FlowYieldVaults { /// Withdraws the requested amount from the Strategy access(FungibleToken.Withdraw) fun withdraw(amount: UFix64): @{FungibleToken.Vault} { post { - result.balance == amount: + result.balance >= amount && result.balance <= amount + 0.00000001: "Invalid Vault balance returned - requested \(amount) but returned \(result.balance)" self.vaultType == result.getType(): "Invalid Vault returned - expected \(self.vaultType.identifier) but returned \(result.getType().identifier)" diff --git a/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc index cd176e9..6d66b4a 100644 --- a/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc @@ -8,6 +8,7 @@ import "SwapConnectors" import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" +import "ERC4626SwapConnectors" import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // Lending protocol @@ -259,9 +260,9 @@ access(all) contract FlowYieldVaultsStrategiesV2 { ) // Swappers: MOET <-> YIELD (YIELD is ERC4626 vault token) - let moetToYieldSwapper = self._createMoetToYieldSwapper(tokens: tokens, uniqueID: uniqueID) + let moetToYieldSwapper = self._createMoetToYieldSwapper(strategyType: type, tokens: tokens, uniqueID: uniqueID) - let yieldToMoetSwapper = self._createYieldToMoetSwapper(tokens: tokens, uniqueID: uniqueID) + let yieldToMoetSwapper = self._createYieldToMoetSwapper(strategyType: type, tokens: tokens, uniqueID: uniqueID) // AutoBalancer-directed swap IO let abaSwapSink = SwapConnectors.SwapSink( @@ -402,6 +403,7 @@ access(all) contract FlowYieldVaultsStrategiesV2 { } access(self) fun _createMoetToYieldSwapper( + strategyType: Type, tokens: FlowYieldVaultsStrategiesV2.TokenBundle, uniqueID: DeFiActions.UniqueIdentifier ): SwapConnectors.MultiSwapper { @@ -424,16 +426,28 @@ access(all) contract FlowYieldVaultsStrategiesV2 { ) // UNDERLYING -> YIELD via ERC4626 vault - let underlyingTo4626 = MorphoERC4626SwapConnectors.Swapper( - vaultEVMAddress: tokens.yieldTokenEVMAddress, - coa: FlowYieldVaultsStrategiesV2._getCOACapability(), - feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), - uniqueID: uniqueID, - isReversed: false - ) + // Morpho vaults use MorphoERC4626SwapConnectors; standard ERC4626 vaults use ERC4626SwapConnectors + var underlyingTo4626: {DeFiActions.Swapper}? = nil + if strategyType == Type<@FUSDEVStrategy>() { + underlyingTo4626 = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: tokens.yieldTokenEVMAddress, + coa: FlowYieldVaultsStrategiesV2._getCOACapability(), + feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: false + ) + } else { + underlyingTo4626 = ERC4626SwapConnectors.Swapper( + asset: tokens.underlying4626AssetType, + vault: tokens.yieldTokenEVMAddress, + coa: FlowYieldVaultsStrategiesV2._getCOACapability(), + feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), + uniqueID: uniqueID + ) + } let seq = SwapConnectors.SequentialSwapper( - swappers: [moetToUnderlying, underlyingTo4626], + swappers: [moetToUnderlying, underlyingTo4626!], uniqueID: uniqueID ) @@ -446,6 +460,7 @@ access(all) contract FlowYieldVaultsStrategiesV2 { } access(self) fun _createYieldToMoetSwapper( + strategyType: Type, tokens: FlowYieldVaultsStrategiesV2.TokenBundle, uniqueID: DeFiActions.UniqueIdentifier ): SwapConnectors.MultiSwapper { @@ -458,35 +473,45 @@ access(all) contract FlowYieldVaultsStrategiesV2 { uniqueID: uniqueID ) - // YIELD -> UNDERLYING redeem via MorphoERC4626 vault - let yieldToUnderlying = MorphoERC4626SwapConnectors.Swapper( - vaultEVMAddress: tokens.yieldTokenEVMAddress, - coa: FlowYieldVaultsStrategiesV2._getCOACapability(), - feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), - uniqueID: uniqueID, - isReversed: true - ) - // UNDERLYING -> MOET via AMM - let underlyingToMoet = self._createUniV3Swapper( - tokenPath: [tokens.underlying4626AssetEVMAddress, tokens.moetTokenEVMAddress], - feePath: [100], - inVault: tokens.underlying4626AssetType, - outVault: tokens.moetTokenType, - uniqueID: uniqueID - ) - + // Reverse path: Morpho vaults support direct redeem; standard ERC4626 vaults use AMM-only path + if strategyType == Type<@FUSDEVStrategy>() { + // YIELD -> UNDERLYING redeem via MorphoERC4626 vault + let yieldToUnderlying = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: tokens.yieldTokenEVMAddress, + coa: FlowYieldVaultsStrategiesV2._getCOACapability(), + feeSource: FlowYieldVaultsStrategiesV2._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: true + ) + // UNDERLYING -> MOET via AMM + let underlyingToMoet = self._createUniV3Swapper( + tokenPath: [tokens.underlying4626AssetEVMAddress, tokens.moetTokenEVMAddress], + feePath: [100], + inVault: tokens.underlying4626AssetType, + outVault: tokens.moetTokenType, + uniqueID: uniqueID + ) - let seq = SwapConnectors.SequentialSwapper( - swappers: [yieldToUnderlying, underlyingToMoet], - uniqueID: uniqueID - ) + let seq = SwapConnectors.SequentialSwapper( + swappers: [yieldToUnderlying, underlyingToMoet], + uniqueID: uniqueID + ) - return SwapConnectors.MultiSwapper( - inVault: tokens.yieldTokenType, - outVault: tokens.moetTokenType, - swappers: [yieldToMoetAMM, seq], - uniqueID: uniqueID - ) + return SwapConnectors.MultiSwapper( + inVault: tokens.yieldTokenType, + outVault: tokens.moetTokenType, + swappers: [yieldToMoetAMM, seq], + uniqueID: uniqueID + ) + } else { + // Standard ERC4626: AMM-only reverse (no synchronous redeem support) + return SwapConnectors.MultiSwapper( + inVault: tokens.yieldTokenType, + outVault: tokens.moetTokenType, + swappers: [yieldToMoetAMM], + uniqueID: uniqueID + ) + } } access(self) fun _initAutoBalancerAndIO( diff --git a/cadence/contracts/PMStrategiesV1.cdc b/cadence/contracts/PMStrategiesV1.cdc index 0d0b061..366e587 100644 --- a/cadence/contracts/PMStrategiesV1.cdc +++ b/cadence/contracts/PMStrategiesV1.cdc @@ -8,6 +8,7 @@ import "SwapConnectors" import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" +import "ERC4626SwapConnectors" import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // FlowYieldVaults platform @@ -346,20 +347,37 @@ access(all) contract PMStrategiesV1 { uniqueID: uniqueID ) // Swap Collateral -> YieldToken via ERC4626 Vault - let collateralToYieldMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swapper( - vaultEVMAddress: yieldTokenEVMAddress, - coa: PMStrategiesV1._getCOACapability(), - feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), - uniqueID: uniqueID, - isReversed: false - ) - // Finally, add the two Collateral -> YieldToken swappers into an aggregate MultiSwapper - let collateralToYieldSwapper = SwapConnectors.MultiSwapper( - inVault: collateralType, - outVault: yieldTokenType, - swappers: [collateralToYieldAMMSwapper, collateralToYieldMorphoERC4626Swapper], - uniqueID: uniqueID - ) + // Morpho vaults use MorphoERC4626SwapConnectors; standard ERC4626 vaults use ERC4626SwapConnectors + var collateralToYieldSwapper: SwapConnectors.MultiSwapper? = nil + if type == Type<@FUSDEVStrategy>() { + let collateralToYieldMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: yieldTokenEVMAddress, + coa: PMStrategiesV1._getCOACapability(), + feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: false + ) + collateralToYieldSwapper = SwapConnectors.MultiSwapper( + inVault: collateralType, + outVault: yieldTokenType, + swappers: [collateralToYieldAMMSwapper, collateralToYieldMorphoERC4626Swapper], + uniqueID: uniqueID + ) + } else { + let collateralToYieldERC4626Swapper = ERC4626SwapConnectors.Swapper( + asset: collateralType, + vault: yieldTokenEVMAddress, + coa: PMStrategiesV1._getCOACapability(), + feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), + uniqueID: uniqueID + ) + collateralToYieldSwapper = SwapConnectors.MultiSwapper( + inVault: collateralType, + outVault: yieldTokenType, + swappers: [collateralToYieldAMMSwapper, collateralToYieldERC4626Swapper], + uniqueID: uniqueID + ) + } // create YieldToken <-> Collateral swappers // @@ -382,29 +400,39 @@ access(all) contract PMStrategiesV1 { uniqueID: uniqueID ) - // Swap (redeem) YieldToken -> Collateral via MorphoERC4626 Vault - let yieldToCollateralMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swaper( - vaultEVMAddress: yieldTokenEVMAddress, - coa: PMStrategiesV1._getCOACapability(), - feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), - uniqueID: uniqueID, - isReversed: true - ) - - // Finally, add the two YieldToken <-> Collateral swappers into an aggregate MultiSwapper - let yieldToCollateralSwapper = SwapConnectors.MultiSwapper( - inVault: yieldTokenType, - outVault: collateralType, - swappers: [yieldToCollateralAMMSwapper, yieldToCollateralMorphoERC4626Swapper], - uniqueID: uniqueID - ) + // Reverse path: YieldToken -> Collateral + // Morpho vaults support direct redeem; standard ERC4626 vaults use AMM-only path + var yieldToCollateralSwapper: SwapConnectors.MultiSwapper? = nil + if type == Type<@FUSDEVStrategy>() { + let yieldToCollateralMorphoERC4626Swapper = MorphoERC4626SwapConnectors.Swapper( + vaultEVMAddress: yieldTokenEVMAddress, + coa: PMStrategiesV1._getCOACapability(), + feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), + uniqueID: uniqueID, + isReversed: true + ) + yieldToCollateralSwapper = SwapConnectors.MultiSwapper( + inVault: yieldTokenType, + outVault: collateralType, + swappers: [yieldToCollateralAMMSwapper, yieldToCollateralMorphoERC4626Swapper], + uniqueID: uniqueID + ) + } else { + // Standard ERC4626: AMM-only reverse (no synchronous redeem support) + yieldToCollateralSwapper = SwapConnectors.MultiSwapper( + inVault: yieldTokenType, + outVault: collateralType, + swappers: [yieldToCollateralAMMSwapper], + uniqueID: uniqueID + ) + } // init SwapSink directing swapped funds to AutoBalancer // // Swaps provided Collateral to YieldToken & deposits to the AutoBalancer - let abaSwapSink = SwapConnectors.SwapSink(swapper: collateralToYieldSwapper, sink: abaSink, uniqueID: uniqueID) + let abaSwapSink = SwapConnectors.SwapSink(swapper: collateralToYieldSwapper!, sink: abaSink, uniqueID: uniqueID) // Swaps YieldToken & provides swapped Collateral, sourcing YieldToken from the AutoBalancer - let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToCollateralSwapper, source: abaSource, uniqueID: uniqueID) + let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToCollateralSwapper!, source: abaSource, uniqueID: uniqueID) abaSwapSink.depositCapacity(from: &withFunds as auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) diff --git a/cadence/tests/PMStrategiesV1_test.cdc b/cadence/tests/PMStrategiesV1_test.cdc new file mode 100644 index 0000000..65849fa --- /dev/null +++ b/cadence/tests/PMStrategiesV1_test.cdc @@ -0,0 +1,364 @@ +#test_fork(network: "mainnet", height: nil) + +import Test + +import "EVM" +import "FlowToken" +import "FlowYieldVaults" +import "PMStrategiesV1" +import "FlowYieldVaultsClosedBeta" + +/// Fork test for PMStrategiesV1 — validates the full YieldVault lifecycle (create, deposit, withdraw, close) +/// against real mainnet state using Morpho ERC4626 connectors. +/// +/// This test: +/// - Forks Flow mainnet to access real EVM state (Morpho vaults, UniswapV3 pools) +/// - Configures PMStrategiesV1 strategies for both syWFLOWv (FLOW collateral) and FUSDEV (PYUSD0 collateral) +/// - Tests the complete yield vault lifecycle through the strategy factory +/// - Validates Morpho ERC4626 swap connectors work with real vault contracts +/// +/// Mainnet addresses: +/// - Admin (FlowYieldVaults deployer): 0xb1d63873c3cc9f79 +/// - UniV3 Factory: 0xca6d7Bb03334bBf135902e1d919a5feccb461632 +/// - UniV3 Router: 0xeEDC6Ff75e1b10B903D9013c358e446a73d35341 +/// - UniV3 Quoter: 0x370A8DF17742867a44e56223EC20D82092242C85 +/// - WFLOW: 0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e +/// - syWFLOWv (More vault): 0xCBf9a7753F9D2d0e8141ebB36d99f87AcEf98597 +/// - PYUSD0: 0x99aF3EeA856556646C98c8B9b2548Fe815240750 +/// - FUSDEV (Morpho vault): 0xd069d989e2F44B70c65347d1853C0c67e10a9F8D + +// --- Accounts --- + +/// Mainnet admin account — deployer of PMStrategiesV1, FlowYieldVaults, FlowYieldVaultsClosedBeta +access(all) let adminAccount = Test.getAccount(0xb1d63873c3cc9f79) + +/// Mainnet user account — used to test yield vault operations (has 5 PYUSD0) +access(all) let userAccount = Test.getAccount(0x443472749ebdaac8) + +// --- Strategy Config Constants --- + +/// syWFLOWvStrategy: FLOW collateral -> syWFLOWv Morpho ERC4626 vault +access(all) let syWFLOWvStrategyIdentifier = "A.b1d63873c3cc9f79.PMStrategiesV1.syWFLOWvStrategy" +access(all) let flowVaultIdentifier = "A.1654653399040a61.FlowToken.Vault" +access(all) let syWFLOWvEVMAddress = "0xCBf9a7753F9D2d0e8141ebB36d99f87AcEf98597" + +/// FUSDEVStrategy: PYUSD0 collateral -> FUSDEV Morpho ERC4626 vault +access(all) let fusdEvStrategyIdentifier = "A.b1d63873c3cc9f79.PMStrategiesV1.FUSDEVStrategy" +access(all) let pyusd0VaultIdentifier = "A.1e4aa0b87d10b141.EVMVMBridgedToken_99af3eea856556646c98c8b9b2548fe815240750.Vault" +access(all) let fusdEvEVMAddress = "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" + +/// ERC4626VaultStrategyComposer type and issuer path +access(all) let composerIdentifier = "A.b1d63873c3cc9f79.PMStrategiesV1.ERC4626VaultStrategyComposer" +access(all) let issuerStoragePath: StoragePath = /storage/PMStrategiesV1ComposerIssuer_0xb1d63873c3cc9f79 + +/// Swap fee tier for Morpho vault <-> underlying asset UniV3 pools +access(all) let swapFeeTier: UInt32 = 100 + +// --- Test State --- + +access(all) var syWFLOWvYieldVaultID: UInt64 = 0 +access(all) var fusdEvYieldVaultID: UInt64 = 0 + +/* --- Test Helpers --- */ + +access(all) +fun _executeScript(_ path: String, _ args: [AnyStruct]): Test.ScriptResult { + return Test.executeScript(Test.readFile(path), args) +} + +access(all) +fun _executeTransactionFile(_ path: String, _ args: [AnyStruct], _ signers: [Test.TestAccount]): Test.TransactionResult { + let txn = Test.Transaction( + code: Test.readFile(path), + authorizers: signers.map(fun (s: Test.TestAccount): Address { return s.address }), + signers: signers, + arguments: args + ) + return Test.executeTransaction(txn) +} + +/* --- Setup --- */ + +access(all) fun setup() { + log("==== PMStrategiesV1 Fork Test Setup ====") + + log("Deploying EVMAmountUtils contract ...") + var err = Test.deployContract( + name: "EVMAmountUtils", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/EVMAmountUtils.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + log("Deploying UniswapV3SwapConnectors contract ...") + err = Test.deployContract( + name: "UniswapV3SwapConnectors", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/UniswapV3SwapConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + // Deploy Morpho contracts (latest local code) to the forked environment + log("Deploying Morpho contracts...") + err = Test.deployContract( + name: "ERC4626Utils", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/utils/ERC4626Utils.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + err = Test.deployContract( + name: "ERC4626SwapConnectors", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/ERC4626SwapConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + err = Test.deployContract( + name: "MorphoERC4626SinkConnectors", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SinkConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + err = Test.deployContract( + name: "MorphoERC4626SwapConnectors", + path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SwapConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + log("Deploying FlowYieldVaults contract ...") + err = Test.deployContract( + name: "FlowYieldVaults", + path: "../../../cadence/contracts/FlowYieldVaults.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + // Redeploy PMStrategiesV1 with latest local code to override mainnet version + log("Deploying PMStrategiesV1...") + err = Test.deployContract( + name: "PMStrategiesV1", + path: "../../../cadence/contracts/PMStrategiesV1.cdc", + arguments: [ + "0xca6d7Bb03334bBf135902e1d919a5feccb461632", + "0xeEDC6Ff75e1b10B903D9013c358e446a73d35341", + "0x370A8DF17742867a44e56223EC20D82092242C85" + ] + ) + Test.expect(err, Test.beNil()) + + // // 1. Configure syWFLOWvStrategy with FlowToken collateral + // log("Configuring syWFLOWvStrategy...") + // var result = _executeTransactionFile( + // "../../transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc", + // [syWFLOWvStrategyIdentifier, flowVaultIdentifier, syWFLOWvEVMAddress, swapFeeTier], + // [adminAccount] + // ) + // Test.expect(result, Test.beSucceeded()) + // + // // 2. Configure FUSDEVStrategy with PYUSD0 collateral + // log("Configuring FUSDEVStrategy...") + // result = _executeTransactionFile( + // "../../transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc", + // [fusdEvStrategyIdentifier, pyusd0VaultIdentifier, fusdEvEVMAddress, swapFeeTier], + // [adminAccount] + // ) + // Test.expect(result, Test.beSucceeded()) + // + // // 3. Register syWFLOWvStrategy with the StrategyFactory + // log("Adding syWFLOWvStrategy composer...") + // result = _executeTransactionFile( + // "../../transactions/flow-yield-vaults/admin/add_strategy_composer.cdc", + // [syWFLOWvStrategyIdentifier, composerIdentifier, issuerStoragePath], + // [adminAccount] + // ) + // Test.expect(result, Test.beSucceeded()) + // + // // 4. Register FUSDEVStrategy with the StrategyFactory + // log("Adding FUSDEVStrategy composer...") + // result = _executeTransactionFile( + // "../../transactions/flow-yield-vaults/admin/add_strategy_composer.cdc", + // [fusdEvStrategyIdentifier, composerIdentifier, issuerStoragePath], + // [adminAccount] + // ) + // Test.expect(result, Test.beSucceeded()) + // + // 5. Grant beta access to user account for testing yield vault operations + log("Granting beta access to user...") + var result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/admin/grant_beta.cdc", + [], + [adminAccount, userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + log("==== Setup Complete ====") +} + +/* --- syWFLOWvStrategy Tests (FLOW collateral, Morpho syWFLOWv vault) --- */ + +access(all) fun testCreateSyWFLOWvYieldVault() { + log("Creating syWFLOWvStrategy yield vault with 1.0 FLOW...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/create_yield_vault.cdc", + [syWFLOWvStrategyIdentifier, flowVaultIdentifier, 1.0], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + // Retrieve the vault IDs + let idsResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", + [userAccount.address] + ) + Test.expect(idsResult, Test.beSucceeded()) + let ids = idsResult.returnValue! as! [UInt64]? + Test.assert(ids != nil && ids!.length > 0, message: "Expected at least one yield vault") + syWFLOWvYieldVaultID = ids![ids!.length - 1] + log("Created syWFLOWv yield vault ID: ".concat(syWFLOWvYieldVaultID.toString())) + + // Verify initial balance + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, syWFLOWvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil, message: "Expected balance to be available") + Test.assert(balance! > 0.0, message: "Expected positive balance after deposit") + log("syWFLOWv vault balance: ".concat(balance!.toString())) +} + +access(all) fun testDepositToSyWFLOWvYieldVault() { + log("Depositing 0.5 FLOW to syWFLOWv yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", + [syWFLOWvYieldVaultID, 0.5], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, syWFLOWvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil && balance! > 0.0, message: "Expected positive balance after additional deposit") + log("syWFLOWv vault balance after deposit: ".concat(balance!.toString())) +} + +access(all) fun testWithdrawFromSyWFLOWvYieldVault() { + log("Withdrawing 0.3 FLOW from syWFLOWv yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", + [syWFLOWvYieldVaultID, 0.3], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, syWFLOWvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil && balance! > 0.0, message: "Expected positive balance after withdrawal") + log("syWFLOWv vault balance after withdrawal: ".concat(balance!.toString())) +} + +access(all) fun testCloseSyWFLOWvYieldVault() { + log("Closing syWFLOWv yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/close_yield_vault.cdc", + [syWFLOWvYieldVaultID], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + log("syWFLOWv yield vault closed successfully") +} + +/* --- FUSDEVStrategy Tests (PYUSD0 collateral, Morpho FUSDEV vault) --- */ + +access(all) fun testCreateFUSDEVYieldVault() { + log("Creating FUSDEVStrategy yield vault with 1.0 PYUSD0...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/create_yield_vault.cdc", + [fusdEvStrategyIdentifier, pyusd0VaultIdentifier, 1.0], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + // Retrieve the vault IDs + let idsResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", + [userAccount.address] + ) + Test.expect(idsResult, Test.beSucceeded()) + let ids = idsResult.returnValue! as! [UInt64]? + Test.assert(ids != nil && ids!.length > 0, message: "Expected at least one yield vault") + fusdEvYieldVaultID = ids![ids!.length - 1] + log("Created FUSDEV yield vault ID: ".concat(fusdEvYieldVaultID.toString())) + + // Verify initial balance + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, fusdEvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil, message: "Expected balance to be available") + Test.assert(balance! > 0.0, message: "Expected positive balance after deposit") + log("FUSDEV vault balance: ".concat(balance!.toString())) +} + +access(all) fun testDepositToFUSDEVYieldVault() { + log("Depositing 0.5 PYUSD0 to FUSDEV yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", + [fusdEvYieldVaultID, 0.5], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, fusdEvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil && balance! > 0.0, message: "Expected positive balance after additional deposit") + log("FUSDEV vault balance after deposit: ".concat(balance!.toString())) +} + +access(all) fun testWithdrawFromFUSDEVYieldVault() { + log("Withdrawing 0.3 PYUSD0 from FUSDEV yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", + [fusdEvYieldVaultID, 0.3], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + + let balResult = _executeScript( + "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + [userAccount.address, fusdEvYieldVaultID] + ) + Test.expect(balResult, Test.beSucceeded()) + let balance = balResult.returnValue! as! UFix64? + Test.assert(balance != nil && balance! > 0.0, message: "Expected positive balance after withdrawal") + log("FUSDEV vault balance after withdrawal: ".concat(balance!.toString())) +} + +access(all) fun testCloseFUSDEVYieldVault() { + log("Closing FUSDEV yield vault...") + let result = _executeTransactionFile( + "../../transactions/flow-yield-vaults/close_yield_vault.cdc", + [fusdEvYieldVaultID], + [userAccount] + ) + Test.expect(result, Test.beSucceeded()) + log("FUSDEV yield vault closed successfully") +} diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index 02f0805..7340703 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -262,6 +262,12 @@ access(all) fun deployContracts() { arguments: [] ) Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "EVMAmountUtils", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/EVMAmountUtils.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) err = Test.deployContract( name: "UniswapV3SwapConnectors", path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/UniswapV3SwapConnectors.cdc", @@ -304,6 +310,20 @@ access(all) fun deployContracts() { ) Test.expect(err, Test.beNil()) + err = Test.deployContract( + name: "MorphoERC4626SinkConnectors", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SinkConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + + err = Test.deployContract( + name: "MorphoERC4626SwapConnectors", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SwapConnectors.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) + let onboarder = Test.createAccount() transferFlow(signer: serviceAccount, recipient: onboarder.address, amount: 100.0) let onboardMoet = _executeTransaction( diff --git a/cadence/tests/transactions/swap_flow_to_pyusd0.cdc b/cadence/tests/transactions/swap_flow_to_pyusd0.cdc new file mode 100644 index 0000000..8637a27 --- /dev/null +++ b/cadence/tests/transactions/swap_flow_to_pyusd0.cdc @@ -0,0 +1,159 @@ +import "FungibleToken" +import "FungibleTokenMetadataViews" +import "ViewResolver" +import "FlowToken" +import "EVM" +import "FlowEVMBridgeUtils" +import "FlowEVMBridgeConfig" +import "ScopedFTProviders" + +/// Funds the signer with PYUSD0 by swapping FLOW on EVM via UniswapV3, then bridging to Cadence. +/// +/// Steps: +/// 1. Deposit FLOW to the signer's COA +/// 2. Wrap FLOW to WFLOW +/// 3. Swap WFLOW -> PYUSD0 via UniswapV3 exactInput +/// 4. Bridge PYUSD0 from EVM to Cadence +/// +/// @param flowAmount: Amount of FLOW to swap for PYUSD0 +/// +transaction(flowAmount: UFix64) { + + let coa: auth(EVM.Owner, EVM.Call, EVM.Bridge) &EVM.CadenceOwnedAccount + let scopedProvider: @ScopedFTProviders.ScopedFTProvider + let receiver: &{FungibleToken.Vault} + + prepare(signer: auth(BorrowValue, SaveValue, IssueStorageCapabilityController, PublishCapability, UnpublishCapability, CopyValue) &Account) { + // Borrow COA + self.coa = signer.storage.borrow(from: /storage/evm) + ?? panic("No COA at /storage/evm") + + // Withdraw FLOW and deposit to COA + let flowVault = signer.storage.borrow(from: /storage/flowTokenVault) + ?? panic("No FlowToken vault") + let deposit <- flowVault.withdraw(amount: flowAmount) as! @FlowToken.Vault + self.coa.deposit(from: <-deposit) + + // Set up scoped fee provider for bridging + let approxFee = FlowEVMBridgeUtils.calculateBridgeFee(bytes: 400_000) + if signer.storage.type(at: FlowEVMBridgeConfig.providerCapabilityStoragePath) == nil { + let providerCap = signer.capabilities.storage.issue( + /storage/flowTokenVault + ) + signer.storage.save(providerCap, to: FlowEVMBridgeConfig.providerCapabilityStoragePath) + } + let providerCapCopy = signer.storage.copy>( + from: FlowEVMBridgeConfig.providerCapabilityStoragePath + ) ?? panic("Invalid provider capability") + self.scopedProvider <- ScopedFTProviders.createScopedFTProvider( + provider: providerCapCopy, + filters: [ScopedFTProviders.AllowanceFilter(approxFee)], + expiration: getCurrentBlock().timestamp + 1000.0 + ) + + // Set up PYUSD0 vault if needed + let pyusd0Type = CompositeType("A.1e4aa0b87d10b141.EVMVMBridgedToken_99af3eea856556646c98c8b9b2548fe815240750.Vault")! + let tokenContractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: pyusd0Type) + ?? panic("Could not get PYUSD0 contract address") + let tokenContractName = FlowEVMBridgeUtils.getContractName(fromType: pyusd0Type) + ?? panic("Could not get PYUSD0 contract name") + let viewResolver = getAccount(tokenContractAddress).contracts.borrow<&{ViewResolver}>(name: tokenContractName) + ?? panic("Could not borrow ViewResolver for PYUSD0") + let vaultData = viewResolver.resolveContractView( + resourceType: pyusd0Type, + viewType: Type() + ) as! FungibleTokenMetadataViews.FTVaultData? + ?? panic("Could not resolve FTVaultData for PYUSD0") + if signer.storage.borrow<&{FungibleToken.Vault}>(from: vaultData.storagePath) == nil { + signer.storage.save(<-vaultData.createEmptyVault(), to: vaultData.storagePath) + signer.capabilities.unpublish(vaultData.receiverPath) + signer.capabilities.unpublish(vaultData.metadataPath) + let receiverCap = signer.capabilities.storage.issue<&{FungibleToken.Vault}>(vaultData.storagePath) + let metadataCap = signer.capabilities.storage.issue<&{FungibleToken.Vault}>(vaultData.storagePath) + signer.capabilities.publish(receiverCap, at: vaultData.receiverPath) + signer.capabilities.publish(metadataCap, at: vaultData.metadataPath) + } + self.receiver = signer.storage.borrow<&{FungibleToken.Vault}>(from: vaultData.storagePath) + ?? panic("Could not borrow PYUSD0 vault") + } + + execute { + let wflowAddr = EVM.addressFromString("0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e") + let pyusd0Addr = EVM.addressFromString("0x99aF3EeA856556646C98c8B9b2548Fe815240750") + let routerAddr = EVM.addressFromString("0xeEDC6Ff75e1b10B903D9013c358e446a73d35341") + let zeroValue = EVM.Balance(attoflow: 0) + + // 1. Wrap FLOW -> WFLOW + let flowBalance = EVM.Balance(attoflow: 0) + flowBalance.setFLOW(flow: flowAmount) + let wrapRes = self.coa.call( + to: wflowAddr, + data: EVM.encodeABIWithSignature("deposit()", []), + gasLimit: 100_000, + value: flowBalance + ) + assert(wrapRes.status == EVM.Status.successful, message: "WFLOW wrap failed: ".concat(wrapRes.errorMessage)) + + // 2. Approve UniV3 Router to spend WFLOW + let amountEVM = FlowEVMBridgeUtils.convertCadenceAmountToERC20Amount(flowAmount, erc20Address: wflowAddr) + let approveRes = self.coa.call( + to: wflowAddr, + data: EVM.encodeABIWithSignature("approve(address,uint256)", [routerAddr, amountEVM]), + gasLimit: 100_000, + value: zeroValue + ) + assert(approveRes.status == EVM.Status.successful, message: "WFLOW approve failed: ".concat(approveRes.errorMessage)) + + // 3. Swap WFLOW -> PYUSD0 via UniV3 exactInput + // Path encoding: tokenIn(20) | fee(3 bytes big-endian) | tokenOut(20) + var pathBytes: [UInt8] = [] + let wflowFixed: [UInt8; 20] = wflowAddr.bytes + let pyusd0Fixed: [UInt8; 20] = pyusd0Addr.bytes + var i = 0 + while i < 20 { pathBytes.append(wflowFixed[i]); i = i + 1 } + // fee 3000 = 0x000BB8 big-endian + pathBytes.append(0x00) + pathBytes.append(0x0B) + pathBytes.append(0xB8) + i = 0 + while i < 20 { pathBytes.append(pyusd0Fixed[i]); i = i + 1 } + + let swapRes = self.coa.call( + to: routerAddr, + data: EVM.encodeABIWithSignature( + "exactInput((bytes,address,uint256,uint256))", + [EVM.EVMBytes(value: pathBytes), self.coa.address(), amountEVM, UInt256(0)] + ), + gasLimit: 1_000_000, + value: zeroValue + ) + assert(swapRes.status == EVM.Status.successful, message: "UniV3 swap failed: ".concat(swapRes.errorMessage)) + + // 4. Check PYUSD0 balance in COA + let balRes = self.coa.call( + to: pyusd0Addr, + data: EVM.encodeABIWithSignature("balanceOf(address)", [self.coa.address()]), + gasLimit: 100_000, + value: zeroValue + ) + assert(balRes.status == EVM.Status.successful, message: "balanceOf failed") + let decoded = EVM.decodeABI(types: [Type()], data: balRes.data) + let pyusd0Balance = decoded[0] as! UInt256 + assert(pyusd0Balance > UInt256(0), message: "No PYUSD0 received from swap") + + // 5. Bridge PYUSD0 from EVM to Cadence + let pyusd0Type = CompositeType("A.1e4aa0b87d10b141.EVMVMBridgedToken_99af3eea856556646c98c8b9b2548fe815240750.Vault")! + let bridgedVault <- self.coa.withdrawTokens( + type: pyusd0Type, + amount: pyusd0Balance, + feeProvider: &self.scopedProvider as auth(FungibleToken.Withdraw) &{FungibleToken.Provider} + ) + assert(bridgedVault.balance > 0.0, message: "Bridged PYUSD0 vault is empty") + log("Bridged PYUSD0 amount: ".concat(bridgedVault.balance.toString())) + + // Deposit bridged PYUSD0 into the signer's Cadence vault + self.receiver.deposit(from: <-bridgedVault) + + destroy self.scopedProvider + } +} diff --git a/flow.json b/flow.json index 821d073..9a8fd73 100644 --- a/flow.json +++ b/flow.json @@ -53,6 +53,15 @@ "testnet": "7014dcffa1f14186" } }, + "EVMAmountUtils": { + "source": "./lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/EVMAmountUtils.cdc", + "aliases": { + "emulator": "045a1763c93006ca", + "mainnet": "6d888f175c158410", + "testing": "0000000000000009", + "testnet": "0b11b1848a8aa2c0" + } + }, "ERC4626SwapConnectors": { "source": "./lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/ERC4626SwapConnectors.cdc", "aliases": { @@ -199,6 +208,7 @@ "source": "cadence/contracts/mocks/MockOracle.cdc", "aliases": { "emulator": "045a1763c93006ca", + "mainnet": "b1d63873c3cc9f79", "testing": "0000000000000009", "testnet": "d2580caf2ef07c2f" } @@ -215,14 +225,32 @@ "source": "cadence/contracts/mocks/MockSwapper.cdc", "aliases": { "emulator": "045a1763c93006ca", + "mainnet": "b1d63873c3cc9f79", "testing": "0000000000000009", "testnet": "d2580caf2ef07c2f" } }, + "MorphoERC4626SinkConnectors": { + "source": "./lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SinkConnectors.cdc", + "aliases": { + "emulator": "045a1763c93006ca", + "mainnet": "251032a66e9700ef", + "testing": "0000000000000009" + } + }, + "MorphoERC4626SwapConnectors": { + "source": "./lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SwapConnectors.cdc", + "aliases": { + "emulator": "045a1763c93006ca", + "mainnet": "251032a66e9700ef", + "testing": "0000000000000009" + } + }, "PMStrategiesV1": { "source": "cadence/contracts/PMStrategiesV1.cdc", "aliases": { "emulator": "045a1763c93006ca", + "mainnet": "b1d63873c3cc9f79", "testing": "0000000000000009" } }, From 4a3845285f45c3831144d1c9326836d498a6a03f Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 21:48:36 -0500 Subject: [PATCH 09/13] update ref --- lib/FlowCreditMarket | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FlowCreditMarket b/lib/FlowCreditMarket index 8163518..3eaa1ba 160000 --- a/lib/FlowCreditMarket +++ b/lib/FlowCreditMarket @@ -1 +1 @@ -Subproject commit 816351826a9deb86033469d8dea9cc847104ecbd +Subproject commit 3eaa1badcb17d45aff6bbe50bba330458828a045 From 94258991f93bfd5ed6f0fa062445f1ebd463afcf Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 22:38:24 -0500 Subject: [PATCH 10/13] fix renamed reference --- README.md | 44 ++++----- .../contracts/FlowYieldVaultsStrategies.cdc | 26 +++--- .../contracts/FlowYieldVaultsStrategiesV2.cdc | 14 +-- ...Consumer.cdc => MockFlowALPv1Consumer.cdc} | 22 ++--- cadence/contracts/mocks/MockSwapper.cdc | 6 +- .../get_complete_user_position_info.cdc | 18 ++-- cadence/tests/PMStrategiesV1_test.cdc | 90 ++++++------------- cadence/tests/atomic_registration_gc_test.cdc | 8 +- cadence/tests/rebalance_scenario1_test.cdc | 4 +- cadence/tests/rebalance_scenario2_test.cdc | 6 +- cadence/tests/rebalance_scenario3a_test.cdc | 12 +-- cadence/tests/rebalance_scenario3b_test.cdc | 8 +- cadence/tests/rebalance_scenario3c_test.cdc | 10 +-- cadence/tests/rebalance_scenario3d_test.cdc | 10 +-- cadence/tests/rebalance_yield_test.cdc | 4 +- .../scheduled_rebalance_integration_test.cdc | 6 +- .../scheduled_rebalance_scenario_test.cdc | 6 +- cadence/tests/scheduled_supervisor_test.cdc | 4 +- cadence/tests/scheduler_edge_cases_test.cdc | 4 +- cadence/tests/test_helpers.cdc | 44 ++++----- cadence/tests/tracer_strategy_test.cdc | 14 +-- cadence/tests/yield_vault_lifecycle_test.cdc | 6 +- .../position/create_wrapped_position.cdc | 10 +-- ...autobalancer-restart-recurring-proposal.md | 2 +- docs/rebalancing_architecture.md | 58 ++++++------ flow.json | 18 ++-- local/setup_emulator.sh | 6 +- local/setup_mainnet.sh | 38 ++++---- local/setup_testnet.sh | 28 +++--- 29 files changed, 245 insertions(+), 281 deletions(-) rename cadence/contracts/mocks/{MockFlowCreditMarketConsumer.cdc => MockFlowALPv1Consumer.cdc} (66%) diff --git a/README.md b/README.md index 37328b2..abe74e5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # FlowYieldVaults Smart Contracts -FlowYieldVaults is a yield farming platform built on the Flow blockchain using [Cadence](https://cadence-lang.org). The platform enables users to deposit tokens to supported DeFi strategies such as collateralized borrowing via FlowCreditMarket's Active Lending Platform. FlowYieldVaults aims to support yield-generating strategies, automatically optimizing returns through [DeFi Actions](https://developers.flow.com/blockchain-development-tutorials/forte/flow-actions) components and auto-balancing mechanisms. +FlowYieldVaults is a yield farming platform built on the Flow blockchain using [Cadence](https://cadence-lang.org). The platform enables users to deposit tokens to supported DeFi strategies such as collateralized borrowing via FlowALPv1's Active Lending Platform. FlowYieldVaults aims to support yield-generating strategies, automatically optimizing returns through [DeFi Actions](https://developers.flow.com/blockchain-development-tutorials/forte/flow-actions) components and auto-balancing mechanisms. ## System Architecture @@ -22,7 +22,7 @@ The main contract that orchestrates the entire yield farming system: Implements specific yield strategies: -- **TracerStrategy**: A strategy that uses FlowCreditMarket lending positions with auto-balancing +- **TracerStrategy**: A strategy that uses FlowALPv1 lending positions with auto-balancing - **TracerStrategyComposer**: Creates TracerStrategy instances with complex DeFi Actions stacking - **StrategyComposerIssuer**: Controls access to strategy composer creation @@ -41,7 +41,7 @@ Manages automated rebalancing of positions: Mock FungibleToken implementations representing: - **YieldToken**: Receipt tokens for yield-bearing positions -- **MOET**: FlowCreditMarket's synthetic stablecoin +- **MOET**: FlowALPv1's synthetic stablecoin ### Mock Infrastructure @@ -63,7 +63,7 @@ Mock FungibleToken implementations representing: | Asset Name | Cadence Address | Cadence Contract Name | EVM | |---|---|---|---| | FlowActions | 0xd27920b6384e2a78 | DeFiActions | TBD | -| FlowCreditMarket | 0xd27920b6384e2a78 | FlowALP | TBD | +| FlowALPv1 | 0xd27920b6384e2a78 | FlowALPv1 | TBD | | FlowYieldVaults | 0xd27920b6384e2a78 | FlowYieldVaults | TBD | | FlowYieldVaultsStrategiesV2 | 0xd27920b6384e2a78 | FlowYieldVaultsStrategiesV2 | TBD | | PMStrategiesV1 | 0xd27920b6384e2a78 | PMStrategiesV1 | TBD | @@ -78,7 +78,7 @@ Mock FungibleToken implementations representing: | Asset Name | Cadence Address | Cadence Contract Name | EVM | |---|---|---|---| | FlowActions | 0x6d888f175c158410 | DeFiActions | TBD | -| FlowCreditMarket | 0x6b00ff876c299c61 | FlowALP | TBD | +| FlowALPv1 | 0x6b00ff876c299c61 | FlowALPv1 | TBD | | FlowYieldVaults | 0xb1d63873c3cc9f79 | FlowYieldVaults | TBD | | FlowYieldVaultsStrategiesV2 | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategiesV2 | TBD | | PMStrategiesV1 | 0xb1d63873c3cc9f79 | PMStrategiesV1 | TBD | @@ -92,14 +92,14 @@ Mock FungibleToken implementations representing: ## How the System Works -Below is an overview of the initial prototype Tracer Strategy in the broader context of FlowCreditMarket and the FlowYieldVaults platform. +Below is an overview of the initial prototype Tracer Strategy in the broader context of FlowALPv1 and the FlowYieldVaults platform. ### 1. Strategy Architecture The TracerStrategy demonstrates the power of DeFi Actions composition: ``` -User Deposit (FLOW) → FlowCreditMarket Position → MOET Issuance → Swap to YieldToken → AutoBalancer +User Deposit (FLOW) → FlowALPv1 Position → MOET Issuance → Swap to YieldToken → AutoBalancer ↑ YieldToken → Swap to FLOW → Recollateralize Position ``` @@ -188,7 +188,7 @@ The FlowYieldVaults platform implements sophisticated automatic rebalancing and **Important Distinction:** The system has TWO different rebalancing mechanisms: 1. **AutoBalancer Rebalancing** (DFB): Maintains optimal ratio between YieldToken holdings and expected deposit value -2. **Position Rebalancing** (FlowCreditMarket): Maintains healthy collateralization ratios for lending positions +2. **Position Rebalancing** (FlowALPv1): Maintains healthy collateralization ratios for lending positions These work together but serve different purposes and can trigger independently based on market conditions. @@ -210,12 +210,12 @@ The AutoBalancer continuously monitors the **value ratio** between: **When:** Current YieldToken value > 105% historical value of deposits **Cause:** YieldToken price has increased OR position became over-collateralized leading to excess token holdings -**Action:** AutoBalancer deposits excess YieldToken to the rebalanceSink, swapping to FLOW and recollateralizing the FlowCreditMarket position. +**Action:** AutoBalancer deposits excess YieldToken to the rebalanceSink, swapping to FLOW and recollateralizing the FlowALPv1 position. **Automated Flow:** ``` -YieldToken (excess) → Swap to FLOW → Deposit to FlowCreditMarket Position (recollateralization) +YieldToken (excess) → Swap to FLOW → Deposit to FlowALPv1 Position (recollateralization) ``` **Result:** @@ -264,7 +264,7 @@ The system creates a sophisticated token flow: 1. **Initial Position Opening:** - - User deposits FLOW → FlowCreditMarket Position + - User deposits FLOW → FlowALPv1 Position - Position issues MOET → Swaps to YieldToken - YieldToken held in AutoBalancer @@ -335,7 +335,7 @@ This creates a fully automated yield farming system that adapts to market condit ## Interest Rate System -The FlowCreditMarket implements a sophisticated interest rate system that governs borrowing costs and lending yields. This system is fundamental to the protocol's economics and affects all lending positions. +The FlowALPv1 implements a sophisticated interest rate system that governs borrowing costs and lending yields. This system is fundamental to the protocol's economics and affects all lending positions. ### How Interest Rates Work @@ -520,15 +520,15 @@ The interest rate system is designed to: 3. **Manage Risk**: Insurance reserves and dynamic adjustments protect the protocol 4. **Enable Automation**: Continuous compounding without manual intervention -This interest system is what enables the FlowCreditMarket to function as a sustainable lending platform while providing the foundation for complex yield farming strategies built on top. +This interest system is what enables the FlowALPv1 to function as a sustainable lending platform while providing the foundation for complex yield farming strategies built on top. -## FlowCreditMarket Loan Health Mechanism +## FlowALPv1 Loan Health Mechanism -The FlowCreditMarket implements a sophisticated loan health system that determines borrowing capacity, monitors position safety, and prevents liquidations. This system is fundamental to how the TracerStrategy calculates how much can be borrowed against a user's initial collateral position. +The FlowALPv1 implements a sophisticated loan health system that determines borrowing capacity, monitors position safety, and prevents liquidations. This system is fundamental to how the TracerStrategy calculates how much can be borrowed against a user's initial collateral position. ### Key Definitions -Before diving into the mechanics, it's important to understand the core terminology used throughout the FlowCreditMarket loan system: +Before diving into the mechanics, it's important to understand the core terminology used throughout the FlowALPv1 loan system: #### Position-Related Terms @@ -577,7 +577,7 @@ Position Health = Effective Collateral / Effective Debt #### Health Computation Function ```cadence -// From FlowCreditMarket.cdc +// From FlowALPv1.cdc access(all) fun healthComputation(effectiveCollateral: UFix64, effectiveDebt: UFix64): UFix64 { if effectiveCollateral == 0.0 { return 0.0 @@ -866,7 +866,7 @@ let value = tokenPrice * trueBalance - Cross-collateralization enables complex strategies - Unified health calculation across all assets -This comprehensive loan health system enables the FlowCreditMarket to safely support leveraged yield farming strategies while maintaining strict risk management and protecting user funds from liquidation through automated rebalancing mechanisms. +This comprehensive loan health system enables the FlowALPv1 to safely support leveraged yield farming strategies while maintaining strict risk management and protecting user funds from liquidation through automated rebalancing mechanisms. ## Testing Rebalancing @@ -1020,7 +1020,7 @@ flow transactions send cadence/transactions/flow-yield-vaults/admin/rebalance_au $YIELD_VAULT_ID true \ --signer test-account -flow transactions send cadence/transactions/flow-credit-market/pool-management/rebalance_position.cdc \ +flow transactions send cadence/transactions/flow-alp/pool-management/rebalance_position.cdc \ $YIELD_VAULT_ID true \ --signer test-account @@ -1512,10 +1512,10 @@ scripts/flow-yield-vaults/get_auto_balancer_balance_by_id.cdc ```bash # Overall position health (collateralization ratio) -scripts/flow-credit-market/position_health.cdc +scripts/flow-alp/position_health.cdc # Available balance for withdrawal from position -scripts/flow-credit-market/get_available_balance.cdc +scripts/flow-alp/get_available_balance.cdc ``` #### User Balance @@ -1557,7 +1557,7 @@ scripts/tokens/get_balance.cdc 1. **"Could not borrow AutoBalancer"** - Ensure YieldVault ID is correct 2. **"No price set for token"** - Set initial prices for all tokens before testing 3. **"Insufficient liquidity"** - Fund MockSwapper with adequate token reserves -4. **"Position not found"** - Verify FlowCreditMarket position ID (different from YieldVault ID) +4. **"Position not found"** - Verify FlowALPv1 position ID (different from YieldVault ID) #### Debugging Commands: diff --git a/cadence/contracts/FlowYieldVaultsStrategies.cdc b/cadence/contracts/FlowYieldVaultsStrategies.cdc index d7f7f46..a5d4d1f 100644 --- a/cadence/contracts/FlowYieldVaultsStrategies.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategies.cdc @@ -12,7 +12,7 @@ import "UniswapV3SwapConnectors" import "ERC4626SwapConnectors" import "ERC4626Utils" // Lending protocol -import "FlowCreditMarket" +import "FlowALPv1" // FlowYieldVaults platform import "FlowYieldVaultsClosedBeta" import "FlowYieldVaults" @@ -57,7 +57,7 @@ access(all) contract FlowYieldVaultsStrategies { /// Canonical StoragePath where the StrategyComposerIssuer should be stored access(all) let IssuerStoragePath: StoragePath - /// This is the first Strategy implementation, wrapping a @FlowCreditMarket.Position along with its related Sink & + /// This is the first Strategy implementation, wrapping a @FlowALPv1.Position along with its related Sink & /// Source. While this object is a simple wrapper for the top-level collateralized position, the true magic of the /// DeFiActions is in the stacking of the related connectors. This stacking logic can be found in the /// TracerStrategyComposer construct. @@ -65,11 +65,11 @@ access(all) contract FlowYieldVaultsStrategies { /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- /// specific Identifier to associated connectors on construction access(contract) var uniqueID: DeFiActions.UniqueIdentifier? - access(self) let position: @FlowCreditMarket.Position + access(self) let position: @FlowALPv1.Position access(self) var sink: {DeFiActions.Sink} access(self) var source: {DeFiActions.Source} - init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowCreditMarket.Position) { + init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowALPv1.Position) { self.uniqueID = id self.sink = position.createSink(type: collateralType) self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) @@ -193,9 +193,9 @@ access(all) contract FlowYieldVaultsStrategies { // Swaps YieldToken & provides swapped Stable, sourcing YieldToken from the AutoBalancer let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToStableSwapper, source: abaSource, uniqueID: uniqueID) - // open a FlowCreditMarket position - let poolCap = FlowYieldVaultsStrategies.account.storage.load>( - from: FlowCreditMarket.PoolCapStoragePath + // open a FlowALPv1 position + let poolCap = FlowYieldVaultsStrategies.account.storage.load>( + from: FlowALPv1.PoolCapStoragePath ) ?? panic("Missing pool capability") let poolRef = poolCap.borrow() ?? panic("Invalid Pool Cap") @@ -206,7 +206,7 @@ access(all) contract FlowYieldVaultsStrategies { repaymentSource: abaSwapSource, pushToDrawDownSink: true ) - FlowYieldVaultsStrategies.account.storage.save(poolCap, to: FlowCreditMarket.PoolCapStoragePath) + FlowYieldVaultsStrategies.account.storage.save(poolCap, to: FlowALPv1.PoolCapStoragePath) // get Sink & Source connectors relating to the new Position let positionSink = position.createSinkWithOptions(type: collateralType, pushToDrawDownSink: true) @@ -240,11 +240,11 @@ access(all) contract FlowYieldVaultsStrategies { /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- /// specific Identifier to associated connectors on construction access(contract) var uniqueID: DeFiActions.UniqueIdentifier? - access(self) let position: @FlowCreditMarket.Position + access(self) let position: @FlowALPv1.Position access(self) var sink: {DeFiActions.Sink} access(self) var source: {DeFiActions.Source} - init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowCreditMarket.Position) { + init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowALPv1.Position) { self.uniqueID = id self.sink = position.createSink(type: collateralType) self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) @@ -469,9 +469,9 @@ access(all) contract FlowYieldVaultsStrategies { // Swaps YIELD & provides swapped MOET, sourcing YIELD from the AutoBalancer let abaSwapSource = SwapConnectors.SwapSource(swapper: yieldToMOETSwapper, source: abaSource, uniqueID: uniqueID) - // open a FlowCreditMarket position - let poolCap = FlowYieldVaultsStrategies.account.storage.copy>( - from: FlowCreditMarket.PoolCapStoragePath + // open a FlowALPv1 position + let poolCap = FlowYieldVaultsStrategies.account.storage.copy>( + from: FlowALPv1.PoolCapStoragePath ) ?? panic("Missing or invalid pool capability") let poolRef = poolCap.borrow() ?? panic("Invalid Pool Cap") diff --git a/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc index 6d66b4a..1712e92 100644 --- a/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc @@ -12,7 +12,7 @@ import "ERC4626SwapConnectors" import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // Lending protocol -import "FlowCreditMarket" +import "FlowALPv1" // FlowYieldVaults platform import "FlowYieldVaults" import "FlowYieldVaultsAutoBalancers" @@ -77,11 +77,11 @@ access(all) contract FlowYieldVaultsStrategiesV2 { /// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol- /// specific Identifier to associated connectors on construction access(contract) var uniqueID: DeFiActions.UniqueIdentifier? - access(self) let position: @FlowCreditMarket.Position + access(self) let position: @FlowALPv1.Position access(self) var sink: {DeFiActions.Sink} access(self) var source: {DeFiActions.Source} - init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowCreditMarket.Position) { + init(id: DeFiActions.UniqueIdentifier, collateralType: Type, position: @FlowALPv1.Position) { self.uniqueID = id self.sink = position.createSink(type: collateralType) self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) @@ -276,7 +276,7 @@ access(all) contract FlowYieldVaultsStrategiesV2 { uniqueID: uniqueID ) - // Open FlowCreditMarket position + // Open FlowALPv1 position let position <- self._openCreditPosition( funds: <-withFunds, issuanceSink: abaSwapSink, @@ -549,10 +549,10 @@ access(all) contract FlowYieldVaultsStrategiesV2 { funds: @{FungibleToken.Vault}, issuanceSink: {DeFiActions.Sink}, repaymentSource: {DeFiActions.Source} - ): @FlowCreditMarket.Position { + ): @FlowALPv1.Position { let poolCap = FlowYieldVaultsStrategiesV2.account.storage.copy< - Capability - >(from: FlowCreditMarket.PoolCapStoragePath) + Capability + >(from: FlowALPv1.PoolCapStoragePath) ?? panic("Missing or invalid pool capability") let poolRef = poolCap.borrow() ?? panic("Invalid Pool Cap") diff --git a/cadence/contracts/mocks/MockFlowCreditMarketConsumer.cdc b/cadence/contracts/mocks/MockFlowALPv1Consumer.cdc similarity index 66% rename from cadence/contracts/mocks/MockFlowCreditMarketConsumer.cdc rename to cadence/contracts/mocks/MockFlowALPv1Consumer.cdc index da5719b..ec8225e 100644 --- a/cadence/contracts/mocks/MockFlowCreditMarketConsumer.cdc +++ b/cadence/contracts/mocks/MockFlowALPv1Consumer.cdc @@ -1,20 +1,20 @@ import "FungibleToken" import "DeFiActions" -import "FlowCreditMarket" +import "FlowALPv1" /// THIS CONTRACT IS NOT SAFE FOR PRODUCTION - FOR TEST USE ONLY /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /// /// A simple contract enabling the persistent storage of a Position similar to a pattern expected for platforms -/// building on top of FlowCreditMarket's lending protocol +/// building on top of FlowALPv1's lending protocol /// -access(all) contract MockFlowCreditMarketConsumer { +access(all) contract MockFlowALPv1Consumer { /// Canonical path for where the wrapper is to be stored access(all) let WrapperStoragePath: StoragePath - /// Opens a FlowCreditMarket Position and returns a PositionWrapper containing that new position + /// Opens a FlowALPv1 Position and returns a PositionWrapper containing that new position /// access(all) fun createPositionWrapper( @@ -24,7 +24,7 @@ access(all) contract MockFlowCreditMarketConsumer { pushToDrawDownSink: Bool ): @PositionWrapper { return <- create PositionWrapper( - position: FlowCreditMarket.openPosition( + position: FlowALPv1.openPosition( collateral: <-collateral, issuanceSink: issuanceSink, repaymentSource: repaymentSource, @@ -33,28 +33,28 @@ access(all) contract MockFlowCreditMarketConsumer { ) } - /// A simple resource encapsulating a FlowCreditMarket Position + /// A simple resource encapsulating a FlowALPv1 Position access(all) resource PositionWrapper { - access(self) let position: FlowCreditMarket.Position + access(self) let position: FlowALPv1.Position - init(position: FlowCreditMarket.Position) { + init(position: FlowALPv1.Position) { self.position = position } /// NOT SAFE FOR PRODUCTION /// /// Returns a reference to the wrapped Position - access(all) fun borrowPosition(): &FlowCreditMarket.Position { + access(all) fun borrowPosition(): &FlowALPv1.Position { return &self.position } - access(all) fun borrowPositionForWithdraw(): auth(FungibleToken.Withdraw) &FlowCreditMarket.Position { + access(all) fun borrowPositionForWithdraw(): auth(FungibleToken.Withdraw) &FlowALPv1.Position { return &self.position } } init() { - self.WrapperStoragePath = /storage/flowCreditMarketPositionWrapper + self.WrapperStoragePath = /storage/flowALPv1PositionWrapper } } diff --git a/cadence/contracts/mocks/MockSwapper.cdc b/cadence/contracts/mocks/MockSwapper.cdc index 1d7f394..99ed06d 100644 --- a/cadence/contracts/mocks/MockSwapper.cdc +++ b/cadence/contracts/mocks/MockSwapper.cdc @@ -5,7 +5,7 @@ import "MockOracle" import "DeFiActions" import "SwapConnectors" -import "FlowCreditMarketMath" +import "FlowALPMath" /// /// THIS CONTRACT IS A MOCK AND IS NOT INTENDED FOR USE IN PRODUCTION @@ -114,8 +114,8 @@ access(all) contract MockSwapper { let uintInAmount = out ? uintAmount : (uintAmount / uintPrice) let uintOutAmount = out ? uintAmount * uintPrice : uintAmount - let inAmount = FlowCreditMarketMath.toUFix64Round(uintInAmount) - let outAmount = FlowCreditMarketMath.toUFix64Round(uintOutAmount) + let inAmount = FlowALPMath.toUFix64Round(uintInAmount) + let outAmount = FlowALPMath.toUFix64Round(uintOutAmount) return SwapConnectors.BasicQuote( inType: reverse ? self.outVault : self.inVault, diff --git a/cadence/scripts/flow-yield-vaults/get_complete_user_position_info.cdc b/cadence/scripts/flow-yield-vaults/get_complete_user_position_info.cdc index 8458e3d..e14e617 100644 --- a/cadence/scripts/flow-yield-vaults/get_complete_user_position_info.cdc +++ b/cadence/scripts/flow-yield-vaults/get_complete_user_position_info.cdc @@ -1,6 +1,6 @@ import "FlowYieldVaults" import "FlowYieldVaultsAutoBalancers" -import "FlowCreditMarket" +import "FlowALPv1" import "MockOracle" import "YieldToken" import "MOET" @@ -181,8 +181,8 @@ fun main(address: Address): CompleteUserSummary { let moetPrice = oracle.price(ofToken: Type<@MOET.Vault>()) ?? 1.0 let flowPrice = oracle.price(ofToken: Type<@FlowToken.Vault>()) ?? 1.0 - // Note: FlowCreditMarket positions and FlowYieldVaults yield vaults use different ID systems - // We'll calculate health manually since yield vault IDs don't correspond to FlowCreditMarket position IDs + // Note: FlowALPv1 positions and FlowYieldVaults yield vaults use different ID systems + // We'll calculate health manually since yield vault IDs don't correspond to FlowALPv1 position IDs var totalCollateralValue = 0.0 var totalYieldTokenValue = 0.0 @@ -196,7 +196,7 @@ fun main(address: Address): CompleteUserSummary { let yieldTokenBalance = autoBalancer?.vaultBalance() ?? 0.0 // Use the AutoBalancer's balance as the primary balance source - // This bypasses the FlowCreditMarket overflow issue + // This bypasses the FlowALPv1 overflow issue let realAvailableBalance = yieldTokenBalance let yieldTokenIdentifier = Type<@YieldToken.Vault>().identifier @@ -231,13 +231,13 @@ fun main(address: Address): CompleteUserSummary { let netWorth = estimatedCollateralValue + yieldTokenValue - estimatedDebtValue - // Get the actual position health from FlowCreditMarket.Pool - // FlowCreditMarket positions use sequential IDs (0, 1, 2, ...) while yield vault IDs are different + // Get the actual position health from FlowALPv1.Pool + // FlowALPv1 positions use sequential IDs (0, 1, 2, ...) while yield vault IDs are different var actualHealth: UFix128 = 999.0 - // Try to get the real health from FlowCreditMarket.Pool using sequential position IDs - let protocolAddress = Type<@FlowCreditMarket.Pool>().address! - if let pool = getAccount(protocolAddress).capabilities.borrow<&FlowCreditMarket.Pool>(FlowCreditMarket.PoolPublicPath) { + // Try to get the real health from FlowALPv1.Pool using sequential position IDs + let protocolAddress = Type<@FlowALPv1.Pool>().address! + if let pool = getAccount(protocolAddress).capabilities.borrow<&FlowALPv1.Pool>(FlowALPv1.PoolPublicPath) { // Since we can't directly map yield vault IDs to position IDs, we'll try sequential IDs // This assumes positions are created in order (0, 1, 2, ...) let positionIndex = UInt64(positions.length) // Use the current position index diff --git a/cadence/tests/PMStrategiesV1_test.cdc b/cadence/tests/PMStrategiesV1_test.cdc index 65849fa..bc46901 100644 --- a/cadence/tests/PMStrategiesV1_test.cdc +++ b/cadence/tests/PMStrategiesV1_test.cdc @@ -1,4 +1,4 @@ -#test_fork(network: "mainnet", height: nil) +#test_fork(network: "mainnet", height: 141935000) import Test @@ -85,7 +85,7 @@ access(all) fun setup() { log("Deploying EVMAmountUtils contract ...") var err = Test.deployContract( name: "EVMAmountUtils", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/EVMAmountUtils.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/EVMAmountUtils.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -93,7 +93,7 @@ access(all) fun setup() { log("Deploying UniswapV3SwapConnectors contract ...") err = Test.deployContract( name: "UniswapV3SwapConnectors", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/UniswapV3SwapConnectors.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/UniswapV3SwapConnectors.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -102,28 +102,28 @@ access(all) fun setup() { log("Deploying Morpho contracts...") err = Test.deployContract( name: "ERC4626Utils", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/utils/ERC4626Utils.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/utils/ERC4626Utils.cdc", arguments: [] ) Test.expect(err, Test.beNil()) err = Test.deployContract( name: "ERC4626SwapConnectors", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/ERC4626SwapConnectors.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/ERC4626SwapConnectors.cdc", arguments: [] ) Test.expect(err, Test.beNil()) err = Test.deployContract( name: "MorphoERC4626SinkConnectors", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SinkConnectors.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SinkConnectors.cdc", arguments: [] ) Test.expect(err, Test.beNil()) err = Test.deployContract( name: "MorphoERC4626SwapConnectors", - path: "../../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SwapConnectors.cdc", + path: "../../lib/FlowCreditMarket/FlowActions/cadence/contracts/connectors/evm/morpho/MorphoERC4626SwapConnectors.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -131,7 +131,7 @@ access(all) fun setup() { log("Deploying FlowYieldVaults contract ...") err = Test.deployContract( name: "FlowYieldVaults", - path: "../../../cadence/contracts/FlowYieldVaults.cdc", + path: "../../cadence/contracts/FlowYieldVaults.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -140,7 +140,7 @@ access(all) fun setup() { log("Deploying PMStrategiesV1...") err = Test.deployContract( name: "PMStrategiesV1", - path: "../../../cadence/contracts/PMStrategiesV1.cdc", + path: "../../cadence/contracts/PMStrategiesV1.cdc", arguments: [ "0xca6d7Bb03334bBf135902e1d919a5feccb461632", "0xeEDC6Ff75e1b10B903D9013c358e446a73d35341", @@ -149,46 +149,10 @@ access(all) fun setup() { ) Test.expect(err, Test.beNil()) - // // 1. Configure syWFLOWvStrategy with FlowToken collateral - // log("Configuring syWFLOWvStrategy...") - // var result = _executeTransactionFile( - // "../../transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc", - // [syWFLOWvStrategyIdentifier, flowVaultIdentifier, syWFLOWvEVMAddress, swapFeeTier], - // [adminAccount] - // ) - // Test.expect(result, Test.beSucceeded()) - // - // // 2. Configure FUSDEVStrategy with PYUSD0 collateral - // log("Configuring FUSDEVStrategy...") - // result = _executeTransactionFile( - // "../../transactions/flow-yield-vaults/admin/upsert-pm-strategy-config.cdc", - // [fusdEvStrategyIdentifier, pyusd0VaultIdentifier, fusdEvEVMAddress, swapFeeTier], - // [adminAccount] - // ) - // Test.expect(result, Test.beSucceeded()) - // - // // 3. Register syWFLOWvStrategy with the StrategyFactory - // log("Adding syWFLOWvStrategy composer...") - // result = _executeTransactionFile( - // "../../transactions/flow-yield-vaults/admin/add_strategy_composer.cdc", - // [syWFLOWvStrategyIdentifier, composerIdentifier, issuerStoragePath], - // [adminAccount] - // ) - // Test.expect(result, Test.beSucceeded()) - // - // // 4. Register FUSDEVStrategy with the StrategyFactory - // log("Adding FUSDEVStrategy composer...") - // result = _executeTransactionFile( - // "../../transactions/flow-yield-vaults/admin/add_strategy_composer.cdc", - // [fusdEvStrategyIdentifier, composerIdentifier, issuerStoragePath], - // [adminAccount] - // ) - // Test.expect(result, Test.beSucceeded()) - // - // 5. Grant beta access to user account for testing yield vault operations + // Grant beta access to user account for testing yield vault operations log("Granting beta access to user...") var result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/admin/grant_beta.cdc", + "../transactions/flow-yield-vaults/admin/grant_beta.cdc", [], [adminAccount, userAccount] ) @@ -202,7 +166,7 @@ access(all) fun setup() { access(all) fun testCreateSyWFLOWvYieldVault() { log("Creating syWFLOWvStrategy yield vault with 1.0 FLOW...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/create_yield_vault.cdc", + "../transactions/flow-yield-vaults/create_yield_vault.cdc", [syWFLOWvStrategyIdentifier, flowVaultIdentifier, 1.0], [userAccount] ) @@ -210,7 +174,7 @@ access(all) fun testCreateSyWFLOWvYieldVault() { // Retrieve the vault IDs let idsResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", [userAccount.address] ) Test.expect(idsResult, Test.beSucceeded()) @@ -221,7 +185,7 @@ access(all) fun testCreateSyWFLOWvYieldVault() { // Verify initial balance let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, syWFLOWvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -234,14 +198,14 @@ access(all) fun testCreateSyWFLOWvYieldVault() { access(all) fun testDepositToSyWFLOWvYieldVault() { log("Depositing 0.5 FLOW to syWFLOWv yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", + "../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", [syWFLOWvYieldVaultID, 0.5], [userAccount] ) Test.expect(result, Test.beSucceeded()) let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, syWFLOWvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -253,14 +217,14 @@ access(all) fun testDepositToSyWFLOWvYieldVault() { access(all) fun testWithdrawFromSyWFLOWvYieldVault() { log("Withdrawing 0.3 FLOW from syWFLOWv yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", + "../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", [syWFLOWvYieldVaultID, 0.3], [userAccount] ) Test.expect(result, Test.beSucceeded()) let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, syWFLOWvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -272,7 +236,7 @@ access(all) fun testWithdrawFromSyWFLOWvYieldVault() { access(all) fun testCloseSyWFLOWvYieldVault() { log("Closing syWFLOWv yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/close_yield_vault.cdc", + "../transactions/flow-yield-vaults/close_yield_vault.cdc", [syWFLOWvYieldVaultID], [userAccount] ) @@ -285,7 +249,7 @@ access(all) fun testCloseSyWFLOWvYieldVault() { access(all) fun testCreateFUSDEVYieldVault() { log("Creating FUSDEVStrategy yield vault with 1.0 PYUSD0...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/create_yield_vault.cdc", + "../transactions/flow-yield-vaults/create_yield_vault.cdc", [fusdEvStrategyIdentifier, pyusd0VaultIdentifier, 1.0], [userAccount] ) @@ -293,7 +257,7 @@ access(all) fun testCreateFUSDEVYieldVault() { // Retrieve the vault IDs let idsResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_ids.cdc", [userAccount.address] ) Test.expect(idsResult, Test.beSucceeded()) @@ -304,7 +268,7 @@ access(all) fun testCreateFUSDEVYieldVault() { // Verify initial balance let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, fusdEvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -317,14 +281,14 @@ access(all) fun testCreateFUSDEVYieldVault() { access(all) fun testDepositToFUSDEVYieldVault() { log("Depositing 0.5 PYUSD0 to FUSDEV yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", + "../transactions/flow-yield-vaults/deposit_to_yield_vault.cdc", [fusdEvYieldVaultID, 0.5], [userAccount] ) Test.expect(result, Test.beSucceeded()) let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, fusdEvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -336,14 +300,14 @@ access(all) fun testDepositToFUSDEVYieldVault() { access(all) fun testWithdrawFromFUSDEVYieldVault() { log("Withdrawing 0.3 PYUSD0 from FUSDEV yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", + "../transactions/flow-yield-vaults/withdraw_from_yield_vault.cdc", [fusdEvYieldVaultID, 0.3], [userAccount] ) Test.expect(result, Test.beSucceeded()) let balResult = _executeScript( - "../../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", + "../scripts/flow-yield-vaults/get_yield_vault_balance.cdc", [userAccount.address, fusdEvYieldVaultID] ) Test.expect(balResult, Test.beSucceeded()) @@ -355,7 +319,7 @@ access(all) fun testWithdrawFromFUSDEVYieldVault() { access(all) fun testCloseFUSDEVYieldVault() { log("Closing FUSDEV yield vault...") let result = _executeTransactionFile( - "../../transactions/flow-yield-vaults/close_yield_vault.cdc", + "../transactions/flow-yield-vaults/close_yield_vault.cdc", [fusdEvYieldVaultID], [userAccount] ) diff --git a/cadence/tests/atomic_registration_gc_test.cdc b/cadence/tests/atomic_registration_gc_test.cdc index 1828086..95ad31d 100644 --- a/cadence/tests/atomic_registration_gc_test.cdc +++ b/cadence/tests/atomic_registration_gc_test.cdc @@ -7,7 +7,7 @@ import "FlowYieldVaultsSchedulerRegistry" import "FlowToken" import "MOET" import "YieldToken" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -39,7 +39,7 @@ access(all) fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // Setup FlowCreditMarket with a pool & add FLOW as a supported token. + // Setup FlowALPv1 with a pool & add FLOW as a supported token. createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -51,9 +51,9 @@ access(all) fun setup() { depositCapacityCap: 1_000_000.0 ) - // Open a wrapped FlowCreditMarket position so strategies have an underlying position to work with. + // Open a wrapped FlowALPv1 position so strategies have an underlying position to work with. let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/rebalance_scenario1_test.cdc b/cadence/tests/rebalance_scenario1_test.cdc index 80adf99..5ac7072 100644 --- a/cadence/tests/rebalance_scenario1_test.cdc +++ b/cadence/tests/rebalance_scenario1_test.cdc @@ -42,7 +42,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -57,7 +57,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/rebalance_scenario2_test.cdc b/cadence/tests/rebalance_scenario2_test.cdc index b92f355..dd97774 100644 --- a/cadence/tests/rebalance_scenario2_test.cdc +++ b/cadence/tests/rebalance_scenario2_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" import "FlowYieldVaults" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) @@ -128,7 +128,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -143,7 +143,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/rebalance_scenario3a_test.cdc b/cadence/tests/rebalance_scenario3a_test.cdc index 6baf54a..3d5b865 100644 --- a/cadence/tests/rebalance_scenario3a_test.cdc +++ b/cadence/tests/rebalance_scenario3a_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -29,7 +29,7 @@ access(all) fun getFlowCollateralFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@FlowToken.Vault>() { // Credit means it's a deposit (collateral) - if balance.direction == FlowCreditMarket.BalanceDirection.Credit { + if balance.direction == FlowALPv1.BalanceDirection.Credit { return balance.balance } } @@ -43,7 +43,7 @@ access(all) fun getMOETDebtFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@MOET.Vault>() { // Debit means it's borrowed (debt) - if balance.direction == FlowCreditMarket.BalanceDirection.Debit { + if balance.direction == FlowALPv1.BalanceDirection.Debit { return balance.balance } } @@ -71,7 +71,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -86,7 +86,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) @@ -280,7 +280,7 @@ fun test_RebalanceYieldVaultScenario3A() { let positionDetails = getPositionDetails(pid: 1, beFailed: false) var positionFlowBalance = 0.0 for balance in positionDetails.balances { - if balance.vaultType == Type<@FlowToken.Vault>() && balance.direction == FlowCreditMarket.BalanceDirection.Credit { + if balance.vaultType == Type<@FlowToken.Vault>() && balance.direction == FlowALPv1.BalanceDirection.Credit { positionFlowBalance = balance.balance break } diff --git a/cadence/tests/rebalance_scenario3b_test.cdc b/cadence/tests/rebalance_scenario3b_test.cdc index 6100651..98186c5 100644 --- a/cadence/tests/rebalance_scenario3b_test.cdc +++ b/cadence/tests/rebalance_scenario3b_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -71,7 +71,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -86,7 +86,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) @@ -276,7 +276,7 @@ fun test_RebalanceYieldVaultScenario3B() { let positionDetails = getPositionDetails(pid: 1, beFailed: false) var positionFlowBalance = 0.0 for balance in positionDetails.balances { - if balance.vaultType == Type<@FlowToken.Vault>() && balance.direction == FlowCreditMarket.BalanceDirection.Credit { + if balance.vaultType == Type<@FlowToken.Vault>() && balance.direction == FlowALPv1.BalanceDirection.Credit { positionFlowBalance = balance.balance break } diff --git a/cadence/tests/rebalance_scenario3c_test.cdc b/cadence/tests/rebalance_scenario3c_test.cdc index 330c494..de62ea0 100644 --- a/cadence/tests/rebalance_scenario3c_test.cdc +++ b/cadence/tests/rebalance_scenario3c_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -29,7 +29,7 @@ access(all) fun getFlowCollateralFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@FlowToken.Vault>() { // Credit means it's a deposit (collateral) - if balance.direction == FlowCreditMarket.BalanceDirection.Credit { + if balance.direction == FlowALPv1.BalanceDirection.Credit { return balance.balance } } @@ -43,7 +43,7 @@ access(all) fun getMOETDebtFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@MOET.Vault>() { // Debit means it's borrowed (debt) - if balance.direction == FlowCreditMarket.BalanceDirection.Debit { + if balance.direction == FlowALPv1.BalanceDirection.Debit { return balance.balance } } @@ -71,7 +71,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -86,7 +86,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/rebalance_scenario3d_test.cdc b/cadence/tests/rebalance_scenario3d_test.cdc index 1f467ae..74534a9 100644 --- a/cadence/tests/rebalance_scenario3d_test.cdc +++ b/cadence/tests/rebalance_scenario3d_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -29,7 +29,7 @@ access(all) fun getFlowCollateralFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@FlowToken.Vault>() { // Credit means it's a deposit (collateral) - if balance.direction == FlowCreditMarket.BalanceDirection.Credit { + if balance.direction == FlowALPv1.BalanceDirection.Credit { return balance.balance } } @@ -43,7 +43,7 @@ access(all) fun getMOETDebtFromPosition(pid: UInt64): UFix64 { for balance in positionDetails.balances { if balance.vaultType == Type<@MOET.Vault>() { // Debit means it's borrowed (debt) - if balance.direction == FlowCreditMarket.BalanceDirection.Debit { + if balance.direction == FlowALPv1.BalanceDirection.Debit { return balance.balance } } @@ -71,7 +71,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -86,7 +86,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/rebalance_yield_test.cdc b/cadence/tests/rebalance_yield_test.cdc index c0c9010..f3c20c8 100644 --- a/cadence/tests/rebalance_yield_test.cdc +++ b/cadence/tests/rebalance_yield_test.cdc @@ -41,7 +41,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -56,7 +56,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/scheduled_rebalance_integration_test.cdc b/cadence/tests/scheduled_rebalance_integration_test.cdc index b5e8ec9..4550e57 100644 --- a/cadence/tests/scheduled_rebalance_integration_test.cdc +++ b/cadence/tests/scheduled_rebalance_integration_test.cdc @@ -56,7 +56,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) log("Token liquidity setup") - // Setup FlowCreditMarket with a Pool & add FLOW as supported token + // Setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -67,11 +67,11 @@ fun setup() { depositRate: 1_000_000.0, depositCapacityCap: 1_000_000.0 ) - log("FlowCreditMarket pool configured") + log("FlowALPv1 pool configured") // Open wrapped position let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/scheduled_rebalance_scenario_test.cdc b/cadence/tests/scheduled_rebalance_scenario_test.cdc index 8dda29b..102d32b 100644 --- a/cadence/tests/scheduled_rebalance_scenario_test.cdc +++ b/cadence/tests/scheduled_rebalance_scenario_test.cdc @@ -32,7 +32,7 @@ access(all) var snapshot: UInt64 = 0 // 5. The Supervisor is for recovery only - picks up yield vaults from pending queue // // PRICE SEMANTICS: -// - flowTokenIdentifier (FLOW): The COLLATERAL token deposited into FlowCreditMarket +// - flowTokenIdentifier (FLOW): The COLLATERAL token deposited into FlowALPv1 // - yieldTokenIdentifier (YieldToken): The YIELD-BEARING token the strategy produces // // TEST ISOLATION: @@ -63,7 +63,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // Setup FlowCreditMarket with a Pool + // Setup FlowALPv1 with a Pool createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -77,7 +77,7 @@ fun setup() { // Open wrapped position let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/scheduled_supervisor_test.cdc b/cadence/tests/scheduled_supervisor_test.cdc index 9ba8b7b..bdf5626 100644 --- a/cadence/tests/scheduled_supervisor_test.cdc +++ b/cadence/tests/scheduled_supervisor_test.cdc @@ -49,7 +49,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // FlowCreditMarket + // FlowALPv1 createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -63,7 +63,7 @@ fun setup() { // Wrapped Position let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/scheduler_edge_cases_test.cdc b/cadence/tests/scheduler_edge_cases_test.cdc index 86c6288..c1df43c 100644 --- a/cadence/tests/scheduler_edge_cases_test.cdc +++ b/cadence/tests/scheduler_edge_cases_test.cdc @@ -45,7 +45,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // Setup FlowCreditMarket + // Setup FlowALPv1 createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -59,7 +59,7 @@ fun setup() { // Open wrapped position let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/tests/test_helpers.cdc b/cadence/tests/test_helpers.cdc index 7340703..b5b5280 100644 --- a/cadence/tests/test_helpers.cdc +++ b/cadence/tests/test_helpers.cdc @@ -4,7 +4,7 @@ import "EVM" import "MetadataViews" import "FlowToken" import "MOET" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let serviceAccount = Test.serviceAccount() @@ -37,7 +37,7 @@ access(all) fun grantProtocolBeta(_ admin: Test.TestAccount, _ grantee: Test.TestAccount): Test.TransactionResult { let signers = admin.address == grantee.address ? [admin] : [admin, grantee] let betaTxn = Test.Transaction( - code: Test.readFile("../../lib/FlowCreditMarket/cadence/tests/transactions/flow-credit-market/pool-management/03_grant_beta.cdc"), + code: Test.readFile("../../lib/FlowCreditMarket/cadence/tests/transactions/flow-alp/pool-management/03_grant_beta.cdc"), authorizers: [admin.address, grantee.address], signers: signers, arguments: [] @@ -157,8 +157,8 @@ access(all) fun deployContracts() { ) Test.expect(err, Test.beNil()) err = Test.deployContract( - name: "FlowCreditMarketMath", - path: "../../lib/FlowCreditMarket/cadence/lib/FlowCreditMarketMath.cdc", + name: "FlowALPMath", + path: "../../lib/FlowCreditMarket/cadence/lib/FlowALPMath.cdc", arguments: [] ) err = Test.deployContract( @@ -180,7 +180,7 @@ access(all) fun deployContracts() { ) Test.expect(err, Test.beNil()) - // FlowCreditMarket contracts + // FlowALPv1 contracts let initialMoetSupply = 0.0 err = Test.deployContract( name: "MOET", @@ -189,8 +189,8 @@ access(all) fun deployContracts() { ) Test.expect(err, Test.beNil()) err = Test.deployContract( - name: "FlowCreditMarket", - path: "../../lib/FlowCreditMarket/cadence/contracts/FlowCreditMarket.cdc", + name: "FlowALPv1", + path: "../../lib/FlowCreditMarket/cadence/contracts/FlowALPv1.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -387,8 +387,8 @@ access(all) fun deployContracts() { } access(all) -fun setupFlowCreditMarket(signer: Test.TestAccount) { - let res = _executeTransaction("../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/create_and_store_pool.cdc", +fun setupFlowALPv1(signer: Test.TestAccount) { + let res = _executeTransaction("../../lib/FlowCreditMarket/cadence/transactions/flow-alp/create_and_store_pool.cdc", [], signer ) @@ -432,19 +432,19 @@ fun getAutoBalancerCurrentValue(id: UInt64): UFix64? { } access(all) -fun getPositionDetails(pid: UInt64, beFailed: Bool): FlowCreditMarket.PositionDetails { - let res = _executeScript("../../lib/FlowCreditMarket/cadence/scripts/flow-credit-market/position_details.cdc", +fun getPositionDetails(pid: UInt64, beFailed: Bool): FlowALPv1.PositionDetails { + let res = _executeScript("../../lib/FlowCreditMarket/cadence/scripts/flow-alp/position_details.cdc", [pid] ) Test.expect(res, beFailed ? Test.beFailed() : Test.beSucceeded()) - return res.returnValue as! FlowCreditMarket.PositionDetails + return res.returnValue as! FlowALPv1.PositionDetails } access(all) fun getReserveBalanceForType(vaultIdentifier: String): UFix64 { let res = _executeScript( - "../../lib/FlowCreditMarket/cadence/scripts/flow-credit-market/get_reserve_balance_for_type.cdc", + "../../lib/FlowCreditMarket/cadence/scripts/flow-alp/get_reserve_balance_for_type.cdc", [vaultIdentifier] ) Test.expect(res, Test.beSucceeded()) @@ -460,7 +460,7 @@ fun positionAvailableBalance( beFailed: Bool ): UFix64 { let res = _executeScript( - "../../lib/FlowCreditMarket/cadence/scripts/flow-credit-market/get_available_balance.cdc", + "../../lib/FlowCreditMarket/cadence/scripts/flow-alp/get_available_balance.cdc", [pid, type, pullFromSource] ) Test.expect(res, beFailed ? Test.beFailed() : Test.beSucceeded()) @@ -473,7 +473,7 @@ fun positionAvailableBalance( access(all) fun createAndStorePool(signer: Test.TestAccount, defaultTokenIdentifier: String, beFailed: Bool) { let createRes = _executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-factory/create_and_store_pool.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-factory/create_and_store_pool.cdc", [defaultTokenIdentifier], signer ) @@ -491,7 +491,7 @@ fun addSupportedTokenFixedRateInterestCurve( depositCapacityCap: UFix64 ) { let additionRes = _executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_fixed_rate_curve.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_fixed_rate_curve.cdc", [ tokenTypeIdentifier, collateralFactor, borrowFactor, yearlyRate, depositRate, depositCapacityCap ], signer ) @@ -501,7 +501,7 @@ fun addSupportedTokenFixedRateInterestCurve( access(all) fun rebalancePosition(signer: Test.TestAccount, pid: UInt64, force: Bool, beFailed: Bool) { let rebalanceRes = _executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-management/rebalance_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-management/rebalance_position.cdc", [ pid, force ], signer ) @@ -584,14 +584,14 @@ fun rebalanceYieldVault(signer: Test.TestAccount, id: UInt64, force: Bool, beFai access(all) fun getLastPositionOpenedEvent(_ evts: [AnyStruct]): AnyStruct { // can't return event types directly, they must be cast by caller - Test.assert(evts.length > 0, message: "Expected at least 1 FlowCreditMarket.Opened event but found none") - return evts[evts.length - 1] as! FlowCreditMarket.Opened + Test.assert(evts.length > 0, message: "Expected at least 1 FlowALPv1.Opened event but found none") + return evts[evts.length - 1] as! FlowALPv1.Opened } access(all) fun getLastPositionDepositedEvent(_ evts: [AnyStruct]): AnyStruct { // can't return event types directly, they must be cast by caller - Test.assert(evts.length > 0, message: "Expected at least 1 FlowCreditMarket.Deposited event but found none") - return evts[evts.length - 1] as! FlowCreditMarket.Deposited + Test.assert(evts.length > 0, message: "Expected at least 1 FlowALPv1.Deposited event but found none") + return evts[evts.length - 1] as! FlowALPv1.Deposited } /* --- Mock helpers --- */ @@ -671,7 +671,7 @@ access(all) fun setupBetaAccess(): Void { // Returns the balance for a given Vault 'Type' if present, otherwise nil. access(all) fun findBalance( - details: FlowCreditMarket.PositionDetails, + details: FlowALPv1.PositionDetails, vaultType: Type ): UFix64? { for b in details.balances { diff --git a/cadence/tests/tracer_strategy_test.cdc b/cadence/tests/tracer_strategy_test.cdc index 2c2949a..27ae2f7 100644 --- a/cadence/tests/tracer_strategy_test.cdc +++ b/cadence/tests/tracer_strategy_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) access(all) let flowYieldVaultsAccount = Test.getAccount(0x0000000000000009) @@ -47,7 +47,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -62,7 +62,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) @@ -162,7 +162,7 @@ fun test_RebalanceYieldVaultSucceeds() { amount: fundingAmount, beFailed: false ) - let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowCreditMarket.Opened).pid + let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowALPv1.Opened).pid var yieldVaultIDs = getYieldVaultIDs(address: user.address) Test.assert(yieldVaultIDs != nil, message: "Expected user's YieldVault IDs to be non-nil but encountered nil") @@ -186,7 +186,7 @@ fun test_RebalanceYieldVaultSucceeds() { // for now we can use events to intercept fund flows between pre- and post- Position & AutoBalancer state // assess how much FLOW was deposited into the position - let autoBalancerRecollateralizeEvent = getLastPositionDepositedEvent(Test.eventsOfType(Type())) as! FlowCreditMarket.Deposited + let autoBalancerRecollateralizeEvent = getLastPositionDepositedEvent(Test.eventsOfType(Type())) as! FlowALPv1.Deposited Test.assertEqual(positionID, autoBalancerRecollateralizeEvent.pid) Test.assertEqual(autoBalancerRecollateralizeEvent.amount, (autoBalancerValueAfter - autoBalancerValueBefore) / startingFlowPrice @@ -247,7 +247,7 @@ fun test_RebalanceYieldVaultSucceedsAfterYieldPriceDecrease() { amount: fundingAmount, beFailed: false ) - let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowCreditMarket.Opened).pid + let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowALPv1.Opened).pid var yieldVaultIDs = getYieldVaultIDs(address: user.address) Test.assert(yieldVaultIDs != nil, message: "Expected user's YieldVault IDs to be non-nil but encountered nil") @@ -304,7 +304,7 @@ fun test_RebalanceYieldVaultSucceedsAfterCollateralPriceIncrease() { amount: fundingAmount, beFailed: false ) - let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowCreditMarket.Opened).pid + let positionID = (getLastPositionOpenedEvent(Test.eventsOfType(Type())) as! FlowALPv1.Opened).pid var yieldVaultIDs = getYieldVaultIDs(address: user.address) Test.assert(yieldVaultIDs != nil, message: "Expected user's YieldVault IDs to be non-nil but encountered nil") diff --git a/cadence/tests/yield_vault_lifecycle_test.cdc b/cadence/tests/yield_vault_lifecycle_test.cdc index 0e1ad05..b515b55 100644 --- a/cadence/tests/yield_vault_lifecycle_test.cdc +++ b/cadence/tests/yield_vault_lifecycle_test.cdc @@ -7,7 +7,7 @@ import "FlowToken" import "MOET" import "YieldToken" import "FlowYieldVaultsStrategies" -import "FlowCreditMarket" +import "FlowALPv1" import "FlowYieldVaults" access(all) let protocolAccount = Test.getAccount(0x0000000000000008) @@ -47,7 +47,7 @@ fun setup() { setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: YieldToken.VaultStoragePath) setMockSwapperLiquidityConnector(signer: protocolAccount, vaultStoragePath: /storage/flowTokenVault) - // setup FlowCreditMarket with a Pool & add FLOW as supported token + // setup FlowALPv1 with a Pool & add FLOW as supported token createAndStorePool(signer: protocolAccount, defaultTokenIdentifier: moetTokenIdentifier, beFailed: false) addSupportedTokenFixedRateInterestCurve( signer: protocolAccount, @@ -62,7 +62,7 @@ fun setup() { // open wrapped position (pushToDrawDownSink) // the equivalent of depositing reserves let openRes = executeTransaction( - "../../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/position/create_position.cdc", + "../../lib/FlowCreditMarket/cadence/transactions/flow-alp/position/create_position.cdc", [reserveAmount/2.0, /storage/flowTokenVault, true], protocolAccount ) diff --git a/cadence/transactions/mocks/position/create_wrapped_position.cdc b/cadence/transactions/mocks/position/create_wrapped_position.cdc index c6edbef..01b64ac 100644 --- a/cadence/transactions/mocks/position/create_wrapped_position.cdc +++ b/cadence/transactions/mocks/position/create_wrapped_position.cdc @@ -4,16 +4,16 @@ import "DeFiActions" import "FungibleTokenConnectors" import "MOET" -import "MockFlowCreditMarketConsumer" +import "MockFlowALPv1Consumer" /// TEST TRANSACTION - DO NOT USE IN PRODUCTION /// /// Opens a Position with the amount of funds source from the Vault at the provided StoragePath and wraps it in a -/// MockFlowCreditMarketConsumer PositionWrapper +/// MockFlowALPv1Consumer PositionWrapper /// transaction(amount: UFix64, vaultStoragePath: StoragePath, pushToDrawDownSink: Bool) { - // the funds that will be used as collateral for a FlowCreditMarket loan + // the funds that will be used as collateral for a FlowALPv1 loan let collateral: @{FungibleToken.Vault} // this DeFiActions Sink that will receive the loaned funds let sink: {DeFiActions.Sink} @@ -63,13 +63,13 @@ transaction(amount: UFix64, vaultStoragePath: StoragePath, pushToDrawDownSink: B execute { // open a position & save in the Wrapper - let wrapper <- MockFlowCreditMarketConsumer.createPositionWrapper( + let wrapper <- MockFlowALPv1Consumer.createPositionWrapper( collateral: <-self.collateral, issuanceSink: self.sink, repaymentSource: self.source, pushToDrawDownSink: pushToDrawDownSink ) // save the wrapper into the signer's account - reverts on storage collision - self.account.storage.save(<-wrapper, to: MockFlowCreditMarketConsumer.WrapperStoragePath) + self.account.storage.save(<-wrapper, to: MockFlowALPv1Consumer.WrapperStoragePath) } } diff --git a/docs/autobalancer-restart-recurring-proposal.md b/docs/autobalancer-restart-recurring-proposal.md index f785848..cde18b6 100644 --- a/docs/autobalancer-restart-recurring-proposal.md +++ b/docs/autobalancer-restart-recurring-proposal.md @@ -174,7 +174,7 @@ let autoBalancerRef = scheduleCap!.borrow()! let scheduleError = autoBalancerRef.scheduleNextRebalance(whileExecuting: nil) ``` -### DeFiActions (FlowCreditMarket/FlowActions) +### DeFiActions (FlowALPv1/FlowActions) Only the fee buffer fix (5% margin) was kept. No `restartRecurring` flag was added. diff --git a/docs/rebalancing_architecture.md b/docs/rebalancing_architecture.md index 919a481..1aa587b 100644 --- a/docs/rebalancing_architecture.md +++ b/docs/rebalancing_architecture.md @@ -1,18 +1,18 @@ -# Rebalancing Architecture: AutoBalancer, FlowCreditMarket Position, and Scheduled Transactions +# Rebalancing Architecture: AutoBalancer, FlowALPv1 Position, and Scheduled Transactions ## 1. Main Components and Their Responsibilities ### FlowYieldVaults (YieldVaults) - Owns `YieldVault` and `YieldVaultManager` - Each YieldVault wraps a **FlowYieldVaults Strategy** (e.g. `TracerStrategy`) -- The YieldVault itself does **not** know about scheduling or FlowCreditMarket; it just holds a strategy resource +- The YieldVault itself does **not** know about scheduling or FlowALPv1; it just holds a strategy resource ### FlowYieldVaultsStrategies (TracerStrategy stack) - `TracerStrategyComposer` wires together: - A **DeFiActions.AutoBalancer** (manages Yield token exposure around deposits value) - - A **FlowCreditMarket.Position** (borrow/lend position in the FlowCreditMarket pool) - - Swappers and connectors that shuttle value between AutoBalancer and FlowCreditMarket -- This is where the **YieldVault -> AutoBalancer -> FlowCreditMarket** wiring is defined + - A **FlowALPv1.Position** (borrow/lend position in the FlowALPv1 pool) + - Swappers and connectors that shuttle value between AutoBalancer and FlowALPv1 +- This is where the **YieldVault -> AutoBalancer -> FlowALPv1** wiring is defined ### FlowYieldVaultsAutoBalancers - Utility contract for: @@ -34,7 +34,7 @@ - `executeTransaction(id, data)`: entrypoint for **FlowTransactionScheduler** - `scheduleNextRebalance()`: self-schedules next execution (when configured with recurringConfig) -### FlowCreditMarket.Pool + Position +### FlowALPv1.Pool + Position - Maintains positions, collateral, MOET debt, health - Key function: `rebalancePosition(pid: UInt64, force: Bool)`: - If undercollateralized and there is a `topUpSource`, pulls extra collateral @@ -54,7 +54,7 @@ --- -## 2. How the Tracer Strategy Wires AutoBalancer and FlowCreditMarket Together +## 2. How the Tracer Strategy Wires AutoBalancer and FlowALPv1 Together Inside `FlowYieldVaultsStrategies.TracerStrategyComposer.createStrategy(...)`: @@ -75,21 +75,21 @@ Inside `FlowYieldVaultsStrategies.TracerStrategyComposer.createStrategy(...)`: - Attach swappers (MockSwapper or UniswapV3) for MOET <-> Yield - Direct MOET -> Yield into `abaSink`, Yield -> MOET from `abaSource` -### Step 3: Open a FlowCreditMarket position +### Step 3: Open a FlowALPv1 position - Call `poolRef.createPosition(funds, issuanceSink: abaSwapSink, repaymentSource: abaSwapSource, pushToDrawDownSink: true)` -- Initial user Flow goes through `abaSwapSink` to become Yield, deposited into AutoBalancer, then into FlowCreditMarket position +- Initial user Flow goes through `abaSwapSink` to become Yield, deposited into AutoBalancer, then into FlowALPv1 position -### Step 4: Create FlowCreditMarket position-level sink/source +### Step 4: Create FlowALPv1 position-level sink/source - `positionSink = position.createSinkWithOptions(type: collateralType, pushToDrawDownSink: true)` - `positionSource = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true)` -### Step 5: Wire AutoBalancer's rebalance sink into FlowCreditMarket position +### Step 5: Wire AutoBalancer's rebalance sink into FlowALPv1 position - Create `positionSwapSink` to swap Yield -> Flow and deposit into `positionSink` - Call `autoBalancer.setSink(positionSwapSink, updateSinkID: true)` -- When AutoBalancer rebalances, it withdraws Yield, swaps to Flow, deposits into FlowCreditMarket position +- When AutoBalancer rebalances, it withdraws Yield, swaps to Flow, deposits into FlowALPv1 position -### Step 6: FlowCreditMarket's `pushToDrawDownSink` triggers position rebalancing -- In FlowCreditMarket's `depositAndPush` logic with `pushToDrawDownSink: true`: +### Step 6: FlowALPv1's `pushToDrawDownSink` triggers position rebalancing +- In FlowALPv1's `depositAndPush` logic with `pushToDrawDownSink: true`: ```cadence if pushToDrawDownSink { self.rebalancePosition(pid: pid, force: true) @@ -98,8 +98,8 @@ Inside `FlowYieldVaultsStrategies.TracerStrategyComposer.createStrategy(...)`: - Any deposit via that sink automatically triggers `rebalancePosition(pid, force: true)` **Conclusion:** When AutoBalancer performs a rebalance that moves value through its sink, it indirectly causes: -- An update in the FlowCreditMarket position via deposits/withdrawals -- A call to `FlowCreditMarket.Pool.rebalancePosition(pid, force: true)` +- An update in the FlowALPv1 position via deposits/withdrawals +- A call to `FlowALPv1.Pool.rebalancePosition(pid, force: true)` --- @@ -185,22 +185,22 @@ fun executeTransaction(id: UInt64, data: AnyStruct?) { ## 4. Behavior in Different Price Scenarios ### Only Flow collateral price changes (Yield price constant) -- FlowCreditMarket position's **health** changes (Flow is collateral) +- FlowALPv1 position's **health** changes (Flow is collateral) - AutoBalancer's asset (YieldToken) oracle price unchanged - `currentValue == valueOfDeposits` -> `valueDiff == 0` -> **rebalance is no-op** -- **Only `rebalancePosition` (FlowCreditMarket) will actually move collateral** +- **Only `rebalancePosition` (FlowALPv1) will actually move collateral** ### Only Yield token price changes (Flow price constant) - AutoBalancer's `currentValue` changes versus `valueOfDeposits` - If difference exceeds threshold (or `force == true`): - AutoBalancer rebalances via sink (`positionSwapSink`) - - Yield -> Flow deposited into FlowCreditMarket position with `pushToDrawDownSink == true` - - Triggers `FlowCreditMarket.Pool.rebalancePosition(pid, force: true)` -- **Both AutoBalancer and FlowCreditMarket position are adjusted** + - Yield -> Flow deposited into FlowALPv1 position with `pushToDrawDownSink == true` + - Triggers `FlowALPv1.Pool.rebalancePosition(pid, force: true)` +- **Both AutoBalancer and FlowALPv1 position are adjusted** ### Both Flow and Yield move - If Yield changes enough, AutoBalancer rebalances -- FlowCreditMarket position's health also changes from Flow's move +- FlowALPv1 position's health also changes from Flow's move - AutoBalancer-induced deposit triggers `rebalancePosition(pid, force: true)` - **Scheduled executions become effective when Yield-side value moves** @@ -212,15 +212,15 @@ fun executeTransaction(id: UInt64, data: AnyStruct?) { - Semantically equivalent to manual `rebalanceYieldVault` 2. **`rebalanceYieldVault` does NOT directly call `rebalancePosition`** - - Position rebalancing happens **indirectly** via connector graph and FlowCreditMarket's `pushToDrawDownSink` logic + - Position rebalancing happens **indirectly** via connector graph and FlowALPv1's `pushToDrawDownSink` logic 3. **Flow-only price changes do NOT trigger AutoBalancer rebalance** - AutoBalancer's `valueDiff` only sensitive to Yield side - - Scheduled executions won't touch FlowCreditMarket position in this case + - Scheduled executions won't touch FlowALPv1 position in this case -4. **For FlowCreditMarket position rebalancing on collateral moves** - - Would need separate scheduling in FlowCreditMarket - - Belongs in FlowCreditMarket/FlowActions, not FlowYieldVaults +4. **For FlowALPv1 position rebalancing on collateral moves** + - Would need separate scheduling in FlowALPv1 + - Belongs in FlowALPv1/FlowActions, not FlowYieldVaults --- @@ -229,9 +229,9 @@ fun executeTransaction(id: UInt64, data: AnyStruct?) { | Component | Responsibility | |-----------|---------------| | FlowYieldVaults YieldVault | Holds strategy, user-facing | -| TracerStrategy | Wires AutoBalancer <-> FlowCreditMarket | +| TracerStrategy | Wires AutoBalancer <-> FlowALPv1 | | AutoBalancer | Manages Yield exposure, executes rebalance | -| FlowCreditMarket Position | Manages collateral/debt health | +| FlowALPv1 Position | Manages collateral/debt health | | FlowYieldVaultsScheduler | Registration, atomic initial scheduling | | FlowYieldVaultsSchedulerRegistry | Stores registry, pending queue | | Supervisor | Recovery for failed schedules (bounded) | diff --git a/flow.json b/flow.json index 9a8fd73..471fe51 100644 --- a/flow.json +++ b/flow.json @@ -98,8 +98,8 @@ "testnet": "b88ba0e976146cd1" } }, - "FlowCreditMarket": { - "source": "./lib/FlowCreditMarket/cadence/contracts/FlowCreditMarket.cdc", + "FlowALPv1": { + "source": "./lib/FlowCreditMarket/cadence/contracts/FlowALPv1.cdc", "aliases": { "emulator": "045a1763c93006ca", "mainnet": "6b00ff876c299c61", @@ -107,8 +107,8 @@ "testnet": "426f0458ced60037" } }, - "FlowCreditMarketMath": { - "source": "./lib/FlowCreditMarket/cadence/lib/FlowCreditMarketMath.cdc", + "FlowALPMath": { + "source": "./lib/FlowCreditMarket/cadence/lib/FlowALPMath.cdc", "aliases": { "emulator": "045a1763c93006ca", "mainnet": "6b00ff876c299c61", @@ -819,7 +819,7 @@ "resourceID": "projects/flow-foundation-admin/locations/global/keyRings/defi-actions/cryptoKeys/mainnet-defi-actions/cryptoKeyVersions/1" } }, - "mainnet-flow-credit-market-deployer": { + "mainnet-flow-alp-deployer": { "address": "6b00ff876c299c61", "key": { "type": "google-kms", @@ -856,7 +856,7 @@ "resourceID": "projects/dl-flow-devex-staging/locations/us-central1/keyRings/tidal-keyring/cryptoKeys/tidal_admin_pk/cryptoKeyVersions/1" } }, - "testnet-flow-credit-market-deployer": { + "testnet-flow-alp-deployer": { "address": "426f0458ced60037", "key": { "type": "google-kms", @@ -879,11 +879,11 @@ }, "DeFiActionsUtils", "DeFiActions", - "FlowCreditMarketMath", + "FlowALPMath", "FungibleTokenConnectors", "SwapConnectors", "DummyConnectors", - "FlowCreditMarket", + "FlowALPv1", { "name": "YieldToken", "args": [ @@ -1217,4 +1217,4 @@ ] } } -} \ No newline at end of file +} diff --git a/local/setup_emulator.sh b/local/setup_emulator.sh index 5fddabb..7012625 100755 --- a/local/setup_emulator.sh +++ b/local/setup_emulator.sh @@ -21,9 +21,9 @@ flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.045a # configure FlowCreditMarket # # create Pool with MOET as default token -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-factory/create_and_store_pool.cdc 'A.045a1763c93006ca.MOET.Vault' --signer emulator-flow-yield-vaults +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-factory/create_and_store_pool.cdc 'A.045a1763c93006ca.MOET.Vault' --signer emulator-flow-yield-vaults # add FLOW as supported token - params: collateralFactor, borrowFactor, depositRate, depositCapacityCap -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_zero_rate_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_zero_rate_curve.cdc \ 'A.0ae53cb6e3f42a79.FlowToken.Vault' \ 0.8 \ 1.0 \ @@ -58,7 +58,7 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate # grant PoolBeta cap echo "Grant Protocol Beta access to FlowYieldVaults" -flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-credit-market/pool-management/03_grant_beta.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-alp/pool-management/03_grant_beta.cdc \ --authorizer emulator-flow-yield-vaults,emulator-flow-yield-vaults \ --proposer emulator-flow-yield-vaults \ --payer emulator-flow-yield-vaults diff --git a/local/setup_mainnet.sh b/local/setup_mainnet.sh index 3cd923f..b4be034 100755 --- a/local/setup_mainnet.sh +++ b/local/setup_mainnet.sh @@ -12,24 +12,24 @@ flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.1654 echo "bridge YieldToken to Cadence" flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboarding/onboard_by_evm_address.cdc 0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c --network mainnet --signer mainnet-admin echo "bridge MOET to EVM" -flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboarding/onboard_by_type_identifier.cdc "A.6b00ff876c299c61.MOET.Vault" --compute-limit 9999 --network mainnet --signer mainnet-flow-credit-market-deployer +flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboarding/onboard_by_type_identifier.cdc "A.6b00ff876c299c61.MOET.Vault" --compute-limit 9999 --network mainnet --signer mainnet-flow-alp-deployer -# configure FlowCreditMarket +# configure FlowALPv1 # # create Pool with MOET as default token -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-factory/create_and_store_pool.cdc 'A.6b00ff876c299c61.MOET.Vault' --network mainnet --signer mainnet-flow-credit-market-deployer +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-factory/create_and_store_pool.cdc 'A.6b00ff876c299c61.MOET.Vault' --network mainnet --signer mainnet-flow-alp-deployer # update Pool with Band Oracle instead of Mock Oracle -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/update_oracle.cdc --network mainnet --signer mainnet-flow-credit-market-deployer +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/update_oracle.cdc --network mainnet --signer mainnet-flow-alp-deployer # add FLOW as supported token - params: collateralFactor, borrowFactor, depositRate, depositCapacityCap -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.1654653399040a61.FlowToken.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network mainnet \ - --signer mainnet-flow-credit-market-deployer + --signer mainnet-flow-alp-deployer # add WBTC to band oracle cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transactions/band-oracle-connector/add_symbol.cdc "BTC" "A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault" --network mainnet --signer mainnet-band-oracle-connectors && cd ../../.. @@ -38,30 +38,30 @@ cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transa cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transactions/band-oracle-connector/add_symbol.cdc "ETH" "A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault" --network mainnet --signer mainnet-band-oracle-connectors && cd ../../.. # WBTC simple curve -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network mainnet \ - --signer mainnet-flow-credit-market-deployer + --signer mainnet-flow-alp-deployer # WETH simple curve -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network mainnet \ - --signer mainnet-flow-credit-market-deployer + --signer mainnet-flow-alp-deployer # kink interest curve setup # enable when FCM_V1 is deployed # # # add WBTC as supported token -# flow transactions send ../lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_kink_curve.cdc \ +# flow transactions send ../lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_kink_curve.cdc \ # 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ # 0.8 \ # 1.0 \ @@ -72,10 +72,10 @@ flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-m # 1_000_000.0 \ # 1_000_000.0 \ # --network mainnet \ -# --signer mainnet-flow-credit-market-deployer +# --signer mainnet-flow-alp-deployer # # # add WETH as supported token -# flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_kink_curve.cdc \ +# flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_kink_curve.cdc \ # 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ # 0.8 \ # 1.0 \ @@ -86,17 +86,17 @@ flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-m # 1_000_000.0 \ # 1_000_000.0 \ # --network mainnet \ -# --signer mainnet-flow-credit-market-deployer +# --signer mainnet-flow-alp-deployer # TODO # swap # echo "swap Flow to MOET" -# flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/create_position.cdc 100000.0 --network mainnet --signer mainnet-flow-credit-market-deployer +# flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/create_position.cdc 100000.0 --network mainnet --signer mainnet-flow-alp-deployer # TODO # flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/tokens/bridge_tokens_to_any_evm_address.cdc \ # "A.6b00ff876c299c61.MOET.Vault" 100000.0 "0xOWNER" \ -# --network mainnet --signer mainnet-flow-credit-market-deployer +# --network mainnet --signer mainnet-flow-alp-deployer # create pool # add liquidity to pool @@ -202,9 +202,9 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate # grant PoolBeta cap echo "Grant Protocol Beta access to FlowYieldVaults" -flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-credit-market/pool-management/03_grant_beta.cdc \ - --authorizer mainnet-flow-credit-market-deployer,mainnet-admin \ - --proposer mainnet-flow-credit-market-deployer \ +flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-alp/pool-management/03_grant_beta.cdc \ + --authorizer mainnet-flow-alp-deployer,mainnet-admin \ + --proposer mainnet-flow-alp-deployer \ --payer mainnet-admin \ --network mainnet diff --git a/local/setup_testnet.sh b/local/setup_testnet.sh index a1d90e1..ec5f73a 100755 --- a/local/setup_testnet.sh +++ b/local/setup_testnet.sh @@ -10,7 +10,7 @@ flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.d258 flow transactions send ./cadence/transactions/mocks/oracle/set_price.cdc 'A.dfc20aee650fcbdf.EVMVMBridgedToken_4154d5b0e2931a0a1e5b733f19161aa7d2fc4b95.Vault' 1.0 --network testnet --signer testnet-admin echo "bridge MOET to EVM" -flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboarding/onboard_by_type_identifier.cdc "A.426f0458ced60037.MOET.Vault" --compute-limit 9999 --network testnet --signer testnet-flow-credit-market-deployer +flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboarding/onboard_by_type_identifier.cdc "A.426f0458ced60037.MOET.Vault" --compute-limit 9999 --network testnet --signer testnet-flow-alp-deployer # configure FlowCreditMarket # @@ -18,18 +18,18 @@ flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/onboard cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transactions/band-oracle-connector/add_symbol.cdc "USD" "A.426f0458ced60037.MOET.Vault" --network testnet --signer testnet-band-oracle-connectors # create Pool with MOET as default token with Mock Oracle -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-factory/create_and_store_pool.cdc 'A.426f0458ced60037.MOET.Vault' --network testnet --signer testnet-flow-credit-market-deployer +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-factory/create_and_store_pool.cdc 'A.426f0458ced60037.MOET.Vault' --network testnet --signer testnet-flow-alp-deployer # update Pool with Band Oracle instead of Mock Oracle -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/update_oracle.cdc --network testnet --signer testnet-flow-credit-market-deployer +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/update_oracle.cdc --network testnet --signer testnet-flow-alp-deployer # add FLOW as supported token - params: collateralFactor, borrowFactor, depositRate, depositCapacityCap -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.7e60df042a9c0868.FlowToken.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network testnet \ - --signer testnet-flow-credit-market-deployer + --signer testnet-flow-alp-deployer # add WBTC to band oracle cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transactions/band-oracle-connector/add_symbol.cdc "BTC" "A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault" --network testnet --signer testnet-band-oracle-connectors && cd ../../.. @@ -38,32 +38,32 @@ cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transa cd ./lib/FlowCreditMarket/FlowActions && flow transactions send ./cadence/transactions/band-oracle-connector/add_symbol.cdc "ETH" "A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault" --network testnet --signer testnet-band-oracle-connectors && cd ../../.. # add WBTC as supported token -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network testnet \ - --signer testnet-flow-credit-market-deployer + --signer testnet-flow-alp-deployer # add WETH as supported token -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/pool-governance/add_supported_token_simple_interest_curve.cdc \ +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/pool-governance/add_supported_token_simple_interest_curve.cdc \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ 0.8 \ 1.0 \ 1_000_000.0 \ 1_000_000.0 \ --network testnet \ - --signer testnet-flow-credit-market-deployer + --signer testnet-flow-alp-deployer echo "swap Flow to MOET" -flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-credit-market/create_position.cdc 100000.0 --network testnet --signer testnet-flow-credit-market-deployer +flow transactions send ./lib/FlowCreditMarket/cadence/transactions/flow-alp/create_position.cdc 100000.0 --network testnet --signer testnet-flow-alp-deployer # TODO: # flow transactions send ./lib/flow-evm-bridge/cadence/transactions/bridge/tokens/bridge_tokens_to_any_evm_address.cdc \ # "A.426f0458ced60037.MOET.Vault" 100000.0 "0xOWNER" \ -# --network testnet --signer testnet-flow-credit-market-deployer +# --network testnet --signer testnet-flow-alp-deployer # create pool # add liquidity to pool @@ -147,9 +147,9 @@ flow transactions send ./cadence/transactions/flow-yield-vaults/admin/add_strate # grant PoolBeta cap echo "Grant Protocol Beta access to FlowYieldVaults" -flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-credit-market/pool-management/03_grant_beta.cdc \ - --authorizer testnet-flow-credit-market-deployer,testnet-admin \ - --proposer testnet-flow-credit-market-deployer \ +flow transactions send ./lib/FlowCreditMarket/cadence/tests/transactions/flow-alp/pool-management/03_grant_beta.cdc \ + --authorizer testnet-flow-alp-deployer,testnet-admin \ + --proposer testnet-flow-alp-deployer \ --payer testnet-admin \ --network testnet From 58779754f281e25d3a814f6d1979cf1dc6f86706 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 23:29:22 -0500 Subject: [PATCH 11/13] update ref --- lib/FlowCreditMarket | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FlowCreditMarket b/lib/FlowCreditMarket index 3eaa1ba..cdb155c 160000 --- a/lib/FlowCreditMarket +++ b/lib/FlowCreditMarket @@ -1 +1 @@ -Subproject commit 3eaa1badcb17d45aff6bbe50bba330458828a045 +Subproject commit cdb155cdda36658b424760b9c1fa7a5db6487624 From f495d102dc44e5de9ce72716269b94ed0bfe18fc Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:18:01 -0500 Subject: [PATCH 12/13] update ref --- lib/FlowCreditMarket | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FlowCreditMarket b/lib/FlowCreditMarket index cdb155c..6ef4a6e 160000 --- a/lib/FlowCreditMarket +++ b/lib/FlowCreditMarket @@ -1 +1 @@ -Subproject commit cdb155cdda36658b424760b9c1fa7a5db6487624 +Subproject commit 6ef4a6e0d63b396332a219fa5a89f9440a251f68 From 12288bd57bc9af634ad3483a9343f0e588bede12 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:49:00 -0500 Subject: [PATCH 13/13] tweak fork height --- cadence/tests/PMStrategiesV1_test.cdc | 2 +- lib/FlowCreditMarket | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cadence/tests/PMStrategiesV1_test.cdc b/cadence/tests/PMStrategiesV1_test.cdc index bc46901..0db4941 100644 --- a/cadence/tests/PMStrategiesV1_test.cdc +++ b/cadence/tests/PMStrategiesV1_test.cdc @@ -1,4 +1,4 @@ -#test_fork(network: "mainnet", height: 141935000) +#test_fork(network: "mainnet", height: 141994362) import Test diff --git a/lib/FlowCreditMarket b/lib/FlowCreditMarket index 6ef4a6e..74f939b 160000 --- a/lib/FlowCreditMarket +++ b/lib/FlowCreditMarket @@ -1 +1 @@ -Subproject commit 6ef4a6e0d63b396332a219fa5a89f9440a251f68 +Subproject commit 74f939bcb795b03c733758d74c76f9eaa72455f5