commit 179e25adff67c0ff7dd5f710db478d80e9b68024
parent d795a77deb96e9b2dab9c03e622e8ac62c6025ce
Author: nolash <dev@holbrook.no>
Date: Fri, 5 Feb 2021 09:22:36 +0100
Add approve, transferfrom
Diffstat:
2 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py
@@ -45,7 +45,7 @@ class Test(unittest.TestCase):
provider = web3.Web3.EthereumTesterProvider(self.eth_tester)
self.w3 = web3.Web3(provider)
c = self.w3.eth.contract(abi=self.abi, bytecode=self.bytecode)
- tx_hash = c.constructor('Foo Token', 'FOO', TAX_LEVEL, PERIOD).transact({'from': self.w3.eth.accounts[0]})
+ tx_hash = c.constructor('Foo Token', 'FOO', 6, TAX_LEVEL, PERIOD).transact({'from': self.w3.eth.accounts[0]})
r = self.w3.eth.getTransactionReceipt(tx_hash)
self.contract = self.w3.eth.contract(abi=self.abi, address=r.contractAddress)
@@ -56,14 +56,12 @@ class Test(unittest.TestCase):
pass
- @unittest.skip('test')
def test_hello(self):
self.assertEqual(self.contract.functions.actualPeriod().call(), 1)
self.eth_tester.mine_blocks(PERIOD)
self.assertEqual(self.contract.functions.actualPeriod().call(), 2)
- @unittest.skip('test')
def test_mint(self):
tx_hash = self.contract.functions.mintTo(self.w3.eth.accounts[1], 1024).transact()
r = self.w3.eth.getTransactionReceipt(tx_hash)
@@ -101,7 +99,32 @@ class Test(unittest.TestCase):
self.assertEqual(r.status, 1)
logg.debug('tx {}'.format(r))
- @unittest.skip('test')
+
+ def test_transfer_from(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.approve(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)
+ logg.debug('tx {}'.format(r))
+
+ balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
+ self.assertEqual(balance_alice, 1024)
+
+ tx_hash = self.contract.functions.transferFrom(self.w3.eth.accounts[1], self.w3.eth.accounts[3], 500).transact({'from': self.w3.eth.accounts[2]})
+ r = self.w3.eth.getTransactionReceipt(tx_hash)
+ self.assertEqual(r.status, 1)
+ logg.debug('tx {}'.format(r))
+
+ balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[1]).call()
+ self.assertEqual(balance_alice, 524)
+
+ balance_alice = self.contract.functions.balanceOf(self.w3.eth.accounts[3]).call()
+ self.assertEqual(balance_alice, 500)
+
+
def test_apply_tax(self):
self.eth_tester.mine_blocks(PERIOD)
tx_hash = self.contract.functions.applyTax().transact()
@@ -116,7 +139,6 @@ class Test(unittest.TestCase):
self.assertEqual(self.contract.functions.demurrageModifier().call(), 960400)
- @unittest.skip('test')
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)
@@ -131,7 +153,6 @@ class Test(unittest.TestCase):
self.assertEqual(balance, 980)
- @unittest.skip('test')
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)
diff --git a/solidity/RedistributedDemurrageToken.sol b/solidity/RedistributedDemurrageToken.sol
@@ -17,8 +17,9 @@ contract RedistributedDemurrageToken {
uint256 public demurrageModifier; // PPM
bytes32[] public redistributions; // uint1(usedDustSink) | uint1(isFractional) | uint38(participants) | uint160(value) | uint56(period)
- mapping (address => bytes32) account; // uint12(period) | uint160(value)
+ mapping (address => bytes32) account; // uint20(unused) | uint56(period) | uint160(value)
mapping (address => bool) minter;
+ mapping (address => mapping (address => uint256 ) ) allowance; // holder -> spender -> amount (amount is subject to demurrage)
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
@@ -27,7 +28,7 @@ contract RedistributedDemurrageToken {
event Taxed(uint256 indexed _period);
event Redistribution(address indexed _account, uint256 indexed _period, uint256 _value);
- constructor(string memory _name, string memory _symbol, uint32 _taxLevel, uint256 _period) {
+ constructor(string memory _name, string memory _symbol, uint8 _decimals, uint32 _taxLevel, uint256 _period) {
owner = msg.sender;
minter[owner] = true;
periodStart = block.number;
@@ -35,7 +36,7 @@ contract RedistributedDemurrageToken {
taxLevel = _taxLevel;
name = _name;
symbol = _symbol;
- decimals = 6;
+ decimals = _decimals;
demurrageModifier = 1000000;
bytes32 initialRedistribution = toRedistribution(0, 0, 1);
redistributions.push(initialRedistribution);
@@ -250,6 +251,11 @@ contract RedistributedDemurrageToken {
return true;
}
+ // Inflates the given amount according to the current demurrage modifier
+ function toBaseAmount(uint256 _value) public view returns (uint256) {
+ return (_value * 1000000) / demurrageModifier;
+ }
+
// ERC20, triggers tax and/or redistribution
function transfer(address _to, uint256 _value) public returns (bool) {
uint256 baseValue;
@@ -259,7 +265,7 @@ contract RedistributedDemurrageToken {
applyRedistributionOnAccount(msg.sender);
// TODO: Prefer to truncate the result, instead it seems to round to nearest :/
- baseValue = (_value * 1000000) / demurrageModifier;
+ baseValue = toBaseAmount(_value);
result = transferBase(msg.sender, _to, baseValue);
return result;
@@ -281,4 +287,32 @@ contract RedistributedDemurrageToken {
}
return true;
}
+
+ // ERC20, triggers tax and/or redistribution
+ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
+ uint256 baseValue;
+ bool result;
+
+ applyTax();
+ applyRedistributionOnAccount(msg.sender);
+
+ baseValue = toBaseAmount(_value);
+ require(allowance[_from][msg.sender] >= baseValue);
+
+ result = transferBase(_from, _to, baseValue);
+ return result;
+ }
+
+ // ERC20, triggers tax and/or redistribution
+ function approve(address _spender, uint256 _value) public returns (bool) {
+ uint256 baseValue;
+
+ applyTax();
+ applyRedistributionOnAccount(msg.sender);
+
+ baseValue = toBaseAmount(_value);
+ allowance[msg.sender][_spender] += baseValue;
+ emit Approval(msg.sender, _spender, _value);
+ return true;
+ }
}