# Converting to/from per-second and annualized interest rates with BigNumber.js

In the MakerDao contracts, there are conversions between annualized percentage rates and per-second percentage rates. For example, their Stability Fees documentation gives this example:

If the Stability Fee is set to 2%, it will accumulate at 1.0000000006279371924910298109948‬% per second. At the end of year one, the user will owe exactly 2% on the principal.

The basic way to convert from the annualized format to the per-second format and vice-versa is like so, where `31536000` is the number of seconds in a year:

1.0000000006279371924910298109948^31536000 = 2%
1.02^(1/31536000) = 1.0000000006279371924910298109948%

Since Solidity only supports integers, one may use fixed-point arithmetic for converting between the annualized rate and the per-second rate. My first question: what is the integer representation of these two rates (in ray)?

My next question is how would one go about using the BigNumber.js utility to convert to-and-from the per-second/annualized rates?

The JavaScript code I have below is not working.

``````PER_SECOND_RATE.pow(toBN(SECONDS_IN_YEAR).toString())
ANNUALIZED_RATE.pow(toBN(-SECONDS_IN_YEAR).toString())
``````

Maker Protocol does not use or store an annual rate and there is no representation for it internally.

All rates are in per-second which uses the `RAY` number format which are regular uint256 values and are always handled by special math functions like `rmul` or `rdiv` which automatically consider the 27 right most numbers as the decimal part of the RAY fixed-point number.

So the integer representation for `1.02%` will be the uint256 value `10000000006279371924910298109948`.

I've tried using BN.js but it never worked for either calculations possibly due to the size of the numbers and exponentiation involved.

### Annualized to Per-Second Rate Conversion

There is a slightly hacky approach to doing this with the `bc` command from javascript that worked well for me.

Input to the function is the annual rate. Ex: 5.6432% `bc` outputs the value with a decimal point and 27 decimals after. The decimal point is removed from the output to get the number in the `RAY` format used by the smart contracts.

``````public async getRatePerSecond(annual: number) {
let annRate = ((annual / 100) + 1).toFixed(4);

const { stdout, stderr } = await exec(
"bc -l <<< 'scale=27; e( l(" +
annRate.toString() +
")/31557600 )'"
);

if (stderr) {
console.error(`error: \${stderr}`);
return;
}

let ratePerSec = BigNumber.from(
stdout
.toString()
.replace(".", "")
.replace(/(\r\n|\n|\r)/gm, "")
);

return ratePerSec;
}
``````

Ex: `getRatePerSecond(2.75)` = `1000000000859655594846036300`

### Per-Second to Annualized Rate Conversion

This doesn't answer your question but I'm leaving this python script here for others looking for a simple way to do this calculation,

``````\$ python -c "print 1.000000000627507392906712186**31557600"
``````

1.01999999956

The Intro to Rate Mechanism guide provides an introduction to rates in the Maker Protocol if you are interested in learning more.