WIP implement full history of account balance snapshot

This commit is contained in:
lash 2023-01-18 09:34:31 +00:00
parent 9d7b87be9c
commit 8c57aa02d6
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
3 changed files with 70 additions and 23 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,13 @@ contract DemurrageTokenSingleCap {
uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 36) - 1) << 140 uint256 constant maskRedistributionDemurrage = 0x0000000000ffffffffffffffffffffffffffff00000000000000000000000000; // ((1 << 36) - 1) << 140
// Account balances // Account balances
mapping (address => uint256) account; 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
uint8 constant shiftAccountUsed = 255;
uint256 constant maskAccountUsed = 0x8000000000000000000000000000000000000000000000000000000000000000; // (1 << 255)
// Cached demurrage amount, ppm with 38 digit resolution // Cached demurrage amount, ppm with 38 digit resolution
uint128 public demurrageAmount; uint128 public demurrageAmount;
@ -163,43 +169,36 @@ contract DemurrageTokenSingleCap {
return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000); return (baseBalance * currentDemurragedAmount) / (nanoDivider * 1000000000000);
} }
/// Balance unmodified by demurrage /// Balance unmodified by demurrage
function baseBalanceOf(address _account) public view returns (uint256) { function baseBalanceOf(address _account) public view returns (uint256) {
return account[_account]; uint256 lastPeriodUsed;
lastPeriodUsed = account[_account].length;
if (lastPeriodUsed == 0) {
return 0;
}
return uint256(account[_account][lastPeriodUsed]) & maskAccountValue;
} }
/// Increases base balance for a single account /// Increases base balance for a single account
function increaseBaseBalance(address _account, uint256 _delta) private returns (bool) { function increaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
uint256 oldBalance;
uint256 newBalance;
uint256 workAccount;
workAccount = uint256(account[_account]);
if (_delta == 0) { if (_delta == 0) {
return false; return false;
} }
oldBalance = baseBalanceOf(_account); movePeriodBalance(_account, int256(_delta));
account[_account] = oldBalance + _delta;
return true; return true;
} }
/// Decreases base balance for a single account /// Decreases base balance for a single account
function decreaseBaseBalance(address _account, uint256 _delta) private returns (bool) { function decreaseBaseBalance(address _account, uint256 _delta) private returns (bool) {
uint256 oldBalance;
uint256 newBalance;
uint256 workAccount;
workAccount = uint256(account[_account]);
if (_delta == 0) { if (_delta == 0) {
return false; return false;
} }
oldBalance = baseBalanceOf(_account); movePeriodBalance(_account, int256(_delta) * -1);
require(oldBalance >= _delta, 'ERR_OVERSPEND'); // overspend guard
account[_account] = oldBalance - _delta;
return true; return true;
} }
@ -354,6 +353,54 @@ contract DemurrageTokenSingleCap {
return (block.timestamp - _target) / 60; 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 // 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. // 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) { function changePeriod() public returns (bool) {
@ -525,7 +572,7 @@ contract DemurrageTokenSingleCap {
// Only token minters can burn tokens // Only token minters can burn tokens
function burn(uint256 _value) public { function burn(uint256 _value) public {
require(minter[msg.sender]); require(minter[msg.sender]);
require(_value <= account[msg.sender]); require(_value <= balanceOf(msg.sender));
uint256 _delta = toBaseAmount(_value); uint256 _delta = toBaseAmount(_value);
applyDemurrage(); applyDemurrage();