Skip to content

Commit 6e0066f

Browse files
committed
fix: correctly calculate APR for gnosis
See: BEDS-1138
1 parent 635a10d commit 6e0066f

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

backend/pkg/api/data_access/vdb_helpers.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"database/sql"
66
"fmt"
7-
"math"
87
"math/big"
98
"time"
109

@@ -13,6 +12,7 @@ import (
1312
"github.com/gobitfly/beaconchain/pkg/api/services"
1413
t "github.com/gobitfly/beaconchain/pkg/api/types"
1514
"github.com/gobitfly/beaconchain/pkg/commons/cache"
15+
"github.com/gobitfly/beaconchain/pkg/commons/price"
1616
"github.com/gobitfly/beaconchain/pkg/commons/utils"
1717
"github.com/lib/pq"
1818
"github.com/pkg/errors"
@@ -210,10 +210,11 @@ func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId,
210210
if hours == -1 { // for all time APR
211211
aprDivisor = 90 * 24
212212
}
213-
clAPR = ((float64(rewardsResultTable.Reward.Int64) / float64(aprDivisor)) / (float64(32e9) * float64(rewardsResultTable.ValidatorCount))) * 24.0 * 365.0 * 100.0
214-
if math.IsNaN(clAPR) {
215-
clAPR = 0
216-
}
213+
214+
// invested amount is not post-pectra safe
215+
investedAmount := d.convertClToMain(decimal.NewFromUint64(d.config.ClConfig.MaxEffectiveBalance))
216+
217+
clAPR = calcAPR(d.convertClToMain(decimal.NewFromInt(rewardsResultTable.Reward.Int64)), investedAmount, aprDivisor, rewardsResultTable.ValidatorCount)
217218

218219
clIncome = decimal.NewFromInt(rewardsResultTable.Reward.Int64).Mul(decimal.NewFromInt(1e9))
219220

@@ -235,7 +236,7 @@ func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId,
235236
}
236237

237238
elDs := goqu.Dialect("postgres").
238-
Select(goqu.COALESCE(goqu.SUM(goqu.L("value / 1e18")), 0)).
239+
Select(goqu.COALESCE(goqu.SUM(goqu.L("value")), 0)).
239240
From(goqu.I("execution_rewards_finalized").As("b"))
240241

241242
if len(dashboardId.Validators) > 0 {
@@ -264,11 +265,8 @@ func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId,
264265
if err != nil {
265266
return decimal.Zero, 0, decimal.Zero, 0, err
266267
}
267-
elIncomeFloat, _ := elIncome.Float64() // EL income is in ETH
268-
elAPR = ((elIncomeFloat / float64(aprDivisor)) / (float64(32) * float64(rewardsResultTable.ValidatorCount))) * 24.0 * 365.0 * 100.0
269-
if math.IsNaN(elAPR) {
270-
elAPR = 0
271-
}
268+
269+
elAPR = calcAPR(d.convertElToMain(elIncome), investedAmount, aprDivisor, rewardsResultTable.ValidatorCount)
272270

273271
if hours == -1 {
274272
elTotalDs := elDs.
@@ -284,11 +282,30 @@ func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId,
284282
return decimal.Zero, 0, decimal.Zero, 0, err
285283
}
286284
}
287-
elIncome = elIncome.Mul(decimal.NewFromInt(1e18))
288285

289286
return elIncome, elAPR, clIncome, clAPR, nil
290287
}
291288

289+
// precondition: invested amount and rewards are in the same currency
290+
func calcAPR(rewards, investedAmount decimal.Decimal, aprDivisor int, validatorCount uint64) float64 {
291+
if rewards.IsZero() || investedAmount.IsZero() || validatorCount == 0 {
292+
return 0
293+
}
294+
return (rewards.Div(decimal.NewFromInt(int64(aprDivisor))).Div(investedAmount.Mul(decimal.NewFromInt(int64(validatorCount)))).Mul(decimal.NewFromInt(24 * 365 * 100))).InexactFloat64()
295+
}
296+
297+
// converts a cl amount to the main currency
298+
func (d *DataAccessService) convertClToMain(amount decimal.Decimal) decimal.Decimal {
299+
price := decimal.NewFromFloat(price.GetPrice(d.config.Frontend.MainCurrency, d.config.Frontend.ClCurrency))
300+
return amount.Div(decimal.NewFromInt(d.config.Frontend.ClCurrencyDivisor)).Div(price)
301+
}
302+
303+
// converts a el amount to the main currency
304+
func (d *DataAccessService) convertElToMain(amount decimal.Decimal) decimal.Decimal {
305+
price := decimal.NewFromFloat(price.GetPrice(d.config.Frontend.MainCurrency, d.config.Frontend.ElCurrency))
306+
return amount.Div(decimal.NewFromInt(d.config.Frontend.ElCurrencyDivisor)).Div(price)
307+
}
308+
292309
type RpOperatorInfo struct {
293310
ValidatorIndex uint64 `db:"validatorindex"`
294311
NodeFee float64 `db:"node_fee"`

0 commit comments

Comments
 (0)