Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
8e99b52
add initial Tidal contract & supporting scripts & transactions
sisyphusSmiling May 14, 2025
7c754ee
update DFB to include PriceOracle interface
sisyphusSmiling May 14, 2025
32d1f26
add initial USDA contract for use with MockOracle
sisyphusSmiling May 15, 2025
be1f7c4
add MockOracle contract & supporting txns & scripts
sisyphusSmiling May 15, 2025
8dfb7de
remove unused import
sisyphusSmiling May 15, 2025
f538ddd
add MockSwapper contract
sisyphusSmiling May 15, 2025
5270eb4
update MockSwapper to better represent sourcing liquidity from pools …
sisyphusSmiling May 15, 2025
58bd454
update flow.json
sisyphusSmiling May 15, 2025
3e7dddb
add MockSwapper.setLiquidityConnector transaction
sisyphusSmiling May 15, 2025
07cc65e
update transaction comment
sisyphusSmiling May 16, 2025
675e146
add MockSwapper to emulator deployment
sisyphusSmiling May 19, 2025
1b5055b
add supporting USDA transactions
sisyphusSmiling May 19, 2025
dee1f14
update MockOracle to return 1.0 for unitOfAccount price
sisyphusSmiling May 19, 2025
bc24908
fix internal dependency pre-condition
sisyphusSmiling May 19, 2025
60efc8d
Merge branch 'gio/mock-oracle' into gio/mock-amm
sisyphusSmiling May 19, 2025
d4efa70
add emulator setup script
sisyphusSmiling May 19, 2025
535b231
Merge branch 'main' into gio/mock-amm
sisyphusSmiling May 22, 2025
c5fd5ef
update USDA initialization args
sisyphusSmiling May 22, 2025
815f75f
update internal dependencies
sisyphusSmiling May 28, 2025
987fd7d
remove Tidal.UniqueID definition in favor of DFB.UniqueIdentifier
sisyphusSmiling May 28, 2025
c62b6d0
update mocked PriceOracle to return optional on price()
sisyphusSmiling May 28, 2025
1d14d05
update MockSwapper based on updated DFB interfaces
sisyphusSmiling May 28, 2025
2e83803
add initial strategy framing
sisyphusSmiling May 29, 2025
648141f
add initial strategy constructor contract
sisyphusSmiling Jun 4, 2025
3800ff5
Merge branch 'main' into gio/add-strategy-factory
sisyphusSmiling Jun 9, 2025
17e8219
update internal dependencies
sisyphusSmiling Jun 9, 2025
a2d335a
rename Tidal contract to TidalYield
sisyphusSmiling Jun 9, 2025
8e87097
update TidalStrategies StrategyFactory & StrategyBuilder constructs
sisyphusSmiling Jun 9, 2025
c6f0bb5
rename TidalStrategies to TidalYieldFactory
sisyphusSmiling Jun 9, 2025
f91bb25
update contract comments
sisyphusSmiling Jun 9, 2025
b02a551
move mocke strategy components from TidalYieldFactory to MockStrategy
sisyphusSmiling Jun 9, 2025
9057569
consolidate former Factory contract to TidalYield primary contract
sisyphusSmiling Jun 9, 2025
7ef3e80
fix mock strategies
sisyphusSmiling Jun 9, 2025
c9dbc0a
fix flow.json config
sisyphusSmiling Jun 10, 2025
71ab6f4
add TidalYieldAutoBalancers contract & update flow.json config
sisyphusSmiling Jun 10, 2025
657e9b1
rename StrategyBuilder to StrategyComposer
sisyphusSmiling Jun 10, 2025
7f6cac0
update initial TraceStrategy and TracerStrategyComposer
sisyphusSmiling Jun 10, 2025
c03b0c3
refactor Strategy from struct to resource
sisyphusSmiling Jun 10, 2025
63733a4
update contract comments
sisyphusSmiling Jun 10, 2025
5774e7e
update TidalYield interface conditions & defaults, update contract fo…
sisyphusSmiling Jun 10, 2025
015f2eb
update contract comments
sisyphusSmiling Jun 10, 2025
e005eb2
remove redundant dependency DFBUtils
sisyphusSmiling Jun 10, 2025
4716e79
add contract comments to TidalYield
sisyphusSmiling Jun 11, 2025
11cf0de
add AutoBalancer cleanup on Strategy burn
sisyphusSmiling Jun 11, 2025
d9f35f4
refactor StrategyComposer from struct interface to resource interface
sisyphusSmiling Jun 11, 2025
1fa0b7a
update comments & error messages
sisyphusSmiling Jun 11, 2025
8218909
add StrategyComposerIssuer to contract init block
sisyphusSmiling Jun 11, 2025
e3e3bf8
rename cadence/transactions/tidal to cadence/transactions/tidal-yield
sisyphusSmiling Jun 11, 2025
79d0ad6
rename scripts sub-directory
sisyphusSmiling Jun 11, 2025
5aa2138
update MockStrategy contract construct names
sisyphusSmiling Jun 11, 2025
ac345cb
add TidalProtocol supporting txns & scripts
sisyphusSmiling Jun 11, 2025
c3abff2
add initial test and test helpers & update flow.json testing aliases
sisyphusSmiling Jun 11, 2025
7aea0ad
add Cadence tests to github ci action
sisyphusSmiling Jun 11, 2025
dd29732
rename usda/ to moet/
sisyphusSmiling Jun 11, 2025
1e75a4d
update setup_emulator.sh script
sisyphusSmiling Jun 11, 2025
27a4c0a
remove Owner entitlement from TidalYield contract
sisyphusSmiling Jun 11, 2025
a585d98
fix MockStrategy getters
sisyphusSmiling Jun 11, 2025
e733ffd
add initial Tide management tests
sisyphusSmiling Jun 11, 2025
374d8c7
fix createTide route caused by TracerStrategy composition errors
sisyphusSmiling Jun 12, 2025
fb72fb5
remove deprecated TidalYield.Owner entitlement usage
sisyphusSmiling Jun 12, 2025
e1471cf
update contract comments
sisyphusSmiling Jun 12, 2025
235143b
update DeFiBlocks to latest
sisyphusSmiling Jun 12, 2025
8932939
update get_balance script
sisyphusSmiling Jun 12, 2025
0bea1a3
fix MockStrategy interface conformance
sisyphusSmiling Jun 12, 2025
bf62a2a
rename token-related transactions
sisyphusSmiling Jun 12, 2025
3f47e72
add behavioral tests covering TracerStrategy
sisyphusSmiling Jun 12, 2025
22d7d0d
update scripts
sisyphusSmiling Jun 12, 2025
6268d2e
add AutoBalancer rebalance transaction
sisyphusSmiling Jun 12, 2025
058bbe8
undo Tidal contract renaming
sisyphusSmiling Jun 13, 2025
02f252c
rename Tidal to TidalYield
sisyphusSmiling Jun 13, 2025
e085da2
fix MOET deposit logic
sisyphusSmiling Jun 16, 2025
f960a01
fix YieldToken deposit logic
sisyphusSmiling Jun 16, 2025
fdbe1a2
update addStrategyComposer pre-condition
sisyphusSmiling Jun 16, 2025
051302c
fix mock price getter script
sisyphusSmiling Jun 17, 2025
6715204
update flow.json emulator aliases
sisyphusSmiling Jun 17, 2025
662660a
add test user
nialexsan Jun 17, 2025
6bf8ccf
add +x
nialexsan Jun 17, 2025
77057b6
swap git module
nialexsan Jun 18, 2025
fe61688
Merge branch 'gio/add-strategy-factory' into gio/rename-tidal-contract
Kay-Zee Jun 18, 2025
9f4d3f7
Merge pull request #8 from onflow/gio/rename-tidal-contract
Kay-Zee Jun 18, 2025
b7d182c
Revert "Rename Tidal to TidalYield" (#10)
sisyphusSmiling Jun 18, 2025
4923b4c
update tidal protocol with events
nialexsan Jun 19, 2025
34d2ecd
Add rebalance test
Kay-Zee Jun 20, 2025
059cd1a
Update to latest defi blocks
Kay-Zee Jun 20, 2025
8661eac
Make adjustment to allow closing the tide and retain the full collate…
Kay-Zee Jun 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/cadence_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: CI

on: pull_request

jobs:
tests:
name: Flow CLI Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GH_PAT }}
submodules: "true"
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: "1.23.x"
- uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install Flow CLI
run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)"
- name: Flow CLI Version
run: flow version
- name: Update PATH
run: echo "/root/.local/bin" >> $GITHUB_PATH
- name: Install dependencies
run: flow deps install --skip-alias --skip-deployments
- name: Run tests
run: flow test --cover --covercode="contracts" --coverprofile="coverage.lcov" ./cadence/tests/*_test.cdc
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "DeFiBlocks"]
path = DeFiBlocks
url = https://github.com/onflow/DeFiBlocks
url = git@github.com:onflow/DeFiBlocks.git
2 changes: 1 addition & 1 deletion DeFiBlocks
364 changes: 307 additions & 57 deletions cadence/contracts/Tidal.cdc

Large diffs are not rendered by default.

123 changes: 123 additions & 0 deletions cadence/contracts/TidalYieldAutoBalancers.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// standards
import "Burner"
import "FungibleToken"
// DeFiBlocks
import "DFB"

/// TidalYieldAutoBalancers
///
/// This contract deals with the storage, retrieval and cleanup of DeFiBlocks AutoBalancers as they are used in
/// TidalYield defined Strategies.
///
/// AutoBalancers are stored in contract account storage at paths derived by their related DFB.UniqueIdentifier.id
/// which identifies all DeFiBlocks components in the stack related to their composite Strategy.
///
/// When a Tide and necessarily the related Strategy is closed & burned, the related AutoBalancer and its Capabilities
/// are destroyed and deleted
///
access(all) contract TidalYieldAutoBalancers {

/// The path prefix used for StoragePath & PublicPath derivations
access(all) let pathPrefix: String

/* --- PUBLIC METHODS --- */

/// Returns the path (StoragePath or PublicPath) at which an AutoBalancer is stored with the associated
/// UniqueIdentifier.id.
access(all) view fun deriveAutoBalancerPath(id: UInt64, storage: Bool): Path {
return storage ? StoragePath(identifier: "\(self.pathPrefix)\(id)")! : PublicPath(identifier: "\(self.pathPrefix)\(id)")!
}

/// Returns an unauthorized reference to an AutoBalancer with the given UniqueIdentifier.id value. If none is
/// configured, `nil` will be returned.
access(all) fun borrowAutoBalancer(id: UInt64): &DFB.AutoBalancer? {
let publicPath = self.deriveAutoBalancerPath(id: id, storage: false) as! PublicPath
return self.account.capabilities.borrow<&DFB.AutoBalancer>(publicPath)
}

/* --- INTERNAL METHODS --- */

/// Configures a new AutoBalancer in storage, configures its public Capability, and sets its inner authorized
/// Capability. If an AutoBalancer is stored with an associated UniqueID value, the operation reverts.
access(account) fun _initNewAutoBalancer(
oracle: {DFB.PriceOracle},
vaultType: Type,
lowerThreshold: UFix64,
upperThreshold: UFix64,
rebalanceSink: {DFB.Sink}?,
rebalanceSource: {DFB.Source}?,
uniqueID: DFB.UniqueIdentifier
): auth(DFB.Auto, DFB.Set, DFB.Get, FungibleToken.Withdraw) &DFB.AutoBalancer {

// derive paths & prevent collision
let storagePath = self.deriveAutoBalancerPath(id: uniqueID.id, storage: true) as! StoragePath
let publicPath = self.deriveAutoBalancerPath(id: uniqueID.id, storage: false) as! PublicPath
var storedType = self.account.storage.type(at: storagePath)
var publishedCap = self.account.capabilities.exists(publicPath)
assert(storedType == nil,
message: "Storage collision when creating AutoBalancer for UniqueIdentifier.id \(uniqueID.id) at path \(storagePath)")
assert(!publishedCap,
message: "Published Capability collision found when publishing AutoBalancer for UniqueIdentifier.id \(uniqueID.id) at path \(publicPath)")

// create & save AutoBalancer
let autoBalancer <- DFB.createAutoBalancer(
oracle: oracle,
vaultType: vaultType,
lowerThreshold: lowerThreshold,
upperThreshold: upperThreshold,
rebalanceSink: rebalanceSink,
rebalanceSource: rebalanceSource,
uniqueID: uniqueID
)
self.account.storage.save(<-autoBalancer, to: storagePath)
let autoBalancerRef = self._borrowAutoBalancer(uniqueID.id)

// issue & publish public capability
let publicCap = self.account.capabilities.storage.issue<&DFB.AutoBalancer>(storagePath)
self.account.capabilities.publish(publicCap, at: publicPath)

// issue private capability & set within AutoBalancer
let authorizedCap = self.account.capabilities.storage.issue<auth(FungibleToken.Withdraw) &DFB.AutoBalancer>(storagePath)
autoBalancerRef.setSelfCapability(authorizedCap)

// ensure proper configuration before closing
storedType = self.account.storage.type(at: storagePath)
publishedCap = self.account.capabilities.exists(publicPath)
assert(storedType == Type<@DFB.AutoBalancer>(),
message: "Error when configuring AutoBalancer for UniqueIdentifier.id \(uniqueID.id) at path \(storagePath)")
assert(publishedCap,
message: "Error when publishing AutoBalancer Capability for UniqueIdentifier.id \(uniqueID.id) at path \(publicPath)")
return autoBalancerRef
}

/// Returns an authorized reference on the AutoBalancer with the associated UniqueIdentifier.id. If none is found,
/// the operation reverts.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it just return nil instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could, though it would revert where called since it's required for write operations

access(account)
fun _borrowAutoBalancer(_ id: UInt64): auth(DFB.Auto, DFB.Set, DFB.Get, FungibleToken.Withdraw) &DFB.AutoBalancer {
let storagePath = self.deriveAutoBalancerPath(id: id, storage: true) as! StoragePath
return self.account.storage.borrow<auth(DFB.Auto, DFB.Set, DFB.Get, FungibleToken.Withdraw) &DFB.AutoBalancer>(
from: storagePath
) ?? panic("Could not borrow reference to AutoBalancer with UniqueIdentifier.id \(id) from StoragePath \(storagePath)")
}

/// Called by strategies defined in the TidalYield account which leverage account-hosted AutoBalancers when a
/// Strategy is burned
access(account) fun _cleanupAutoBalancer(id: UInt64) {
let storagePath = self.deriveAutoBalancerPath(id: id, storage: true) as! StoragePath
let publicPath = self.deriveAutoBalancerPath(id: id, storage: false) as! PublicPath
// unpublish the public AutoBalancer Capability
self.account.capabilities.unpublish(publicPath)
// delete any CapabilityControllers targetting the AutoBalancer
self.account.capabilities.storage.forEachController(forPath: storagePath, fun(_ controller: &StorageCapabilityController): Bool {
controller.delete()
return true
})
// load & burn the AutoBalancer
let autoBalancer <-self.account.storage.load<@DFB.AutoBalancer>(from: storagePath)
Burner.burn(<-autoBalancer)
}

init() {
self.pathPrefix = "TidalYieldAutoBalancer_"
}
}
210 changes: 210 additions & 0 deletions cadence/contracts/TidalYieldStrategies.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// standards
import "FungibleToken"
import "FlowToken"
// DeFiBlocks
import "DFBUtils"
import "DFB"
import "SwapStack"
// Lending protocol
import "TidalProtocol"
// TidalYield platform
import "Tidal"
import "TidalYieldAutoBalancers"
// tokens
import "YieldToken"
import "MOET"
// mocks
import "MockOracle"
import "MockSwapper"

/// THIS CONTRACT IS A MOCK AND IS NOT INTENDED FOR USE IN PRODUCTION
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
///
/// TidalYieldStrategies
///
/// This contract defines Strategies used in the TidalYield platform.
///
/// A Strategy instance can be thought of as objects wrapping a stack of DeFiBlocks connectors wired together to
/// (optimally) generate some yield on initial deposits. Strategies can be simple such as swapping into a yield-bearing
/// asset (such as stFLOW) or more complex DeFiBlocks stacks.
///
/// A StrategyComposer is tasked with the creation of a supported Strategy. It's within the stacking of DeFiBlocks
/// connectors that the true power of the components lies.
///
access(all) contract TidalYieldStrategies {

/// Canonical StoragePath where the StrategyComposerIssuer should be stored
access(all) let IssuerStoragePath: StoragePath

/// This is the first Strategy implementation, wrapping a TidalProtocol 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
/// DeFiBlocks is in the stacking of the related connectors. This stacking logic can be found in the
/// TracerStrategyComposer construct.
access(all) resource TracerStrategy : Tidal.Strategy {
/// An optional identifier allowing protocols to identify stacked connector operations by defining a protocol-
/// specific Identifier to associated connectors on construction
access(contract) let uniqueID: DFB.UniqueIdentifier?
access(self) let position: TidalProtocol.Position
access(self) var sink: {DFB.Sink}
access(self) var source: {DFB.Source}

init(id: DFB.UniqueIdentifier, collateralType: Type, position: TidalProtocol.Position) {
self.uniqueID = id
self.position = position
self.sink = position.createSink(type: collateralType)
self.source = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true)
}

// Inherited from Tidal.Strategy default implementation
// access(all) view fun isSupportedCollateralType(_ type: Type): Bool

access(all) view fun getSupportedCollateralTypes(): {Type: Bool} {
return { self.sink.getSinkType(): true }
}
/// Returns the amount available for withdrawal via the inner Source
access(all) fun availableBalance(ofToken: Type): UFix64 {
return ofToken == self.source.getSourceType() ? self.source.minimumAvailable() : 0.0
}
/// Deposits up to the inner Sink's capacity from the provided authorized Vault reference
access(all) fun deposit(from: auth(FungibleToken.Withdraw) &{FungibleToken.Vault}) {
self.sink.depositCapacity(from: from)
}
/// Withdraws up to the max amount, returning the withdrawn Vault. If the requested token type is unsupported,
/// an empty Vault is returned.
access(FungibleToken.Withdraw) fun withdraw(maxAmount: UFix64, ofToken: Type): @{FungibleToken.Vault} {
if ofToken != self.source.getSourceType() {
return <- DFBUtils.getEmptyVault(ofToken)
}
return <- self.source.withdrawAvailable(maxAmount: maxAmount)
}
/// Executed when a Strategy is burned, cleaning up the Strategy's stored AutoBalancer
access(contract) fun burnCallback() {
TidalYieldAutoBalancers._cleanupAutoBalancer(id: self.id()!)
}
}

/// This StrategyComposer builds a TracerStrategy
access(all) resource TracerStrategyComposer : Tidal.StrategyComposer {
/// Returns the Types of Strategies composed by this StrategyComposer
access(all) view fun getComposedStrategyTypes(): {Type: Bool} {
return { Type<@TracerStrategy>(): true }
}

/// Returns the Vault types which can be used to initialize a given Strategy
access(all) view fun getSupportedInitializationVaults(forStrategy: Type): {Type: Bool} {
return { Type<@FlowToken.Vault>(): true }
}

/// Returns the Vault types which can be deposited to a given Strategy instance if it was initialized with the
/// provided Vault type
access(all) view fun getSupportedInstanceVaults(forStrategy: Type, initializedWith: Type): {Type: Bool} {
return { Type<@FlowToken.Vault>(): true }
}

/// Composes a Strategy of the given type with the provided funds
access(all) fun createStrategy(
_ type: Type,
uniqueID: DFB.UniqueIdentifier,
withFunds: @{FungibleToken.Vault}
): @{Tidal.Strategy} {
// this PriceOracle is mocked and will be shared by all components used in the TracerStrategy
let oracle = MockOracle.PriceOracle()

// assign token types
let collateralType = withFunds.getType()
let yieldTokenType = Type<@YieldToken.Vault>()
let moetTokenType = Type<@MOET.Vault>()
let flowTokenType = Type<@FlowToken.Vault>()

// configure and AutoBalancer for this stack
let autoBalancer = TidalYieldAutoBalancers._initNewAutoBalancer(
oracle: oracle, // used to determine value of deposits & when to rebalance
vaultType: yieldTokenType, // the type of Vault held by the AutoBalancer
lowerThreshold: 0.95, // set AutoBalancer to pull from rebalanceSource when balance is 5% below value of deposits
upperThreshold: 1.05, // set AutoBalancer to push to rebalanceSink when balance is 5% below value of deposits
rebalanceSink: nil, // nil on init - will be set once a PositionSink is available
rebalanceSource: nil, // nil on init - not set for TracerStrategy
uniqueID: uniqueID // identifies AutoBalancer as part of this Strategy
)
// enables deposits of YieldToken to the AutoBalancer
let abaSink = autoBalancer.createBalancerSink() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)")
// enables withdrawals of YieldToken from the AutoBalancer
let abaSource = autoBalancer.createBalancerSource() ?? panic("Could not retrieve Sink from AutoBalancer with id \(uniqueID.id)")

// init MOET <> YIELD swappers
//
// MOET -> YieldToken
let moetToYieldSwapper = MockSwapper.Swapper(
inVault: moetTokenType,
outVault: yieldTokenType,
uniqueID: uniqueID
)
// YieldToken -> MOET
let yieldToMoetSwapper = MockSwapper.Swapper(
inVault: yieldTokenType,
outVault: moetTokenType,
uniqueID: uniqueID
)

// init SwapSink directing swapped funds to AutoBalancer
//
// Swaps provided MOET to YieldToken & deposits to the AutoBalancer
let abaSwapSink = SwapStack.SwapSink(swapper: moetToYieldSwapper, sink: abaSink, uniqueID: uniqueID)
// Swaps YieldToken & provides swapped MOET, sourcing YieldToken from the AutoBalancer
let abaSwapSource = SwapStack.SwapSource(swapper: yieldToMoetSwapper, source: abaSource, uniqueID: uniqueID)

// open a TidalProtocol position
let position = TidalProtocol.openPosition(
collateral: <-withFunds,
issuanceSink: abaSwapSink,
repaymentSource: abaSwapSource,
pushToDrawDownSink: true
)
// get Sink & Source connectors relating to the new Position
let positionSink = position.createSinkWithOptions(type: collateralType, pushToDrawDownSink: true)
let positionSource = position.createSourceWithOptions(type: collateralType, pullFromTopUpSource: true) // TODO: may need to be false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would it be false?


// init YieldToken -> FLOW Swapper
let yieldToFlowSwapper = MockSwapper.Swapper(
inVault: yieldTokenType,
outVault: flowTokenType, // TODO: before
uniqueID: uniqueID
)
// allows for YieldToken to be deposited to the Position
let positionSwapSink = SwapStack.SwapSink(swapper: yieldToFlowSwapper, sink: positionSink, uniqueID: uniqueID)

// set the AutoBalancer's rebalance Sink which it will use to deposit overflown value,
// recollateralizing the position
autoBalancer.setSink(positionSwapSink)

return <-create TracerStrategy(
id: DFB.UniqueIdentifier(),
collateralType: collateralType,
position: position
)
}
}

/// This resource enables the issuance of StrategyComposers, thus safeguarding the issuance of Strategies which
/// may utilize resource consumption (i.e. account storage). Since TracerStrategy creation consumes account storage
/// via configured AutoBalancers
access(all) resource StrategyComposerIssuer : Tidal.StrategyComposerIssuer {
access(all) view fun getSupportedComposers(): {Type: Bool} {
return { Type<@TracerStrategyComposer>(): true }
}
access(all) fun issueComposer(_ type: Type): @{Tidal.StrategyComposer} {
switch type {
case Type<@TracerStrategyComposer>():
return <- create TracerStrategyComposer()
default:
panic("Unsupported StrategyComposer requested: \(type.identifier)")
}
}
}

init() {
self.IssuerStoragePath = StoragePath(identifier: "TidalYieldStrategyComposerIssuer_\(self.account.address)")!

self.account.storage.save(<-create StrategyComposerIssuer(), to: self.IssuerStoragePath)
}
}
Loading