Add transfer, mint

This commit is contained in:
nolash 2021-02-02 16:10:21 +01:00
parent 8e60539245
commit 1a2b3bab37
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
2 changed files with 151 additions and 16 deletions

View File

@ -22,6 +22,7 @@ TAX_LEVEL = 10000 * 2 # 2%
#PERIOD = int(60/BLOCKTIME) * 60 * 24 * 30 # month #PERIOD = int(60/BLOCKTIME) * 60 * 24 * 30 # month
PERIOD = 2 PERIOD = 2
class Test(unittest.TestCase): class Test(unittest.TestCase):
contract = None contract = None
@ -55,26 +56,103 @@ class Test(unittest.TestCase):
pass pass
@unittest.skip('foo')
def test_period(self): def test_period(self):
self.assertEqual(self.contract.functions.actualPeriod().call(), 0) self.assertEqual(self.contract.functions.actualPeriod().call(), 0)
self.eth_tester.mine_blocks(PERIOD) self.eth_tester.mine_blocks(PERIOD)
self.assertEqual(self.contract.functions.actualPeriod().call(), 1) self.assertEqual(self.contract.functions.actualPeriod().call(), 1)
@unittest.skip('foo')
def test_mint(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact();
r = self.w3.eth.getTransactionReceipt(tx_hash);
self.assertEqual(r.status, 1);
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call();
self.assertEqual(balance, 1024);
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 976).transact();
r = self.w3.eth.getTransactionReceipt(tx_hash);
self.assertEqual(r.status, 1);
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call();
self.assertEqual(balance, 2000);
def test_transfer(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact();
r = self.w3.eth.getTransactionReceipt(tx_hash);
self.assertEqual(r.status, 1);
tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500).transact({'from': self.w3.eth.accounts[1]});
r = self.w3.eth.getTransactionReceipt(tx_hash);
self.assertEqual(r.status, 1);
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call();
self.assertEqual(balance_alice, 524);
balance_bob = self.contract.functions.balanceOf(self.w3.eth.accounts[2]).call();
self.assertEqual(balance_bob, 500);
@unittest.skip('foo')
def test_apply_tax(self): def test_apply_tax(self):
tx = self.contract.functions.noop().buildTransaction() self.eth_tester.mine_blocks(PERIOD)
logg.debug('gas {}'.format(self.w3.eth.estimateGas(tx))) tx_hash = self.contract.functions.applyTax().transact()
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(self.contract.functions.redistributionCount().call(), 2)
self.assertEqual(self.contract.functions.demurrageModifier().call(), 980000)
self.eth_tester.mine_blocks(PERIOD) self.eth_tester.mine_blocks(PERIOD)
tx_hash = self.contract.functions.applyTax().transact(); tx_hash = self.contract.functions.applyTax().transact()
r = self.w3.eth.getTransactionReceipt(tx_hash); r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(self.contract.functions.redistributionCount().call(), 2); self.assertEqual(self.contract.functions.redistributionCount().call(), 3)
self.assertEqual(self.contract.functions.demurrageModifier().call(), TAX_LEVEL); self.assertEqual(self.contract.functions.demurrageModifier().call(), 960400)
@unittest.skip('foo')
def test_tax_balance(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1)
self.eth_tester.mine_blocks(PERIOD) self.eth_tester.mine_blocks(PERIOD)
tx_hash = self.contract.functions.applyTax().transact(); tx_hash = self.contract.functions.applyTax().transact()
r = self.w3.eth.getTransactionReceipt(tx_hash); r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(self.contract.functions.redistributionCount().call(), 3); self.assertEqual(r.status, 1)
self.assertEqual(self.contract.functions.demurrageModifier().call(), TAX_LEVEL * 2);
balance = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance, 980)
def test_taxed_transfer(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1000000).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1)
self.eth_tester.mine_blocks(PERIOD)
tx_hash = self.contract.functions.applyTax().transact()
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1)
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
self.assertEqual(balance_alice, 980000);
tx_hash = self.contract.functions.transfer(self.w3.eth.accounts[2], 500000).transact({'from': self.w3.eth.accounts[1]})
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.assertEqual(r.status, 1)
balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
balance_alice_trunc = int(balance_alice/1000)*1000
self.assertEqual(balance_alice_trunc, 480000)
balance_bob = self.contract.functions.balanceOf(self.w3.eth.accounts[2]).call()
balance_bob_trunc = int(balance_bob/1000)*1000
self.assertEqual(balance_bob_trunc, 500000)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -12,26 +12,70 @@ contract RedistributedDemurrageToken {
uint256 public periodStart; uint256 public periodStart;
uint256 public periodDuration; uint256 public periodDuration;
uint32 public taxLevel; uint256 public taxLevel; // PPM
uint256 public demurrageModifier; uint256 public demurrageModifier; // PPM
bytes32[] redistributions; // uint40(participants) uint160(value) uint56(period) bytes32[] redistributions; // uint40(participants) uint160(value) uint56(period)
mapping (address => bytes32) account;
mapping (address => bool) minter;
event Transfer(address indexed _from, address indexed _to, uint256 _value); event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value);
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _amount);
constructor(string memory _name, string memory _symbol, uint32 _taxLevel, uint256 _period) { constructor(string memory _name, string memory _symbol, uint32 _taxLevel, uint256 _period) {
owner = msg.sender; owner = msg.sender;
minter[owner] = true;
periodStart = block.number; periodStart = block.number;
periodDuration = _period; periodDuration = _period;
taxLevel = _taxLevel; taxLevel = _taxLevel;
name = _name; name = _name;
symbol = _symbol; symbol = _symbol;
decimals = 6; decimals = 6;
demurrageModifier = 1000000;
bytes32 initialRedistribution = toRedistribution(0, 1, 0); bytes32 initialRedistribution = toRedistribution(0, 1, 0);
redistributions.push(initialRedistribution); redistributions.push(initialRedistribution);
} }
function addMinter(address _minter) public returns (bool) {
require(msg.sender == owner);
minter[_minter] = true;
return true;
}
function balanceOf(address _account) public view returns (uint256) {
uint256 baseBalance = getBaseBalance(_account);
uint256 inverseModifier = 1000000 - demurrageModifier;
uint256 balanceModifier = (inverseModifier * baseBalance) / 1000000;
return baseBalance - balanceModifier;
}
function getBaseBalance(address _account) private view returns (uint256) {
return uint256(account[_account]) & 0x00ffffffffffffffffffffffffffffffffffffffff;
}
function increaseBalance(address _account, uint256 _delta) private returns (bool) {
uint256 oldBalance = getBaseBalance(_account);
account[_account] &= bytes20(0x00);
account[_account] |= bytes32((oldBalance + _delta) & 0x00ffffffffffffffffffffffffffffffffffffffff);
return true;
}
function decreaseBalance(address _account, uint256 _delta) private returns (bool) {
uint256 oldBalance = getBaseBalance(_account);
account[_account] &= bytes20(0x00);
account[_account] |= bytes32((oldBalance - _delta) & 0x00ffffffffffffffffffffffffffffffffffffffff);
return true;
}
function mintTo(address _beneficiary, uint256 _amount) external returns (bool) {
require(minter[msg.sender]);
increaseBalance(_beneficiary, _amount);
emit Mint(msg.sender, _beneficiary, _amount);
return true;
}
function toRedistribution(uint256 _participants, uint256 _value, uint256 _period) private pure returns(bytes32) { function toRedistribution(uint256 _participants, uint256 _value, uint256 _period) private pure returns(bytes32) {
bytes32 redistribution; bytes32 redistribution;
redistribution |= bytes32((_participants & 0xffffffffff) << 215); redistribution |= bytes32((_participants & 0xffffffffff) << 215);
@ -64,18 +108,31 @@ contract RedistributedDemurrageToken {
function applyTax() public returns (uint256) { function applyTax() public returns (uint256) {
bytes32 pendingRedistribution; bytes32 pendingRedistribution;
bytes32 nextRedistribution; bytes32 nextRedistribution;
uint256 currentPeriod;
pendingRedistribution = checkPeriod(); pendingRedistribution = checkPeriod();
if (pendingRedistribution == bytes32(0x00)) { if (pendingRedistribution == bytes32(0x00)) {
return demurrageModifier; return demurrageModifier;
} }
demurrageModifier += taxLevel; demurrageModifier -= (demurrageModifier * taxLevel) / 1000000;
nextRedistribution = toRedistribution(0, actualPeriod(), 0); // this should increment for one single period at at time
currentPeriod = toRedistributionPeriod(pendingRedistribution);
nextRedistribution = toRedistribution(0, currentPeriod + 1, 0);
redistributions.push(nextRedistribution); redistributions.push(nextRedistribution);
return demurrageModifier; return demurrageModifier;
} }
function noop() public returns (uint256) { function transfer(address _to, uint256 _value) public returns (bool ) {
return 0; //&uint256 baseValue = (_value * 1000000) / demurrageModifier;
uint256 baseValue = (_value * 1000000) / demurrageModifier;
bool result = transferBase(_to, baseValue);
emit Transfer(msg.sender, _to, _value);
return result;
}
function transferBase(address _to, uint256 _value) private returns (bool) {
decreaseBalance(msg.sender, _value);
increaseBalance(_to, _value);
return true;
} }
} }