Protocol Math
This section has been updated following the launch in IOTA EVM.
The Deepr protocol contracts use a system of exponential math, ExponentialNoError.sol, in order to represent fractional quantities with sufficient precision.
Most numbers are represented as a mantissa, an unsigned integer scaled by 1 * 10 ^ 18
, in order to perform basic math at a high level of precision.
Technical information
dToken and Underlying Decimals
Prices and exchange rates are scaled by the decimals unique to each asset; dTokens are ERC-20 tokens with 8 decimals, while their underlying tokens vary, and have a public member named decimals.
dToken | dToken Decimals | Underlying | Underlying Decimals |
---|---|---|---|
dWIOTA | 8 | WIOTA | 18 |
dWETH | 8 | WETH | 18 |
dUSDC | 8 | USDC | 6 |
dSMR | 8 | SMR | 6 |
Interpreting Exchange Rates
The dToken Exchange Rate is scaled by the difference in decimals between the dToken and the underlying asset.
oneDTokenInUnderlying = exchangeRateCurrent / (1 * 10 ^ (18 + underlyingDecimals - dTokenDecimals))
Here is an example of finding the value of 1 dWIOTA in WIOTA with Web3.js JavaScript.
const dTokenDecimals = 8; // all dTokens have 8 decimal places
const underlying = new web3.eth.Contract(erc20Abi, wiotaAddress);
const dToken = new web3.eth.Contract(dTokenAbi, dwiotaAddress);
const underlyingDecimals = await underlying.methods.decimals().call();
const exchangeRateCurrent = await dToken.methods.exchangeRateCurrent().call();
const mantissa = 18 + parseInt(underlyingDecimals) - dTokenDecimals;
const oneDTokenInUnderlying = exchangeRateCurrent / Math.pow(10, mantissa);
console.log(`1 dWIOTA can be redeemed for ${oneDTokenInUnderlying} WIOTA`);
To find the number of underlying tokens that can be redeemed for dTokens, multiply the number of dTokens by the above value oneDTokenInUnderlying
.
underlyingTokens = dTokenAmount * oneDTokenInUnderlying
Calculating Accrued Interest
Interest rates for each market update on any second in which the ratio of borrowed assets to supplied assets in the market has changed. The amount interest rates are changed depends on the interest rate model smart contract implemented for the market, and the amount of change in the ratio of borrowed assets to supplied assets in the market.
Interest accrues to all suppliers and borrowers in a market when any IOTA address interacts with the market's dToken contract, calling one of these functions: mint, redeem, borrow, or repay. Successful execution of one of these functions triggers the accrueInterest
method, which causes interest to be added to the underlying balance of every supplier and borrower in the market. Interest accrues for the current second, as well as each prior second in which the accrueInterest
method was not triggered (no user interacted with the dToken contract). Interest compounds only during seconds in which the dToken contract has one of the aforementioned methods invoked.
Here is an example of supply interest accrual:
Alice supplies 1 wIOTA to the Deepr protocol. At the time of supply, the supplyRatePerSecond
is 37893605 Wei, or 0.000000000037893605 wIOTA per second. No one interacts with the dWIOTA contract for 3 seconds. On the subsequent 4th second, Bob borrows some IOTA. Alice's underlying balance is now 1.000000000151574420 wIOTA (which is 37893605 Wei times 4 seconds, plus the original 1 wIOTA). Alice's underlying wIOTA balance in subsequent seconds will have interest accrued based on the new value of 1.000000000151574420 wIOTA instead of the initial 1 wIOTA. Note that the supplyRatePerSecond
value may change at any time.
Calculating the APY Using Rate Per Second
The Annual Percentage Yield (APY) for supplying or borrowing in each market can be calculated using the value of supplyRatePerSecond
(for supply APY) or borrowRatePerSecond
(for borrow APY) in this formula:
Rate = dToken.supplyRatePerSecond(); // Integer
Rate = 380879996
wIOTA Mantissa = 1 * 10 ^ 18 (wIOTA has 18 decimal places)
Seconds Per Day = 86400
Days Per Year = 365
APY = ((((Rate / wIOTA Mantissa * Seconds Per Day + 1) ^ Days Per Year)) - 1) * 100
Here is an example of calculating the supply and borrow APY with Web3.js JavaScript:
const wIOTAMantissa = 1e18;
const secondsPerDay = 86400;
const daysPerYear = 365;
const dToken = new web3.eth.Contract(dIOTA, dIOTA);
const supplyRatePerSecond = await dToken.methods.supplyRatePerSecond().call();
const borrowRatePerSecond = await dToken.methods.borrowRatePerSecond().call();
const supplyApy =
(Math.pow(
(supplyRatePerSecond / IOTAMantissa) * secondsPerDay + 1,
daysPerYear
) -
1) *
100;
const borrowApy =
(Math.pow(
(borrowRatePerSecond / IOTAMantissa) * secondsPerDay + 1,
daysPerYear
) -
1) *
100;
console.log(`Supply APY for IOTA ${supplyApy} %`);
console.log(`Borrow APY for IOTA ${borrowApy} %`);
If you wish to run these examples locally, please visit our public Protocol Math Examples repository which includes versions in both Web3.js and Ethers.