From 7c721e1d04ca7e989489586c940510f90c1e58d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Brand=C3=A3o?= Date: Fri, 8 Dec 2023 19:47:41 +0000 Subject: [PATCH] Refactoring `RouterOperation` Added `addStep` function for more atomic and more readable addition of router steps. --- .../asset-strategies/AaveV2DepositStrategy.ts | 148 +++++---------- .../asset-strategies/AaveV3DepositStrategy.ts | 103 ++++------- .../BalancerDepositStrategy.ts | 166 ++++++++--------- .../asset-strategies/BeefyDepositStrategy.ts | 127 +++++++------ .../asset-strategies/GammaDepositStrategy.ts | 166 +++++++---------- .../SavingsDaiDepositStrategy.ts | 91 ++++------ .../UniswapV2LiquidityStrategy.ts | 171 +++++++++--------- core/src/path/exchanges.ts | 165 +++++++---------- core/src/transaction/types.ts | 142 ++++++++++++++- core/src/utils/get-magic-offset.ts | 32 ---- 10 files changed, 618 insertions(+), 693 deletions(-) diff --git a/core/src/asset-strategies/AaveV2DepositStrategy.ts b/core/src/asset-strategies/AaveV2DepositStrategy.ts index bf3c291..0be55c9 100644 --- a/core/src/asset-strategies/AaveV2DepositStrategy.ts +++ b/core/src/asset-strategies/AaveV2DepositStrategy.ts @@ -4,7 +4,6 @@ import { fetchPriceData, getPrice, } from "../transaction/asset-type-strategies-helpers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { AaveIncentivesController, IERC20, LendingPool } from "core/src/abis"; import { FRACTION_MULTIPLIER, @@ -95,56 +94,41 @@ export class AaveV2DepositStrategy extends InterfaceStrategy { delta: variation, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - lendingPoolAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + lendingPoolAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberToken, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(FRACTION_MULTIPLIER * newFraction), }, ], }); - const { data: depositEncodedCall, offsets: depositFromOffsets } = - getMagicOffsets({ - data: LendingPool.encodeFunctionData("deposit", [ - linkedAsset.address, // assetIn - MAGIC_REPLACERS[0], // amount - walletAddress, // onBehalfOf - 0, // referralCode - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: lendingPoolAddress, - stepEncodedCall: depositEncodedCall, + encodedFunctionData: LendingPool.encodeFunctionData("deposit", [ + linkedAsset.address, // assetIn + MAGIC_REPLACERS[0], // amount + walletAddress, // onBehalfOf + 0, // referralCode + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberToken, - secondaryStoreNumber: 0, - offset: depositFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.AddStoreToStore, storeNumber: storeNumberAToken, secondaryStoreNumber: storeNumberToken, - offset: 0, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, ], @@ -173,108 +157,74 @@ export class AaveV2DepositStrategy extends InterfaceStrategy { }); }); - const { data: withdrawEncodedCall, offsets: withdrawFromOffsets } = - getMagicOffsets({ - data: LendingPool.encodeFunctionData("withdraw", [ - linkedAsset.address, // asset - MAGIC_REPLACERS[0], // amount - walletAddress, // to - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: withdrawToOffsets } = getMagicOffsets({ - data: LendingPool.encodeFunctionResult("withdraw", [ + routerOperation.addStep({ + stepAddress: lendingPoolAddress, + encodedFunctionData: LendingPool.encodeFunctionData("withdraw", [ + linkedAsset.address, // asset + MAGIC_REPLACERS[0], // amount + walletAddress, // to + ]), + encodedFunctionResult: LendingPool.encodeFunctionResult("withdraw", [ MAGIC_REPLACERS[0], ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ - stepAddress: lendingPoolAddress, - stepEncodedCall: withdrawEncodedCall, storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberAToken, - secondaryStoreNumber: 0, - offset: withdrawFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberToken, - secondaryStoreNumber: 0, - offset: withdrawToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], }); - // uint256 amountToClaim = distributor.getRewardsBalance(assets, address(this)); - // uint256 claimedReward = distributor.claimRewards(assets, amountToClaim, address(this)); - - const { - data: getRewardBalanceEncodedCall, - offsets: _getRewardBalanceFromOffsets, - } = getMagicOffsets({ - data: AaveIncentivesController.encodeFunctionData("getRewardsBalance", [ - [asset.address], // assets - walletAddress, // to - ]), - magicReplacers: [], - }); - - const { offsets: getRewardBalanceToOffsets } = getMagicOffsets({ - data: AaveIncentivesController.encodeFunctionResult( + routerOperation.addStep({ + stepAddress: incentivesControllerAddress, + encodedFunctionData: AaveIncentivesController.encodeFunctionData( + "getRewardsBalance", + [ + [asset.address], // assets + walletAddress, // to + ] + ), + encodedFunctionResult: AaveIncentivesController.encodeFunctionResult( "getRewardsBalance", [MAGIC_REPLACERS[0]] ), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ - stepAddress: incentivesControllerAddress, - stepEncodedCall: getRewardBalanceEncodedCall, storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberReward, - secondaryStoreNumber: 0, - offset: withdrawToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], }); - const { - data: claimRewardsEncodedCall, - offsets: claimRewardsFromOffsets, - } = getMagicOffsets({ - data: AaveIncentivesController.encodeFunctionData("claimRewards", [ - [asset.address], // assets - MAGIC_REPLACERS[0], // amount - walletAddress, // to - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: claimRewardsToOffsets } = getMagicOffsets({ - data: AaveIncentivesController.encodeFunctionResult("claimRewards", [ - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: incentivesControllerAddress, - stepEncodedCall: claimRewardsEncodedCall, + encodedFunctionData: AaveIncentivesController.encodeFunctionData( + "claimRewards", + [ + [asset.address], // assets + MAGIC_REPLACERS[0], // amount + walletAddress, // to + ] + ), + encodedFunctionResult: AaveIncentivesController.encodeFunctionResult( + "claimRewards", + [MAGIC_REPLACERS[0]] + ), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberReward, - secondaryStoreNumber: 0, - offset: withdrawFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/AaveV3DepositStrategy.ts b/core/src/asset-strategies/AaveV3DepositStrategy.ts index b85702a..c508835 100644 --- a/core/src/asset-strategies/AaveV3DepositStrategy.ts +++ b/core/src/asset-strategies/AaveV3DepositStrategy.ts @@ -4,7 +4,6 @@ import { fetchPriceData, getPrice, } from "../transaction/asset-type-strategies-helpers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { IERC20, IPool } from "core/src/abis"; import { FRACTION_MULTIPLIER, @@ -87,93 +86,77 @@ export class AaveV3DepositStrategy extends InterfaceStrategy { delta: variation, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - poolAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + poolAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(FRACTION_MULTIPLIER * newFraction), }, ], }); - const { offsets: balanceOfToOffsets } = getMagicOffsets({ - data: IERC20.encodeFunctionResult("balanceOf", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], }); - const { data: supplyEncodedCall, offsets: supplyFromOffsets } = - getMagicOffsets({ - data: IPool.encodeFunctionData("supply", [ - linkedAsset.address, // asset - MAGIC_REPLACERS[0], // amount - walletAddress, // onBehalfOf - 0, // referralCode - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: poolAddress, - stepEncodedCall: supplyEncodedCall, + encodedFunctionData: IPool.encodeFunctionData("supply", [ + linkedAsset.address, // asset + MAGIC_REPLACERS[0], // amount + walletAddress, // onBehalfOf + 0, // referralCode + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: supplyFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, ], }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberTo, secondaryStoreNumber: storeNumberTmp, - offset: 0, fraction: FRACTION_MULTIPLIER, }, ], @@ -203,37 +186,29 @@ export class AaveV3DepositStrategy extends InterfaceStrategy { }); }); - const { data: withdrawEncodedCall, offsets: withdrawFromOffsets } = - getMagicOffsets({ - data: IPool.encodeFunctionData("withdraw", [ - linkedAsset.address, // asset - MAGIC_REPLACERS[0], // _shares - walletAddress, // to - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: withdrawToOffsets } = getMagicOffsets({ - data: IPool.encodeFunctionResult("withdraw", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: poolAddress, - stepEncodedCall: withdrawEncodedCall, + encodedFunctionData: IPool.encodeFunctionData("withdraw", [ + linkedAsset.address, // asset + MAGIC_REPLACERS[0], // _shares + walletAddress, // to + ]), + encodedFunctionResult: IPool.encodeFunctionResult("withdraw", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: withdrawFromOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: withdrawToOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/BalancerDepositStrategy.ts b/core/src/asset-strategies/BalancerDepositStrategy.ts index 3631a16..54ed7ab 100644 --- a/core/src/asset-strategies/BalancerDepositStrategy.ts +++ b/core/src/asset-strategies/BalancerDepositStrategy.ts @@ -3,7 +3,7 @@ import { Asset, AssetStore, StoreOpType, - StoreOperations, + StoreOperation, } from "../transaction/types"; import { fetchPriceData, @@ -12,7 +12,6 @@ import { import { FRACTION_MULTIPLIER, MAGIC_REPLACERS, - getMagicOffsets, } from "core/src/utils/get-magic-offset"; import { IComposableStablePool, IERC20, IVault } from "core/src/abis"; import { @@ -244,23 +243,18 @@ export class BalancerDepositStrategy extends InterfaceStrategy { continue; } - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - vaultAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + vaultAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumbersLinkedAssets[i], - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round( FRACTION_MULTIPLIER * linkedAssetFractions[i] ), @@ -269,30 +263,27 @@ export class BalancerDepositStrategy extends InterfaceStrategy { }); } - const { offsets: balanceOfToOffsets } = getMagicOffsets({ - data: IERC20.encodeFunctionResult("balanceOf", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], }); - // ordered assets - // amounts (following same order) - // selfIndex - const { selfIndex, orderedAddresses } = this.getSelfIndex({ asset, assetStore, @@ -333,73 +324,64 @@ export class BalancerDepositStrategy extends InterfaceStrategy { console.log({ selfIndex, amountsMinusSelf, userData }); - const usedReplacers = MAGIC_REPLACERS.slice(0, amountsMinusSelf.length); - const { data: joinPoolEncodedCall, offsets: joinPoolFromOffsets } = - getMagicOffsets({ - data: IVault.encodeFunctionData("joinPool", [ - asset.callParams.poolId, // poolId - walletAddress, // sender - walletAddress, // recipient - [ - orderedAddresses, // assets - amounts, // maxAmountsIn - userData, // userData - false, // fromInternalBalance - ], - ]), - magicReplacers: [...usedReplacers, ...usedReplacers], // Each replacer appear once in amounts and once in userData. - }); - - const storeOperations: StoreOperations[] = []; + const storeOperations: StoreOperation[] = []; console.log({ storeNumbersLinkedAssets, - joinPoolEncodedCall, - joinPoolFromOffsets, linkedAssetFractions, mreplacers: MAGIC_REPLACERS.slice(0, amountsMinusSelf.length), }); for (const [i] of linkedAssets.entries()) { - console.log({ i1: i, i2: i + usedReplacers.length }); storeOperations.push({ storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumbersLinkedAssets[i], - secondaryStoreNumber: 0, - offset: joinPoolFromOffsets[i], + offsetReplacer: { replacer: MAGIC_REPLACERS[i], occurrence: 0 }, fraction: Math.round(linkedAssetFractions[i] * FRACTION_MULTIPLIER), }); storeOperations.push({ storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumbersLinkedAssets[i], - secondaryStoreNumber: 0, - offset: joinPoolFromOffsets[i + usedReplacers.length], + offsetReplacer: { replacer: MAGIC_REPLACERS[i], occurrence: 1 }, fraction: Math.round(linkedAssetFractions[i] * FRACTION_MULTIPLIER), }); } - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: vaultAddress, - stepEncodedCall: joinPoolEncodedCall, + encodedFunctionData: IVault.encodeFunctionData("joinPool", [ + asset.callParams.poolId, // poolId + walletAddress, // sender + walletAddress, // recipient + [ + orderedAddresses, // assets + amounts, // maxAmountsIn + userData, // userData + false, // fromInternalBalance + ], + ]), storeOperations, }); - routerOperation.steps.push({ + // + + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberPool, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberPool, secondaryStoreNumber: storeNumberTmp, - offset: 0, fraction: FRACTION_MULTIPLIER, }, ], @@ -427,24 +409,25 @@ export class BalancerDepositStrategy extends InterfaceStrategy { }); }); - const { offsets: balanceOfToOffsets } = getMagicOffsets({ - data: IERC20.encodeFunctionResult("balanceOf", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - asset.linkedAssets.map((la, i) => { const linkedAsset = assetStore.getAssetById(la.assetId); - routerOperation.steps.push({ + + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumbersTmp[i], - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], @@ -480,31 +463,28 @@ export class BalancerDepositStrategy extends InterfaceStrategy { ] ); - const { data: exitPoolEncodedCall, offsets: exitPoolFromOffsets } = - getMagicOffsets({ - data: IVault.encodeFunctionData("exitPool", [ - asset.callParams.poolId, // poolId - walletAddress, // sender - walletAddress, // recipient - [ - orderedAddresses, // assets - amounts, // maxAmountsIn - userData, // userData - false, // fromInternalBalance - ], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: vaultAddress, - stepEncodedCall: exitPoolEncodedCall, + encodedFunctionData: IVault.encodeFunctionData("exitPool", [ + asset.callParams.poolId, // poolId + walletAddress, // sender + walletAddress, // recipient + [ + orderedAddresses, // assets + amounts, // maxAmountsIn + userData, // userData + false, // fromInternalBalance + ], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberPool, - secondaryStoreNumber: 0, - offset: exitPoolFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, ], @@ -513,24 +493,26 @@ export class BalancerDepositStrategy extends InterfaceStrategy { asset.linkedAssets.map((la, i) => { const linkedAsset = assetStore.getAssetById(la.assetId); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumbersLinkedAssets[i], - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumbersLinkedAssets[i], secondaryStoreNumber: storeNumbersTmp[i], - offset: 0, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/BeefyDepositStrategy.ts b/core/src/asset-strategies/BeefyDepositStrategy.ts index a96acf4..0e3e2e8 100644 --- a/core/src/asset-strategies/BeefyDepositStrategy.ts +++ b/core/src/asset-strategies/BeefyDepositStrategy.ts @@ -6,7 +6,6 @@ import { getPrice, } from "../transaction/asset-type-strategies-helpers"; import { Contract } from "ethers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { IBeefyVaultV6, IERC20 } from "core/src/abis"; import { FRACTION_MULTIPLIER, @@ -104,90 +103,90 @@ export class BeefyDepositStrategy extends InterfaceStrategy { delta: variation, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - asset.address, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + asset.address, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(FRACTION_MULTIPLIER * newFraction), }, ], }); - const { offsets: balanceOfToOffsets } = getMagicOffsets({ - data: IERC20.encodeFunctionResult("balanceOf", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], }); - const { data: depositEncodedCall, offsets: depositFromOffsets } = - getMagicOffsets({ - data: IBeefyVaultV6.encodeFunctionData("deposit", [ - MAGIC_REPLACERS[0], // _amount - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: depositEncodedCall, + encodedFunctionData: IBeefyVaultV6.encodeFunctionData("deposit", [ + MAGIC_REPLACERS[0], // _amount + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: depositFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberTo, secondaryStoreNumber: storeNumberTmp, - offset: 0, fraction: FRACTION_MULTIPLIER, }, ], @@ -220,67 +219,63 @@ export class BeefyDepositStrategy extends InterfaceStrategy { }); }); - const { offsets: balanceOfToOffsets } = getMagicOffsets({ - data: IERC20.encodeFunctionResult("balanceOf", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], }); - const { data: withdrawEncodedCall, offsets: withdrawFromOffsets } = - getMagicOffsets({ - data: IBeefyVaultV6.encodeFunctionData("withdraw", [ - MAGIC_REPLACERS[0], // _shares - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: withdrawEncodedCall, + encodedFunctionData: IBeefyVaultV6.encodeFunctionData("withdraw", [ + MAGIC_REPLACERS[0], // _shares + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: withdrawFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, ], }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: IERC20.encodeFunctionData("balanceOf", [ + encodedFunctionData: IERC20.encodeFunctionData("balanceOf", [ walletAddress, ]), + encodedFunctionResult: IERC20.encodeFunctionResult("balanceOf", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: balanceOfToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberTo, secondaryStoreNumber: storeNumberTmp, - offset: 0, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/GammaDepositStrategy.ts b/core/src/asset-strategies/GammaDepositStrategy.ts index 257e4e1..ddf06c5 100644 --- a/core/src/asset-strategies/GammaDepositStrategy.ts +++ b/core/src/asset-strategies/GammaDepositStrategy.ts @@ -11,7 +11,6 @@ import { getPrice, } from "../transaction/asset-type-strategies-helpers"; import { Contract } from "ethers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { GammaRatiosCalculator, IERC20, @@ -179,56 +178,49 @@ export class GammaDepositStrategy extends InterfaceStrategy { const hypervisorRouterAddress = await hypervisor.whitelistedAddress(); const config = await loadConfig(); - const { - data: calculateRatiosEncodedCall, - offsets: calculateRatiosFromOffsets, - } = getMagicOffsets({ - data: GammaRatiosCalculator.encodeFunctionData("calculateRatios", [ - [linkedAssetAddresses[0], linkedAssetAddresses[1]], - [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - asset.address, - hypervisorRouterAddress, // hypervisorRouterAddress - ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - const { offsets: calculateRatiosToOffsets } = getMagicOffsets({ - data: GammaRatiosCalculator.encodeFunctionResult("calculateRatios", [ - MAGIC_REPLACERS[0], - MAGIC_REPLACERS[1], - ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: config.networks[chainId].gammaRatiosCalculator, - stepEncodedCall: calculateRatiosEncodedCall, + encodedFunctionData: GammaRatiosCalculator.encodeFunctionData( + "calculateRatios", + [ + [linkedAssetAddresses[0], linkedAssetAddresses[1]], + [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], + asset.address, + hypervisorRouterAddress, // hypervisorRouterAddress + ] + ), + encodedFunctionResult: GammaRatiosCalculator.encodeFunctionResult( + "calculateRatios", + [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]] + ), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom0, - secondaryStoreNumber: 0, - offset: calculateRatiosFromOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(linkedAssetFractions[0] * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom1, - secondaryStoreNumber: 0, - offset: calculateRatiosFromOffsets[1], + + offsetReplacer: { replacer: MAGIC_REPLACERS[1], occurrence: 0 }, fraction: Math.round(linkedAssetFractions[1] * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp[0], - secondaryStoreNumber: 0, - offset: calculateRatiosToOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTmp[1], - secondaryStoreNumber: 0, - offset: calculateRatiosToOffsets[1], + + offsetReplacer: { replacer: MAGIC_REPLACERS[1], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], @@ -237,86 +229,69 @@ export class GammaDepositStrategy extends InterfaceStrategy { for (const [i, la] of asset.linkedAssets.entries()) { const linkedAsset = assetStore.getAssetById(la.assetId); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - asset.address, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + asset.address, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberTmp[i], - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], }); } - const { data: depositEncodedCall, offsets: depositFromOffsets } = - getMagicOffsets({ - data: IHypervisorRouter.encodeFunctionData("deposit", [ - MAGIC_REPLACERS[0], - MAGIC_REPLACERS[1], - walletAddress, - asset.address, - [0, 0, 0, 0], // minIn - ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - - const { offsets: depositToOffsets } = getMagicOffsets({ - data: IHypervisorRouter.encodeFunctionResult("deposit", [ + routerOperation.addStep({ + stepAddress: hypervisorRouterAddress, + encodedFunctionData: IHypervisorRouter.encodeFunctionData("deposit", [ MAGIC_REPLACERS[0], + MAGIC_REPLACERS[1], + walletAddress, + asset.address, + [0, 0, 0, 0], // minIn ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ - stepAddress: hypervisorRouterAddress, - stepEncodedCall: depositEncodedCall, + encodedFunctionResult: IHypervisorRouter.encodeFunctionResult( + "deposit", + [MAGIC_REPLACERS[0]] + ), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberTmp[0], - secondaryStoreNumber: 0, - offset: depositFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberTmp[1], - secondaryStoreNumber: 0, - offset: depositFromOffsets[1], + offsetReplacer: { replacer: MAGIC_REPLACERS[1], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberFrom0, secondaryStoreNumber: storeNumberTmp[0], - offset: 0, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.SubtractStoreFromStore, storeNumber: storeNumberFrom1, secondaryStoreNumber: storeNumberTmp[1], - offset: 0, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: depositToOffsets[0], + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], @@ -351,48 +326,47 @@ export class GammaDepositStrategy extends InterfaceStrategy { }); }); - const { data: withdrawEncodedCall, offsets: withdrawFromOffsets } = - getMagicOffsets({ - data: IHypervisor.encodeFunctionData("withdraw", [ - MAGIC_REPLACERS[0], - walletAddress, - walletAddress, - [0, 0, 0, 0], // minAmounts - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: withdrawToOffsets } = getMagicOffsets({ - data: IHypervisor.encodeFunctionResult("withdraw", [ + routerOperation.addStep({ + stepAddress: asset.address, + encodedFunctionData: IHypervisor.encodeFunctionData("withdraw", [ + MAGIC_REPLACERS[0], + walletAddress, + walletAddress, + [0, 0, 0, 0], // minAmounts + ]), + encodedFunctionResult: IHypervisor.encodeFunctionResult("withdraw", [ MAGIC_REPLACERS[0], MAGIC_REPLACERS[1], ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - - routerOperation.steps.push({ - stepAddress: asset.address, - stepEncodedCall: withdrawEncodedCall, storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: withdrawFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo0, - secondaryStoreNumber: 0, - offset: withdrawToOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo1, - secondaryStoreNumber: 0, - offset: withdrawToOffsets[1], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[1], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/SavingsDaiDepositStrategy.ts b/core/src/asset-strategies/SavingsDaiDepositStrategy.ts index d87c97d..233817b 100644 --- a/core/src/asset-strategies/SavingsDaiDepositStrategy.ts +++ b/core/src/asset-strategies/SavingsDaiDepositStrategy.ts @@ -4,7 +4,6 @@ import { fetchPriceData, getPrice, } from "../transaction/asset-type-strategies-helpers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { IERC20, SavingsDai } from "core/src/abis"; import { FRACTION_MULTIPLIER, @@ -83,61 +82,45 @@ export class SavingsDaiDepositStrategy extends InterfaceStrategy { delta: variation, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - asset.address, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + asset.address, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberDai, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(FRACTION_MULTIPLIER * newFraction), }, ], }); - const { data: depositEncodedCall, offsets: depositFromOffsets } = - getMagicOffsets({ - data: SavingsDai.encodeFunctionData("deposit", [ - MAGIC_REPLACERS[0], // assets - walletAddress, // receiver - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: depositToOffsets } = getMagicOffsets({ - data: SavingsDai.encodeFunctionResult("deposit", [ + routerOperation.addStep({ + stepAddress: asset.address, + encodedFunctionData: SavingsDai.encodeFunctionData("deposit", [ + MAGIC_REPLACERS[0], // assets + walletAddress, // receiver + ]), + encodedFunctionResult: SavingsDai.encodeFunctionResult("deposit", [ MAGIC_REPLACERS[0], // shares ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ - stepAddress: asset.address, - stepEncodedCall: depositEncodedCall, storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberDai, - secondaryStoreNumber: 0, - offset: depositFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberSDai, - secondaryStoreNumber: 0, - offset: depositToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: FRACTION_MULTIPLIER, }, ], @@ -160,37 +143,33 @@ export class SavingsDaiDepositStrategy extends InterfaceStrategy { }); }); - const { data: redeemEncodedCall, offsets: redeemFromOffsets } = - getMagicOffsets({ - data: SavingsDai.encodeFunctionData("redeem", [ - MAGIC_REPLACERS[0], // shares - walletAddress, // receiver - walletAddress, // owner - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: redeemToOffsets } = getMagicOffsets({ - data: SavingsDai.encodeFunctionResult("redeem", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: asset.address, - stepEncodedCall: redeemEncodedCall, + encodedFunctionData: SavingsDai.encodeFunctionData("redeem", [ + MAGIC_REPLACERS[0], // shares + walletAddress, // receiver + walletAddress, // owner + ]), + encodedFunctionResult: SavingsDai.encodeFunctionResult("redeem", [ + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberSDai, - secondaryStoreNumber: 0, - offset: redeemFromOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberDai, - secondaryStoreNumber: 0, - offset: redeemToOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/asset-strategies/UniswapV2LiquidityStrategy.ts b/core/src/asset-strategies/UniswapV2LiquidityStrategy.ts index 5488671..6681f17 100644 --- a/core/src/asset-strategies/UniswapV2LiquidityStrategy.ts +++ b/core/src/asset-strategies/UniswapV2LiquidityStrategy.ts @@ -6,7 +6,6 @@ import { getPrice, } from "../transaction/asset-type-strategies-helpers"; import { Contract } from "ethers"; -import { getMagicOffsets } from "core/src/utils/get-magic-offset"; import { IERC20, UniswapV2Pair, UniswapV2Router02 } from "core/src/abis"; import { FRACTION_MULTIPLIER, @@ -143,23 +142,20 @@ export class UniswapV2LiquidityStrategy extends InterfaceStrategy { continue; } - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - routerAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: linkedAsset.address, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + routerAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumbersLinkedAssets[i], - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round( FRACTION_MULTIPLIER * linkedAssetFractions[i] ), @@ -174,73 +170,74 @@ export class UniswapV2LiquidityStrategy extends InterfaceStrategy { throw new Error("Failed to fetch the latest block"); } - const { - data: addLiquidityEncodedCall, - offsets: addLiquidityFromOffsets, - } = getMagicOffsets({ - data: UniswapV2Router02.encodeFunctionData("addLiquidity", [ - linkedAssets[0].address, // address tokenA, - linkedAssets[1].address, // address tokenB, - MAGIC_REPLACERS[0], // uint amountADesired, - MAGIC_REPLACERS[1], // uint amountBDesired, - 1, // uint amountAMin, // TODO: set minimum amount - 1, // uint amountBMin, // TODO: set minimum amount - walletAddress, // address to, - block.timestamp + 100000, // uint deadline - ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - - const { offsets: addLiquidityToOffsets } = getMagicOffsets({ - data: UniswapV2Router02.encodeFunctionResult("addLiquidity", [ - MAGIC_REPLACERS[0], - MAGIC_REPLACERS[1], - MAGIC_REPLACERS[2], - ]), - magicReplacers: [ - MAGIC_REPLACERS[0], - MAGIC_REPLACERS[1], - MAGIC_REPLACERS[2], - ], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: routerAddress, - stepEncodedCall: addLiquidityEncodedCall, + encodedFunctionData: UniswapV2Router02.encodeFunctionData( + "addLiquidity", + [ + linkedAssets[0].address, // address tokenA, + linkedAssets[1].address, // address tokenB, + MAGIC_REPLACERS[0], // uint amountADesired, + MAGIC_REPLACERS[1], // uint amountBDesired, + 1, // uint amountAMin, // TODO: set minimum amount + 1, // uint amountBMin, // TODO: set minimum amount + walletAddress, // address to, + block.timestamp + 100000, // uint deadline + ] + ), + encodedFunctionResult: UniswapV2Router02.encodeFunctionResult( + "addLiquidity", + [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1], MAGIC_REPLACERS[2]] + ), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumbersLinkedAssets[0], - secondaryStoreNumber: 0, - offset: addLiquidityFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(linkedAssetFractions[0] * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumbersLinkedAssets[1], - secondaryStoreNumber: 0, - offset: addLiquidityFromOffsets[1], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[1], + occurrence: 0, + }, fraction: Math.round(linkedAssetFractions[1] * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultSubtractStore, storeNumber: storeNumbersLinkedAssets[0], - secondaryStoreNumber: 0, - offset: addLiquidityToOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultSubtractStore, storeNumber: storeNumbersLinkedAssets[1], - secondaryStoreNumber: 0, - offset: addLiquidityToOffsets[1], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[1], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberPool, - secondaryStoreNumber: 0, - offset: addLiquidityToOffsets[2], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[2], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], @@ -269,53 +266,53 @@ export class UniswapV2LiquidityStrategy extends InterfaceStrategy { throw new Error("Failed to fetch the latest block"); } - const { - data: removeLiquidityEncodedCall, - offsets: removeLiquidityFromOffsets, - } = getMagicOffsets({ - data: UniswapV2Router02.encodeFunctionData("removeLiquidity", [ - linkedAssets[0].address, // tokenA - linkedAssets[1].address, // tokenB - MAGIC_REPLACERS[0], // liquidity, - 1, // amountAMin // TODO: set minimum amount - 1, // amountBMin // TODO: set minimum amount - walletAddress, // address to, - block.timestamp + 100000, // uint deadline - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - const { offsets: removeLiquidityToOffsets } = getMagicOffsets({ - data: UniswapV2Router02.encodeFunctionResult("removeLiquidity", [ - MAGIC_REPLACERS[0], - MAGIC_REPLACERS[1], - ]), - magicReplacers: [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]], - }); - - routerOperation.steps.push({ + routerOperation.addStep({ stepAddress: routerAddress, - stepEncodedCall: removeLiquidityEncodedCall, + encodedFunctionData: UniswapV2Router02.encodeFunctionData( + "removeLiquidity", + [ + linkedAssets[0].address, // tokenA + linkedAssets[1].address, // tokenB + MAGIC_REPLACERS[0], // liquidity, + 1, // amountAMin // TODO: set minimum amount + 1, // amountBMin // TODO: set minimum amount + walletAddress, // address to, + block.timestamp + 100000, // uint deadline + ] + ), + encodedFunctionResult: UniswapV2Router02.encodeFunctionResult( + "removeLiquidity", + [MAGIC_REPLACERS[0], MAGIC_REPLACERS[1]] + ), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberPool, - secondaryStoreNumber: 0, - offset: removeLiquidityFromOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: Math.round(newFraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumbersLinkedAssets[0], - secondaryStoreNumber: 0, - offset: removeLiquidityToOffsets[0], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[0], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumbersLinkedAssets[1], - secondaryStoreNumber: 0, - offset: removeLiquidityToOffsets[1], + + offsetReplacer: { + replacer: MAGIC_REPLACERS[1], + occurrence: 0, + }, fraction: FRACTION_MULTIPLIER, }, ], diff --git a/core/src/path/exchanges.ts b/core/src/path/exchanges.ts index 82fdff6..e08548a 100644 --- a/core/src/path/exchanges.ts +++ b/core/src/path/exchanges.ts @@ -5,7 +5,6 @@ import { Provider } from "ethers"; import { FRACTION_MULTIPLIER, MAGIC_REPLACERS, - getMagicOffsets, } from "../utils/get-magic-offset"; interface BuildSwapOutputParams { @@ -63,24 +62,17 @@ export class Paraswap extends Exchange { address: path.toToken, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - path.params.approveAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - output.steps.push({ + output.addStep({ stepAddress: path.fromToken, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + path.params.approveAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), }, ], @@ -101,8 +93,9 @@ export class Paraswap extends Exchange { } if (decodedData?.name === "megaSwap") { - const { data, offsets: fromOffsets } = getMagicOffsets({ - data: IParaswap.encodeFunctionData("megaSwap", [ + output.addStep({ + stepAddress: path.params.paraswapAddress as string, + encodedFunctionData: IParaswap.encodeFunctionData("megaSwap", [ [ path.fromToken, // fromToken MAGIC_REPLACERS[0], // fromAmount @@ -119,21 +112,30 @@ export class Paraswap extends Exchange { decodedData.args[0].uuid, // uuid ], ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - swapEncodedCall = data; - swapFromOffset = fromOffsets[0]; - - const { offsets: toOffsets } = getMagicOffsets({ - data: IParaswap.encodeFunctionResult("megaSwap", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], + encodedFunctionResult: IParaswap.encodeFunctionResult("megaSwap", [ + MAGIC_REPLACERS[0], + ]), + storeOperations: [ + { + storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, + storeNumber: storeNumberFrom, + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, + fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), + }, + { + storeOpType: StoreOpType.RetrieveResultAddStore, + storeNumber: storeNumberTo, + + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, + fraction: 0, + }, + ], }); - - swapToOffset = toOffsets[0]; } else if (decodedData?.name === "multiSwap") { - const { data, offsets: fromOffsets } = getMagicOffsets({ - data: IParaswap.encodeFunctionData("multiSwap", [ + output.addStep({ + stepAddress: path.params.paraswapAddress as string, + encodedFunctionData: IParaswap.encodeFunctionData("multiSwap", [ [ path.fromToken, // fromToken MAGIC_REPLACERS[0], // fromAmount @@ -150,43 +152,28 @@ export class Paraswap extends Exchange { decodedData.args[0].uuid, // uuid ], ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - swapEncodedCall = data; - swapFromOffset = fromOffsets[0]; - - const { offsets: toOffsets } = getMagicOffsets({ - data: IParaswap.encodeFunctionResult("multiSwap", [MAGIC_REPLACERS[0]]), - magicReplacers: [MAGIC_REPLACERS[0]], + encodedFunctionResult: IParaswap.encodeFunctionResult("multiSwap", [ + MAGIC_REPLACERS[0], + ]), + storeOperations: [ + { + storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, + storeNumber: storeNumberFrom, + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, + fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), + }, + { + storeOpType: StoreOpType.RetrieveResultAddStore, + storeNumber: storeNumberTo, + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, + fraction: 0, + }, + ], }); - - swapToOffset = toOffsets[0]; } else { throw new Error(`Paraswap: unimplemented function ${decodedData?.name}`); } - output.steps.push({ - stepAddress: path.params.paraswapAddress as string, - stepEncodedCall: swapEncodedCall, - storeOperations: [ - { - storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, - storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: swapFromOffset, - fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), - }, - { - storeOpType: StoreOpType.RetrieveResultAddStore, - storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: swapToOffset, - fraction: 0, - }, - ], - }); - console.dir( { paraswapPath: path, @@ -237,24 +224,17 @@ export class ZeroX extends Exchange { address: path.toToken, }); - const { data: approveEncodedCall, offsets: approveFromOffsets } = - getMagicOffsets({ - data: IERC20.encodeFunctionData("approve", [ - path.params.approveAddress, - MAGIC_REPLACERS[0], - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - output.steps.push({ + output.addStep({ stepAddress: path.fromToken, - stepEncodedCall: approveEncodedCall, + encodedFunctionData: IERC20.encodeFunctionData("approve", [ + path.params.approveAddress, + MAGIC_REPLACERS[0], + ]), storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCall, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: approveFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), }, ], @@ -265,42 +245,29 @@ export class ZeroX extends Exchange { path.params.data ); - const { data: swapEncodedCall, offsets: swapFromOffsets } = getMagicOffsets( - { - data: ZeroXERC20.encodeFunctionData("transformERC20", [ - path.fromToken, // inputToken - path.toToken, // outputToken - MAGIC_REPLACERS[0], // inputTokenAmount - 1, // minOutputTokenAmount - decodedTransformERC20[4], // transformations - ]), - magicReplacers: [MAGIC_REPLACERS[0]], - } - ); - - const { offsets: swapToOffsets } = getMagicOffsets({ - data: ZeroXERC20.encodeFunctionResult("transformERC20", [ + output.addStep({ + stepAddress: path.params.zeroXAddress as string, + encodedFunctionData: ZeroXERC20.encodeFunctionData("transformERC20", [ + path.fromToken, // inputToken + path.toToken, // outputToken + MAGIC_REPLACERS[0], // inputTokenAmount + 1, // minOutputTokenAmount + decodedTransformERC20[4], // transformations + ]), + encodedFunctionResult: ZeroXERC20.encodeFunctionResult("transformERC20", [ MAGIC_REPLACERS[0], ]), - magicReplacers: [MAGIC_REPLACERS[0]], - }); - - output.steps.push({ - stepAddress: path.params.zeroXAddress as string, - stepEncodedCall: swapEncodedCall, storeOperations: [ { storeOpType: StoreOpType.RetrieveStoreAssignCallSubtract, storeNumber: storeNumberFrom, - secondaryStoreNumber: 0, - offset: swapFromOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: Math.round(path.fraction * FRACTION_MULTIPLIER), }, { storeOpType: StoreOpType.RetrieveResultAddStore, storeNumber: storeNumberTo, - secondaryStoreNumber: 0, - offset: swapToOffsets[0], + offsetReplacer: { replacer: MAGIC_REPLACERS[0], occurrence: 0 }, fraction: 0, }, ], diff --git a/core/src/transaction/types.ts b/core/src/transaction/types.ts index eb9d391..016e5e8 100644 --- a/core/src/transaction/types.ts +++ b/core/src/transaction/types.ts @@ -306,7 +306,15 @@ export enum StoreOpType { AddStoreToStore, // 7 } -export type StoreOperations = { +export type StoreOperation = { + storeOpType: StoreOpType; + storeNumber: BigNumberish; + secondaryStoreNumber?: BigNumberish; + offsetReplacer?: { replacer: string; occurrence: BigNumberish }; + fraction: BigNumberish; +}; + +export type DetailedStoreOperation = { storeOpType: StoreOpType; storeNumber: BigNumberish; secondaryStoreNumber?: BigNumberish; @@ -316,7 +324,7 @@ export type StoreOperations = { export type DetailedStep = { stepAddress: string; stepEncodedCall: string; - storeOperations: StoreOperations[]; + storeOperations: DetailedStoreOperation[]; }; export class DetailedStore { assetId?: string; @@ -445,6 +453,136 @@ export class RouterOperation { this.stores = new DetailedStores(); } + addStep({ + stepAddress, + encodedFunctionData, + encodedFunctionResult, + storeOperations, + }: { + stepAddress: string; + encodedFunctionData: string; + encodedFunctionResult?: string; + storeOperations: StoreOperation[]; + }) { + function nthIndex(str, pat, n) { + console.log({ str, pat, n }); + + var L = str.length, + i = -1; + while (n-- >= 0 && i++ < L) { + i = str.indexOf(pat, i); + if (i < 0) break; + } + + console.log({ i }); + return i; + } + + const detailedStoreOperations: DetailedStoreOperation[] = + storeOperations.map((storeOperation) => { + if ( + storeOperation.storeOpType === StoreOpType.RetrieveStoreAssignCall || + storeOperation.storeOpType === + StoreOpType.RetrieveStoreAssignCallSubtract + ) { + const replacerWithout0x = + storeOperation.offsetReplacer.replacer.substring(2); + const idx = nthIndex( + encodedFunctionData, + replacerWithout0x, + storeOperation.offsetReplacer.occurrence + ); + if (idx === -1) { + throw new Error( + `Replacer ${storeOperation.offsetReplacer.replacer} not found in data ${encodedFunctionData}` + ); + } + const offset = idx / 2 - 1; + return { + storeOpType: storeOperation.storeOpType, + fraction: storeOperation.fraction, + storeNumber: storeOperation.storeNumber, + secondaryStoreNumber: 0, + offset, + }; + } else if ( + storeOperation.storeOpType === StoreOpType.RetrieveResultAddStore || + storeOperation.storeOpType === StoreOpType.RetrieveResultSubtractStore + ) { + const replacerWithout0x = + storeOperation.offsetReplacer.replacer.substring(2); + const idx = nthIndex( + encodedFunctionResult, + replacerWithout0x, + storeOperation.offsetReplacer.occurrence + ); + if (idx === -1) { + throw new Error( + `Replacer ${storeOperation.offsetReplacer.replacer} not found in data ${encodedFunctionResult}` + ); + } + const offset = idx / 2 - 1; + return { + storeOpType: storeOperation.storeOpType, + fraction: storeOperation.fraction, + storeNumber: storeOperation.storeNumber, + secondaryStoreNumber: 0, + offset, + }; + } else if ( + storeOperation.storeOpType === StoreOpType.RetrieveStoreAssignValue || + storeOperation.storeOpType === + StoreOpType.RetrieveStoreAssignValueSubtract + ) { + return { + storeOpType: storeOperation.storeOpType, + fraction: storeOperation.fraction, + storeNumber: storeOperation.storeNumber, + secondaryStoreNumber: 0, + offset: 0, + }; + } else if ( + storeOperation.storeOpType === StoreOpType.AddStoreToStore || + storeOperation.storeOpType === StoreOpType.SubtractStoreFromStore + ) { + return { + storeOpType: storeOperation.storeOpType, + fraction: storeOperation.fraction, + storeNumber: storeOperation.storeNumber, + secondaryStoreNumber: storeOperation.secondaryStoreNumber, + offset: 0, + }; + } else { + throw new Error( + `Invalid store operation type ${storeOperation.storeOpType}` + ); + } + }); + + let stepEncodedCall = encodedFunctionData; + storeOperations.map((storeOperation) => { + if ( + storeOperation.storeOpType === StoreOpType.RetrieveStoreAssignCall || + storeOperation.storeOpType === + StoreOpType.RetrieveStoreAssignCallSubtract + ) { + const replacerWithout0x = + storeOperation.offsetReplacer.replacer.substring(2); + const zeroReplacer = "0".repeat(replacerWithout0x.length); + stepEncodedCall = stepEncodedCall.replaceAll( + replacerWithout0x, + zeroReplacer + ); + } + }); + + this.steps.push({ + stepAddress, + stepEncodedCall, + storeOperations: detailedStoreOperations, + }); + } + getTransactionDetails(): { steps: { stepAddress: string; diff --git a/core/src/utils/get-magic-offset.ts b/core/src/utils/get-magic-offset.ts index ea56a17..946a837 100644 --- a/core/src/utils/get-magic-offset.ts +++ b/core/src/utils/get-magic-offset.ts @@ -1,35 +1,3 @@ -export function getMagicOffsets({ - data, - magicReplacers, -}: { - data: string; - magicReplacers: string[]; -}): { data: string; offsets: number[] } { - let updatedData = data; - const offsets: number[] = []; - - for (const magicReplacer of magicReplacers) { - const magicReplacerWithout0x = magicReplacer.substring(2); - const indexOf = updatedData.indexOf(magicReplacerWithout0x); - - if (indexOf === -1) { - throw new Error(`Magic replacer ${magicReplacer} not found in data`); - } - - const before = updatedData.substring(0, indexOf); - const after = updatedData.substring(indexOf + 64); - const zeroReplacer = "0".repeat(64); - - updatedData = before + zeroReplacer + after; - offsets.push(indexOf / 2 - 1); - } - - return { - data: updatedData, - offsets: offsets, - }; -} - export const MAGIC_REPLACERS = [ "0x7fa9b53d120de9cd66856522bcf6d4a7797019996b607a7c9da51787beed38d1", "0x7f797936f1e9ca0b2ab9736276d6a755468ef28a6cefe78c0c0c3b1903f97a5f",