linear lease vesting math
parent
338b7d075a
commit
913fcf8a3d
|
@ -0,0 +1,47 @@
|
||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Calculate amount due to provider assuming linear payout schedule.
|
||||||
|
//
|
||||||
|
// Does NOT account for anything out-of-bounds. This must be checked beforehand.
|
||||||
|
func CalcAmountVestableLinear(
|
||||||
|
total *big.Int,
|
||||||
|
remaining *big.Int,
|
||||||
|
date time.Time,
|
||||||
|
beginDate time.Time,
|
||||||
|
endDate time.Time,
|
||||||
|
) (*big.Int, error) {
|
||||||
|
timePassed := big.NewInt(date.Unix() - beginDate.Unix())
|
||||||
|
totalTime := big.NewInt(endDate.Unix() - beginDate.Unix())
|
||||||
|
|
||||||
|
taken := big.NewInt(0)
|
||||||
|
taken.Sub(total, remaining)
|
||||||
|
|
||||||
|
out := big.NewInt(0)
|
||||||
|
out.Mul(total, timePassed)
|
||||||
|
out.Div(out, totalTime)
|
||||||
|
out.Sub(out, taken)
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// No longer using exponential - use linear distribution schedule
|
||||||
|
// because exponential rewards are a weak incentive for providers
|
||||||
|
|
||||||
|
// func CalcAmountVestableExponential(
|
||||||
|
// ctx sdk.Context,
|
||||||
|
// total big.Int,
|
||||||
|
// remaining big.Int,
|
||||||
|
// date time.Time,
|
||||||
|
// beginDate time.Time,
|
||||||
|
// endDate time.Time,
|
||||||
|
// ) big.Int {
|
||||||
|
// timescale := big.NewInt(endDate.Unix() - beginDate.Unix())
|
||||||
|
// timePassed := big.NewInt(date.Unix() - beginDate.Unix())
|
||||||
|
// expTerm := big.NewInt(1)
|
||||||
|
// expTerm.Exp(big.NewInt(2), timePassed, big.NewInt(1))
|
||||||
|
// }
|
|
@ -0,0 +1,115 @@
|
||||||
|
package math
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLinearVesting(t *testing.T) {
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: halfway through
|
||||||
|
// Claimed: 0
|
||||||
|
// Expected: 500
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(1000),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()-1000, 0),
|
||||||
|
time.Unix(time.Now().Unix()+1000, 0),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: beginning through
|
||||||
|
// Claimed: 0
|
||||||
|
// Expected: 0
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(1000),
|
||||||
|
time.Now(),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()+1000, 0),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: end
|
||||||
|
// Claimed: 0
|
||||||
|
// Expected: 1000
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(1000),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()-1000, 0),
|
||||||
|
time.Now(),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: end
|
||||||
|
// Claimed: 1000
|
||||||
|
// Expected: 1000
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(0),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()-1000, 0),
|
||||||
|
time.Now(),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: 33%
|
||||||
|
// Claimed: 250 (25%)
|
||||||
|
// Expected: 333-250 = 83
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(750),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()-1000, 0),
|
||||||
|
time.Unix(time.Now().Unix()+2000, 0),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 83)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total: 1000 tokens
|
||||||
|
// Time: 66%
|
||||||
|
// Claimed: 250 (25%)
|
||||||
|
// Expected: 666-250 = 416
|
||||||
|
if res, err := CalcAmountVestableLinear(
|
||||||
|
big.NewInt(1000),
|
||||||
|
big.NewInt(750),
|
||||||
|
time.Now(),
|
||||||
|
time.Unix(time.Now().Unix()-2000, 0),
|
||||||
|
time.Unix(time.Now().Unix()+1000, 0),
|
||||||
|
); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
expectEq(res, 416)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectEq(a *big.Int, b int) {
|
||||||
|
a2 := int(a.Uint64())
|
||||||
|
if a2 != b {
|
||||||
|
panic(fmt.Sprintf("expected %d, got %d", b, a2))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue