Skip to content

Commit

Permalink
gas optimisations on the escrow curve
Browse files Browse the repository at this point in the history
  • Loading branch information
jordaniza committed Sep 25, 2024
1 parent 6fee3fc commit 7bc4ef2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 41 deletions.
8 changes: 5 additions & 3 deletions src/escrow/increasing/QuadraticIncreasingEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ contract QuadraticIncreasingEscrow is
int256 t = SignedFixedPointMath.toFP(timeElapsed.toInt256());

// bias = a.t^2 + b.t + c
int256 bias = quadratic.mul(t.pow(2e18)).add(linear.mul(t)).add(const);
int256 tSquared = t.mul(t); // t*t much more gas efficient than t.pow(SD2)
int256 bias = quadratic.mul(tSquared).add(linear.mul(t)).add(const);

// never return negative values
// in the increasing case, this should never happen
Expand Down Expand Up @@ -297,9 +298,10 @@ contract QuadraticIncreasingEscrow is
bool isExiting = amount == 0;

if (!isExiting) {
uNew.coefficients = _getCoefficients(amount);
int256[3] memory coefficients = _getCoefficients(amount);
// for a new lock, write the base bias (elapsed == 0)
uNew.bias = getBias(0, amount);
uNew.coefficients = coefficients;
uNew.bias = _getBias(0, coefficients);
}
// write the new timestamp - in the case of an increasing curve
// we align the checkpoint to the start of the upcoming deposit interval
Expand Down
8 changes: 5 additions & 3 deletions test/e2e.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,10 @@ contract TestE2E is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveUserSt
vm.warp(block.timestamp + 1);
// python: 1067.784256559766831104
// solmate: 1067.784196491481599990
// solmate(2):1067.784196491481600000
assertEq(
curve.votingPowerAt(tokenId, block.timestamp),
1067784196491481599990,
1067784196491481600000,
"Balance incorrect after warmup"
);
assertEq(curve.isWarm(tokenId), true, "Still warming up");
Expand All @@ -304,9 +305,10 @@ contract TestE2E is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveUserSt
vm.warp(start + clock.epochDuration());
// python: 1428.571428571428683776
// solmate: 1428.570120419660799763
// solmate(2): 1428.570120419660800000
assertEq(
curve.votingPowerAt(tokenId, block.timestamp),
1428570120419660799763,
1428570120419660800000,
"Balance incorrect after p1"
);

Expand All @@ -316,7 +318,7 @@ contract TestE2E is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveUserSt
vm.warp(start + clock.epochDuration() * 5 + 30);
assertEq(
curve.votingPowerAt(tokenId, block.timestamp),
5999967296216703996928,
5999967296216704000000,
"Balance incorrect after p6"
);
}
Expand Down
69 changes: 35 additions & 34 deletions test/escrow/curve/QuadraticCurveMath.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,31 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {

console.log("Coefficients: %st^2 + %st + %s", quadratic, linear, const);

// for (uint i; i <= 6; i++) {
// uint period = 2 weeks * i;
// console.log(
// "Period: %d Voting Power : %s",
// i,
// curve.getBiasUnbound(period, 100e18) / 1e18
// );
// console.log(
// "Period: %d Voting Power Bound: %s",
// i,
// curve.getBias(period, 100e18) / 1e18
// );
// console.log(
// "Period: %d Voting Power Raw: %s\n",
// i,
// curve.getBiasUnbound(period, 100e18)
// );
// }
//
// uncomment to see the full curve
for (uint i; i <= 14 * 6; i++) {
uint day = i * 1 days;
uint week = day / 7 days;
uint period = day / 2 weeks;

console.log("[Day: %d | Week %d | Period %d]", i, week, period);
console.log("Voting Power : %s", curve.getBias(day, 100e18) / 1e18);
console.log("Voting Power (raw): %s\n", curve.getBias(day, 100e18));
for (uint i; i <= 6; i++) {
uint period = 2 weeks * i;
console.log(
"Period: %d Voting Power : %s",
i,
curve.getBias(period, 100e18) / 1e18
);
console.log(
"Period: %d Voting Power Bound: %s",
i,
curve.getBias(period, 100e18) / 1e18
);
console.log("Period: %d Voting Power Raw: %s\n", i, curve.getBias(period, 100e18));
}

// uncomment to see the full curve
// for (uint i; i <= 14 * 6; i++) {
// uint day = i * 1 days;
// uint week = day / 7 days;
// uint period = day / 2 weeks;

// console.log("[Day: %d | Week %d | Period %d]", i, week, period);
// console.log("Voting Power : %s", curve.getBias(day, 100e18) / 1e18);
// console.log("Voting Power (raw): %s\n", curve.getBias(day, 100e18));
// }
}

// write a new checkpoint
Expand Down Expand Up @@ -109,19 +105,22 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {

// excel: 449.206158900000000000
// solmate: 449.206133622001394300
// solmate (optimized): 449.06723257244469756
// python: 449.206158892128337920
// solmate (xmulx): 449.206133622001394304
assertEq(
curve.votingPowerAt(tokenIdFirst, block.timestamp),
449206133622001394300,
449206133622001394304,
"Balance incorrect after warmup"
);
assertEq(curve.isWarm(tokenIdFirst), true, "Still warming up");

// excel: 1_067_784_257_000000000000000000
// solmate: 1_067_784_196_491481599990798396
// python: 1_067_784_256_559766801878089728
// solmate2: 1_067_784_196_491481600000000000
assertEq(
curve.votingPowerAt(tokenIdSecond, block.timestamp),
1067784196491481599990798396,
1067784196491481600000000000,
"Balance incorrect after warmup II"
);

Expand All @@ -130,14 +129,16 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {
// excel: 600.985714300000000000
// PRB: 600.985163959347100568
// solmate: 600.985163959347101852
// python : 600.985714285714341888
// solmate2: 600.985163959347101952
assertEq(
curve.votingPowerAt(tokenIdFirst, block.timestamp),
600985163959347101852,
600985163959347101952,
"Balance incorrect after p1"
);

uint256 expectedMaxI = 2524126241845405204467;
uint256 expectedMaxII = 5999967296216703996928705792;
uint256 expectedMaxI = 2524126241845405205760;
uint256 expectedMaxII = 5999967296216704000000000000;

// warp to the final period
// TECHNICALLY, this should finish at exactly 5 periodd and 6 * voting power
Expand Down
13 changes: 12 additions & 1 deletion test/python/crosscheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
WEEK = 7 * DAY

# Variables
AMOUNT = 1000 # example amount to deposit
AMOUNT = 1_000_000_000 # example amount to deposit
PERIOD_LENGTH = 2 * WEEK # example period length in seconds (1 week)
WARMUP_PERIOD = 3 * DAY # warmup period in days
MAX_PERIODS = 5 # maximum periods
Expand All @@ -26,6 +26,15 @@ def evaluate_y(secondsElapsed, PeriodLength, amount_scaled):
)
return y

def evaluate_y_v2(secondsElapsed, PeriodLength, amount_scaled):
x = secondsElapsed / PeriodLength
y = amount_scaled * (
QUADRATIC_COEFFICIENT * (x*x)
+ LINEAR_COEFFICIENT * x
+ CONSTANT
)
return y

# Time points to evaluate, using tuples with optional labels
time_points = [
("0", 0),
Expand All @@ -47,3 +56,5 @@ def evaluate_y(secondsElapsed, PeriodLength, amount_scaled):
y_value = evaluate_y(t, PERIOD_LENGTH, amount_scaled)
# Avoid scientific notation by formatting with commas and align values vertically
print(f"{label:<30} Voting Power: {y_value:>20.0f}")


0 comments on commit 7bc4ef2

Please sign in to comment.