Skip to content

Commit

Permalink
arbitrary precision in compound interest state
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Feb 16, 2022
1 parent 8851848 commit 7c3bff8
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
24 changes: 16 additions & 8 deletions packages/run-protocol/src/vaultFactory/interest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
import '@agoric/zoe/exported.js';
import '@agoric/zoe/src/contracts/callSpread/types.js';
import { natSafeMath } from '@agoric/zoe/src/contractSupport/index.js';
import {
makeRatio,
multiplyRatios,
} from '@agoric/zoe/src/contractSupport/ratio.js';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import './types.js';

export const SECONDS_PER_YEAR = 60n * 60n * 24n * 365n;
const BASIS_POINTS = 10000;
// single digit APR is less than a basis point per day.
const LARGE_DENOMINATOR = BASIS_POINTS * BASIS_POINTS;

const COMPOUNDED_INTEREST_PRECISION = 10n ** 30n; // to 30 decimal places

/**
* @param {Ratio} annualRate
* @param {RelativeTime} chargingPeriod
Expand Down Expand Up @@ -102,8 +101,17 @@ export const calculateCompoundedInterest = (
if (priorDebt === 0n) {
throw new Error('No interest on zero debt');
}
return multiplyRatios(
priorCompoundedInterest,
makeRatio(newDebt, brand, priorDebt, brand),
);
let numerator = newDebt * priorCompoundedInterest.numerator.value;
let denominator = priorDebt * priorCompoundedInterest.denominator.value;

// scale down to avoid runaway growth of repeated multiplication
while (
numerator > COMPOUNDED_INTEREST_PRECISION &&
denominator > COMPOUNDED_INTEREST_PRECISION
) {
numerator /= COMPOUNDED_INTEREST_PRECISION;
denominator /= COMPOUNDED_INTEREST_PRECISION;
}

return makeRatio(numerator, brand, denominator, brand);
};
3 changes: 2 additions & 1 deletion packages/run-protocol/test/vaultFactory/test-interest.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ test('calculateCompoundedInterest on zero debt', t => {
});

// -illions
const M = 1_000_000n;
const B = 1_000_000_000n;
const Q = B * B;

Expand All @@ -434,7 +435,7 @@ test('calculateCompoundedInterest', t => {
[11n, 10n, 1n, 2n * Q, 22n * Q, 10n], // >1 previous interest
[1n, 1n, 1n, 2n * Q, 2n * Q, 1n], // ludicrous rate greater than Number.MAX_SAFE_INTEGER
[2n, 1n, 1n * Q, 2n * Q, 4n * Q, 1n * Q], // 2x on huge debt
[4n * Q, 1n * Q, 4n * Q, 8n * Q, 32n * Q * Q, 4n * Q * Q], // 2x again
[4n * Q, 1n * Q, 4n * Q, 8n * Q, 32n * M, 4n * M], // 2x again, ratio reduced
];
for (const [priorNum, priorDen, oldDebt, newDebt, newNum, newDen] of cases) {
const oldInterest = makeRatio(priorNum, brand, priorDen, brand);
Expand Down

0 comments on commit 7c3bff8

Please sign in to comment.