From 9966238464079dbb7349ff207bdb68452b16c226 Mon Sep 17 00:00:00 2001 From: Silo Chad Date: Mon, 3 Jul 2023 11:01:17 -0500 Subject: [PATCH] when converting, ignore small ratio diffs and prioritize season --- projects/ui/src/lib/Beanstalk/Silo/Convert.ts | 5 ++-- projects/ui/src/lib/Beanstalk/Silo/Utils.ts | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/projects/ui/src/lib/Beanstalk/Silo/Convert.ts b/projects/ui/src/lib/Beanstalk/Silo/Convert.ts index 9c6fc5f519..96a7e4dd75 100644 --- a/projects/ui/src/lib/Beanstalk/Silo/Convert.ts +++ b/projects/ui/src/lib/Beanstalk/Silo/Convert.ts @@ -1,8 +1,7 @@ import BigNumber from 'bignumber.js'; -import { defaultAbiCoder } from 'ethers/lib/utils'; import { Token } from '~/classes'; import { DepositCrate } from '~/state/farmer/silo'; -import { sortCratesByBDVRatio, sortCratesBySeason } from './Utils'; +import { sortConvertCratesByBest, sortCratesBySeason } from './Utils'; import { STALK_PER_SEED_PER_SEASON } from '~/util'; export enum ConvertKind { @@ -47,7 +46,7 @@ export function selectCratesToConvert( : /// LP -> BEAN: use the crates with the lowest [BDV/Amount] ratio first. /// Since LP deposits can have varying BDV, the best option for the Farmer /// is to increase the BDV of their existing lowest-BDV crates. - sortCratesByBDVRatio(depositedCrates, 'asc'); + sortConvertCratesByBest(depositedCrates); /// FIXME: symmetry with `Withdraw` sortedCrates.some((crate) => { diff --git a/projects/ui/src/lib/Beanstalk/Silo/Utils.ts b/projects/ui/src/lib/Beanstalk/Silo/Utils.ts index 8a5f0e0ea9..7ef739cc0e 100644 --- a/projects/ui/src/lib/Beanstalk/Silo/Utils.ts +++ b/projects/ui/src/lib/Beanstalk/Silo/Utils.ts @@ -25,3 +25,33 @@ export function sortCratesByBDVRatio( return m * _b.minus(_a).toNumber(); }); } + +/** + * Order crates by what's best to convert. + * + * Pre Silo V3, the season sorting is important to minimize potential stalk loss. + * After Silo V3, BDV ratio is the only thing that matters. + */ +export function sortConvertCratesByBest( + crates: T[], +) { + return [...crates].sort((a, b) => { + // Calculate the BDV ratio for each crate. + // Fix to 4 decimal places to avoid small rounding differences from resorting. + const _a = Number(a.bdv.div(a.amount).toPrecision(4)); + const _b = Number(b.bdv.div(b.amount).toPrecision(4)); + + // sorting a - b puts lowest ratio crates first, which is desirable + const delta = _a - _b; + + // If the BDV ratio is the same, sort more recent seasons (higher numbers) first. + // All else equal, pre-Silo V3 users would rather convert more recent crates. + if (delta === 0) { + // sorting b.season - a.season sorts higher (more recent) seasons first, + // which is desirable + return b.season.minus(a.season).toNumber(); + } + + return delta; + }); +}