diff --git a/README.md b/README.md index b98d7a2b..abe74e5e 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,39 +63,43 @@ 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 | -| FlowYieldVaultsStrategies | 0xd27920b6384e2a78 | FlowYieldVaultsStrategies | TBD | +| FlowYieldVaultsStrategiesV2 | 0xd27920b6384e2a78 | FlowYieldVaultsStrategiesV2 | 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 | |---|---|---|---| | FlowActions | 0x6d888f175c158410 | DeFiActions | TBD | -| FlowCreditMarket | 0x6b00ff876c299c61 | FlowALP | TBD | +| FlowALPv1 | 0x6b00ff876c299c61 | FlowALPv1 | TBD | | FlowYieldVaults | 0xb1d63873c3cc9f79 | FlowYieldVaults | TBD | -| FlowYieldVaultsStrategies | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategies | TBD | +| FlowYieldVaultsStrategiesV2 | 0xb1d63873c3cc9f79 | FlowYieldVaultsStrategiesV2 | 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 -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 ``` @@ -184,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. @@ -206,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:** @@ -260,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 @@ -331,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 @@ -516,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 @@ -573,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 @@ -862,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 @@ -1016,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 @@ -1508,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 @@ -1553,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/FlowYieldVaults.cdc b/cadence/contracts/FlowYieldVaults.cdc index ccf618ea..8449f990 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/FlowYieldVaultsStrategies.cdc b/cadence/contracts/FlowYieldVaultsStrategies.cdc index d7f7f46a..a5d4d1ff 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/FlowYieldVaultsStrategiesV1_1.cdc b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc similarity index 81% rename from cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc rename to cadence/contracts/FlowYieldVaultsStrategiesV2.cdc index f613ce72..1712e924 100644 --- a/cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc +++ b/cadence/contracts/FlowYieldVaultsStrategiesV2.cdc @@ -9,9 +9,10 @@ import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" import "ERC4626SwapConnectors" +import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // Lending protocol -import "FlowCreditMarket" +import "FlowALPv1" // FlowYieldVaults platform import "FlowYieldVaults" import "FlowYieldVaultsAutoBalancers" @@ -24,7 +25,7 @@ import "FlowEVMBridgeConfig" // live oracles import "ERC4626PriceOracles" -/// FlowYieldVaultsStrategiesV1_1 +/// FlowYieldVaultsStrategiesV2 /// /// This contract defines Strategies used in the FlowYieldVaults platform. /// @@ -35,7 +36,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,16 +72,16 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } } - /// This strategy uses mUSDF vaults - access(all) resource mUSDFStrategy : FlowYieldVaults.Strategy, DeFiActions.IdentifiableResource { + /// 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 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) @@ -178,12 +179,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 } @@ -199,7 +200,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 } @@ -228,6 +229,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( @@ -245,7 +249,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( @@ -256,15 +260,9 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { ) // 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._createUniV3Swapper( - tokenPath: [tokens.yieldTokenEVMAddress, tokens.moetTokenEVMAddress], - feePath: [100], - inVault: tokens.yieldTokenType, - outVault: tokens.moetTokenType, - uniqueID: uniqueID - ) + let yieldToMoetSwapper = self._createYieldToMoetSwapper(strategyType: type, tokens: tokens, uniqueID: uniqueID) // AutoBalancer-directed swap IO let abaSwapSink = SwapConnectors.SwapSink( @@ -278,7 +276,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { uniqueID: uniqueID ) - // Open FlowCreditMarket position + // Open FlowALPv1 position let position <- self._openCreditPosition( funds: <-withFunds, issuanceSink: abaSwapSink, @@ -306,11 +304,16 @@ 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<@FUSDEVStrategy>(): + return <-create FUSDEVStrategy( + id: uniqueID, + collateralType: collateralType, + position: <-position + ) + default: + panic("Unsupported strategy type \(type.identifier)") + } } /* =========================== @@ -320,7 +323,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)" @@ -333,8 +336,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) @@ -357,7 +360,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, @@ -387,20 +390,21 @@ 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, + strategyType: Type, + tokens: FlowYieldVaultsStrategiesV2.TokenBundle, uniqueID: DeFiActions.UniqueIdentifier ): SwapConnectors.MultiSwapper { // Direct MOET -> YIELD via AMM @@ -422,16 +426,28 @@ 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 - ) + // 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 ) @@ -443,12 +459,67 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { ) } + access(self) fun _createYieldToMoetSwapper( + strategyType: Type, + 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 + ) + + // 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 + ) + + 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( 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( @@ -467,7 +538,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 @@ -478,10 +549,10 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { funds: @{FungibleToken.Vault}, issuanceSink: {DeFiActions.Sink}, repaymentSource: {DeFiActions.Source} - ): @FlowCreditMarket.Position { - let poolCap = FlowYieldVaultsStrategiesV1_1.account.storage.copy< - Capability - >(from: FlowCreditMarket.PoolCapStoragePath) + ): @FlowALPv1.Position { + let poolCap = FlowYieldVaultsStrategiesV2.account.storage.copy< + Capability + >(from: FlowALPv1.PoolCapStoragePath) ?? panic("Missing or invalid pool capability") let poolRef = poolCap.borrow() ?? panic("Invalid Pool Cap") @@ -497,7 +568,7 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } access(self) fun _createYieldToCollateralSwapper( - collateralConfig: FlowYieldVaultsStrategiesV1_1.CollateralConfig, + collateralConfig: FlowYieldVaultsStrategiesV2.CollateralConfig, yieldTokenEVMAddress: EVM.EVMAddress, yieldTokenType: Type, collateralType: Type, @@ -553,10 +624,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 } @@ -575,12 +646,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 { @@ -590,8 +661,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") } @@ -600,7 +671,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: @@ -624,7 +695,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]! @@ -653,7 +724,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 @@ -670,8 +741,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } access(Configure) fun purgeConfig() { self.configs = { - Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV1_1.CollateralConfig} + Type<@MorphoERC4626StrategyComposer>(): { + Type<@FUSDEVStrategy>(): {} as {Type: FlowYieldVaultsStrategiesV2.CollateralConfig} } } } @@ -747,7 +818,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>() @@ -756,8 +827,8 @@ access(all) contract FlowYieldVaultsStrategiesV1_1 { } let configs = { - Type<@mUSDFStrategyComposer>(): { - Type<@mUSDFStrategy>(): ({} 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/PMStrategiesV1.cdc b/cadence/contracts/PMStrategiesV1.cdc index ba0ff9e9..366e5878 100644 --- a/cadence/contracts/PMStrategiesV1.cdc +++ b/cadence/contracts/PMStrategiesV1.cdc @@ -9,6 +9,7 @@ import "FungibleTokenConnectors" // amm integration import "UniswapV3SwapConnectors" import "ERC4626SwapConnectors" +import "MorphoERC4626SwapConnectors" import "ERC4626Utils" // FlowYieldVaults platform import "FlowYieldVaults" @@ -346,24 +347,48 @@ access(all) contract PMStrategiesV1 { uniqueID: uniqueID ) // Swap Collateral -> YieldToken via ERC4626 Vault - let collateralTo4626Swapper = ERC4626SwapConnectors.Swapper( - asset: collateralType, - vault: yieldTokenEVMAddress, - coa: PMStrategiesV1._getCOACapability(), - feeSource: PMStrategiesV1._createFeeSource(withID: uniqueID), - uniqueID: uniqueID - ) - // Finally, add the two Collateral -> YieldToken swappers into an aggregate MultiSwapper - let collateralToYieldSwapper = SwapConnectors.MultiSwapper( - inVault: collateralType, - outVault: yieldTokenType, - swappers: [collateralToYieldAMMSwapper, collateralTo4626Swapper], - 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 + ) + } - // 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,12 +400,39 @@ access(all) contract PMStrategiesV1 { 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/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 da5719b6..ec8225ef 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 1d7f3944..99ed06d4 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 8458e3d0..e14e617e 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 new file mode 100644 index 00000000..0db49416 --- /dev/null +++ b/cadence/tests/PMStrategiesV1_test.cdc @@ -0,0 +1,328 @@ +#test_fork(network: "mainnet", height: 141994362) + +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()) + + // 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/atomic_registration_gc_test.cdc b/cadence/tests/atomic_registration_gc_test.cdc index 18280862..95ad31d1 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 80adf99e..5ac7072f 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 b92f3554..dd97774d 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 6baf54ae..3d5b865b 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 6100651a..98186c5f 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 330c4944..de62ea0f 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 1f467ae0..74534a96 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 c0c90108..f3c20c83 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 b5e8ec92..4550e57d 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 8dda29bd..102d32bb 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 9ba8b7b9..bdf56261 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 86c62889..c1df43c7 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 a833a8a2..b5b5280c 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()) @@ -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( @@ -328,8 +348,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", @@ -367,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 ) @@ -412,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()) @@ -440,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()) @@ -453,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 ) @@ -471,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 ) @@ -481,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 ) @@ -564,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 --- */ @@ -651,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 2c2949af..27ae2f7a 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/transactions/swap_flow_to_pyusd0.cdc b/cadence/tests/transactions/swap_flow_to_pyusd0.cdc new file mode 100644 index 00000000..8637a277 --- /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/cadence/tests/yield_vault_lifecycle_test.cdc b/cadence/tests/yield_vault_lifecycle_test.cdc index 0e1ad05e..b515b554 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/flow-yield-vaults/admin/upsert_musdf_config.cdc b/cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc similarity index 68% 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 80f22443..792c7031 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,20 @@ 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...FlowYieldVaultsStrategiesV2.FUSDEVStrategy" + strategyTypeIdentifier: String, + + // collateral vault type (e.g. "A.0x...FlowToken.Vault") tokenTypeIdentifier: String, + + // yield token (EVM) address yieldTokenEVMAddress: String, // collateral path/fees: [YIELD, ..., ] @@ -17,13 +23,15 @@ 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 // 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) @@ -37,8 +45,7 @@ transaction( return out } - let composerType = Type<@FlowYieldVaultsStrategiesV1_1.mUSDFStrategyComposer>() - let strategyType = Type<@FlowYieldVaultsStrategiesV1_1.mUSDFStrategy>() + let composerType = Type<@FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer>() if swapPath.length > 0 { issuer.addOrUpdateCollateralConfig( diff --git a/cadence/transactions/mocks/position/create_wrapped_position.cdc b/cadence/transactions/mocks/position/create_wrapped_position.cdc index c6edbefb..01b64aca 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 f7858487..cde18b69 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 919a4817..1aa587b9 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 53bd25ac..471fe51f 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": { @@ -89,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", @@ -98,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", @@ -161,8 +170,8 @@ "testnet": "d2580caf2ef07c2f" } }, - "FlowYieldVaultsStrategiesV1_1": { - "source": "cadence/contracts/FlowYieldVaultsStrategiesV1_1.cdc", + "FlowYieldVaultsStrategiesV2": { + "source": "cadence/contracts/FlowYieldVaultsStrategiesV2.cdc", "aliases": { "emulator": "045a1763c93006ca", "mainnet": "b1d63873c3cc9f79", @@ -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" } }, @@ -791,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", @@ -828,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", @@ -851,11 +879,11 @@ }, "DeFiActionsUtils", "DeFiActions", - "FlowCreditMarketMath", + "FlowALPMath", "FungibleTokenConnectors", "SwapConnectors", "DummyConnectors", - "FlowCreditMarket", + "FlowALPv1", { "name": "YieldToken", "args": [ @@ -920,7 +948,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0x986Cb42b0557159431d48fE0A40073296414d410", @@ -1048,7 +1076,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0xca6d7Bb03334bBf135902e1d919a5feccb461632", @@ -1153,7 +1181,7 @@ ] }, { - "name": "FlowYieldVaultsStrategiesV1_1", + "name": "FlowYieldVaultsStrategiesV2", "args": [ { "value": "0x92657b195e22b69E4779BBD09Fa3CD46F0CF8e39", @@ -1189,4 +1217,4 @@ ] } } -} \ No newline at end of file +} diff --git a/lib/FlowCreditMarket b/lib/FlowCreditMarket index 81635182..74f939bc 160000 --- a/lib/FlowCreditMarket +++ b/lib/FlowCreditMarket @@ -1 +1 @@ -Subproject commit 816351826a9deb86033469d8dea9cc847104ecbd +Subproject commit 74f939bcb795b03c733758d74c76f9eaa72455f5 diff --git a/local/setup_emulator.sh b/local/setup_emulator.sh index 65ffddbf..70126259 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 \ @@ -51,14 +51,14 @@ 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 # 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 d5bf83fd..b4be0348 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 @@ -115,41 +115,42 @@ 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 \ +# Setup UniV3 path FUSDEV -> PYUSD0 -> WFLOW +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1654653399040a61.FlowToken.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ + "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ + '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","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 \ +# Setup UniV3 path FUSDEV -> PYUSD0 -> WBTC +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x717DAE2BaF7656BE9a9B01deE31d571a9d4c9579"]' \ + "0xd069d989e2F44B70c65347d1853C0c67e10a9F8D" \ + '["0xd069d989e2F44B70c65347d1853C0c67e10a9F8D","0x99aF3EeA856556646C98c8B9b2548Fe815240750","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 \ +# Setup UniV3 path FUSDEV -> PYUSD0 -> WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.1e4aa0b87d10b141.EVMVMBridgedToken_2f6f07cdcf3588944bf4c42ac74ff24bf56e7590.Vault' \ - "0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c" \ - '["0xc52E820d2D6207D18667a97e2c6Ac22eB26E803c","0x2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED","0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"]' \ + "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 \ - 'A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV1_1.mUSDFStrategy' \ - '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 @@ -201,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 @@ -223,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.FlowYieldVaultsStrategies.mUSDCStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.1654653399040a61.FlowToken.Vault \ # 1.0 \ # --compute-limit 9999 \ @@ -233,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.mUSDFStrategy \ +# A.b1d63873c3cc9f79.FlowYieldVaultsStrategiesV2.FUSDEVStrategy \ # A.1e4aa0b87d10b141.EVMVMBridgedToken_717dae2baf7656be9a9b01dee31d571a9d4c9579.Vault \ # 0.0000001 \ # --compute-limit 9999 \ @@ -242,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.mUSDFStrategy \ +# 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 c8cfb0f9..ec5f73a5 100755 --- a/local/setup_testnet.sh +++ b/local/setup_testnet.sh @@ -6,11 +6,11 @@ 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" -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 @@ -88,36 +88,44 @@ 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 \ +## PYUSD0 Vault +# WFLOW univ3 path and fees +# path: FUSDEV - WFLOW +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.7e60df042a9c0868.FlowToken.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95", "0xd3bF53DAC106A0290B0483EcBC89d40FcC961f3e"]' \ + "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ + '["0x61b44D19486EE492449E83C1201581C754e9e1E1", "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 \ +# path: FUSDEV - MOET - WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_059a77239dafa770977dd9f1e98632c3e4559848.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c", "0x059A77239daFa770977DD9f1E98632C3E4559848"]' \ + "0x61b44D19486EE492449E83C1201581C754e9e1E1" \ + '["0x61b44D19486EE492449E83C1201581C754e9e1E1","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 \ +# path: FUSDEV - MOET - WETH +flow transactions send ./cadence/transactions/flow-yield-vaults/admin/upsert_strategy_config.cdc \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ 'A.dfc20aee650fcbdf.EVMVMBridgedToken_208d09d2a6dd176e3e95b3f0de172a7471c5b2d6.Vault' \ - "0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95" \ - '["0x4154d5B0E2931a0A1E5b733f19161aa7D2fc4b95","0x02d3575e2516a515E9B91a52b294Edc80DC7987c","0x208d09d2a6Dd176e3e95b3F0DE172A7471C5B2d6"]' \ + "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' \ - /storage/FlowYieldVaultsStrategyV1_1ComposerIssuer_0xd2580caf2ef07c2f \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.FUSDEVStrategy' \ + 'A.d2580caf2ef07c2f.FlowYieldVaultsStrategiesV2.MorphoERC4626StrategyComposer' \ + /storage/FlowYieldVaultsStrategyV2ComposerIssuer_0xd2580caf2ef07c2f \ --network testnet \ --signer testnet-admin @@ -139,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 @@ -158,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 \ @@ -168,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 \ @@ -177,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 \