Compare commits
1 Commits
lash/snaps
...
lash/snaps
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c57aa02d6
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -90,7 +90,6 @@ class TestRedistributionSingle(TestDemurrageSingle):
|
||||
r = self.rpc.do(o)
|
||||
balance = c.parse_balance(r)
|
||||
expected_balance = new_supply - (new_supply * tax_modifier)
|
||||
logg.debug('expected balance {}'.format(expected_balance))
|
||||
self.assert_within_lower(balance, expected_balance, 1)
|
||||
|
||||
|
||||
|
||||
@@ -10,24 +10,17 @@ contract DemurrageTokenSingleCap {
|
||||
uint256 constant maskRedistributionPeriod = 0x00000000000000000000000000000000000000000000000000000000ffffffff; // (1 << 32) - 1
|
||||
uint8 constant shiftRedistributionValue = 32;
|
||||
uint256 constant maskRedistributionValue = 0x00000000000000000000000000000000000000ffffffffffffffffff00000000; // ((1 << 72) - 1) << 32
|
||||
uint8 constant shiftRedistributionParticipants = 104;
|
||||
uint256 constant maskRedistributionParticipants = 0x00000000000000000000000000000fffffffff00000000000000000000000000; // ((1 << 36) - 1) << 104
|
||||
uint8 constant shiftRedistributionDemurrage = 140;
|
||||
uint256 constant maskRedistributionDemurrage = 0x000000000000000000000000fffff00000000000000000000000000000000000; // ((1 << 20) - 1) << 140
|
||||
uint8 constant shiftRedistributionDemurrage = 104;
|
||||
uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 36) - 1) << 140
|
||||
|
||||
//uint8 constant shiftRedistributionDemurrage = 104;
|
||||
//uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 36) - 1) << 140
|
||||
|
||||
// Account bit field, with associated shifts and masks
|
||||
// Mirrors structure of redistributions for consistency
|
||||
mapping (address => bytes32) account; // uint152(unused) | uint32(period) | uint72(value)
|
||||
// Account balances
|
||||
mapping (address => bytes32[] ) account;
|
||||
uint8 constant shiftAccountValue = 0;
|
||||
uint256 constant maskAccountValue = 0x0000000000000000000000000000000000000000000000ffffffffffffffffff; // (1 << 72) - 1
|
||||
uint8 constant shiftAccountPeriod = 72;
|
||||
uint256 constant maskAccountPeriod = 0x00000000000000000000000000000000000000ffffffff000000000000000000; // ((1 << 32) - 1) << 72
|
||||
|
||||
// Account balances
|
||||
//mapping (address => uint256) account;
|
||||
uint8 constant shiftAccountUsed = 255;
|
||||
uint256 constant maskAccountUsed = 0x8000000000000000000000000000000000000000000000000000000000000000; // (1 << 255)
|
||||
|
||||
// Cached demurrage amount, ppm with 38 digit resolution
|
||||
uint128 public demurrageAmount;
|
||||
@@ -161,36 +154,6 @@ contract DemurrageTokenSingleCap {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deserialize the pemurrage period for the given account is participating in
|
||||
function accountPeriod(address _account) public view returns (uint256) {
|
||||
return (uint256(account[_account]) & maskAccountPeriod) >> shiftAccountPeriod;
|
||||
}
|
||||
|
||||
// Add number of participants for the current redistribution period by one
|
||||
function incrementRedistributionParticipants() private returns (bool) {
|
||||
bytes32 currentRedistribution;
|
||||
uint256 tmpRedistribution;
|
||||
uint256 participants;
|
||||
|
||||
currentRedistribution = redistributions[redistributions.length-1];
|
||||
participants = toRedistributionParticipants(currentRedistribution) + 1;
|
||||
tmpRedistribution = uint256(currentRedistribution);
|
||||
tmpRedistribution &= (~maskRedistributionParticipants);
|
||||
tmpRedistribution |= ((participants << shiftRedistributionParticipants) & maskRedistributionParticipants);
|
||||
|
||||
redistributions[redistributions.length-1] = bytes32(tmpRedistribution);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Save the given demurrage period as the currently participation period for the given address
|
||||
function registerAccountPeriod(address _account, uint256 _period) private returns (bool) {
|
||||
account[_account] &= bytes32(~maskAccountPeriod);
|
||||
account[_account] |= bytes32((_period << shiftAccountPeriod) & maskAccountPeriod);
|
||||
incrementRedistributionParticipants();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Implements ERC20
|
||||
function balanceOf(address _account) public view returns (uint256) {
|
||||
uint256 baseBalance;
|
||||
@@ -206,94 +169,39 @@ contract DemurrageTokenSingleCap {
|
||||
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
|
||||
}
|
||||
|
||||
|
||||
/// Balance unmodified by demurrage
|
||||
function baseBalanceOf(address _account) public view returns (uint256) {
|
||||
return uint256(account[_account]) & maskAccountValue;
|
||||
uint256 lastPeriodUsed;
|
||||
|
||||
lastPeriodUsed = account[_account].length;
|
||||
if (lastPeriodUsed == 0) {
|
||||
return 0;
|
||||
}
|
||||
return uint256(account[_account][lastPeriodUsed]) & maskAccountValue;
|
||||
}
|
||||
|
||||
|
||||
/// Increases base balance for a single account
|
||||
function increaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
|
||||
uint256 oldBalance;
|
||||
uint256 newBalance;
|
||||
uint256 workAccount;
|
||||
|
||||
workAccount = uint256(account[_account]);
|
||||
|
||||
if (_delta == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
oldBalance = baseBalanceOf(_account);
|
||||
newBalance = oldBalance + _delta;
|
||||
require(uint160(newBalance) > uint160(oldBalance), 'ERR_WOULDWRAP'); // revert if increase would result in a wrapped value
|
||||
workAccount &= (~maskAccountValue);
|
||||
workAccount |= (newBalance & maskAccountValue);
|
||||
account[_account] = bytes32(workAccount);
|
||||
|
||||
movePeriodBalance(_account, int256(_delta));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Decreases base balance for a single account
|
||||
function decreaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
|
||||
uint256 oldBalance;
|
||||
uint256 newBalance;
|
||||
uint256 workAccount;
|
||||
|
||||
workAccount = uint256(account[_account]);
|
||||
|
||||
if (_delta == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
oldBalance = baseBalanceOf(_account);
|
||||
require(oldBalance >= _delta, 'ERR_OVERSPEND'); // overspend guard
|
||||
newBalance = oldBalance - _delta;
|
||||
workAccount &= (~maskAccountValue);
|
||||
workAccount |= (newBalance & maskAccountValue);
|
||||
account[_account] = bytes32(workAccount);
|
||||
movePeriodBalance(_account, int256(_delta) * -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// /// Balance unmodified by demurrage
|
||||
// function baseBalanceOf(address _account) public view returns (uint256) {
|
||||
// return account[_account];
|
||||
// }
|
||||
//
|
||||
// /// Increases base balance for a single account
|
||||
// function increaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
|
||||
// uint256 oldBalance;
|
||||
// uint256 newBalance;
|
||||
// uint256 workAccount;
|
||||
//
|
||||
// workAccount = uint256(account[_account]);
|
||||
//
|
||||
// if (_delta == 0) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// oldBalance = baseBalanceOf(_account);
|
||||
// account[_account] = oldBalance + _delta;
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// /// Decreases base balance for a single account
|
||||
// function decreaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
|
||||
// uint256 oldBalance;
|
||||
// uint256 newBalance;
|
||||
// uint256 workAccount;
|
||||
//
|
||||
// workAccount = uint256(account[_account]);
|
||||
//
|
||||
// if (_delta == 0) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// oldBalance = baseBalanceOf(_account);
|
||||
// require(oldBalance >= _delta, 'ERR_OVERSPEND'); // overspend guard
|
||||
// account[_account] = oldBalance - _delta;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// Creates new tokens out of thin air, and allocates them to the given address
|
||||
// Triggers tax
|
||||
function mintTo(address _beneficiary, uint256 _amount) external returns (bool) {
|
||||
@@ -336,11 +244,6 @@ contract DemurrageTokenSingleCap {
|
||||
return (uint256(redistribution) & maskRedistributionDemurrage) >> shiftRedistributionDemurrage;
|
||||
}
|
||||
|
||||
// Serializes the number of participants part of the redistribution word
|
||||
function toRedistributionParticipants(bytes32 redistribution) public pure returns (uint256) {
|
||||
return (uint256(redistribution) & maskRedistributionParticipants) >> shiftRedistributionParticipants;
|
||||
}
|
||||
|
||||
// Client accessor to the redistributions array length
|
||||
function redistributionCount() public view returns (uint256) {
|
||||
return redistributions.length;
|
||||
@@ -404,7 +307,6 @@ contract DemurrageTokenSingleCap {
|
||||
increaseBaseBalance(sinkAddress, baseUnit);
|
||||
lastPeriod += 1;
|
||||
totalSink += baseUnit;
|
||||
registerAccountPeriod(sinkAddress, lastPeriod);
|
||||
return unit;
|
||||
}
|
||||
|
||||
@@ -451,6 +353,54 @@ contract DemurrageTokenSingleCap {
|
||||
return (block.timestamp - _target) / 60;
|
||||
}
|
||||
|
||||
|
||||
// Deserialize the pemurrage period for the given account is participating in
|
||||
function accountPeriod(address _account) public view returns (uint256) {
|
||||
uint256 accountPeriods;
|
||||
|
||||
accountPeriods = account[_account].length;
|
||||
if (accountPeriods == 0) {
|
||||
return 0;
|
||||
}
|
||||
return accountPeriodBase(_account, accountPeriods - 1);
|
||||
}
|
||||
|
||||
function accountPeriodBase(address _account, uint256 _idx) private view returns (uint256) {
|
||||
return (uint256(account[_account][_idx]) & maskAccountPeriod) >> shiftAccountPeriod;
|
||||
}
|
||||
|
||||
function movePeriodBalance(address _account, int256 _delta) private {
|
||||
int256 oldBalance;
|
||||
uint256 newBalance;
|
||||
uint256 workAccount;
|
||||
|
||||
//workAccount = uint256(account[_index][_account]);
|
||||
|
||||
oldBalance = int256(baseBalanceOf(_account));
|
||||
newBalance = uint256(oldBalance + _delta);
|
||||
require(uint72(newBalance) > uint72(uint256(oldBalance)), 'ERR_WOULDWRAP'); // revert if increase would result in a wrapped value
|
||||
workAccount = (1 << 255);
|
||||
|
||||
workAccount |= ((uint32(lastPeriod) << shiftAccountPeriod) & maskAccountPeriod);
|
||||
workAccount |= (baseBalanceOf(_account) & maskAccountValue);
|
||||
account[_account].push(bytes32(workAccount));
|
||||
}
|
||||
|
||||
function registerAccountPeriod(address _account, int256 _delta) public {
|
||||
uint256 accountPeriods;
|
||||
uint256 lastPeriodUsed;
|
||||
|
||||
accountPeriods = account[_account].length;
|
||||
if (lastPeriodUsed == 0) {
|
||||
account[_account].push(bytes32(uint256(_delta) | (1 << 255)));
|
||||
return;
|
||||
}
|
||||
lastPeriodUsed = accountPeriodBase(_account, accountPeriods - 1);
|
||||
if (lastPeriodUsed != lastPeriod) {
|
||||
movePeriodBalance(_account, _delta);
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate the demurrage modifier for the new period
|
||||
// Note that the supply for the consecutive period will be taken at the time of code execution, and thus not necessarily at the time when the redistribution period threshold was crossed.
|
||||
function changePeriod() public returns (bool) {
|
||||
@@ -597,10 +547,6 @@ contract DemurrageTokenSingleCap {
|
||||
|
||||
decreaseBaseBalance(_from, _value);
|
||||
increaseBaseBalance(_to, _value);
|
||||
period = actualPeriod();
|
||||
if (accountPeriod(_from) != period && _from != _to) {
|
||||
registerAccountPeriod(_from, period);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -626,7 +572,7 @@ contract DemurrageTokenSingleCap {
|
||||
// Only token minters can burn tokens
|
||||
function burn(uint256 _value) public {
|
||||
require(minter[msg.sender]);
|
||||
//require(_value <= account[msg.sender]);
|
||||
require(_value <= balanceOf(msg.sender));
|
||||
uint256 _delta = toBaseAmount(_value);
|
||||
|
||||
applyDemurrage();
|
||||
|
||||
Reference in New Issue
Block a user