Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
83 changes: 77 additions & 6 deletions cadence/contracts/FlowCreditMarket.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ access(all) contract FlowCreditMarket {
}
}



/// Risk parameters for a token used in effective collateral/debt computations.
/// - collateralFactor: fraction applied to credit value to derive effective collateral
Expand Down Expand Up @@ -650,7 +650,55 @@ access(all) contract FlowCreditMarket {
}
}


/// Internal Registry
///
access(all) entitlement Register
access(all) entitlement Schedule

/// IRegistry
///
/// An interface for a resource enabling arbitrary logic on Position creation & close. These are intended to allow
/// FCM to schedule transaction for new Positions on creation. Registries should maintain an implicit association
/// with Pool resources such that each Pool has an associated Registry for it. While there is only one Pool at the
/// moment, this structure allows for both upgradeability of the current contract as well as extensibility in the
/// event governance chooses to add multi-pool support in the future. Also note that this is codified as an
/// interface here to resolve potential circular dependencies compared to a canonical registry contract.
///
access(all) resource interface IRegistry {
/// Registers a new position in the identified pool
access(Register) fun registerPosition(poolUUID: UInt64, pid: UInt64, rebalanceConfig: {String: AnyStruct}?)
/// Unregisters a position in the identified pool
access(Register) fun unregisterPosition(poolUUID: UInt64, pid: UInt64): Bool
}

/// Derives the storage path for the Registry implementation for the given pool
///
/// @param forPool - the UUID of the pool to derive the storage path for
///
/// @return the storage path for the Registry implementation for the given pool
access(all) view fun deriveRegistryStoragePath(forPool: UInt64): StoragePath {
return StoragePath(identifier: "flowCreditMarketRegistry_\(forPool)")!
}

/// Derives the storage path for the Registry implementation for the given pool
///
/// @param forPool - the UUID of the pool to derive the storage path for
///
/// @return the storage path for the Registry implementation for the given pool
access(all) view fun deriveRegistryPublicPath(forPool: UInt64): PublicPath {
return PublicPath(identifier: "flowCreditMarketRegistry_\(forPool)")!
}

/// Returns an authorized reference on the Registry implementation for the given pool
///
/// @param forPool - the UUID of the pool to borrow the registry for
///
/// @return an authorized reference on the Registry implementation for the given pool
access(self) view fun _borrowFCMRegistry(forPool: UInt64): auth(Register) &{IRegistry} {
let path = self.deriveRegistryStoragePath(forPool: forPool)
return self.account.storage.borrow<auth(Register) &{IRegistry}>(from: path)
?? panic("Could not borrow FCMRegistry for pool \(forPool) from path \(path)")
}

/// Pool
///
Expand All @@ -666,7 +714,7 @@ access(all) contract FlowCreditMarket {
/// The actual reserves of each token
access(self) var reserves: @{Type: {FungibleToken.Vault}}
/// Auto-incrementing position identifier counter
access(self) var nextPositionID: UInt64
access(all) var nextPositionID: UInt64
/// The default token type used as the "unit of account" for the pool.
access(self) let defaultToken: Type
/// A price oracle that will return the price of each token in terms of the default token.
Expand Down Expand Up @@ -900,6 +948,23 @@ access(all) contract FlowCreditMarket {
)
}

/// Returns whether a given position exists in the pool
///
/// @param pid: The Position ID
///
/// @return Bool: True if the position exists, false otherwise
access(all) view fun positionExists(pid: UInt64): Bool {
return self.positions[pid] != nil
}

/// Returns the IDs of all positions in the pool
/// NOTE: This will likely need pagination to scale as the number of positions grows
///
/// @return [UInt64]: The IDs of all positions in the pool
access(all) view fun getPositionIDs(): [UInt64] {
return self.positions.keys
}

/// Returns the details of a given position as a PositionDetails external struct
access(all) fun getPositionDetails(pid: UInt64): PositionDetails {
if self.debugLogging { log(" [CONTRACT] getPositionDetails(pid: \(pid))") }
Expand All @@ -920,7 +985,7 @@ access(all) contract FlowCreditMarket {
))
}

let health = self.positionHealth(pid: pid)
let health: UFix128 = self.positionHealth(pid: pid)
Copy link
Member

Choose a reason for hiding this comment

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

Type can be inferred

Suggested change
let health: UFix128 = self.positionHealth(pid: pid)
let health = self.positionHealth(pid: pid)

let defaultTokenAvailable = self.availableBalance(pid: pid, type: self.defaultToken, pullFromTopUpSource: false)

return PositionDetails(
Expand Down Expand Up @@ -1676,7 +1741,7 @@ access(all) contract FlowCreditMarket {
withdrawType: Type,
effectiveCollateral: UFix128,
effectiveDebt: UFix128,
targetHealth: UFix128
targetHealth: UFix128
): UFix64 {
var effectiveCollateralAfterDeposit = effectiveCollateral
var effectiveDebtAfterDeposit = effectiveDebt
Expand Down Expand Up @@ -1894,6 +1959,12 @@ access(all) contract FlowCreditMarket {
from: <-funds,
pushToDrawDownSink: pushToDrawDownSink
)

// register the new position with the Pool's associated registry
let registry = FlowCreditMarket._borrowFCMRegistry(forPool: self.uuid)
// NOTE: rebalanceConfig allows for more granular recurring rebalance configuration per position in the future
registry.registerPosition(poolUUID: self.uuid, pid: id, rebalanceConfig: nil)

return id
}

Expand Down Expand Up @@ -2331,7 +2402,7 @@ access(all) contract FlowCreditMarket {
let sinkCapacity = drawDownSink.minimumCapacity()
let sinkAmount = (idealWithdrawal > sinkCapacity) ? sinkCapacity : idealWithdrawal

if sinkAmount > 0.0 && sinkType == Type<@MOET.Vault>() {
if sinkAmount > 0.0 && sinkType == Type<@MOET.Vault>() {
let tokenState = self._borrowUpdatedTokenState(type: Type<@MOET.Vault>())
if position.balances[Type<@MOET.Vault>()] == nil {
position.balances[Type<@MOET.Vault>()] = InternalBalance(direction: BalanceDirection.Credit, scaledBalance: 0.0 as UFix128)
Expand Down
Loading
Loading