contributions_to_token_batches(): takes desired_token_price as argument
TokenBatch: self.current_date to be set externally, unittests updated Commons unittest: initialization and burn()
This commit is contained in:
parent
dd98402875
commit
b77bb3a87e
25
hatch.py
25
hatch.py
|
|
@ -26,13 +26,14 @@ def hatch_raise_split_pools(total_hatch_raise, hatch_tribute) -> Tuple[float, fl
|
||||||
collateral_pool = total_hatch_raise * (1-hatch_tribute)
|
collateral_pool = total_hatch_raise * (1-hatch_tribute)
|
||||||
return funding_pool, collateral_pool
|
return funding_pool, collateral_pool
|
||||||
|
|
||||||
def contributions_to_token_batches(hatcher_contributions: List[int], initial_token_supply: int, vesting_80p_unlocked: int) -> List[float]:
|
def contributions_to_token_batches(hatcher_contributions: List[int], desired_token_price: float, vesting_80p_unlocked: int) -> Tuple[List[float], float]:
|
||||||
"""
|
"""
|
||||||
hatcher_contributions: a list of hatcher contributions
|
hatcher_contributions: a list of hatcher contributions in DAI/ETH/whatever
|
||||||
initial_token_supply: NOT denominated in millions
|
desired_token_price: used to determine the initial token supply
|
||||||
vesting_80p_unlocked: vesting parameter - the number of days after which 80% of tokens will be unlocked, including the cliff period
|
vesting_80p_unlocked: vesting parameter - the number of days after which 80% of tokens will be unlocked, including the cliff period
|
||||||
"""
|
"""
|
||||||
total_hatch_raise = sum(hatcher_contributions)
|
total_hatch_raise = sum(hatcher_contributions)
|
||||||
|
initial_token_supply = total_hatch_raise / desired_token_price
|
||||||
|
|
||||||
# In the hatch, everyone buys in at the same time, with the same price. So just split the token supply amongst the hatchers proportionally to their contributions
|
# In the hatch, everyone buys in at the same time, with the same price. So just split the token supply amongst the hatchers proportionally to their contributions
|
||||||
tokens_per_hatcher = [(x / total_hatch_raise) * initial_token_supply for x in hatcher_contributions]
|
tokens_per_hatcher = [(x / total_hatch_raise) * initial_token_supply for x in hatcher_contributions]
|
||||||
|
|
@ -40,7 +41,7 @@ def contributions_to_token_batches(hatcher_contributions: List[int], initial_tok
|
||||||
cliff_days, halflife_days = convert_80p_to_cliff_and_halflife(vesting_80p_unlocked)
|
cliff_days, halflife_days = convert_80p_to_cliff_and_halflife(vesting_80p_unlocked)
|
||||||
|
|
||||||
token_batches = [TokenBatch(x, cliff_days, halflife_days, hatch=True) for x in tokens_per_hatcher]
|
token_batches = [TokenBatch(x, cliff_days, halflife_days, hatch=True) for x in tokens_per_hatcher]
|
||||||
return token_batches
|
return token_batches, initial_token_supply
|
||||||
|
|
||||||
class TokenBatch:
|
class TokenBatch:
|
||||||
def __init__(self, value: float, cliff_days: int, halflife_days: int, hatch = False):
|
def __init__(self, value: float, cliff_days: int, halflife_days: int, hatch = False):
|
||||||
|
|
@ -51,16 +52,18 @@ class TokenBatch:
|
||||||
self.halflife_days = halflife_days
|
self.halflife_days = halflife_days
|
||||||
self.spent = 0
|
self.spent = 0
|
||||||
|
|
||||||
|
self.current_date = datetime.today() # to be set externally before each spend check
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
o = "TokenBatch {} {}, Unlocked: {}".format("Hatch" if self.hatch_tokens else "", self.value, self.unlocked_fraction(datetime.today()))
|
o = "TokenBatch {} {}, Unlocked: {}".format("Hatch" if self.hatch_tokens else "", self.value, self.unlocked_fraction())
|
||||||
return o
|
return o
|
||||||
|
|
||||||
def unlocked_fraction(self, day: datetime = datetime.today()) -> float:
|
def unlocked_fraction(self) -> float:
|
||||||
"""
|
"""
|
||||||
returns what fraction of the TokenBatch is unlocked to date
|
returns what fraction of the TokenBatch is unlocked to date
|
||||||
"""
|
"""
|
||||||
if self.hatch_tokens:
|
if self.hatch_tokens:
|
||||||
days_delta = day - self.creation_date
|
days_delta = self.current_date - self.creation_date
|
||||||
u = vesting_curve(days_delta.days, self.cliff_days, self.halflife_days)
|
u = vesting_curve(days_delta.days, self.cliff_days, self.halflife_days)
|
||||||
return u if u > 0 else 0
|
return u if u > 0 else 0
|
||||||
else:
|
else:
|
||||||
|
|
@ -72,7 +75,7 @@ class TokenBatch:
|
||||||
returns the argument if successful for your convenience
|
returns the argument if successful for your convenience
|
||||||
"""
|
"""
|
||||||
if x > self.spendable():
|
if x > self.spendable():
|
||||||
raise Exception("Not so many tokens are available for you to spend yet!")
|
raise Exception("Not so many tokens are available for you to spend yet ({})".format(self.current_date))
|
||||||
|
|
||||||
self.value -= x
|
self.value -= x
|
||||||
self.spent += x
|
self.spent += x
|
||||||
|
|
@ -98,7 +101,7 @@ class Commons:
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
self.exit_tribute = exit_tribute
|
self.exit_tribute = exit_tribute
|
||||||
|
|
||||||
def deposit(self, dai):
|
def deposit(self, dai):
|
||||||
"""
|
"""
|
||||||
Deposit DAI after the hatch phase. This means all the incoming deposit goes to the collateral pool.
|
Deposit DAI after the hatch phase. This means all the incoming deposit goes to the collateral pool.
|
||||||
|
|
@ -118,8 +121,8 @@ class Commons:
|
||||||
money_returned = dai
|
money_returned = dai
|
||||||
|
|
||||||
if self.exit_tribute:
|
if self.exit_tribute:
|
||||||
self._funding_pool += commons.exit_tribute * dai
|
self._funding_pool += self.exit_tribute * dai
|
||||||
money_returned = (1-commons.exit_tribute) * dai
|
money_returned = (1-self.exit_tribute) * dai
|
||||||
|
|
||||||
return money_returned, realized_price
|
return money_returned, realized_price
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from hatch import *
|
||||||
import unittest
|
import unittest
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
class TestHatch(unittest.TestCase):
|
class HatchTest(unittest.TestCase):
|
||||||
def test_vesting_curve(self):
|
def test_vesting_curve(self):
|
||||||
self.assertEqual(vesting_curve(90, 90, 90), 0) # At Day 90, the cliff has just ended and the vesting curve has begun at 0
|
self.assertEqual(vesting_curve(90, 90, 90), 0) # At Day 90, the cliff has just ended and the vesting curve has begun at 0
|
||||||
self.assertEqual(vesting_curve(180, 90, 90), 0.5) # At Day 180, the cliff has ended and we are in the vesting curve, whose half-life is 90 as well, so at 180 we should get 0.5.
|
self.assertEqual(vesting_curve(180, 90, 90), 0.5) # At Day 180, the cliff has ended and we are in the vesting curve, whose half-life is 90 as well, so at 180 we should get 0.5.
|
||||||
|
|
@ -16,9 +16,11 @@ class TokenBatchTest(unittest.TestCase):
|
||||||
tbh = TokenBatch(10000, 3, 3, True)
|
tbh = TokenBatch(10000, 3, 3, True)
|
||||||
tb = TokenBatch(10000, 5, 10, False)
|
tb = TokenBatch(10000, 5, 10, False)
|
||||||
|
|
||||||
|
self. assertEqual(tbh.unlocked_fraction(), 0)
|
||||||
|
tbh.current_date = datetime.datetime.today() + datetime.timedelta(days=3)
|
||||||
self.assertEqual(tbh.unlocked_fraction(), 0)
|
self.assertEqual(tbh.unlocked_fraction(), 0)
|
||||||
self.assertEqual(tbh.unlocked_fraction(datetime.datetime.today() + datetime.timedelta(days=3)), 0)
|
tbh.current_date = datetime.datetime.today() + datetime.timedelta(days=6)
|
||||||
self.assertEqual(tbh.unlocked_fraction(datetime.datetime.today() + datetime.timedelta(days=6)), 0.5)
|
self.assertEqual(tbh.unlocked_fraction(), 0.5)
|
||||||
|
|
||||||
self.assertEqual(tb.unlocked_fraction(), 1.0)
|
self.assertEqual(tb.unlocked_fraction(), 1.0)
|
||||||
|
|
||||||
|
|
@ -39,22 +41,30 @@ class TokenBatchTest(unittest.TestCase):
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
tb.spend(10000)
|
tb.spend(10000)
|
||||||
|
|
||||||
class TestSystem(unittest.TestCase):
|
class CommonsTest(unittest.TestCase):
|
||||||
def test_system(self):
|
def setUp(self):
|
||||||
# 100,000 DAI invested for 1,000,000 tokens.
|
# 100,000 DAI invested for 1,000,000 tokens.
|
||||||
desired_token_price = 0.1
|
self.desired_token_price = 0.1
|
||||||
hatcher_contributions = [25000, 25000, 50000]
|
self.hatcher_contributions = [25000, 25000, 50000]
|
||||||
token_supply_initial = sum(hatcher_contributions) / desired_token_price
|
self.token_batches, self.token_supply_initial = contributions_to_token_batches(self.hatcher_contributions, self.desired_token_price, 90)
|
||||||
token_batches = contributions_to_token_batches(hatcher_contributions, token_supply_initial, 90)
|
|
||||||
|
|
||||||
# Because of hatch_tribute, the collateral_pool is 0.7e6. This causes the token's post-hatch price to be 0.14.
|
# Because of hatch_tribute, the collateral_pool is 0.7e6. This causes the token's post-hatch price to be 0.14.
|
||||||
o = Commons(sum(hatcher_contributions), token_supply_initial, hatch_tribute=0.3)
|
self.commons = Commons(sum(self.hatcher_contributions), self.token_supply_initial, hatch_tribute=0.3)
|
||||||
self.assertEqual(o._collateral_pool, 70000)
|
|
||||||
self.assertEqual(o._funding_pool, 30000)
|
|
||||||
self.assertEqual(o._token_supply, token_supply_initial)
|
|
||||||
|
|
||||||
self.assertEqual(o.token_price(), 0.14)
|
def test_initialization(self):
|
||||||
print(token_batches)
|
self.assertEqual(self.commons._collateral_pool, 70000)
|
||||||
# print(o.deposit(100))
|
self.assertEqual(self.commons._funding_pool, 30000)
|
||||||
# print(o.token_price())
|
self.assertEqual(self.commons._token_supply, self.token_supply_initial)
|
||||||
# print(o._collateral_pool)
|
|
||||||
|
self.assertEqual(self.commons.token_price(), 0.14)
|
||||||
|
|
||||||
|
def test_burn_without_exit_tribute(self):
|
||||||
|
old_token_supply = self.commons._token_supply
|
||||||
|
old_collateral_pool = self.commons._collateral_pool
|
||||||
|
|
||||||
|
money_returned, realized_price = self.commons.burn(50000)
|
||||||
|
|
||||||
|
self.assertEqual(money_returned, 6825.0)
|
||||||
|
self.assertEqual(realized_price, 0.1365)
|
||||||
|
self.assertEqual(self.commons._token_supply, old_token_supply-50000)
|
||||||
|
self.assertEqual(self.commons._collateral_pool, old_collateral_pool-money_returned)
|
||||||
Loading…
Reference in New Issue