DeploySEALED
?^█*▪▫!█●%■&▒@■▫╳╳◇&█╱●◆▫◆■^^?░~?&▫□%╲▪■□~╳!○╲~■●■~@○▒~$▫@$█◇◇●■
Transaction ID
Execution Fee
0.00000824 FLOWTransaction Summary
DeployContract deployment
Contract deployment
Script Arguments
0nameString
IncrementFiSwapperConnector
1codeString
import FungibleToken from 0xf233dcee88fe0abe
import DeFiActions from 0x17ae3b1b0b0d50db
import SwapRouter from 0xa6850776a94e6551
import SwapFactory from 0xb063c16cac85dbd1
/// IncrementFiSwapperConnector: FlowActions connector for Increment.fi DEX
///
/// Implements Swapper interface for atomic swaps on Increment.fi
///
/// SLIPPAGE PROTECTION: This connector returns RAW market data. Slippage protection
/// is enforced at the caller layer (DCAVaultActions.executePurchaseWithSwapper) which:
/// 1. Applies user-configured slippage tolerance to calculate minAmount
/// 2. Passes minAmount to swap() which enforces it via SwapRouter.swapExactTokensForTokens
/// 3. Validates actual slippage after execution against user's tolerance
///
/// This separation allows users to configure slippage per DCA plan, rather than
/// hardcoding a one-size-fits-all value in the connector.
///
/// Official Documentation: https://docs.increment.fi
///
access(all) contract IncrementFiSwapperConnector {
/// Events
access(all) event SwapExecuted(
fromToken: String,
toToken: String,
amountIn: UFix64,
amountOut: UFix64,
pairAddress: Address
)
/// IncrementFiSwapper resource implementing Swapper interface
access(all) resource IncrementFiSwapper: DeFiActions.Swapper {
access(all) let pairAddress: Address
access(all) let routerAddress: Address
access(all) let tokenKeyPath: [String] // Token identifiers for swap route
init(pairAddress: Address, routerAddress: Address, tokenKeyPath: [String]) {
self.pairAddress = pairAddress
self.routerAddress = routerAddress
self.tokenKeyPath = tokenKeyPath
}
/// Execute swap on Increment.fi with slippage protection
///
/// Uses SwapRouter.swapExactTokensForTokens to execute the swap.
/// SLIPPAGE PROTECTION: Enforced via quote.minAmount parameter, which is
/// calculated by the caller (DCAVaultActions) based on user's slippageTolerance.
/// The swap will revert if output < minAmount.
///
access(all) fun swap(
inVault: @{FungibleToken.Vault},
quote: DeFiActions.Quote
): @{FungibleToken.Vault} {
pre {
inVault.balance > 0.0: "Input vault must have balance"
quote.minAmount > 0.0: "Minimum amount must be positive"
quote.deadline != nil && quote.deadline! >= getCurrentBlock().timestamp: "Quote expired"
}
let amountIn = inVault.balance
let fromTokenType = inVault.getType().identifier
// Execute swap through Increment.fi SwapRouter
let outVault <- SwapRouter.swapExactTokensForTokens(
exactVaultIn: <-inVault,
amountOutMin: quote.minAmount,
tokenKeyPath: self.tokenKeyPath,
deadline: quote.deadline!
)
let amountOut = outVault.balance
let toTokenType = outVault.getType().identifier
// Emit swap event
emit SwapExecuted(
fromToken: fromTokenType,
toToken: toTokenType,
amountIn: amountIn,
amountOut: amountOut,
pairAddress: self.pairAddress
)
return <-outVault
}
/// Get quote for swap - Returns RAW market data
///
/// Queries Increment.fi SwapRouter for expected output amounts
/// based on current pool reserves.
///
/// SLIPPAGE PROTECTION DESIGN:
/// This connector returns RAW market data (minAmount = expectedAmount).
/// The CALLER is responsible for applying slippage protection by:
/// 1. Reading their desired slippageTolerance from DCA plan configuration
/// 2. Calculating: minAmount = expectedAmount * (1.0 - slippageTolerance)
/// 3. Creating an adjusted Quote with the calculated minAmount
/// 4. Passing that Quote to swap(), which enforces the minimum
///
/// This design allows users to configure different slippage tolerances per
/// DCA plan (e.g., 0.5% for stable pairs, 2% for volatile pairs).
///
access(all) fun getQuote(
fromTokenType: Type,
toTokenType: Type,
amount: UFix64
): DeFiActions.Quote {
// Query SwapRouter for expected amounts
let amounts = SwapRouter.getAmountsOut(
amountIn: amount,
tokenKeyPath: self.tokenKeyPath
)
// Last element is the expected output amount
let expectedAmount = amounts[amounts.length - 1]
// Return raw quote WITHOUT slippage applied
// Caller should calculate minAmount based on their slippage tolerance
// Example: minAmount = expectedAmount * (1.0 - slippageTolerance)
return DeFiActions.Quote(
expectedAmount: expectedAmount,
minAmount: expectedAmount, // No slippage - caller applies their own
slippageTolerance: 0.0, // Indicates no slippage applied by connector
deadline: getCurrentBlock().timestamp + 300.0, // 5 minutes default
data: {
"pairAddress": self.pairAddress.toString(),
"routerAddress": self.routerAddress.toString(),
"tokenPath": self.tokenKeyPath.length.toString()
}
)
}
/// Get swapper info
access(all) fun getInfo(): DeFiActions.ComponentInfo {
return DeFiActions.ComponentInfo(
type: "Swapper",
identifier: "IncrementFi",
version: "1.0.0"
)
}
}
/// Create IncrementFi swapper
///
/// @param pairAddress: Address of the trading pair
/// @param routerAddress: Address of SwapRouter contract
/// Mainnet: 0xa6850776a94e6551
/// Testnet: 0x2f8af5ed05bbde0d
/// @param tokenKeyPath: Array of token identifiers for swap route
/// Format: ["A.{address}.{ContractName}", ...]
/// Example: ["A.1654653399040a61.FlowToken", "A.f1ab99c82dee3526.USDCFlow"]
///
access(all) fun createSwapper(
pairAddress: Address,
routerAddress: Address,
tokenKeyPath: [String]
): @IncrementFiSwapper {
pre {
tokenKeyPath.length >= 2: "Token path must have at least 2 tokens"
}
return <- create IncrementFiSwapper(
pairAddress: pairAddress,
routerAddress: routerAddress,
tokenKeyPath: tokenKeyPath
)
}
/// Helper to verify pair exists
///
/// @param token0Key: First token identifier
/// @param token1Key: Second token identifier
/// @return Pair address if exists, nil otherwise
///
access(all) fun getPairAddress(token0Key: String, token1Key: String): Address? {
return SwapFactory.getPairAddress(token0Key: token0Key, token1Key: token1Key)
}
}
Cadence Script
1transaction(name: String, code: String ) {
2 prepare(signer: auth(AddContract) &Account) {
3 signer.contracts.add(name: name, code: code.utf8 )
4 }
5 }