Add transfer, mint
This commit is contained in:
		
							parent
							
								
									8e60539245
								
							
						
					
					
						commit
						1a2b3bab37
					
				@ -22,6 +22,7 @@ TAX_LEVEL = 10000 * 2 # 2%
 | 
			
		||||
#PERIOD = int(60/BLOCKTIME) * 60 * 24 * 30 # month
 | 
			
		||||
PERIOD = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Test(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    contract = None
 | 
			
		||||
@ -55,26 +56,103 @@ class Test(unittest.TestCase):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @unittest.skip('foo')
 | 
			
		||||
    def test_period(self):
 | 
			
		||||
        self.assertEqual(self.contract.functions.actualPeriod().call(), 0)
 | 
			
		||||
        self.eth_tester.mine_blocks(PERIOD)
 | 
			
		||||
        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):
 | 
			
		||||
        tx = self.contract.functions.noop().buildTransaction()
 | 
			
		||||
        logg.debug('gas {}'.format(self.w3.eth.estimateGas(tx)))
 | 
			
		||||
        self.eth_tester.mine_blocks(PERIOD)
 | 
			
		||||
        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)
 | 
			
		||||
        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(), TAX_LEVEL);
 | 
			
		||||
        tx_hash = self.contract.functions.applyTax().transact()
 | 
			
		||||
        r = self.w3.eth.getTransactionReceipt(tx_hash)
 | 
			
		||||
        self.assertEqual(self.contract.functions.redistributionCount().call(), 3)
 | 
			
		||||
        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)
 | 
			
		||||
        tx_hash = self.contract.functions.applyTax().transact();
 | 
			
		||||
        r = self.w3.eth.getTransactionReceipt(tx_hash);
 | 
			
		||||
        self.assertEqual(self.contract.functions.redistributionCount().call(), 3);
 | 
			
		||||
        self.assertEqual(self.contract.functions.demurrageModifier().call(), TAX_LEVEL * 2);
 | 
			
		||||
        tx_hash = self.contract.functions.applyTax().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, 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__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
@ -12,26 +12,70 @@ contract RedistributedDemurrageToken {
 | 
			
		||||
 | 
			
		||||
	uint256 public periodStart;
 | 
			
		||||
	uint256 public periodDuration;
 | 
			
		||||
	uint32 public taxLevel;
 | 
			
		||||
	uint256 public demurrageModifier;
 | 
			
		||||
	uint256 public taxLevel; // PPM
 | 
			
		||||
	uint256 public demurrageModifier; // PPM
 | 
			
		||||
 | 
			
		||||
	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 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) {
 | 
			
		||||
		owner = msg.sender;
 | 
			
		||||
		minter[owner] = true;
 | 
			
		||||
		periodStart = block.number;
 | 
			
		||||
		periodDuration = _period;
 | 
			
		||||
		taxLevel = _taxLevel;
 | 
			
		||||
		name = _name;
 | 
			
		||||
		symbol = _symbol;
 | 
			
		||||
		decimals = 6;
 | 
			
		||||
		demurrageModifier = 1000000;
 | 
			
		||||
		bytes32 initialRedistribution = toRedistribution(0, 1, 0);
 | 
			
		||||
		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) {
 | 
			
		||||
		bytes32 redistribution;
 | 
			
		||||
		redistribution |= bytes32((_participants & 0xffffffffff) << 215);
 | 
			
		||||
@ -64,18 +108,31 @@ contract RedistributedDemurrageToken {
 | 
			
		||||
	function applyTax() public returns (uint256) {
 | 
			
		||||
		bytes32 pendingRedistribution;
 | 
			
		||||
		bytes32 nextRedistribution;
 | 
			
		||||
		uint256 currentPeriod;
 | 
			
		||||
 | 
			
		||||
		pendingRedistribution = checkPeriod();
 | 
			
		||||
		if (pendingRedistribution == bytes32(0x00)) {
 | 
			
		||||
			return demurrageModifier;	
 | 
			
		||||
		}
 | 
			
		||||
		demurrageModifier += taxLevel;
 | 
			
		||||
		nextRedistribution = toRedistribution(0, actualPeriod(), 0);
 | 
			
		||||
		demurrageModifier -= (demurrageModifier * taxLevel) / 1000000;
 | 
			
		||||
		// this should increment for one single period at at time
 | 
			
		||||
		currentPeriod = toRedistributionPeriod(pendingRedistribution);
 | 
			
		||||
		nextRedistribution = toRedistribution(0, currentPeriod + 1, 0);
 | 
			
		||||
		redistributions.push(nextRedistribution);
 | 
			
		||||
		return demurrageModifier;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function noop() public returns (uint256) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	function transfer(address _to, uint256 _value) public returns (bool ) {
 | 
			
		||||
		//&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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user