Let's say we have a volume-based fee structure that takes a 5% fee of a transaction from $0, and a 2% fee at $1000, with the intermediate amount being a linear interpolation of these two points - for example, $500 would equate to a 3.5% fee.
The crux of the question comes when we want to calculate the inverse. I.e. instead of "if I give $250, what do I receive?", we need to answer "if I need exactly $250, what do I need to give?".
Given the linear interpolation of the fees, simply taking the inverse of the amount is no longer possible, as we would end up with a slightly different fee rate.
An example of what I've tried so far, which due to the above doesn't quite work. First I find out what I end up getting if I give $250.
feeRate = 5 - (5 - 2) * 250/1000 = 4.25%
amountOut = 250 * (1 - 4.25/100) = $239.375
Then, I want to be able to calculate the inverse, which should give me back the original $250:
feeRate = 5 - (5 - 2) * (239.375/1000) = 4.281875%
amountOut = 239.375 * (1 / (1 - 4.281875 / 100)) ~= $250.083
Is there any way, creative or not, to make sure this inverse way of calculating the fee is possible?
I've also tried "chunking" the linear interpolation, i.e. making it into a series of steps instead of completely linear, but that just made it work for the amounts where both fell onto the same steps, but made it even less accurate when they didn't.
As long as any kind of solution is programmable, I'd be satisfied, even if it requires some sort of multi-step process/brute forcing. Herein also if rounding the fee percent to, for example, 2 decimals makes it easier, that wouldn't be a problem either.
Given
feeRate = 5 - (5 - 2) * 250/1000 = 4.25%
amountOut = 250 * (1 - 4.25/100) = $239.375
Let o be the original amount and a be the "out" (interest-adjusted) amount.
a = o(1 - (5 - (5 - 2)o/1000)/100))
= o(1 - 5/100) + o^2(5 - 2)/1000/100
^^^ order-1 term ^^^ order-2 term
This is a quadratic equation. Find the coefficients to put it into this form:
a x^2 + b x + c = 0
Then use the quadratic equation to get your solution. The analytic solution is (in Python notation)
(5/100 - 1 + sqrt((1 - 5/100)**2 + 4e-5*(5 - 2)*239.375))/2/(5 - 2)*1e5
Adding variables i0=2, i1=5, a=239.375 for this to be programmable:
o = (i1/100 - 1 + sqrt((1 - i1/100)**2 + 4e-5*(i1 - i0)*a))*.5e5/(i1 - i0)
This is the non-creative solution. There are plenty of creative solutions, none of which you should use.