DeploySEALED
#^▪$?▪█%○□█▓░●!▓□%╳◇*█◇#%*╲○■^╳~◆%#╲▪░▒#▒◇%$@▓○$&~$□@●○╳▪╳●!◆▓^&
Transaction ID
Execution Fee
0.00000599 FLOWTransaction Summary
DeployContract deployment
Contract deployment
Script Arguments
0nameString
IncrementFiFlashloanConnectors
1codeString
import FungibleToken from 0xf233dcee88fe0abe
import DeFiActions from 0x6d888f175c158410
import SwapInterfaces from 0xb78ef7afa52ff906
import SwapConfig from 0xb78ef7afa52ff906
import SwapFactory from 0xb063c16cac85dbd1
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/// THIS CONTRACT IS IN BETA AND IS NOT FINALIZED - INTERFACES MAY CHANGE AND/OR PENDING CHANGES MAY REQUIRE REDEPLOYMENT
/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
///
/// IncrementFiFlashloanConnectors
///
/// DeFiActions adapter implementations fitting IncrementFi protocols to the DeFiActions Flasher interface.
///
access(all) contract IncrementFiFlashloanConnectors {
/// Canonical path in which to store the generic FlashLoanExecutor resource
access(all) let ExecutorStoragePath: StoragePath
/* --- CONSTRUCTS --- */
/// Flasher
///
/// A DeFiActions connector that performs flash loans using IncrementFi's SwapPair contract
///
access(all) struct Flasher : DeFiActions.Flasher {
/// The address of the SwapPair contract to use for flash loans
access(all) let pairAddress: Address
/// The type of token to borrow
access(all) let type: Type
/// Capability to the FlashLoanExecutor resource
access(self) let executor: Capability<&{SwapInterfaces.FlashLoanExecutor}>
/// 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?
init(
pairAddress: Address,
type: Type,
executor: Capability<&{SwapInterfaces.FlashLoanExecutor}>,
uniqueID: DeFiActions.UniqueIdentifier?
) {
pre {
executor.check(): "Invalid SwapInterfaces.FlashLoanExecutor capability provided"
}
let pair = getAccount(pairAddress).capabilities.borrow<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath)
?? panic("Could not reference SwapPair public capability at address \(pairAddress)")
let pairInfo = pair.getPairInfoStruct()
assert(pairInfo.token0Key == type.identifier || pairInfo.token1Key == type.identifier,
message: "Provided type is not supported by the SwapPair at address \(pairAddress) - "
.concat("valid types for this SwapPair are \(pairInfo.token0Key) and \(pairInfo.token1Key)"))
self.pairAddress = pairAddress
self.type = type
self.executor = executor
self.uniqueID = uniqueID
}
/// Returns a ComponentInfo struct containing information about this Flasher and its inner DFA components
///
/// @return a ComponentInfo struct containing information about this component and a list of ComponentInfo for
/// each inner component in the stack.
///
access(all) fun getComponentInfo(): DeFiActions.ComponentInfo {
return DeFiActions.ComponentInfo(
type: self.getType(),
id: self.id(),
innerComponents: []
)
}
/// Returns a copy of the struct's UniqueIdentifier, used in extending a stack to identify another connector in
/// a DeFiActions stack. See DeFiActions.align() for more information.
///
/// @return a copy of the struct's UniqueIdentifier
///
access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? {
return self.uniqueID
}
/// Sets the UniqueIdentifier of this component to the provided UniqueIdentifier, used in extending a stack to
/// identify another connector in a DeFiActions stack. See DeFiActions.align() for more information.
///
/// @param id: the UniqueIdentifier to set for this component
///
access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) {
self.uniqueID = id
}
/// Returns the asset type this Flasher can issue as a flash loan
///
/// @return the type of token this Flasher can issue as a flash loan
///
access(all) view fun borrowType(): Type {
return self.type
}
/// Returns the estimated fee for a flash loan of the specified amount
///
/// @param loanAmount: The amount of tokens to borrow
/// @return the estimated fee for a flash loan of the specified amount
///
access(all) fun calculateFee(loanAmount: UFix64): UFix64 {
return UFix64(SwapFactory.getFlashloanRateBps()) * loanAmount / 10000.0
}
/// Performs a flash loan of the specified amount. The callback function is passed the fee amount, a Vault
/// containing the loan, and the data. The callback function should return a Vault containing the loan + fee.
///
/// @param amount: The amount of tokens to borrow
/// @param data: Optional data to pass to the callback function
/// @param callback: The callback function to use for the flash loan
///
access(all) fun flashLoan(
amount: UFix64,
data: AnyStruct?,
callback: fun(UFix64, @{FungibleToken.Vault}, AnyStruct?): @{FungibleToken.Vault} // fee, loan, data
) {
// get the SwapPair public capability on which to perform the flash loan
let pair = getAccount(self.pairAddress).capabilities.borrow<&{SwapInterfaces.PairPublic}>(
SwapConfig.PairPublicPath
) ?? panic("Could not reference SwapPair public capability at address \(self.pairAddress)")
// cast data to expected params type and add fee and callback to params for the callback function
let params = data as! {String: AnyStruct}? ?? {}
params["fee"] = self.calculateFee(loanAmount: amount)
params["callback"] = callback
// perform the flash loan
pair.flashloan(
executor: self._borrowExecutor(),
requestedTokenVaultType: self.type,
requestedAmount: amount,
params: params
)
}
/// Returns a reference to the FlashLoanExecutor capability
///
/// @return a reference to the FlashLoanExecutor capability
///
access(self) fun _borrowExecutor(): &{SwapInterfaces.FlashLoanExecutor} {
return self.executor.borrow() ?? panic("Could not borrow FlashLoanExecutor capability")
}
}
/// FlashLoanExecutor
///
/// A resource that implements the SwapInterfaces.FlashLoanExecutor interface and is used to execute flash loans.
/// This resource is required to in order to execute flash loans on IncrementFi's SwapPair contract, but is made
/// generically to be used in conjunction with the Flasher DeFiActions connector defined in this contract. Instead
/// of statically declaring the logic within the Executor's executeAndRepay() function, the callback function is
/// passed as a parameter to the executeAndRepay() function via the params object indexed by "callback".
///
access(all) resource Executor : SwapInterfaces.FlashLoanExecutor {
/// Performs a flash loan of the specified amount. The Flasher.flashLoan() callback function should be found in
/// the params object passed to this function under the key "callback". The callback function is passed the fee
/// amount, a Vault containing the loan, and the data. The callback function should return a Vault containing
/// the loan + fee.
access(all) fun executeAndRepay(loanedToken: @{FungibleToken.Vault}, params: {String: AnyStruct}): @{FungibleToken.Vault} {
// cast params to expected types and execute the callback
let fee = params.remove(key: "fee") as? UFix64 ?? panic("No fee provided in params to executeAndRepay")
let callback = params.remove(key: "callback") as? fun(UFix64, @{FungibleToken.Vault}, AnyStruct?): @{FungibleToken.Vault}
?? panic("No callback function provided in params to executeAndRepay")
// execute the callback logic
let repaidToken <- callback(fee, <-loanedToken, params)
// return the repaid token
return <- repaidToken
}
}
/* --- PUBLIC FUNCTIONS --- */
/// Creates a new FlashLoanExecutor resource
///
/// @return a new FlashLoanExecutor resource
///
access(all) fun createExecutor(): @Executor {
return <- create Executor()
}
init() {
self.ExecutorStoragePath = StoragePath(identifier: "IncrementFiFlashloanConnectorsExecutor_\(self.account.address)")!
}
}
Cadence Script
1transaction(name: String, code: String ) {
2 prepare(signer: auth(AddContract) &Account) {
3 signer.contracts.add(name: name, code: code.utf8 )
4 }
5 }