Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added price-on-exit ratchet - always set shares/heart to worse rate b… #21

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions contracts/GlobalsAndUtility.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ contract GlobalsAndUtility is ERC20 {
uint256 private constant HEX_PER_BTC = 1e4;
uint256 private constant SATOSHIS_PER_BTC = 1e8;
uint256 internal constant HEARTS_PER_SATOSHI = HEARTS_PER_HEX / SATOSHIS_PER_BTC * HEX_PER_BTC;
uint256 internal constant INITIAL_SHARES_PER_HEART = 1e18;

/* Time of contract launch (2019-03-04T00:00:00Z) */
uint256 internal constant LAUNCH_TIME = 1551657600;
Expand Down Expand Up @@ -157,6 +158,7 @@ contract GlobalsAndUtility is ERC20 {
uint256 _daysStored;
uint256 _stakeSharesTotal;
uint256 _nextStakeSharesTotal;
uint256 _sharesPerHeart;
uint48 _latestStakeId;
// 2
uint256 _stakePenaltyPool;
Expand All @@ -170,8 +172,9 @@ contract GlobalsAndUtility is ERC20 {
struct GlobalsStore {
// 1
uint16 daysStored;
uint80 stakeSharesTotal;
uint80 nextStakeSharesTotal;
uint256 stakeSharesTotal;
uint256 nextStakeSharesTotal;
uint256 sharesPerHeart;
uint48 latestStakeId;
// 2
uint80 stakePenaltyPool;
Expand All @@ -188,7 +191,7 @@ contract GlobalsAndUtility is ERC20 {
/* Period data */
struct DailyDataStore {
uint80 dayPayoutTotal;
uint80 dayStakeSharesTotal;
uint256 dayStakeSharesTotal;
}

mapping(uint256 => DailyDataStore) public dailyData;
Expand All @@ -206,7 +209,7 @@ contract GlobalsAndUtility is ERC20 {
struct StakeStore {
uint48 stakeId;
uint80 stakedHearts;
uint80 stakeShares;
uint256 stakeShares;
uint16 pooledDay;
uint16 stakedDays;
uint16 unpooledDay;
Expand Down Expand Up @@ -347,6 +350,7 @@ contract GlobalsAndUtility is ERC20 {
g._daysStored = globals.daysStored;
g._stakeSharesTotal = globals.stakeSharesTotal;
g._nextStakeSharesTotal = globals.nextStakeSharesTotal;
g._sharesPerHeart = globals.sharesPerHeart;
g._latestStakeId = globals.latestStakeId;
// 2
g._stakePenaltyPool = globals.stakePenaltyPool;
Expand All @@ -365,6 +369,7 @@ contract GlobalsAndUtility is ERC20 {
gSnapshot._daysStored = g._daysStored;
gSnapshot._stakeSharesTotal = g._stakeSharesTotal;
gSnapshot._nextStakeSharesTotal = g._nextStakeSharesTotal;
gSnapshot._sharesPerHeart = g._sharesPerHeart;
gSnapshot._latestStakeId = g._latestStakeId;
// 2
gSnapshot._stakePenaltyPool = g._stakePenaltyPool;
Expand All @@ -377,8 +382,9 @@ contract GlobalsAndUtility is ERC20 {
internal
{
globals.daysStored = uint16(g._daysStored);
globals.stakeSharesTotal = uint80(g._stakeSharesTotal);
globals.nextStakeSharesTotal = uint80(g._nextStakeSharesTotal);
globals.stakeSharesTotal = g._stakeSharesTotal;
globals.nextStakeSharesTotal = g._nextStakeSharesTotal;
globals.sharesPerHeart = g._sharesPerHeart;
globals.latestStakeId = g._latestStakeId;
}

Expand All @@ -388,6 +394,7 @@ contract GlobalsAndUtility is ERC20 {
if (g._daysStored == gSnapshot._daysStored
&& g._stakeSharesTotal == gSnapshot._stakeSharesTotal
&& g._nextStakeSharesTotal == gSnapshot._nextStakeSharesTotal
&& g._sharesPerHeart == gSnapshot._sharesPerHeart
&& g._latestStakeId == gSnapshot._latestStakeId) {
return;
}
Expand Down Expand Up @@ -435,7 +442,7 @@ contract GlobalsAndUtility is ERC20 {
{
stRef.stakeId = st._stakeId;
stRef.stakedHearts = uint80(st._stakedHearts);
stRef.stakeShares = uint80(st._stakeShares);
stRef.stakeShares = st._stakeShares;
stRef.pooledDay = uint16(st._pooledDay);
stRef.stakedDays = uint16(st._stakedDays);
stRef.unpooledDay = uint16(st._unpooledDay);
Expand All @@ -455,7 +462,7 @@ contract GlobalsAndUtility is ERC20 {
StakeStore(
newStakeId,
uint80(newStakedHearts),
uint80(newStakeShares),
newStakeShares,
uint16(newPooledDay),
uint16(newStakedDays),
uint16(0) // unpooledDay
Expand Down Expand Up @@ -522,7 +529,7 @@ contract GlobalsAndUtility is ERC20 {
if (g._stakeSharesTotal != 0) {
_calcDailyRound(g, rs, day);
dailyData[day].dayPayoutTotal = uint80(rs._payoutTotal);
dailyData[day].dayStakeSharesTotal = uint80(g._stakeSharesTotal);
dailyData[day].dayStakeSharesTotal = g._stakeSharesTotal;
} else {
if (day == CLAIM_REWARD_DAYS && g._unclaimedSatoshisTotal != 0) {
/*
Expand Down
1 change: 1 addition & 0 deletions contracts/HEX.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contract HEX is StakeableToken {
{
/* Add all Satoshis from UTXO snapshot to contract */
globals.unclaimedSatoshisTotal = uint64(FULL_SATOSHIS_TOTAL);
globals.sharesPerHeart = INITIAL_SHARES_PER_HEART;
_mint(address(this), FULL_SATOSHIS_TOTAL * HEARTS_PER_SATOSHI);
}

Expand Down
17 changes: 14 additions & 3 deletions contracts/StakeableToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract StakeableToken is UTXORedeemableToken {
/* Check if log data needs to be updated */
_storeDailyDataBefore(g, g._currentDay);

uint256 newStakeShares = calcStakeShares(newStakedHearts, newStakedDays);
uint256 newStakeShares = calcStakeShares(newStakedHearts, newStakedDays, g._sharesPerHeart);

/*
The startStake timestamp will always be part-way through the current
Expand Down Expand Up @@ -220,6 +220,17 @@ contract StakeableToken is UTXORedeemableToken {

_removeStakeFromList(stakeListRef, stakeIndex);

/*
Apply worst-price logic
Worst price is the current shares / return, adjusted for potential Larger Pays
Better on a restake OR the current shares/heart, whichever is lower
*/
uint256 effectiveReturn = stakeReturn > LPB_H_CAP_HEARTS ? LPB_H_CAP_HEARTS : stakeReturn;
uint256 proposedPrice = st._stakeShares/(stakeReturn + stakeReturn * effectiveReturn / LPB_H);
if(proposedPrice < g._sharesPerHeart){
g._sharesPerHeart = proposedPrice;
}

_saveGlobals1(g);
_syncGlobals2(g, gSnapshot);
}
Expand Down Expand Up @@ -259,7 +270,7 @@ contract StakeableToken is UTXORedeemableToken {
* @param newStakedHearts Number of Hearts to stake
* @param newStakedDays Number of days to stake
*/
function calcStakeShares(uint256 newStakedHearts, uint256 newStakedDays)
function calcStakeShares(uint256 newStakedHearts, uint256 newStakedDays, uint256 sharesPerHeart)
private
pure
returns (uint256)
Expand Down Expand Up @@ -335,7 +346,7 @@ contract StakeableToken is UTXORedeemableToken {
uint256 combinedAmount = cappedExtraDays * LPB_H + cappedStakedHearts * LPB_D;
combinedAmount = newStakedHearts * combinedAmount / (LPB_D * LPB_H);

return newStakedHearts + combinedAmount;
return sharesPerHeart * (newStakedHearts + combinedAmount);
}

function _unpoolStake(GlobalsCache memory g, StakeCache memory st)
Expand Down