使用 BigNumber.js 轉換/轉換每秒和年化利率
在 MakerDao 合約中,年化百分比和每秒百分比之間存在轉換。例如,他們的Stability Fees文件給出了這個例子:
如果穩定費設置為 2%,它將以每秒 1.0000000006279371924910298109948% 的速度累積。在第一年年底,使用者將欠本金 2%。
從年化格式轉換為每秒格式(反之亦然)的基本方法是這樣的,其中
31536000
是一年中的秒數:1.0000000006279371924910298109948^31536000 = 2%
1.02^(1/31536000) = 1.0000000006279371924910298109948%
由於 Solidity 僅支持整數,因此可以使用定點算法在年化率和每秒率之間進行轉換。我的第一個問題:這兩個速率的整數表示是什麼(以射線為單位)?
我的下一個問題是如何使用 BigNumber.js 實用程序來轉換每秒/年化率?
我在下面的 JavaScript 程式碼不起作用。
PER_SECOND_RATE.pow(toBN(SECONDS_IN_YEAR).toString()) ANNUALIZED_RATE.pow(toBN(-SECONDS_IN_YEAR).toString())
Maker Protocol 不使用或儲存年費率,內部也沒有任何代表。
所有速率均以每秒為單位,使用
RAY
正常 uint256 值的數字格式,並且始終由特殊數學函式處理,例如rmul
自動rdiv
將最右邊的 27 個數字視為 RAY 定點數的小數部分。所以整數表示
1.02%
將是 uint256 值10000000006279371924910298109948
。我嘗試過使用 BN.js,但由於數字的大小和所涉及的冪運算,它對這兩種計算都不起作用。
年化到每秒的速率轉換
使用來自 javascript的命令執行此操作有一種稍微有點 hacky 的方法,這
bc
對我來說效果很好。該函式的輸入是年利率。例如:5.6432%
bc
輸出帶小數點和小數點後 27 位的值。從輸出中刪除小數點以獲得RAY
智能合約使用的格式的數字。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; }
例如:
getRatePerSecond(2.75)
=1000000000859655594846036300
每秒到年化率的轉換
這不能回答你的問題,但我把這個 python 腳本留在這裡,供其他人尋找一種簡單的方法來做這個計算,
$ python -c "print 1.000000000627507392906712186**31557600"
1.01999999956
如果您有興趣了解更多資訊,那麼匯率機制簡介指南會介紹 Maker 協議中的匯率。