From f6dac4b6e475a236b73596ccf0e8de4a7b6e84fb Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sat, 30 Dec 2023 18:41:49 -0300 Subject: [PATCH 01/29] Route WETH<->USDC swaps through Uniswap --- .../abi/Uniswap/UniswapV3QuoterV2.json | 1 + .../abi/Uniswap/UniswapV3Router.json | 1 + projects/sdk/src/constants/addresses.ts | 6 ++ projects/sdk/src/lib/contracts.ts | 13 ++++ projects/sdk/src/lib/farm/LibraryPresets.ts | 47 +++++++++++ .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 78 +++++++++++++++++++ projects/sdk/src/lib/farm/actions/index.ts | 6 +- projects/sdk/src/lib/swap/graph.ts | 30 +++++++ 8 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 projects/sdk/src/constants/abi/Uniswap/UniswapV3QuoterV2.json create mode 100644 projects/sdk/src/constants/abi/Uniswap/UniswapV3Router.json create mode 100644 projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts diff --git a/projects/sdk/src/constants/abi/Uniswap/UniswapV3QuoterV2.json b/projects/sdk/src/constants/abi/Uniswap/UniswapV3QuoterV2.json new file mode 100644 index 0000000000..b68835015e --- /dev/null +++ b/projects/sdk/src/constants/abi/Uniswap/UniswapV3QuoterV2.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"quoteExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactInputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"quoteExactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160[]","name":"sqrtPriceX96AfterList","type":"uint160[]"},{"internalType":"uint32[]","name":"initializedTicksCrossedList","type":"uint32[]"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct IQuoterV2.QuoteExactOutputSingleParams","name":"params","type":"tuple"}],"name":"quoteExactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceX96After","type":"uint160"},{"internalType":"uint32","name":"initializedTicksCrossed","type":"uint32"},{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"path","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"view","type":"function"}] diff --git a/projects/sdk/src/constants/abi/Uniswap/UniswapV3Router.json b/projects/sdk/src/constants/abi/Uniswap/UniswapV3Router.json new file mode 100644 index 0000000000..7946192319 --- /dev/null +++ b/projects/sdk/src/constants/abi/Uniswap/UniswapV3Router.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"internalType":"struct ISwapRouter.ExactInputParams","name":"params","type":"tuple"}],"name":"exactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct ISwapRouter.ExactInputSingleParams","name":"params","type":"tuple"}],"name":"exactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct ISwapRouter.ExactOutputParams","name":"params","type":"tuple"}],"name":"exactOutput","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct ISwapRouter.ExactOutputSingleParams","name":"params","type":"tuple"}],"name":"exactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"refundETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowed","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitAllowedIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"selfPermitIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"sweepTokenWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"unwrapWETH9","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"feeBips","type":"uint256"},{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"unwrapWETH9WithFee","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}] diff --git a/projects/sdk/src/constants/addresses.ts b/projects/sdk/src/constants/addresses.ts index bcc866454c..d854dd5dd1 100644 --- a/projects/sdk/src/constants/addresses.ts +++ b/projects/sdk/src/constants/addresses.ts @@ -105,6 +105,12 @@ export const addresses = { // zap CURVE_ZAP: Address.make("0xA79828DF1850E8a3A3064576f380D90aECDD3359"), + // Uniswap V3 Router + UNISWAP_V3_ROUTER: Address.make("0xE592427A0AEce92De3Edee1F18E0157C05861564"), + + // Uniswap V3 Quoter V2 + UNISWAP_V3_QUOTER_V2: Address.make("0x61fFE014bA17989E743c5F6cB21bF9697530B21e"), + // BEAN_ETH_UNIV2_LP !! Deprecated BEAN_ETH_UNIV2_LP: Address.make("0x87898263B6C5BABe34b4ec53F22d98430b91e371"), diff --git a/projects/sdk/src/lib/contracts.ts b/projects/sdk/src/lib/contracts.ts index b27d281786..f1beae668d 100644 --- a/projects/sdk/src/lib/contracts.ts +++ b/projects/sdk/src/lib/contracts.ts @@ -30,6 +30,10 @@ import { Math__factory, UsdOracle, UsdOracle__factory, + UniswapV3Router__factory, + UniswapV3Router, + UniswapV3QuoterV2__factory, + UniswapV3QuoterV2, } from "src/constants/generated"; import { BaseContract } from "ethers"; @@ -64,6 +68,9 @@ export class Contracts { public readonly curve: CurveContracts; + public readonly uniswapV3Router: UniswapV3Router; + public readonly uniswapV3QuoterV2: UniswapV3QuoterV2; + // private chain: string; constructor(sdk: BeanstalkSDK) { @@ -88,6 +95,9 @@ export class Contracts { const cryptoFactoryAddress = sdk.addresses.CRYPTO_FACTORY.get(sdk.chainId); const zapAddress = sdk.addresses.CURVE_ZAP.get(sdk.chainId); + const uniswapV3RouterAddress = sdk.addresses.UNISWAP_V3_ROUTER.get(sdk.chainId); + const uniswapV3QuoterV2Address = sdk.addresses.UNISWAP_V3_QUOTER_V2.get(sdk.chainId); + // Instances this.beanstalk = Beanstalk__factory.connect(beanstalkAddress, sdk.providerOrSigner); this.beanstalkPrice = BeanstalkPrice__factory.connect(beanstalkPriceAddress, sdk.providerOrSigner); @@ -107,6 +117,9 @@ export class Contracts { const cryptoFactory = CurveCryptoFactory__factory.connect(cryptoFactoryAddress, sdk.providerOrSigner); const zap = CurveZap__factory.connect(zapAddress, sdk.providerOrSigner); + this.uniswapV3Router = UniswapV3Router__factory.connect(uniswapV3RouterAddress, sdk.providerOrSigner); + this.uniswapV3QuoterV2 = UniswapV3QuoterV2__factory.connect(uniswapV3QuoterV2Address, sdk.providerOrSigner); + this.curve = { pools: { beanCrv3, diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index ae501f24e4..7b82859ca4 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -43,6 +43,8 @@ export class LibraryPresets { public readonly usdt2beaneth; public readonly dai2beaneth; + public readonly uniswapV3Swap; + /** * Load the Pipeline in preparation for a set Pipe actions. * @param _permit provide a permit directly, or provide a function to extract it from `context`. @@ -339,5 +341,50 @@ export class LibraryPresets { return result; }; + + this.uniswapV3Swap = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { + const result = []; + const advancedPipe = sdk.farm.createAdvancedPipe("uniswapV3Swap"); + + const transferBack = to === FarmToMode.INTERNAL; + const recipient = transferBack ? sdk.contracts.pipeline.address : account; + + // Transfer fromToken to Pipeline + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, from, FarmToMode.EXTERNAL); + + // Approve Uniswap V3 to use fromToken + const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); + + // Swap tokens + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, toToken, recipient); + + // This approves the transferToBeanstalk operation. + const approveClipboard = { + tag: "uniswapV3Swap", + copySlot: 0, + pasteSlot: 1 + } + const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, approveClipboard); + + // Transfers the output token back to Beanstalk, from PIPELINE. + const transferClipboard = { + tag: "uniswapV3Swap", + copySlot: 0, + pasteSlot: 2 + } + const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + + result.push(transfer); + advancedPipe.add(approveUniswap); + advancedPipe.add(swap, { tag: "uniswapV3Swap" }); + if (transferBack) { + advancedPipe.add(approveBack); + advancedPipe.add(transferToBeanstalk); + } + + result.push(advancedPipe); + + return result; + }; } } diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts new file mode 100644 index 0000000000..ee610f2fbd --- /dev/null +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -0,0 +1,78 @@ +import { BigNumberish, BigNumber, ethers } from "ethers"; +import { RunContext, RunMode, StepClass, Workflow } from "src/classes/Workflow"; +import { Token } from "src/classes/Token"; +import { AdvancedPipePreparedResult } from "src/lib/depot/pipe"; +import { FarmFromMode, FarmToMode } from "../types"; +import { deadlineSecondsToBlockchain } from "src/utils"; +import { TokenValue } from "@beanstalk/sdk-core"; + +export class UniswapV3Swap extends StepClass { + public name: string = "uniswapV3Swap"; + private transactionDeadline: BigNumberish; + + constructor( + public readonly tokenIn: Token, + public readonly tokenOut: Token, + public readonly recipient: string, + public readonly deadline?: number, + ) { + super(); + this.transactionDeadline = deadline ? deadlineSecondsToBlockchain(deadline) : TokenValue.MAX_UINT256.toBlockchain(); + } + + async run(_amountInStep: ethers.BigNumber, context: RunContext) { + const [tokenIn, tokenOut] = Workflow.direction( + this.tokenIn, + this.tokenOut, + context.runMode !== RunMode.EstimateReversed // _forward + ); + const reversed = context.runMode === RunMode.EstimateReversed; + + const quoter = UniswapV3Swap.sdk.contracts.uniswapV3QuoterV2; + + let estimate: any; + if (reversed) { + estimate = await quoter.callStatic.quoteExactOutputSingle({ + tokenIn: tokenIn.address, + tokenOut: tokenOut.address, + amount: _amountInStep, + fee: 500, + sqrtPriceLimitX96: 0, + }); + } else { + estimate = await quoter.callStatic.quoteExactInputSingle({ + tokenIn: tokenIn.address, + tokenOut: tokenOut.address, + amountIn: _amountInStep, + fee: 500, + sqrtPriceLimitX96: 0, + }); + }; + + + return { + name: this.name, + amountOut: estimate[0], + prepare: () => { + if (context.data.slippage === undefined) throw new Error("Exchange: slippage required"); + const minAmountOut = Workflow.slip(estimate[0], context.data.slippage); + if (!minAmountOut) throw new Error("Exhange: missing minAmountOut"); + return { + target: UniswapV3Swap.sdk.contracts.uniswapV3Router.address, + callData: UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactInputSingle", [{ + tokenIn: tokenIn.address, + tokenOut: tokenOut.address, + fee: 500, + recipient: this.recipient, + deadline: this.transactionDeadline, + amountIn: _amountInStep, + amountOutMinimum: minAmountOut, + sqrtPriceLimitX96: 0 + }]) + }; + }, + decode: (data: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionData("exactInputSingle", data), + decodeResult: (result: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionResult("exactInputSingle", result) + }; + } +} diff --git a/projects/sdk/src/lib/farm/actions/index.ts b/projects/sdk/src/lib/farm/actions/index.ts index 803bde6fed..2e4879a90d 100644 --- a/projects/sdk/src/lib/farm/actions/index.ts +++ b/projects/sdk/src/lib/farm/actions/index.ts @@ -16,7 +16,8 @@ import { ExchangeUnderlying } from "./ExchangeUnderlying"; import { RemoveLiquidityOneToken } from "./RemoveLiquidityOneToken"; import { WellSwap } from "./WellSwap"; import { WellShift } from "./WellShift"; -import { WellSync } from "./WellSync"; +import { WellSync } from "./WellSync"; +import { UniswapV3Swap } from "./UniswapV3Swap"; import { DevDebug } from "./_DevDebug"; export { @@ -51,6 +52,9 @@ export { WellShift, WellSync, + // DEX: Uniswap V3 + UniswapV3Swap, + // Developers DevDebug }; diff --git a/projects/sdk/src/lib/swap/graph.ts b/projects/sdk/src/lib/swap/graph.ts index 736db459eb..0a6ded0460 100644 --- a/projects/sdk/src/lib/swap/graph.ts +++ b/projects/sdk/src/lib/swap/graph.ts @@ -124,6 +124,36 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { to: "BEAN" }); + // USDC<>WETH via Uniswap V3 + graph.setEdge("USDC", "WETH", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, from, to), + from: "USDC", + to: "WETH" + }); + + graph.setEdge("WETH", "USDC", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.USDC, account, from, to), + from: "WETH", + to: "USDC" + }); + + // DAI<>WETH via Uniswap V3 + graph.setEdge("DAI", "WETH", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, from, to), + from: "DAI", + to: "WETH" + }); + + graph.setEdge("WETH", "DAI", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.DAI, account, from, to), + from: "WETH", + to: "DAI" + }); + /// 3CRV<>Stables via 3Pool Add/Remove Liquidity // HEADS UP: the ordering of these tokens needs to match their indexing in the 3CRV LP token. From d57231341cd1450f533bf3faa4304e548e47b90d Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:10:24 -0300 Subject: [PATCH 02/29] Removed exact output quote, cleaned up debug msgs --- projects/sdk/src/classes/Workflow.ts | 8 +++--- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 25 ++++++------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index 5a5421b216..3b0b3f8329 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -287,7 +287,7 @@ export abstract class Workflow< this.add(elem, options); // recurse } } else { - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`); + if (input instanceof StepClass) { input.setSDK(Workflow.sdk); } @@ -298,14 +298,14 @@ export abstract class Workflow< switch (input.name) { case "pipelineDeposit": pipelineOptions = { tag: `deposit${filteredOptions.length + 1}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] pipelineOptions: `, pipelineOptions); + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineBeanWethSwap": pipelineOptions = { tag: `beanWethSwap${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] pipelineOptions: `, pipelineOptions); + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; default: - Workflow.sdk.debug(`[Workflow][${this.name}][add] Not a bundle of Pipeline operations`); + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`); } this._generators.push(input); diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index ee610f2fbd..8715be9a74 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -31,24 +31,13 @@ export class UniswapV3Swap extends StepClass { const quoter = UniswapV3Swap.sdk.contracts.uniswapV3QuoterV2; let estimate: any; - if (reversed) { - estimate = await quoter.callStatic.quoteExactOutputSingle({ - tokenIn: tokenIn.address, - tokenOut: tokenOut.address, - amount: _amountInStep, - fee: 500, - sqrtPriceLimitX96: 0, - }); - } else { - estimate = await quoter.callStatic.quoteExactInputSingle({ - tokenIn: tokenIn.address, - tokenOut: tokenOut.address, - amountIn: _amountInStep, - fee: 500, - sqrtPriceLimitX96: 0, - }); - }; - + estimate = await quoter.callStatic.quoteExactInputSingle({ + tokenIn: tokenIn.address, + tokenOut: tokenOut.address, + amountIn: _amountInStep, + fee: 500, + sqrtPriceLimitX96: 0, + }); return { name: this.name, From fba676fe2cb605ceb2183f1ef8cf775f3c625ca0 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Thu, 4 Jan 2024 23:02:07 -0300 Subject: [PATCH 03/29] Tag cleanup --- projects/sdk/src/classes/Workflow.ts | 4 ++++ projects/sdk/src/lib/farm/LibraryPresets.ts | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index 3b0b3f8329..3ebb364948 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -304,6 +304,10 @@ export abstract class Workflow< pipelineOptions = { tag: `beanWethSwap${filteredOptions.length}Amount` }; Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; + case "pipelineUniswapV3Swap": + pipelineOptions = { tag: `uniswapV3Swap${filteredOptions.length}Amount` }; + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); + break; default: Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`); } diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 7b82859ca4..12b9c7c04f 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -344,7 +344,7 @@ export class LibraryPresets { this.uniswapV3Swap = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { const result = []; - const advancedPipe = sdk.farm.createAdvancedPipe("uniswapV3Swap"); + const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniswapV3Swap"); const transferBack = to === FarmToMode.INTERNAL; const recipient = transferBack ? sdk.contracts.pipeline.address : account; @@ -360,7 +360,7 @@ export class LibraryPresets { // This approves the transferToBeanstalk operation. const approveClipboard = { - tag: "uniswapV3Swap", + tag: "uniV3SwapAmount", copySlot: 0, pasteSlot: 1 } @@ -368,7 +368,7 @@ export class LibraryPresets { // Transfers the output token back to Beanstalk, from PIPELINE. const transferClipboard = { - tag: "uniswapV3Swap", + tag: "uniV3SwapAmount", copySlot: 0, pasteSlot: 2 } @@ -376,7 +376,7 @@ export class LibraryPresets { result.push(transfer); advancedPipe.add(approveUniswap); - advancedPipe.add(swap, { tag: "uniswapV3Swap" }); + advancedPipe.add(swap, { tag: "uniV3SwapAmount" }); if (transferBack) { advancedPipe.add(approveBack); advancedPipe.add(transferToBeanstalk); From 23ecd37787114c779583ec4fd6a63536e98a7779 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:11:54 -0300 Subject: [PATCH 04/29] cleanup, simplify --- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 1 - projects/sdk/src/lib/swap/Swap.ts | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index 8715be9a74..8e01cbd4fc 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -26,7 +26,6 @@ export class UniswapV3Swap extends StepClass { this.tokenOut, context.runMode !== RunMode.EstimateReversed // _forward ); - const reversed = context.runMode === RunMode.EstimateReversed; const quoter = UniswapV3Swap.sdk.contracts.uniswapV3QuoterV2; diff --git a/projects/sdk/src/lib/swap/Swap.ts b/projects/sdk/src/lib/swap/Swap.ts index 1fc51620ae..1423bdbabd 100644 --- a/projects/sdk/src/lib/swap/Swap.ts +++ b/projects/sdk/src/lib/swap/Swap.ts @@ -35,11 +35,18 @@ export class Swap { let useAdvancedFarm = false; for (let i = 0; i < route.length; i++) { - if (route.getStep(i - 1)) { - if (route.getStep(i - 1).from === "BEAN" && route.getStep(i - 1).to === "WETH" && - route.getStep(i).from === "WETH" && route.getStep(i).to === "ETH") { - useAdvancedFarm = true; - break; + const from = route.getStep(i).from; + const to = route.getStep(i).to; + + if (from === "WETH") { + if (to === "USDC" || to === "DAI" || to === "BEAN") { + useAdvancedFarm = true; + break; + }; + } else if (from === "USDC" || from === "DAI" || from === "BEAN") { + if (to === "WETH") { + useAdvancedFarm = true; + break; }; }; }; From fc3b8b11c0e41dc40f6813dd8dc3c7e3f44fdbc9 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sun, 7 Jan 2024 00:26:57 -0300 Subject: [PATCH 05/29] add clipboard --- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index 8e01cbd4fc..89c9afc0db 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -1,10 +1,11 @@ -import { BigNumberish, BigNumber, ethers } from "ethers"; +import { BigNumberish, ethers } from "ethers"; import { RunContext, RunMode, StepClass, Workflow } from "src/classes/Workflow"; import { Token } from "src/classes/Token"; import { AdvancedPipePreparedResult } from "src/lib/depot/pipe"; -import { FarmFromMode, FarmToMode } from "../types"; import { deadlineSecondsToBlockchain } from "src/utils"; import { TokenValue } from "@beanstalk/sdk-core"; +import { Clipboard } from "src/lib/depot"; +import { ClipboardSettings } from "src/types"; export class UniswapV3Swap extends StepClass { public name: string = "uniswapV3Swap"; @@ -15,6 +16,7 @@ export class UniswapV3Swap extends StepClass { public readonly tokenOut: Token, public readonly recipient: string, public readonly deadline?: number, + public clipboard?: ClipboardSettings ) { super(); this.transactionDeadline = deadline ? deadlineSecondsToBlockchain(deadline) : TokenValue.MAX_UINT256.toBlockchain(); @@ -27,10 +29,23 @@ export class UniswapV3Swap extends StepClass { context.runMode !== RunMode.EstimateReversed // _forward ); + if (!this.clipboard) { + const pipelineBeanWethSwapIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + // If the action before (happens when reverse estimating) or after this one is a BEAN -> WETH swap through Pipeline... + if (pipelineBeanWethSwapIndex >= 0 && Math.abs(pipelineBeanWethSwapIndex - context.step.index) === 1) { + // We use clipboard... + this.clipboard = { + // Then find the correct tag in the tag map + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineBeanWethSwapIndex)!, + copySlot: 9, + pasteSlot: 5 + }; + }; + }; + const quoter = UniswapV3Swap.sdk.contracts.uniswapV3QuoterV2; - - let estimate: any; - estimate = await quoter.callStatic.quoteExactInputSingle({ + + const estimate = await quoter.callStatic.quoteExactInputSingle({ tokenIn: tokenIn.address, tokenOut: tokenOut.address, amountIn: _amountInStep, @@ -44,6 +59,7 @@ export class UniswapV3Swap extends StepClass { prepare: () => { if (context.data.slippage === undefined) throw new Error("Exchange: slippage required"); const minAmountOut = Workflow.slip(estimate[0], context.data.slippage); + const sqrtPriceX96After = estimate[1]; if (!minAmountOut) throw new Error("Exhange: missing minAmountOut"); return { target: UniswapV3Swap.sdk.contracts.uniswapV3Router.address, @@ -55,8 +71,9 @@ export class UniswapV3Swap extends StepClass { deadline: this.transactionDeadline, amountIn: _amountInStep, amountOutMinimum: minAmountOut, - sqrtPriceLimitX96: 0 - }]) + sqrtPriceLimitX96: sqrtPriceX96After + }]), + clipboard: this.clipboard ? Clipboard.encodeSlot(context.step.findTag(this.clipboard.tag), this.clipboard.copySlot, this.clipboard.pasteSlot) : undefined }; }, decode: (data: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionData("exactInputSingle", data), From 0c82cf9f25ec8bdad6355c34afdf3813bc4bfaef Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sun, 7 Jan 2024 12:48:52 -0300 Subject: [PATCH 06/29] update deposit graph --- projects/sdk/src/lib/silo/depositGraph.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/projects/sdk/src/lib/silo/depositGraph.ts b/projects/sdk/src/lib/silo/depositGraph.ts index 9130050db4..9e5d666cae 100644 --- a/projects/sdk/src/lib/silo/depositGraph.ts +++ b/projects/sdk/src/lib/silo/depositGraph.ts @@ -230,17 +230,19 @@ export const getDepositGraph = (sdk: BeanstalkSDK): Graph => { }); graph.setEdge("USDC", "WETH", { - build: (_: string, from: FarmFromMode, to: FarmToMode) => sdk.farm.presets.usdc2weth(from, to), + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, from, to), from: "USDC", to: "WETH", - label: "exchange" + label: "uniswapV3Swap" }); graph.setEdge("DAI", "WETH", { - build: (_: string, from: FarmFromMode, to: FarmToMode) => sdk.farm.presets.dai2weth(from, to), + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, from, to), from: "DAI", to: "WETH", - label: "exchange" + label: "uniswapV3Swap" }); } From 585b350f0e087b5d5e9250246125d6b1ad2a228c Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sun, 7 Jan 2024 13:54:06 -0300 Subject: [PATCH 07/29] update deposit presets --- projects/sdk/src/lib/farm/LibraryPresets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 12b9c7c04f..1add2d3c52 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -230,7 +230,7 @@ export class LibraryPresets { ///////// [ USDC, USDT, DAI ] -> BEANETH /////////// this.usdc2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.usdc2weth(fromMode, FarmToMode.INTERNAL) as StepGenerator, + this.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, fromMode, FarmToMode.INTERNAL), this.wellAddLiquidity(well, sdk.tokens.WETH, account, FarmFromMode.INTERNAL, toMode) ]; @@ -240,7 +240,7 @@ export class LibraryPresets { ]; this.dai2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.dai2weth(fromMode, FarmToMode.INTERNAL) as StepGenerator, + this.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.DAI, account, fromMode, FarmToMode.INTERNAL), this.wellAddLiquidity(well, sdk.tokens.WETH, account, FarmFromMode.INTERNAL, toMode) ]; From 5023df62bdda182fa82a8a49c2554d2fd10b16cf Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sun, 7 Jan 2024 15:40:48 -0300 Subject: [PATCH 08/29] update deposit workflow --- projects/sdk/src/classes/Workflow.ts | 6 ++- projects/sdk/src/lib/farm/LibraryPresets.ts | 51 ++++++++++++++++++-- projects/sdk/src/lib/farm/actions/Deposit.ts | 24 ++++++--- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index 3ebb364948..7aa30fa68f 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -297,7 +297,11 @@ export abstract class Workflow< switch (input.name) { case "pipelineDeposit": - pipelineOptions = { tag: `deposit${filteredOptions.length + 1}Amount` }; + pipelineOptions = { tag: `deposit${filteredOptions.length}Amount` }; + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); + break; + case "pipelineUniV3Deposit": + pipelineOptions = { tag: `depositUniV3${filteredOptions.length}Amount` }; Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineBeanWethSwap": diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 1add2d3c52..43b30d6f80 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -44,6 +44,7 @@ export class LibraryPresets { public readonly dai2beaneth; public readonly uniswapV3Swap; + public readonly uniV3AddLiquidity; /** * Load the Pipeline in preparation for a set Pipe actions. @@ -230,8 +231,7 @@ export class LibraryPresets { ///////// [ USDC, USDT, DAI ] -> BEANETH /////////// this.usdc2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, fromMode, FarmToMode.INTERNAL), - this.wellAddLiquidity(well, sdk.tokens.WETH, account, FarmFromMode.INTERNAL, toMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.USDC, fromMode) ]; this.usdt2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ @@ -240,8 +240,7 @@ export class LibraryPresets { ]; this.dai2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.DAI, account, fromMode, FarmToMode.INTERNAL), - this.wellAddLiquidity(well, sdk.tokens.WETH, account, FarmFromMode.INTERNAL, toMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, fromMode) ]; this.wellWethBean = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { @@ -386,5 +385,49 @@ export class LibraryPresets { return result; }; + + this.uniV3AddLiquidity = (well: BasinWell, account: string, tokenIn: ERC20Token, fromMode?: FarmFromMode) => { + const result = []; + const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3Deposit"); + + // Transfer USDC to Pipeline + const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + + // Approve Uniswap V3 to use fromToken + const approveUniswap = new sdk.farm.actions.ApproveERC20(tokenIn, sdk.contracts.uniswapV3Router.address); + + // Swap tokens, output result to Well + const swap = new sdk.farm.actions.UniswapV3Swap(tokenIn, sdk.tokens.WETH, well.address); + + // Call sync on Well, send output back to Pipeline + const addLiquidity = new sdk.farm.actions.WellSync(well, sdk.tokens.WETH, sdk.contracts.pipeline.address); + + // This approves the transferToBeanstalk operation. + const approveClipboard = { + tag: "amountToDeposit", + copySlot: 0, + pasteSlot: 1 + } + const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); + + // Transfers the output token back to Beanstalk, from Pipeline. + const transferClipboard = { + tag: "amountToDeposit", + copySlot: 0, + pasteSlot: 2 + } + const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + + result.push(transfer); + + advancedPipe.add(approveUniswap); + advancedPipe.add(swap); + advancedPipe.add(addLiquidity, { tag: "amountToDeposit" }); + advancedPipe.add(approveBack); + advancedPipe.add(transferToBeanstalk); + + result.push(advancedPipe); + return result; + }; } } diff --git a/projects/sdk/src/lib/farm/actions/Deposit.ts b/projects/sdk/src/lib/farm/actions/Deposit.ts index d6b1d41073..a5fd4eb32a 100644 --- a/projects/sdk/src/lib/farm/actions/Deposit.ts +++ b/projects/sdk/src/lib/farm/actions/Deposit.ts @@ -21,13 +21,25 @@ export class Deposit extends StepClass { async run(_amountInStep: ethers.BigNumber, context: RunContext) { // Checking if the user isn't directly depositing BEANETH const indirectBeanEth = this.token.symbol === "BEANETH" && context.step.index > 0; - const beanEthClipboard = { - tag: `deposit${context.step.index}Amount`, - copySlot: 6, - pasteSlot: 1 + + const pipeDepositIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + const pipeUniDepositIndex = context.steps.findIndex(step => step.name === "pipelineUniV3Deposit"); + + if (indirectBeanEth && !this.clipboard) { + if (pipeDepositIndex > 0) { + this.clipboard = { + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeDepositIndex)!, + copySlot: 6, + pasteSlot: 1 + }; + } else if (pipeUniDepositIndex > 0) { + this.clipboard = { + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeUniDepositIndex)!, + copySlot: 12, + pasteSlot: 1 + }; + }; }; - - if (indirectBeanEth && !this.clipboard) this.clipboard = beanEthClipboard; return { name: this.name, From 03a6b01f87bac76214b51afc2e1ce5a52cd62f3c Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sun, 7 Jan 2024 20:37:00 -0300 Subject: [PATCH 09/29] condense univ3 and well swap steps --- projects/sdk/src/classes/Workflow.ts | 8 ++ projects/sdk/src/lib/farm/LibraryPresets.ts | 113 ++++++++++++++++++++ projects/sdk/src/lib/swap/Swap.ts | 9 +- projects/sdk/src/lib/swap/graph.ts | 30 ++++++ 4 files changed, 158 insertions(+), 2 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index 7aa30fa68f..a64f3e68e0 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -312,6 +312,14 @@ export abstract class Workflow< pipelineOptions = { tag: `uniswapV3Swap${filteredOptions.length}Amount` }; Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; + case "pipelineUniV3WellSwap": + pipelineOptions = { tag: `uniV3WellSwap${filteredOptions.length}Amount` }; + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); + break; + case "pipelineWellSwapUniV3": + pipelineOptions = { tag: `wellSwapUniV3${filteredOptions.length}Amount` }; + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); + break; default: Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`); } diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 43b30d6f80..708c763837 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -45,6 +45,8 @@ export class LibraryPresets { public readonly uniswapV3Swap; public readonly uniV3AddLiquidity; + public readonly uniV3WellSwap; + public readonly wellSwapUniV3; /** * Load the Pipeline in preparation for a set Pipe actions. @@ -429,5 +431,116 @@ export class LibraryPresets { result.push(advancedPipe); return result; }; + + this.uniV3WellSwap = (well: BasinWell, account: string, tokenIn: ERC20Token, tokenOut: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + const result = []; + const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3WellSwap"); + + const transferBack = toMode === FarmToMode.INTERNAL; + const recipient = transferBack ? sdk.contracts.pipeline.address : account; + + // Transfer Input Token to Pipeline + const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + + // Approve Uniswap V3 to use fromToken + const approveUniswap = new sdk.farm.actions.ApproveERC20(tokenIn, sdk.contracts.uniswapV3Router.address); + + // Swap tokens, output result to Pipeline + const swap = new sdk.farm.actions.UniswapV3Swap(tokenIn, sdk.tokens.WETH, sdk.contracts.pipeline.address); + + // Approve Well to use intermediary token + const approveWell = new sdk.farm.actions.ApproveERC20(sdk.tokens.WETH, well.address); + + // Swap tokens on Well + const wellSwap = new sdk.farm.actions.WellSwap(well.address, sdk.tokens.WETH, tokenOut, recipient); + + // This approves the transferToBeanstalk operation. + const approveClipboard = { + tag: "swapOutput", + copySlot: 0, + pasteSlot: 1 + } + const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); + + // Transfers the output token back to Beanstalk, from Pipeline. + const transferClipboard = { + tag: "swapOutput", + copySlot: 0, + pasteSlot: 2 + } + const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + + result.push(transfer); + + advancedPipe.add(approveUniswap); + advancedPipe.add(swap); + advancedPipe.add(approveWell); + advancedPipe.add(wellSwap, { tag: "swapOutput" }); + if (transferBack) { + advancedPipe.add(approveBack); + advancedPipe.add(transferToBeanstalk); + }; + + result.push(advancedPipe); + return result; + }; + + this.wellSwapUniV3 = (well: BasinWell, account: string, tokenIn: ERC20Token, tokenOut: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + const result = []; + const advancedPipe = sdk.farm.createAdvancedPipe("pipelineWellSwapUniV3"); + + const transferBack = toMode === FarmToMode.INTERNAL; + const recipient = transferBack ? sdk.contracts.pipeline.address : account; + + // Transfer Input Token to Pipeline + const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + + // Approve Well to use input token + const approveWell = new sdk.farm.actions.ApproveERC20(tokenIn, well.address); + + // Swap tokens on Well, send output back to Pipeline + const wellSwap = new sdk.farm.actions.WellSwap(well.address, tokenIn, sdk.tokens.WETH, sdk.contracts.pipeline.address); + + // Approve Uniswap V3 to use output of swap + const uniApproveClipboard = { + tag: "swapOutput", + copySlot: 0, + pasteSlot: 1 + } + const approveUniswap = new sdk.farm.actions.ApproveERC20(sdk.tokens.WETH, sdk.contracts.uniswapV3Router.address, uniApproveClipboard); + + // Swap tokens, send output to recipient + const swap = new sdk.farm.actions.UniswapV3Swap(sdk.tokens.WETH, tokenOut, recipient); + + // This approves the transferToBeanstalk operation. + const transferApproveClipboard = { + tag: "uniV3Output", + copySlot: 0, + pasteSlot: 1 + } + const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, transferApproveClipboard); + + // Transfers the output token back to Beanstalk, from Pipeline. + const transferClipboard = { + tag: "uniV3Output", + copySlot: 0, + pasteSlot: 2 + } + const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + + result.push(transfer); + + advancedPipe.add(approveWell); + advancedPipe.add(wellSwap, { tag: "swapOutput" }); + advancedPipe.add(approveUniswap); + advancedPipe.add(swap, { tag: "uniV3Output" }); + if (transferBack) { + advancedPipe.add(approveBack); + advancedPipe.add(transferToBeanstalk); + }; + + result.push(advancedPipe); + return result; + }; } } diff --git a/projects/sdk/src/lib/swap/Swap.ts b/projects/sdk/src/lib/swap/Swap.ts index 1423bdbabd..f0f5e193e5 100644 --- a/projects/sdk/src/lib/swap/Swap.ts +++ b/projects/sdk/src/lib/swap/Swap.ts @@ -43,8 +43,13 @@ export class Swap { useAdvancedFarm = true; break; }; - } else if (from === "USDC" || from === "DAI" || from === "BEAN") { - if (to === "WETH") { + } else if (from === "USDC" || from === "DAI") { + if (to === "WETH" || to === "BEAN") { + useAdvancedFarm = true; + break; + }; + } else if (from === "BEAN") { + if (to === "USDC" || to === "DAI" || to === "WETH") { useAdvancedFarm = true; break; }; diff --git a/projects/sdk/src/lib/swap/graph.ts b/projects/sdk/src/lib/swap/graph.ts index 0a6ded0460..d62e30443c 100644 --- a/projects/sdk/src/lib/swap/graph.ts +++ b/projects/sdk/src/lib/swap/graph.ts @@ -154,6 +154,36 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { to: "DAI" }); + //BEAN<>USDC via Pipeline + graph.setEdge("USDC", "BEAN", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.USDC, sdk.tokens.BEAN, from, to), + from: "USDC", + to: "BEAN" + }); + + graph.setEdge("BEAN", "USDC", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.USDC, from, to), + from: "BEAN", + to: "USDC" + }); + + //BEAN<>DAI via Pipeline + graph.setEdge("DAI", "BEAN", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.DAI, sdk.tokens.BEAN, from, to), + from: "DAI", + to: "BEAN" + }); + + graph.setEdge("BEAN", "DAI", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.DAI, from, to), + from: "BEAN", + to: "DAI" + }); + /// 3CRV<>Stables via 3Pool Add/Remove Liquidity // HEADS UP: the ordering of these tokens needs to match their indexing in the 3CRV LP token. From 8c0a87e82a7e656e64e462f66467678d69ed9004 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Wed, 10 Jan 2024 20:25:27 -0300 Subject: [PATCH 10/29] Cleanup, formatting --- projects/sdk/src/lib/farm/LibraryPresets.ts | 74 ++++++++++----------- projects/sdk/src/lib/swap/graph.ts | 8 +-- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 708c763837..a9c9836004 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -233,7 +233,7 @@ export class LibraryPresets { ///////// [ USDC, USDT, DAI ] -> BEANETH /////////// this.usdc2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniV3AddLiquidity(well, account, sdk.tokens.USDC, fromMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.USDC, sdk.tokens.WETH, fromMode) ]; this.usdt2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ @@ -242,7 +242,7 @@ export class LibraryPresets { ]; this.dai2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, fromMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, sdk.tokens.WETH, fromMode) ]; this.wellWethBean = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { @@ -356,7 +356,7 @@ export class LibraryPresets { // Approve Uniswap V3 to use fromToken const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); - // Swap tokens + // Swap fromToken -> toToken using Uniswap V3 const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, toToken, recipient); // This approves the transferToBeanstalk operation. @@ -367,7 +367,7 @@ export class LibraryPresets { } const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, approveClipboard); - // Transfers the output token back to Beanstalk, from PIPELINE. + // Transfers toToken back to Beanstalk, from Pipeline. const transferClipboard = { tag: "uniV3SwapAmount", copySlot: 0, @@ -388,21 +388,21 @@ export class LibraryPresets { return result; }; - this.uniV3AddLiquidity = (well: BasinWell, account: string, tokenIn: ERC20Token, fromMode?: FarmFromMode) => { + this.uniV3AddLiquidity = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, fromMode?: FarmFromMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3Deposit"); - // Transfer USDC to Pipeline - const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + // Transfer fromToken to Pipeline + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); // Approve Uniswap V3 to use fromToken - const approveUniswap = new sdk.farm.actions.ApproveERC20(tokenIn, sdk.contracts.uniswapV3Router.address); + const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); - // Swap tokens, output result to Well - const swap = new sdk.farm.actions.UniswapV3Swap(tokenIn, sdk.tokens.WETH, well.address); + // Swap fromToken -> thruToken on Uniswap V3, output result to Well + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, well.address); - // Call sync on Well, send output back to Pipeline - const addLiquidity = new sdk.farm.actions.WellSync(well, sdk.tokens.WETH, sdk.contracts.pipeline.address); + // Call sync on Well, send output (LP tokens) back to Pipeline + const addLiquidity = new sdk.farm.actions.WellSync(well, thruToken, sdk.contracts.pipeline.address); // This approves the transferToBeanstalk operation. const approveClipboard = { @@ -432,27 +432,27 @@ export class LibraryPresets { return result; }; - this.uniV3WellSwap = (well: BasinWell, account: string, tokenIn: ERC20Token, tokenOut: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + this.uniV3WellSwap = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3WellSwap"); const transferBack = toMode === FarmToMode.INTERNAL; const recipient = transferBack ? sdk.contracts.pipeline.address : account; - // Transfer Input Token to Pipeline - const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + // Transfer fromToken to Pipeline + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); // Approve Uniswap V3 to use fromToken - const approveUniswap = new sdk.farm.actions.ApproveERC20(tokenIn, sdk.contracts.uniswapV3Router.address); + const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); - // Swap tokens, output result to Pipeline - const swap = new sdk.farm.actions.UniswapV3Swap(tokenIn, sdk.tokens.WETH, sdk.contracts.pipeline.address); + // Swap fromToken -> thruToken on Uniswap V3, send output back to Pipeline + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, sdk.contracts.pipeline.address); - // Approve Well to use intermediary token - const approveWell = new sdk.farm.actions.ApproveERC20(sdk.tokens.WETH, well.address); + // Approve Well to use thruToken + const approveWell = new sdk.farm.actions.ApproveERC20(thruToken, well.address); - // Swap tokens on Well - const wellSwap = new sdk.farm.actions.WellSwap(well.address, sdk.tokens.WETH, tokenOut, recipient); + // Swap thruToken -> toToken on Well, send output to recipient + const wellSwap = new sdk.farm.actions.WellSwap(well.address, thruToken, toToken, recipient); // This approves the transferToBeanstalk operation. const approveClipboard = { @@ -462,7 +462,7 @@ export class LibraryPresets { } const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); - // Transfers the output token back to Beanstalk, from Pipeline. + // Transfers toToken back to Beanstalk, from Pipeline. const transferClipboard = { tag: "swapOutput", copySlot: 0, @@ -485,32 +485,32 @@ export class LibraryPresets { return result; }; - this.wellSwapUniV3 = (well: BasinWell, account: string, tokenIn: ERC20Token, tokenOut: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + this.wellSwapUniV3 = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineWellSwapUniV3"); const transferBack = toMode === FarmToMode.INTERNAL; const recipient = transferBack ? sdk.contracts.pipeline.address : account; - // Transfer Input Token to Pipeline - const transfer = new sdk.farm.actions.TransferToken(tokenIn.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); + // Transfer fromToken to Pipeline + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); - // Approve Well to use input token - const approveWell = new sdk.farm.actions.ApproveERC20(tokenIn, well.address); + // Approve Well to use fromToken + const approveWell = new sdk.farm.actions.ApproveERC20(fromToken, well.address); - // Swap tokens on Well, send output back to Pipeline - const wellSwap = new sdk.farm.actions.WellSwap(well.address, tokenIn, sdk.tokens.WETH, sdk.contracts.pipeline.address); + // Swap fromToken -> thruToken on Well, send output back to Pipeline + const wellSwap = new sdk.farm.actions.WellSwap(well.address, fromToken, thruToken, sdk.contracts.pipeline.address); - // Approve Uniswap V3 to use output of swap + // Approve Uniswap V3 to use thruToken const uniApproveClipboard = { tag: "swapOutput", copySlot: 0, pasteSlot: 1 } - const approveUniswap = new sdk.farm.actions.ApproveERC20(sdk.tokens.WETH, sdk.contracts.uniswapV3Router.address, uniApproveClipboard); + const approveUniswap = new sdk.farm.actions.ApproveERC20(thruToken, sdk.contracts.uniswapV3Router.address, uniApproveClipboard); - // Swap tokens, send output to recipient - const swap = new sdk.farm.actions.UniswapV3Swap(sdk.tokens.WETH, tokenOut, recipient); + // Swap thruToken -> toToken on Uniswap V3, send output to recipient + const swap = new sdk.farm.actions.UniswapV3Swap(thruToken, toToken, recipient); // This approves the transferToBeanstalk operation. const transferApproveClipboard = { @@ -518,15 +518,15 @@ export class LibraryPresets { copySlot: 0, pasteSlot: 1 } - const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, transferApproveClipboard); + const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, transferApproveClipboard); - // Transfers the output token back to Beanstalk, from Pipeline. + // Transfers toToken back to Beanstalk, from Pipeline. const transferClipboard = { tag: "uniV3Output", copySlot: 0, pasteSlot: 2 } - const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); diff --git a/projects/sdk/src/lib/swap/graph.ts b/projects/sdk/src/lib/swap/graph.ts index d62e30443c..f4fa03027d 100644 --- a/projects/sdk/src/lib/swap/graph.ts +++ b/projects/sdk/src/lib/swap/graph.ts @@ -157,14 +157,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { //BEAN<>USDC via Pipeline graph.setEdge("USDC", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.USDC, sdk.tokens.BEAN, from, to), + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.USDC, sdk.tokens.WETH, sdk.tokens.BEAN, from, to), from: "USDC", to: "BEAN" }); graph.setEdge("BEAN", "USDC", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.USDC, from, to), + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.USDC, from, to), from: "BEAN", to: "USDC" }); @@ -172,14 +172,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { //BEAN<>DAI via Pipeline graph.setEdge("DAI", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.DAI, sdk.tokens.BEAN, from, to), + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.DAI, sdk.tokens.WETH, sdk.tokens.BEAN, from, to), from: "DAI", to: "BEAN" }); graph.setEdge("BEAN", "DAI", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.DAI, from, to), + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.DAI, from, to), from: "BEAN", to: "DAI" }); From 631931e12b8e44b08fd08e67242a68f907f0cf4c Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Thu, 11 Jan 2024 02:09:27 -0300 Subject: [PATCH 11/29] comments, formatting, tweaked clipboard settings --- projects/sdk/src/lib/farm/LibraryPresets.ts | 43 +++++++++++++------ projects/sdk/src/lib/farm/actions/WellSwap.ts | 7 ++- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index a9c9836004..e484c7e285 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -245,6 +245,7 @@ export class LibraryPresets { this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, sdk.tokens.WETH, fromMode) ]; + ///////// BEAN <> BEANETH /////////// this.wellWethBean = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { const WELL_ADDRESS = sdk.addresses.BEANWETH_WELL.get(sdk.chainId); const result = []; @@ -302,6 +303,7 @@ export class LibraryPresets { return result; }; + ///////// [ BEAN, WETH ] -> BEANETH /////////// this.wellAddLiquidity = (well: BasinWell, tokenIn: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineDeposit"); @@ -364,7 +366,7 @@ export class LibraryPresets { tag: "uniV3SwapAmount", copySlot: 0, pasteSlot: 1 - } + }; const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, approveClipboard); // Transfers toToken back to Beanstalk, from Pipeline. @@ -372,7 +374,7 @@ export class LibraryPresets { tag: "uniV3SwapAmount", copySlot: 0, pasteSlot: 2 - } + }; const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); @@ -409,7 +411,7 @@ export class LibraryPresets { tag: "amountToDeposit", copySlot: 0, pasteSlot: 1 - } + }; const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); // Transfers the output token back to Beanstalk, from Pipeline. @@ -417,7 +419,7 @@ export class LibraryPresets { tag: "amountToDeposit", copySlot: 0, pasteSlot: 2 - } + }; const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); @@ -449,17 +451,27 @@ export class LibraryPresets { const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, sdk.contracts.pipeline.address); // Approve Well to use thruToken - const approveWell = new sdk.farm.actions.ApproveERC20(thruToken, well.address); + const wellApproveClipboard = { + tag: "uniV3Output", + copySlot: 0, + pasteSlot: 1 + }; + const approveWell = new sdk.farm.actions.ApproveERC20(thruToken, well.address, wellApproveClipboard); // Swap thruToken -> toToken on Well, send output to recipient - const wellSwap = new sdk.farm.actions.WellSwap(well.address, thruToken, toToken, recipient); + const wellClipboard = { + tag: "uniV3Output", + copySlot: 0, + pasteSlot: 3 + }; + const wellSwap = new sdk.farm.actions.WellSwap(well.address, thruToken, toToken, recipient, undefined, wellClipboard); // This approves the transferToBeanstalk operation. const approveClipboard = { tag: "swapOutput", copySlot: 0, pasteSlot: 1 - } + }; const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); // Transfers toToken back to Beanstalk, from Pipeline. @@ -467,13 +479,13 @@ export class LibraryPresets { tag: "swapOutput", copySlot: 0, pasteSlot: 2 - } + }; const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); advancedPipe.add(approveUniswap); - advancedPipe.add(swap); + advancedPipe.add(swap, { tag: "uniV3Output" }); advancedPipe.add(approveWell); advancedPipe.add(wellSwap, { tag: "swapOutput" }); if (transferBack) { @@ -506,18 +518,23 @@ export class LibraryPresets { tag: "swapOutput", copySlot: 0, pasteSlot: 1 - } + }; const approveUniswap = new sdk.farm.actions.ApproveERC20(thruToken, sdk.contracts.uniswapV3Router.address, uniApproveClipboard); // Swap thruToken -> toToken on Uniswap V3, send output to recipient - const swap = new sdk.farm.actions.UniswapV3Swap(thruToken, toToken, recipient); + const uniClipboard = { + tag: "swapOutput", + copySlot: 0, + pasteSlot: 5 + }; + const swap = new sdk.farm.actions.UniswapV3Swap(thruToken, toToken, recipient, undefined, uniClipboard); // This approves the transferToBeanstalk operation. const transferApproveClipboard = { tag: "uniV3Output", copySlot: 0, pasteSlot: 1 - } + }; const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, transferApproveClipboard); // Transfers toToken back to Beanstalk, from Pipeline. @@ -525,7 +542,7 @@ export class LibraryPresets { tag: "uniV3Output", copySlot: 0, pasteSlot: 2 - } + }; const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); diff --git a/projects/sdk/src/lib/farm/actions/WellSwap.ts b/projects/sdk/src/lib/farm/actions/WellSwap.ts index 562bf14b63..f9c60f4044 100644 --- a/projects/sdk/src/lib/farm/actions/WellSwap.ts +++ b/projects/sdk/src/lib/farm/actions/WellSwap.ts @@ -3,13 +3,15 @@ import { BigNumberish, ethers } from "ethers"; import { Token } from "src/classes/Token"; import { RunContext, RunMode, Step, StepClass, Workflow } from "src/classes/Workflow"; import { AdvancedPipePreparedResult } from "src/lib/depot/pipe"; +import { Clipboard } from "src/lib/depot"; +import { ClipboardSettings } from "src/types"; import { deadlineSecondsToBlockchain } from "src/utils"; export class WellSwap extends StepClass { public name: string = "wellSwap"; private transactionDeadline: BigNumberish; - constructor(public wellAddress: string, public fromToken: Token, public toToken: Token, public recipient: string, deadline?: number) { + constructor(public wellAddress: string, public fromToken: Token, public toToken: Token, public recipient: string, deadline?: number, public clipboard?: ClipboardSettings) { super(); if (deadline !== null && deadline !== undefined && deadline <= 0) { throw new Error("Deadline must be greater than 0"); @@ -94,7 +96,8 @@ export class WellSwap extends StepClass { return { target: this.wellAddress, - callData: callData + callData: callData, + clipboard: this.clipboard ? Clipboard.encodeSlot(context.step.findTag(this.clipboard.tag), this.clipboard.copySlot, this.clipboard.pasteSlot) : undefined }; }, decode: (data: string) => well.contract.interface.decodeFunctionData(wellFunctionName, data), From d8ceb426bd9e6158ee001aabd9215b2f8441400a Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:38:35 -0300 Subject: [PATCH 12/29] use advancedFarm on all swap calls --- projects/sdk/src/lib/swap/Swap.ts | 32 ++----------------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/projects/sdk/src/lib/swap/Swap.ts b/projects/sdk/src/lib/swap/Swap.ts index f0f5e193e5..80ab7d8f66 100644 --- a/projects/sdk/src/lib/swap/Swap.ts +++ b/projects/sdk/src/lib/swap/Swap.ts @@ -29,38 +29,10 @@ export class Swap { } public buildSwap(tokenIn: Token, tokenOut: Token, account: string, _from?: FarmFromMode, _to?: FarmToMode) { + const route = this.router.getRoute(tokenIn.symbol, tokenOut.symbol); + const workflow = Swap.sdk.farm.createAdvancedFarm(`Swap ${tokenIn.symbol}->${tokenOut.symbol}`); - let workflow; - let useAdvancedFarm = false; - - for (let i = 0; i < route.length; i++) { - const from = route.getStep(i).from; - const to = route.getStep(i).to; - - if (from === "WETH") { - if (to === "USDC" || to === "DAI" || to === "BEAN") { - useAdvancedFarm = true; - break; - }; - } else if (from === "USDC" || from === "DAI") { - if (to === "WETH" || to === "BEAN") { - useAdvancedFarm = true; - break; - }; - } else if (from === "BEAN") { - if (to === "USDC" || to === "DAI" || to === "WETH") { - useAdvancedFarm = true; - break; - }; - }; - }; - - if (useAdvancedFarm) { - workflow = Swap.sdk.farm.createAdvancedFarm(`Swap ${tokenIn.symbol}->${tokenOut.symbol}`); - } else { - workflow = Swap.sdk.farm.create(`Swap ${tokenIn.symbol}->${tokenOut.symbol}`); - } // Handle Farm Modes // For a single step swap (ex, ETH > WETH, or BEAN > BEAN), use the passed modes, if available if (route.length === 1) { From 94236e516030af6b8f3be9655d00b5076e56a620 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:22:40 -0300 Subject: [PATCH 13/29] tweaked clipboard settings --- projects/sdk/src/lib/farm/LibraryPresets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index e484c7e285..fbda9c179c 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -462,7 +462,7 @@ export class LibraryPresets { const wellClipboard = { tag: "uniV3Output", copySlot: 0, - pasteSlot: 3 + pasteSlot: 2 }; const wellSwap = new sdk.farm.actions.WellSwap(well.address, thruToken, toToken, recipient, undefined, wellClipboard); From 23f82270ed80b834a3b24fe833dbc30b37f581a7 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:54:07 -0300 Subject: [PATCH 14/29] tweaked clipboard settings --- projects/sdk/src/lib/farm/actions/WellSwap.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/projects/sdk/src/lib/farm/actions/WellSwap.ts b/projects/sdk/src/lib/farm/actions/WellSwap.ts index f9c60f4044..e871c1de04 100644 --- a/projects/sdk/src/lib/farm/actions/WellSwap.ts +++ b/projects/sdk/src/lib/farm/actions/WellSwap.ts @@ -72,6 +72,9 @@ export class WellSwap extends StepClass { ]); } else { const maxAmountIn = estimate.addSlippage(context.data.slippage); + if (this.clipboard) { + this.clipboard.pasteSlot = 3; + }; WellSwap.sdk.debug(`>[${this.name}.prepare()]`, { well: well.name, tokenIn: this.fromToken.symbol, From 3092aae32c7377fac6f3151b2b5753c60b4e0b42 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:30:20 -0300 Subject: [PATCH 15/29] exact output support --- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 78 +++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index 89c9afc0db..a8ddf9d3a3 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -23,11 +23,6 @@ export class UniswapV3Swap extends StepClass { } async run(_amountInStep: ethers.BigNumber, context: RunContext) { - const [tokenIn, tokenOut] = Workflow.direction( - this.tokenIn, - this.tokenOut, - context.runMode !== RunMode.EstimateReversed // _forward - ); if (!this.clipboard) { const pipelineBeanWethSwapIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); @@ -44,40 +39,75 @@ export class UniswapV3Swap extends StepClass { }; const quoter = UniswapV3Swap.sdk.contracts.uniswapV3QuoterV2; + const reversed = context.runMode === RunMode.EstimateReversed; + let estimate: any; - const estimate = await quoter.callStatic.quoteExactInputSingle({ - tokenIn: tokenIn.address, - tokenOut: tokenOut.address, - amountIn: _amountInStep, - fee: 500, - sqrtPriceLimitX96: 0, - }); + if (!reversed) { + estimate = await quoter.callStatic.quoteExactInputSingle({ + tokenIn: this.tokenIn.address, + tokenOut: this.tokenOut.address, + amountIn: _amountInStep, + fee: 500, + sqrtPriceLimitX96: 0, + }); + } else { + estimate = await quoter.callStatic.quoteExactOutputSingle({ + tokenIn: this.tokenIn.address, + tokenOut: this.tokenOut.address, + amount: _amountInStep, + fee: 500, + sqrtPriceLimitX96: 0, + }); + }; + + const swapFunctionName = reversed ? "exactOutputSingle" : "exactInputSingle"; return { name: this.name, amountOut: estimate[0], prepare: () => { + if (context.data.slippage === undefined) throw new Error("Exchange: slippage required"); - const minAmountOut = Workflow.slip(estimate[0], context.data.slippage); + let callData; + const estimatedOutput = TokenValue.fromBlockchain(estimate[0].toString(), this.tokenOut.decimals); const sqrtPriceX96After = estimate[1]; - if (!minAmountOut) throw new Error("Exhange: missing minAmountOut"); - return { - target: UniswapV3Swap.sdk.contracts.uniswapV3Router.address, - callData: UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactInputSingle", [{ - tokenIn: tokenIn.address, - tokenOut: tokenOut.address, + if (!reversed) { + const minAmountOut = estimatedOutput.subSlippage(context.data.slippage); + if (!minAmountOut) throw new Error("UniswapV3Swap: missing minAmountOut"); + callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactInputSingle", [{ + tokenIn: this.tokenIn.address, + tokenOut: this.tokenOut.address, + fee: 500, + recipient: this.recipient, + deadline: this.transactionDeadline, + amountIn: _amountInStep, + amountOutMinimum: minAmountOut.toBlockchain().toString(), + sqrtPriceLimitX96: sqrtPriceX96After + }]); + } else { + const maxAmountIn = estimatedOutput.addSlippage(context.data.slippage); + if (!maxAmountIn) throw new Error("UniswapV3Swap: missing maxAmountOut"); + callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactOutputSingle", [{ + tokenIn: this.tokenIn.address, + tokenOut: this.tokenOut.address, fee: 500, recipient: this.recipient, deadline: this.transactionDeadline, - amountIn: _amountInStep, - amountOutMinimum: minAmountOut, + amountOut: _amountInStep, + amountInMaximum: maxAmountIn.toBlockchain().toString(), sqrtPriceLimitX96: sqrtPriceX96After - }]), + }]); + }; + + return { + target: UniswapV3Swap.sdk.contracts.uniswapV3Router.address, + callData: callData, clipboard: this.clipboard ? Clipboard.encodeSlot(context.step.findTag(this.clipboard.tag), this.clipboard.copySlot, this.clipboard.pasteSlot) : undefined }; }, - decode: (data: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionData("exactInputSingle", data), - decodeResult: (result: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionResult("exactInputSingle", result) + decode: (data: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionData(swapFunctionName, data), + // @ts-ignore + decodeResult: (result: string) => UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.decodeFunctionResult(swapFunctionName, result) }; } } From 4d82ff2e7367cf4195908bea9d6b6d77536ceda0 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:45:37 -0300 Subject: [PATCH 16/29] exposed uniswap v3 fee tier setting --- projects/sdk/src/lib/farm/LibraryPresets.ts | 20 +++++++-------- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 25 ++++++++++--------- projects/sdk/src/lib/silo/depositGraph.ts | 4 +-- projects/sdk/src/lib/swap/graph.ts | 16 ++++++------ 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index fbda9c179c..5f5d409d92 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -233,7 +233,7 @@ export class LibraryPresets { ///////// [ USDC, USDT, DAI ] -> BEANETH /////////// this.usdc2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniV3AddLiquidity(well, account, sdk.tokens.USDC, sdk.tokens.WETH, fromMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.USDC, sdk.tokens.WETH, 500, fromMode) ]; this.usdt2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ @@ -242,7 +242,7 @@ export class LibraryPresets { ]; this.dai2beaneth = (well: BasinWell, account: string, fromMode?: FarmFromMode, toMode?: FarmToMode) => [ - this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, sdk.tokens.WETH, fromMode) + this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, sdk.tokens.WETH, 500, fromMode) ]; ///////// BEAN <> BEANETH /////////// @@ -345,7 +345,7 @@ export class LibraryPresets { return result; }; - this.uniswapV3Swap = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { + this.uniswapV3Swap = (fromToken: ERC20Token, toToken: ERC20Token, account: string, uniswapFeeTier: number, from?: FarmFromMode, to?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniswapV3Swap"); @@ -359,7 +359,7 @@ export class LibraryPresets { const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); // Swap fromToken -> toToken using Uniswap V3 - const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, toToken, recipient); + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, toToken, recipient, uniswapFeeTier); // This approves the transferToBeanstalk operation. const approveClipboard = { @@ -390,7 +390,7 @@ export class LibraryPresets { return result; }; - this.uniV3AddLiquidity = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, fromMode?: FarmFromMode) => { + this.uniV3AddLiquidity = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, uniswapFeeTier: number, fromMode?: FarmFromMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3Deposit"); @@ -401,7 +401,7 @@ export class LibraryPresets { const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); // Swap fromToken -> thruToken on Uniswap V3, output result to Well - const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, well.address); + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, well.address, uniswapFeeTier); // Call sync on Well, send output (LP tokens) back to Pipeline const addLiquidity = new sdk.farm.actions.WellSync(well, thruToken, sdk.contracts.pipeline.address); @@ -434,7 +434,7 @@ export class LibraryPresets { return result; }; - this.uniV3WellSwap = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + this.uniV3WellSwap = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, uniswapFeeTier: number, fromMode?: FarmFromMode, toMode?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineUniV3WellSwap"); @@ -448,7 +448,7 @@ export class LibraryPresets { const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); // Swap fromToken -> thruToken on Uniswap V3, send output back to Pipeline - const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, sdk.contracts.pipeline.address); + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, sdk.contracts.pipeline.address, uniswapFeeTier); // Approve Well to use thruToken const wellApproveClipboard = { @@ -497,7 +497,7 @@ export class LibraryPresets { return result; }; - this.wellSwapUniV3 = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, fromMode?: FarmFromMode, toMode?: FarmToMode) => { + this.wellSwapUniV3 = (well: BasinWell, account: string, fromToken: ERC20Token, thruToken: ERC20Token, toToken: ERC20Token, uniswapFeeTier: number, fromMode?: FarmFromMode, toMode?: FarmToMode) => { const result = []; const advancedPipe = sdk.farm.createAdvancedPipe("pipelineWellSwapUniV3"); @@ -527,7 +527,7 @@ export class LibraryPresets { copySlot: 0, pasteSlot: 5 }; - const swap = new sdk.farm.actions.UniswapV3Swap(thruToken, toToken, recipient, undefined, uniClipboard); + const swap = new sdk.farm.actions.UniswapV3Swap(thruToken, toToken, recipient, uniswapFeeTier, undefined, uniClipboard); // This approves the transferToBeanstalk operation. const transferApproveClipboard = { diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index a8ddf9d3a3..09c29886a1 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -15,6 +15,7 @@ export class UniswapV3Swap extends StepClass { public readonly tokenIn: Token, public readonly tokenOut: Token, public readonly recipient: string, + public readonly feeTier: number, public readonly deadline?: number, public clipboard?: ClipboardSettings ) { @@ -47,7 +48,7 @@ export class UniswapV3Swap extends StepClass { tokenIn: this.tokenIn.address, tokenOut: this.tokenOut.address, amountIn: _amountInStep, - fee: 500, + fee: this.feeTier, sqrtPriceLimitX96: 0, }); } else { @@ -55,7 +56,7 @@ export class UniswapV3Swap extends StepClass { tokenIn: this.tokenIn.address, tokenOut: this.tokenOut.address, amount: _amountInStep, - fee: 500, + fee: this.feeTier, sqrtPriceLimitX96: 0, }); }; @@ -77,7 +78,7 @@ export class UniswapV3Swap extends StepClass { callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactInputSingle", [{ tokenIn: this.tokenIn.address, tokenOut: this.tokenOut.address, - fee: 500, + fee: this.feeTier, recipient: this.recipient, deadline: this.transactionDeadline, amountIn: _amountInStep, @@ -88,15 +89,15 @@ export class UniswapV3Swap extends StepClass { const maxAmountIn = estimatedOutput.addSlippage(context.data.slippage); if (!maxAmountIn) throw new Error("UniswapV3Swap: missing maxAmountOut"); callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactOutputSingle", [{ - tokenIn: this.tokenIn.address, - tokenOut: this.tokenOut.address, - fee: 500, - recipient: this.recipient, - deadline: this.transactionDeadline, - amountOut: _amountInStep, - amountInMaximum: maxAmountIn.toBlockchain().toString(), - sqrtPriceLimitX96: sqrtPriceX96After - }]); + tokenIn: this.tokenIn.address, + tokenOut: this.tokenOut.address, + fee: this.feeTier, + recipient: this.recipient, + deadline: this.transactionDeadline, + amountOut: _amountInStep, + amountInMaximum: maxAmountIn.toBlockchain().toString(), + sqrtPriceLimitX96: sqrtPriceX96After + }]); }; return { diff --git a/projects/sdk/src/lib/silo/depositGraph.ts b/projects/sdk/src/lib/silo/depositGraph.ts index 9e5d666cae..cc1eb64e57 100644 --- a/projects/sdk/src/lib/silo/depositGraph.ts +++ b/projects/sdk/src/lib/silo/depositGraph.ts @@ -231,7 +231,7 @@ export const getDepositGraph = (sdk: BeanstalkSDK): Graph => { graph.setEdge("USDC", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, 500, from, to), from: "USDC", to: "WETH", label: "uniswapV3Swap" @@ -239,7 +239,7 @@ export const getDepositGraph = (sdk: BeanstalkSDK): Graph => { graph.setEdge("DAI", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, 500, from, to), from: "DAI", to: "WETH", label: "uniswapV3Swap" diff --git a/projects/sdk/src/lib/swap/graph.ts b/projects/sdk/src/lib/swap/graph.ts index f4fa03027d..923412406b 100644 --- a/projects/sdk/src/lib/swap/graph.ts +++ b/projects/sdk/src/lib/swap/graph.ts @@ -127,14 +127,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { // USDC<>WETH via Uniswap V3 graph.setEdge("USDC", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.USDC, sdk.tokens.WETH, account, 500, from, to), from: "USDC", to: "WETH" }); graph.setEdge("WETH", "USDC", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.USDC, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.USDC, account, 500, from, to), from: "WETH", to: "USDC" }); @@ -142,14 +142,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { // DAI<>WETH via Uniswap V3 graph.setEdge("DAI", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.DAI, sdk.tokens.WETH, account, 500, from, to), from: "DAI", to: "WETH" }); graph.setEdge("WETH", "DAI", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.DAI, account, from, to), + sdk.farm.presets.uniswapV3Swap(sdk.tokens.WETH, sdk.tokens.DAI, account, 500, from, to), from: "WETH", to: "DAI" }); @@ -157,14 +157,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { //BEAN<>USDC via Pipeline graph.setEdge("USDC", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.USDC, sdk.tokens.WETH, sdk.tokens.BEAN, from, to), + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.USDC, sdk.tokens.WETH, sdk.tokens.BEAN, 500, from, to), from: "USDC", to: "BEAN" }); graph.setEdge("BEAN", "USDC", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.USDC, from, to), + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.USDC, 500, from, to), from: "BEAN", to: "USDC" }); @@ -172,14 +172,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { //BEAN<>DAI via Pipeline graph.setEdge("DAI", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.DAI, sdk.tokens.WETH, sdk.tokens.BEAN, from, to), + sdk.farm.presets.uniV3WellSwap(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.DAI, sdk.tokens.WETH, sdk.tokens.BEAN, 500, from, to), from: "DAI", to: "BEAN" }); graph.setEdge("BEAN", "DAI", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.DAI, from, to), + sdk.farm.presets.wellSwapUniV3(sdk.pools.BEAN_ETH_WELL, account, sdk.tokens.BEAN, sdk.tokens.WETH, sdk.tokens.DAI, 500, from, to), from: "BEAN", to: "DAI" }); From 865824ffc56196f58b42a4efd8ac8ce14aa7d305 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:53:10 -0300 Subject: [PATCH 17/29] debug logs --- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index 09c29886a1..55443f1b5e 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -72,9 +72,25 @@ export class UniswapV3Swap extends StepClass { let callData; const estimatedOutput = TokenValue.fromBlockchain(estimate[0].toString(), this.tokenOut.decimals); const sqrtPriceX96After = estimate[1]; + if (!reversed) { const minAmountOut = estimatedOutput.subSlippage(context.data.slippage); if (!minAmountOut) throw new Error("UniswapV3Swap: missing minAmountOut"); + + UniswapV3Swap.sdk.debug(`>[${this.name}.prepare()]`, { + tokenIn: this.tokenIn.symbol, + tokenOut: this.tokenOut.symbol, + fee: this.feeTier, + recipient: this.recipient, + deadline: this.transactionDeadline, + amountIn: _amountInStep, + amountOutMinimum: minAmountOut.toBlockchain().toString(), + sqrtPriceLimitX96: sqrtPriceX96After, + reversed, + method: "exactInputSingle", + context + }); + callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactInputSingle", [{ tokenIn: this.tokenIn.address, tokenOut: this.tokenOut.address, @@ -85,9 +101,25 @@ export class UniswapV3Swap extends StepClass { amountOutMinimum: minAmountOut.toBlockchain().toString(), sqrtPriceLimitX96: sqrtPriceX96After }]); + } else { const maxAmountIn = estimatedOutput.addSlippage(context.data.slippage); if (!maxAmountIn) throw new Error("UniswapV3Swap: missing maxAmountOut"); + + UniswapV3Swap.sdk.debug(`>[${this.name}.prepare()]`, { + tokenIn: this.tokenIn.symbol, + tokenOut: this.tokenOut.symbol, + fee: this.feeTier, + recipient: this.recipient, + deadline: this.transactionDeadline, + amountOut: _amountInStep, + amountInMaximum: maxAmountIn.toBlockchain().toString(), + sqrtPriceLimitX96: sqrtPriceX96After, + reversed, + method: "exactOutputSingle", + context + }); + callData = UniswapV3Swap.sdk.contracts.uniswapV3Router.interface.encodeFunctionData("exactOutputSingle", [{ tokenIn: this.tokenIn.address, tokenOut: this.tokenOut.address, From 7f9e92e809cdbf2d8e26f8e9b7c3db81f2ee6fef Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:50:20 -0300 Subject: [PATCH 18/29] use shift instead of swap --- projects/sdk/src/lib/farm/LibraryPresets.ts | 32 ++++--------------- .../sdk/src/lib/farm/actions/WellShift.ts | 8 +++-- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 5f5d409d92..f60f3a05c8 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -447,24 +447,11 @@ export class LibraryPresets { // Approve Uniswap V3 to use fromToken const approveUniswap = new sdk.farm.actions.ApproveERC20(fromToken, sdk.contracts.uniswapV3Router.address); - // Swap fromToken -> thruToken on Uniswap V3, send output back to Pipeline - const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, sdk.contracts.pipeline.address, uniswapFeeTier); - - // Approve Well to use thruToken - const wellApproveClipboard = { - tag: "uniV3Output", - copySlot: 0, - pasteSlot: 1 - }; - const approveWell = new sdk.farm.actions.ApproveERC20(thruToken, well.address, wellApproveClipboard); + // Swap fromToken -> thruToken on Uniswap V3, send output to Well + const swap = new sdk.farm.actions.UniswapV3Swap(fromToken, thruToken, well.address, uniswapFeeTier); // Swap thruToken -> toToken on Well, send output to recipient - const wellClipboard = { - tag: "uniV3Output", - copySlot: 0, - pasteSlot: 2 - }; - const wellSwap = new sdk.farm.actions.WellSwap(well.address, thruToken, toToken, recipient, undefined, wellClipboard); + const wellSwap = new sdk.farm.actions.WellShift(well.address, thruToken, toToken, recipient); // This approves the transferToBeanstalk operation. const approveClipboard = { @@ -485,8 +472,7 @@ export class LibraryPresets { result.push(transfer); advancedPipe.add(approveUniswap); - advancedPipe.add(swap, { tag: "uniV3Output" }); - advancedPipe.add(approveWell); + advancedPipe.add(swap); advancedPipe.add(wellSwap, { tag: "swapOutput" }); if (transferBack) { advancedPipe.add(approveBack); @@ -504,14 +490,11 @@ export class LibraryPresets { const transferBack = toMode === FarmToMode.INTERNAL; const recipient = transferBack ? sdk.contracts.pipeline.address : account; - // Transfer fromToken to Pipeline - const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, fromMode, FarmToMode.EXTERNAL); - - // Approve Well to use fromToken - const approveWell = new sdk.farm.actions.ApproveERC20(fromToken, well.address); + // Transfer fromToken to Well + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, well.address, fromMode, FarmToMode.EXTERNAL); // Swap fromToken -> thruToken on Well, send output back to Pipeline - const wellSwap = new sdk.farm.actions.WellSwap(well.address, fromToken, thruToken, sdk.contracts.pipeline.address); + const wellSwap = new sdk.farm.actions.WellShift(well.address, fromToken, thruToken, sdk.contracts.pipeline.address); // Approve Uniswap V3 to use thruToken const uniApproveClipboard = { @@ -547,7 +530,6 @@ export class LibraryPresets { result.push(transfer); - advancedPipe.add(approveWell); advancedPipe.add(wellSwap, { tag: "swapOutput" }); advancedPipe.add(approveUniswap); advancedPipe.add(swap, { tag: "uniV3Output" }); diff --git a/projects/sdk/src/lib/farm/actions/WellShift.ts b/projects/sdk/src/lib/farm/actions/WellShift.ts index d11e009c54..221fd86b80 100644 --- a/projects/sdk/src/lib/farm/actions/WellShift.ts +++ b/projects/sdk/src/lib/farm/actions/WellShift.ts @@ -10,7 +10,7 @@ import { AdvancedPipePreparedResult } from "src/lib/depot/pipe"; export class WellShift extends StepClass { public name: string = "shift"; - constructor(public wellAddress: string, public toToken: Token, public recipient: string) { + constructor(public wellAddress: string, public fromToken: Token, public toToken: Token, public recipient: string) { super(); } @@ -26,7 +26,11 @@ export class WellShift extends StepClass { if (reversed) { throw new Error("Reverse direction is not supported by shift()"); } - const estimate = await well.shiftQuote(this.toToken); + const estimate = await well.swapFromQuote( + this.fromToken, + this.toToken, + TokenValue.fromBlockchain(_amountInStep.toString(), this.fromToken.decimals) + ); return { name: this.name, From 6c9a13b3293ed01550213f5b7356dd10b76235ca Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:09:14 -0300 Subject: [PATCH 19/29] fix approve/transfer --- projects/sdk/src/lib/farm/LibraryPresets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index f60f3a05c8..5c5661f8f9 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -459,7 +459,7 @@ export class LibraryPresets { copySlot: 0, pasteSlot: 1 }; - const approveBack = new sdk.farm.actions.ApproveERC20(well.lpToken, sdk.contracts.beanstalk.address, approveClipboard); + const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, approveClipboard); // Transfers toToken back to Beanstalk, from Pipeline. const transferClipboard = { @@ -467,7 +467,7 @@ export class LibraryPresets { copySlot: 0, pasteSlot: 2 }; - const transferToBeanstalk = new sdk.farm.actions.TransferToken(well.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); result.push(transfer); From 1ea34b0c438b48ed9dfad59d52563db33ad896b1 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:38:07 -0300 Subject: [PATCH 20/29] add more deposit routes --- projects/sdk/src/lib/silo/depositGraph.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/projects/sdk/src/lib/silo/depositGraph.ts b/projects/sdk/src/lib/silo/depositGraph.ts index cc1eb64e57..b564e3d324 100644 --- a/projects/sdk/src/lib/silo/depositGraph.ts +++ b/projects/sdk/src/lib/silo/depositGraph.ts @@ -246,6 +246,29 @@ export const getDepositGraph = (sdk: BeanstalkSDK): Graph => { }); } + + /** + * [ USDC, DAI ] => BEAN + */ + { + const well = sdk.pools.BEAN_ETH_WELL; + graph.setEdge("USDC", "BEAN", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniV3WellSwap(well, account, sdk.tokens.USDC, sdk.tokens.WETH, sdk.tokens.BEAN, 500, from, to), + from: "USDC", + to: "BEAN", + label: "uniV3WellSwap" + }); + + graph.setEdge("DAI", "BEAN", { + build: (account: string, from: FarmFromMode, to: FarmToMode) => + sdk.farm.presets.uniV3WellSwap(well, account, sdk.tokens.DAI, sdk.tokens.WETH, sdk.tokens.BEAN, 500, from, to), + from: "DAI", + to: "BEAN", + label: "uniV3WellSwap" + }); + } + /** * Well Swap: WETH => BEAN */ From 5796b2d58d9f428e909af48a763741d87741750b Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:38:49 -0300 Subject: [PATCH 21/29] update clipboard settings --- projects/sdk/src/lib/farm/LibraryPresets.ts | 2 +- projects/sdk/src/lib/farm/actions/Deposit.ts | 28 +++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index 5c5661f8f9..d612cd6c14 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -286,7 +286,7 @@ export class LibraryPresets { // Approve WELL to spend PIPELINE's input token const approve = new sdk.farm.actions.ApproveERC20(fromToken, WELL_ADDRESS); - // Swap opration executed on WELL, by PIPELINE + // Swap operation executed on WELL, by PIPELINE const swap = new sdk.farm.actions.WellSwap(WELL_ADDRESS, fromToken, toToken, recipient); // Compose the steps diff --git a/projects/sdk/src/lib/farm/actions/Deposit.ts b/projects/sdk/src/lib/farm/actions/Deposit.ts index a5fd4eb32a..ed9f1c554a 100644 --- a/projects/sdk/src/lib/farm/actions/Deposit.ts +++ b/projects/sdk/src/lib/farm/actions/Deposit.ts @@ -19,22 +19,36 @@ export class Deposit extends StepClass { } async run(_amountInStep: ethers.BigNumber, context: RunContext) { - // Checking if the user isn't directly depositing BEANETH - const indirectBeanEth = this.token.symbol === "BEANETH" && context.step.index > 0; + // Checking if the user isn't directly depositing BEAN or BEANETH + const indirectDeposit = (this.token.symbol === "BEAN" || this.token.symbol === "BEANETH") && context.step.index > 0; - const pipeDepositIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); - const pipeUniDepositIndex = context.steps.findIndex(step => step.name === "pipelineUniV3Deposit"); + const pipeDepositIndex = context.steps.findIndex(step => step.name === "pipelineDeposit"); + const pipeBeanWethDepositIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + const pipeUniV3DepositIndex = context.steps.findIndex(step => step.name === "pipelineUniV3Deposit"); + const pipeUniV3WellSwapIndex = context.steps.findIndex(step => step.name === "pipelineUniV3WellSwap"); - if (indirectBeanEth && !this.clipboard) { + if (indirectDeposit && !this.clipboard) { if (pipeDepositIndex > 0) { this.clipboard = { tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeDepositIndex)!, copySlot: 6, pasteSlot: 1 }; - } else if (pipeUniDepositIndex > 0) { + } else if (pipeBeanWethDepositIndex > 0) { this.clipboard = { - tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeUniDepositIndex)!, + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeBeanWethDepositIndex)!, + copySlot: 9, + pasteSlot: 1 + }; + } else if (pipeUniV3DepositIndex > 0) { + this.clipboard = { + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeUniV3DepositIndex)!, + copySlot: 12, + pasteSlot: 1 + }; + } else if (pipeUniV3WellSwapIndex > 0) { + this.clipboard = { + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeUniV3WellSwapIndex)!, copySlot: 12, pasteSlot: 1 }; From ee93d0d4a981f514d5c0f6901bd7e1f0b8a91ea5 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:02:51 -0300 Subject: [PATCH 22/29] update deposit settings --- projects/ui/src/components/Silo/Actions/Deposit.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/ui/src/components/Silo/Actions/Deposit.tsx b/projects/ui/src/components/Silo/Actions/Deposit.tsx index 9f64e8b3d0..4331c5a695 100644 --- a/projects/ui/src/components/Silo/Actions/Deposit.tsx +++ b/projects/ui/src/components/Silo/Actions/Deposit.tsx @@ -542,8 +542,8 @@ const DepositPropProvider: FC<{ depositTxn, amountIn, values.settings.slippage, - target.equals(BEAN_ETH_WELL_LP) ? 1.2 : undefined, - tokenIn.symbol !== "BEANETH" && target.equals(BEAN_ETH_WELL_LP) + 1.2, + true ); const txn = await execute(); From bca6f8c4e1b7d88722b2273629c172d9ddbc7979 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:05:32 -0300 Subject: [PATCH 23/29] disable swap output field --- projects/ui/src/components/Swap/Actions/Swap.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/projects/ui/src/components/Swap/Actions/Swap.tsx b/projects/ui/src/components/Swap/Actions/Swap.tsx index ab12bf4a73..52a36f387a 100644 --- a/projects/ui/src/components/Swap/Actions/Swap.tsx +++ b/projects/ui/src/components/Swap/Actions/Swap.tsx @@ -486,15 +486,7 @@ const SwapForm: FC< /> ), }} - disabled={ - /// Disable while quoting an `amount` for the output. - quotingOut || - /// Can't type into the output field if - /// user has no balance of the input. - noBalance - /// No way to quote for this pathway - // || !pathwayCheck - } + disabled quote={quotingIn ? Quoting : undefined} onChange={handleChangeAmountOut} /> From 9cab864907911e6902857c68db2587c1a68d4859 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:04:33 -0300 Subject: [PATCH 24/29] enable reverse direction on well shifts --- .../sdk/src/lib/farm/actions/WellShift.ts | 23 ++++++++++++------- .../Common/Form/TokenInputField.tsx | 2 +- .../src/components/Silo/Actions/Deposit.tsx | 2 +- .../ui/src/components/Swap/Actions/Swap.tsx | 10 +++++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/WellShift.ts b/projects/sdk/src/lib/farm/actions/WellShift.ts index 221fd86b80..c31363b3e6 100644 --- a/projects/sdk/src/lib/farm/actions/WellShift.ts +++ b/projects/sdk/src/lib/farm/actions/WellShift.ts @@ -23,14 +23,21 @@ export class WellShift extends StepClass { const reversed = context.runMode === RunMode.EstimateReversed; - if (reversed) { - throw new Error("Reverse direction is not supported by shift()"); - } - const estimate = await well.swapFromQuote( - this.fromToken, - this.toToken, - TokenValue.fromBlockchain(_amountInStep.toString(), this.fromToken.decimals) - ); + let estimate: any; + + if (!reversed) { + estimate = await well.swapFromQuote( + this.fromToken, + this.toToken, + TokenValue.fromBlockchain(_amountInStep.toString(), this.fromToken.decimals) + ); + } else { + estimate = await well.swapToQuote( + this.fromToken, + this.toToken, + TokenValue.fromBlockchain(_amountInStep.toString(), this.toToken.decimals) + ); + }; return { name: this.name, diff --git a/projects/ui/src/components/Common/Form/TokenInputField.tsx b/projects/ui/src/components/Common/Form/TokenInputField.tsx index 1afd1280ed..fc2af426c6 100644 --- a/projects/ui/src/components/Common/Form/TokenInputField.tsx +++ b/projects/ui/src/components/Common/Form/TokenInputField.tsx @@ -252,7 +252,7 @@ const TokenInput: FC = ({ } } }, - [form, field.name, field.value, onChange, clamp] + [form, field.name, field.value, onChange, clamp, balance] ); // diff --git a/projects/ui/src/components/Silo/Actions/Deposit.tsx b/projects/ui/src/components/Silo/Actions/Deposit.tsx index 4331c5a695..64f08f9d1e 100644 --- a/projects/ui/src/components/Silo/Actions/Deposit.tsx +++ b/projects/ui/src/components/Silo/Actions/Deposit.tsx @@ -487,7 +487,7 @@ const DepositPropProvider: FC<{ throw new Error('Only one token supported at this time'); } - const { BEAN, BEAN_ETH_WELL_LP } = sdk.tokens; + const { BEAN } = sdk.tokens; const formData = values.tokens[0]; const claimData = values.claimableBeans; diff --git a/projects/ui/src/components/Swap/Actions/Swap.tsx b/projects/ui/src/components/Swap/Actions/Swap.tsx index 52a36f387a..ab12bf4a73 100644 --- a/projects/ui/src/components/Swap/Actions/Swap.tsx +++ b/projects/ui/src/components/Swap/Actions/Swap.tsx @@ -486,7 +486,15 @@ const SwapForm: FC< /> ), }} - disabled + disabled={ + /// Disable while quoting an `amount` for the output. + quotingOut || + /// Can't type into the output field if + /// user has no balance of the input. + noBalance + /// No way to quote for this pathway + // || !pathwayCheck + } quote={quotingIn ? Quoting : undefined} onChange={handleChangeAmountOut} /> From 4c04ba06b7423715016e30946adb435bbbd465e9 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Tue, 16 Jan 2024 01:42:24 -0300 Subject: [PATCH 25/29] use shift on bean weth route --- projects/sdk/src/classes/Workflow.ts | 4 +- projects/sdk/src/lib/farm/LibraryPresets.ts | 58 +++++++++---------- projects/sdk/src/lib/farm/actions/Deposit.ts | 8 +-- .../sdk/src/lib/farm/actions/UniswapV3Swap.ts | 8 +-- .../sdk/src/lib/farm/actions/UnwrapEth.ts | 8 +-- projects/sdk/src/lib/silo/depositGraph.ts | 11 ++-- projects/sdk/src/lib/swap/graph.ts | 4 +- 7 files changed, 48 insertions(+), 53 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index a64f3e68e0..66b80d1258 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -304,8 +304,8 @@ export abstract class Workflow< pipelineOptions = { tag: `depositUniV3${filteredOptions.length}Amount` }; Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; - case "pipelineBeanWethSwap": - pipelineOptions = { tag: `beanWethSwap${filteredOptions.length}Amount` }; + case "pipelineWellSwap": + pipelineOptions = { tag: `wellSwap${filteredOptions.length}Amount` }; Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineUniswapV3Swap": diff --git a/projects/sdk/src/lib/farm/LibraryPresets.ts b/projects/sdk/src/lib/farm/LibraryPresets.ts index d612cd6c14..6c03ae9695 100644 --- a/projects/sdk/src/lib/farm/LibraryPresets.ts +++ b/projects/sdk/src/lib/farm/LibraryPresets.ts @@ -23,8 +23,6 @@ export class LibraryPresets { public readonly weth2bean: ActionBuilder; public readonly bean2weth: ActionBuilder; public readonly weth2bean3crv: ActionBuilder; - public readonly wellWethBean; - public readonly wellAddLiquidity; public readonly usdc2bean: ActionBuilder; public readonly bean2usdc: ActionBuilder; @@ -43,6 +41,8 @@ export class LibraryPresets { public readonly usdt2beaneth; public readonly dai2beaneth; + public readonly wellSwap; + public readonly wellAddLiquidity; public readonly uniswapV3Swap; public readonly uniV3AddLiquidity; public readonly uniV3WellSwap; @@ -245,59 +245,53 @@ export class LibraryPresets { this.uniV3AddLiquidity(well, account, sdk.tokens.DAI, sdk.tokens.WETH, 500, fromMode) ]; - ///////// BEAN <> BEANETH /////////// - this.wellWethBean = (fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { - const WELL_ADDRESS = sdk.addresses.BEANWETH_WELL.get(sdk.chainId); + ///////// BEAN <> WETH /////////// + this.wellSwap = (well: BasinWell, fromToken: ERC20Token, toToken: ERC20Token, account: string, from?: FarmFromMode, to?: FarmToMode) => { const result = []; + // Set up the AdvancedPipe workflow that will call Wells via Pipeline + const advancedPipe = sdk.farm.createAdvancedPipe("pipelineWellSwap"); + // If the TO mode is INTERNAL that means this is not the last step of a swap/workflow. // We must transfer result of the swap back to User's INTERNAL balance on Beanstalk. - // This means setting the swap recipient to PIPELINE, have PIPELINE approve Beanstalk to spend - // the output token, then transfer the output token from PIPELINE's external balance to USER's internal balance + // This means setting the swap recipient to Pipeline, have Pipeline approve Beanstalk to spend + // the output token, then transfer the output token from Pipeline's external balance to User's INTERNAL balance const transferBack = to === FarmToMode.INTERNAL; - // Transfer input token to PIPELINE (via Beanstalk, so a beanstalk approval will be required, but - // that is a separate transaction, not part of this workflow) - const transfer = new sdk.farm.actions.TransferToken(fromToken.address, sdk.contracts.pipeline.address, from, FarmToMode.EXTERNAL); + // When transferBack is true, we tell Wells to send the swap result to Pipeline, otherwise + // send it directly to the User + const recipient = transferBack ? sdk.contracts.pipeline.address : account; - // This transfers the output token back to Beanstalk, from PIPELINE. Used when transferBack == true - const transferClipboard = { - tag: "swap", - copySlot: 0, - pasteSlot: 2 - } - const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); + // Transfer input token to Well + const transfer = new sdk.farm.actions.TransferToken(fromToken.address, well.address, from, FarmToMode.EXTERNAL); + + // Swap fromToken -> toToken on Well, send output back to recipient (either the User or Pipeline) + const swap = new sdk.farm.actions.WellShift(well.address, fromToken, toToken, recipient); // This approves the transferToBeanstalk operation. Used when transferBack == true const approveClipboard = { tag: "swap", copySlot: 0, pasteSlot: 1 - } + }; const approveBack = new sdk.farm.actions.ApproveERC20(toToken, sdk.contracts.beanstalk.address, approveClipboard); - // When transferBack is true, we tell Wells to send the swap result to PIPELINE, otherwise - // send it directly to the user - const recipient = transferBack ? sdk.contracts.pipeline.address : account; - - // Set up the AdvancedPipe workflow that will call Wells via PIPELINE - const advancedPipe = sdk.farm.createAdvancedPipe("pipelineBeanWethSwap"); - - // Approve WELL to spend PIPELINE's input token - const approve = new sdk.farm.actions.ApproveERC20(fromToken, WELL_ADDRESS); - // Swap operation executed on WELL, by PIPELINE - const swap = new sdk.farm.actions.WellSwap(WELL_ADDRESS, fromToken, toToken, recipient); + // This transfers the output token back to Beanstalk, from Pipeline. Used when transferBack == true + const transferClipboard = { + tag: "swap", + copySlot: 0, + pasteSlot: 2 + }; + const transferToBeanstalk = new sdk.farm.actions.TransferToken(toToken.address, account, FarmFromMode.EXTERNAL, FarmToMode.INTERNAL, transferClipboard); // Compose the steps - advancedPipe.add(approve); + result.push(transfer); advancedPipe.add(swap, { tag: "swap" }); if (transferBack) { advancedPipe.add(approveBack); advancedPipe.add(transferToBeanstalk); } - - result.push(transfer); result.push(advancedPipe); return result; diff --git a/projects/sdk/src/lib/farm/actions/Deposit.ts b/projects/sdk/src/lib/farm/actions/Deposit.ts index ed9f1c554a..074358fe1b 100644 --- a/projects/sdk/src/lib/farm/actions/Deposit.ts +++ b/projects/sdk/src/lib/farm/actions/Deposit.ts @@ -23,7 +23,7 @@ export class Deposit extends StepClass { const indirectDeposit = (this.token.symbol === "BEAN" || this.token.symbol === "BEANETH") && context.step.index > 0; const pipeDepositIndex = context.steps.findIndex(step => step.name === "pipelineDeposit"); - const pipeBeanWethDepositIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + const pipeWellSwapDepositIndex = context.steps.findIndex(step => step.name === "pipelineWellSwap"); const pipeUniV3DepositIndex = context.steps.findIndex(step => step.name === "pipelineUniV3Deposit"); const pipeUniV3WellSwapIndex = context.steps.findIndex(step => step.name === "pipelineUniV3WellSwap"); @@ -34,10 +34,10 @@ export class Deposit extends StepClass { copySlot: 6, pasteSlot: 1 }; - } else if (pipeBeanWethDepositIndex > 0) { + } else if (pipeWellSwapDepositIndex > 0) { this.clipboard = { - tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeBeanWethDepositIndex)!, - copySlot: 9, + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeWellSwapDepositIndex)!, + copySlot: 6, pasteSlot: 1 }; } else if (pipeUniV3DepositIndex > 0) { diff --git a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts index 55443f1b5e..b38bfec66b 100644 --- a/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts +++ b/projects/sdk/src/lib/farm/actions/UniswapV3Swap.ts @@ -26,14 +26,14 @@ export class UniswapV3Swap extends StepClass { async run(_amountInStep: ethers.BigNumber, context: RunContext) { if (!this.clipboard) { - const pipelineBeanWethSwapIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + const pipelineWellSwapIndex = context.steps.findIndex(step => step.name === "pipelineWellSwap"); // If the action before (happens when reverse estimating) or after this one is a BEAN -> WETH swap through Pipeline... - if (pipelineBeanWethSwapIndex >= 0 && Math.abs(pipelineBeanWethSwapIndex - context.step.index) === 1) { + if (pipelineWellSwapIndex >= 0 && Math.abs(pipelineWellSwapIndex - context.step.index) === 1) { // We use clipboard... this.clipboard = { // Then find the correct tag in the tag map - tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineBeanWethSwapIndex)!, - copySlot: 9, + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineWellSwapIndex)!, + copySlot: 6, pasteSlot: 5 }; }; diff --git a/projects/sdk/src/lib/farm/actions/UnwrapEth.ts b/projects/sdk/src/lib/farm/actions/UnwrapEth.ts index 5a740191f1..beb8196604 100644 --- a/projects/sdk/src/lib/farm/actions/UnwrapEth.ts +++ b/projects/sdk/src/lib/farm/actions/UnwrapEth.ts @@ -13,14 +13,14 @@ export class UnwrapEth extends StepClass { async run(_amountInStep: ethers.BigNumber, context: RunContext) { if (!this.clipboard) { - const pipelineBeanWethSwapIndex = context.steps.findIndex(step => step.name === "pipelineBeanWethSwap"); + const pipelineWellSwapIndex = context.steps.findIndex(step => step.name === "pipelineWellSwap"); // If the action before (happens when reverse estimating) or after this one is a BEAN -> WETH swap through Pipeline... - if (pipelineBeanWethSwapIndex >= 0 && Math.abs(pipelineBeanWethSwapIndex - context.step.index) === 1) { + if (pipelineWellSwapIndex >= 0 && Math.abs(pipelineWellSwapIndex - context.step.index) === 1) { // We use clipboard... this.clipboard = { // Then find the correct tag in the tag map - tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineBeanWethSwapIndex)!, - copySlot: 9, + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineWellSwapIndex)!, + copySlot: 6, pasteSlot: 0 }; }; diff --git a/projects/sdk/src/lib/silo/depositGraph.ts b/projects/sdk/src/lib/silo/depositGraph.ts index b564e3d324..3d643a2ca1 100644 --- a/projects/sdk/src/lib/silo/depositGraph.ts +++ b/projects/sdk/src/lib/silo/depositGraph.ts @@ -270,22 +270,23 @@ export const getDepositGraph = (sdk: BeanstalkSDK): Graph => { } /** - * Well Swap: WETH => BEAN + * Well Swap: WETH <> BEAN */ { + const well = sdk.pools.BEAN_ETH_WELL; graph.setEdge("WETH", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellWethBean(sdk.tokens.WETH, sdk.tokens.BEAN, account, from, to), + sdk.farm.presets.wellSwap(well, sdk.tokens.WETH, sdk.tokens.BEAN, account, from, to), from: "WETH", to: "BEAN", - label: "wellWethBean" + label: "wellSwap" }); graph.setEdge("BEAN", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellWethBean(sdk.tokens.BEAN, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.wellSwap(well, sdk.tokens.BEAN, sdk.tokens.WETH, account, from, to), from: "BEAN", to: "WETH", - label: "wellWethBean" + label: "wellSwap" }); } diff --git a/projects/sdk/src/lib/swap/graph.ts b/projects/sdk/src/lib/swap/graph.ts index 923412406b..58f9cf7acd 100644 --- a/projects/sdk/src/lib/swap/graph.ts +++ b/projects/sdk/src/lib/swap/graph.ts @@ -112,14 +112,14 @@ export const getSwapGraph = (sdk: BeanstalkSDK): Graph => { // BEAN<>WETH via Basin Well graph.setEdge("BEAN", "WETH", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellWethBean(sdk.tokens.BEAN, sdk.tokens.WETH, account, from, to), + sdk.farm.presets.wellSwap(sdk.pools.BEAN_ETH_WELL, sdk.tokens.BEAN, sdk.tokens.WETH, account, from, to), from: "BEAN", to: "WETH" }); graph.setEdge("WETH", "BEAN", { build: (account: string, from: FarmFromMode, to: FarmToMode) => - sdk.farm.presets.wellWethBean(sdk.tokens.WETH, sdk.tokens.BEAN, account, from, to), + sdk.farm.presets.wellSwap(sdk.pools.BEAN_ETH_WELL, sdk.tokens.WETH, sdk.tokens.BEAN, account, from, to), from: "WETH", to: "BEAN" }); From f4b4d307fdb57d4b15aa657631eb2ee62054c7e4 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Wed, 17 Jan 2024 01:33:57 -0300 Subject: [PATCH 26/29] updated tests --- projects/sdk/src/lib/silo/Deposit.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/projects/sdk/src/lib/silo/Deposit.test.ts b/projects/sdk/src/lib/silo/Deposit.test.ts index 914092894b..4dc72dd539 100644 --- a/projects/sdk/src/lib/silo/Deposit.test.ts +++ b/projects/sdk/src/lib/silo/Deposit.test.ts @@ -23,15 +23,15 @@ const happyPaths: Record = { "BEAN:BEAN3CRV": "BEAN -> BEAN3CRV -> BEAN3CRV:SILO", "BEAN:BEANETH": "BEAN -> BEANETH -> BEANETH:SILO", - "3CRV:BEAN": "3CRV -> USDC -> WETH -> BEAN -> BEAN:SILO", // TODO: Fix this path + "3CRV:BEAN": "3CRV -> USDC -> BEAN -> BEAN:SILO", "3CRV:BEAN3CRV": "3CRV -> BEAN3CRV -> BEAN3CRV:SILO", "3CRV:BEANETH": "3CRV -> USDC -> BEANETH -> BEANETH:SILO", - "DAI:BEAN": "DAI -> WETH -> BEAN -> BEAN:SILO", + "DAI:BEAN": "DAI -> BEAN -> BEAN:SILO", "DAI:BEAN3CRV": "DAI -> 3CRV -> BEAN3CRV -> BEAN3CRV:SILO", "DAI:BEANETH": "DAI -> BEANETH -> BEANETH:SILO", - "USDC:BEAN": "USDC -> WETH -> BEAN -> BEAN:SILO", + "USDC:BEAN": "USDC -> BEAN -> BEAN:SILO", "USDC:BEAN3CRV": "USDC -> 3CRV -> BEAN3CRV -> BEAN3CRV:SILO", "USDC:BEANETH": "USDC -> BEANETH -> BEANETH:SILO", From 9cf81ad02987e337c19954570c1e22579e0d0dc9 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Wed, 17 Jan 2024 01:53:59 -0300 Subject: [PATCH 27/29] cleanup --- projects/sdk/src/classes/Workflow.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/projects/sdk/src/classes/Workflow.ts b/projects/sdk/src/classes/Workflow.ts index 66b80d1258..3f83045413 100644 --- a/projects/sdk/src/classes/Workflow.ts +++ b/projects/sdk/src/classes/Workflow.ts @@ -298,31 +298,26 @@ export abstract class Workflow< switch (input.name) { case "pipelineDeposit": pipelineOptions = { tag: `deposit${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineUniV3Deposit": pipelineOptions = { tag: `depositUniV3${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineWellSwap": pipelineOptions = { tag: `wellSwap${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineUniswapV3Swap": pipelineOptions = { tag: `uniswapV3Swap${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineUniV3WellSwap": pipelineOptions = { tag: `uniV3WellSwap${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; case "pipelineWellSwapUniV3": pipelineOptions = { tag: `wellSwapUniV3${filteredOptions.length}Amount` }; - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions); break; default: - Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`); - } + }; + + Workflow.sdk.debug(`[Workflow][${this.name}][add] ${input.name || ""}`, pipelineOptions || ''); this._generators.push(input); this._options.push(pipelineOptions || options || null); // null = no options set From 2cb5092336470002afeacf34050bde81be166019 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Wed, 17 Jan 2024 18:05:17 -0300 Subject: [PATCH 28/29] updated clipboard settings --- projects/sdk/src/lib/farm/actions/UnwrapEth.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/UnwrapEth.ts b/projects/sdk/src/lib/farm/actions/UnwrapEth.ts index beb8196604..b6b7d42acd 100644 --- a/projects/sdk/src/lib/farm/actions/UnwrapEth.ts +++ b/projects/sdk/src/lib/farm/actions/UnwrapEth.ts @@ -14,12 +14,15 @@ export class UnwrapEth extends StepClass { async run(_amountInStep: ethers.BigNumber, context: RunContext) { if (!this.clipboard) { const pipelineWellSwapIndex = context.steps.findIndex(step => step.name === "pipelineWellSwap"); - // If the action before (happens when reverse estimating) or after this one is a BEAN -> WETH swap through Pipeline... - if (pipelineWellSwapIndex >= 0 && Math.abs(pipelineWellSwapIndex - context.step.index) === 1) { + const pipelineUniV3SwapIndex = context.steps.findIndex(step => step.name === "pipelineUniswapV3Swap"); + + const pipelineStepIndex = Math.max(pipelineWellSwapIndex, pipelineUniV3SwapIndex); + // If the action before or after (happens when reverse estimating) this one is a BEAN/USDC/DAI -> WETH swap through Pipeline... + if (pipelineStepIndex >= 0 && Math.abs(pipelineStepIndex - context.step.index) === 1) { // We use clipboard... this.clipboard = { // Then find the correct tag in the tag map - tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineWellSwapIndex)!, + tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipelineStepIndex)!, copySlot: 6, pasteSlot: 0 }; From 132af06baef21eff3bb814cf3aa4e5dcbe15ee78 Mon Sep 17 00:00:00 2001 From: uncoolzero <107518216+uncoolzero@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:11:29 -0300 Subject: [PATCH 29/29] cleanup --- projects/sdk/src/lib/farm/actions/Deposit.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/projects/sdk/src/lib/farm/actions/Deposit.ts b/projects/sdk/src/lib/farm/actions/Deposit.ts index 074358fe1b..2bbf5803c0 100644 --- a/projects/sdk/src/lib/farm/actions/Deposit.ts +++ b/projects/sdk/src/lib/farm/actions/Deposit.ts @@ -19,15 +19,12 @@ export class Deposit extends StepClass { } async run(_amountInStep: ethers.BigNumber, context: RunContext) { - // Checking if the user isn't directly depositing BEAN or BEANETH - const indirectDeposit = (this.token.symbol === "BEAN" || this.token.symbol === "BEANETH") && context.step.index > 0; - const pipeDepositIndex = context.steps.findIndex(step => step.name === "pipelineDeposit"); const pipeWellSwapDepositIndex = context.steps.findIndex(step => step.name === "pipelineWellSwap"); const pipeUniV3DepositIndex = context.steps.findIndex(step => step.name === "pipelineUniV3Deposit"); const pipeUniV3WellSwapIndex = context.steps.findIndex(step => step.name === "pipelineUniV3WellSwap"); - if (indirectDeposit && !this.clipboard) { + if (!this.clipboard) { if (pipeDepositIndex > 0) { this.clipboard = { tag: Object.keys(context.tagMap).find(tag => context.tagMap[tag] === pipeDepositIndex)!,