Add burn to giftable tokebs

This commit is contained in:
lash 2023-02-22 10:48:32 +00:00
parent d7fb3f232c
commit 04f9b5868b
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
7 changed files with 146 additions and 14 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

@ -12,6 +12,9 @@ from chainlib.eth.contract import (
ABIContractEncoder, ABIContractEncoder,
ABIContractType, ABIContractType,
) )
from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.jsonrpc import JSONRPCRequest
from hexathon import add_0x
# local imports # local imports
from giftable_erc20_token.data import data_dir from giftable_erc20_token.data import data_dir
@ -107,6 +110,48 @@ class GiftableToken(ERC20):
return tx return tx
def burn(self, contract_address, sender_address, value, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('burn')
enc.typ(ABIContractType.UINT256)
enc.uint256(value)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
def burned(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
j = JSONRPCRequest(id_generator)
o = j.template()
o['method'] = 'eth_call'
enc = ABIContractEncoder()
enc.method('burned')
data = add_0x(enc.get())
tx = self.template(sender_address, contract_address)
tx = self.set_code(tx, data)
o['params'].append(self.normalize(tx))
o['params'].append('latest')
o = j.finalize(o)
return o
def total_minted(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None):
j = JSONRPCRequest(id_generator)
o = j.template()
o['method'] = 'eth_call'
enc = ABIContractEncoder()
enc.method('totalMinted')
data = add_0x(enc.get())
tx = self.template(sender_address, contract_address)
tx = self.set_code(tx, data)
o['params'].append(self.normalize(tx))
o['params'].append('latest')
o = j.finalize(o)
return o
def bytecode(**kwargs): def bytecode(**kwargs):
return GiftableToken.bytecode(version=kwargs.get('version')) return GiftableToken.bytecode(version=kwargs.get('version'))

View File

@ -80,5 +80,44 @@ class TestExpire(TestGiftableExpireToken):
self.assertEqual(supply, mint_amount) self.assertEqual(supply, mint_amount)
def test_burn(self):
mint_amount = self.initial_supply
nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.burn(self.address, self.accounts[1], int(mint_amount / 4))
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 0)
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.burn(self.address, self.accounts[0], int(mint_amount / 4))
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
o = c.burned(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
burned = c.parse_balance(r)
self.assertEqual(burned, int(mint_amount / 4))
o = c.balance_of(self.address, self.accounts[0], sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance(r)
self.assertEqual(balance, mint_amount - burned)
o = c.total_supply(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance(r)
self.assertEqual(balance, mint_amount - burned)
o = c.total_minted(self.address, sender_address=self.accounts[0])
r = self.rpc.do(o)
balance = c.parse_balance(r)
self.assertEqual(balance, mint_amount)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,11 @@ pragma solidity >=0.6.11;
contract GiftableToken { contract GiftableToken {
// Implements EIP173
address public owner; address public owner;
mapping(address => bool) minters;
// Implements Writer
mapping(address => bool) writer;
// Implements ERC20 // Implements ERC20
string public name; string public name;
@ -15,62 +18,90 @@ contract GiftableToken {
// Implements ERC20 // Implements ERC20
uint8 public decimals; uint8 public decimals;
// Implements ERC20 // Implements ERC20
uint256 public totalSupply;
// Implements ERC20
mapping (address => uint256) public balanceOf; mapping (address => uint256) public balanceOf;
// Implements ERC20 // Implements ERC20
mapping (address => mapping (address => uint256)) public allowance; mapping (address => mapping (address => uint256)) public allowance;
// timestamp when token contract expires // Implements Burner
uint256 public totalMinted;
// Implements Burner
uint256 public burned;
// Implements expire
uint256 public expires; uint256 public expires;
bool expired; bool expired;
// Implements ERC20
event Transfer(address indexed _from, address indexed _to, uint256 _value); event Transfer(address indexed _from, address indexed _to, uint256 _value);
// Implements ERC20
event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value); event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value);
// Implements ERC20
event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value);
// Implements Minter
event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value); event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value);
// Implement Expire
event Expired(uint256 _timestamp); event Expired(uint256 _timestamp);
// Implements Writer
event WriterAdded(address _writer);
// Implements Writer
event WriterRemoved(address _writer);
// Implements Burner
event Burn(uint256 _value);
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _expireTimestamp) public { constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _expireTimestamp) public {
owner = msg.sender; owner = msg.sender;
name = _name; name = _name;
symbol = _symbol; symbol = _symbol;
decimals = _decimals; decimals = _decimals;
minters[msg.sender] = true;
expires = _expireTimestamp; expires = _expireTimestamp;
} }
// Implements ERC20
function totalSupply() public returns (uint256) {
return totalMinted - burned;
}
// Implements Minter
mapping(address => bool) writers;
function mintTo(address _to, uint256 _value) public returns (bool) { function mintTo(address _to, uint256 _value) public returns (bool) {
require(minters[msg.sender] || msg.sender == owner); require(writers[msg.sender] || msg.sender == owner);
balanceOf[_to] += _value; balanceOf[_to] += _value;
totalSupply += _value; totalMinted += _value;
emit Mint(msg.sender, _to, _value); emit Mint(msg.sender, _to, _value);
return true; return true;
} }
// Implements Writer
function addWriter(address _minter) public returns (bool) { function addWriter(address _minter) public returns (bool) {
require(msg.sender == owner); require(msg.sender == owner);
minters[_minter] = true; writers[_minter] = true;
return true; return true;
} }
// Implements Writer
function removeWriter(address _minter) public returns (bool) { function removeWriter(address _minter) public returns (bool) {
require(msg.sender == owner || msg.sender == _minter); require(msg.sender == owner || msg.sender == _minter);
minters[_minter] = false; writers[_minter] = false;
return true; return true;
} }
// Implements Writer
function isWriter(address _minter) public view returns(bool) { function isWriter(address _minter) public view returns(bool) {
return minters[_minter] || _minter == owner; return writers[_minter] || _minter == owner;
} }
// Implements Expire
function applyExpiry() public returns(uint8) { function applyExpiry() public returns(uint8) {
if (expires == 0) { if (expires == 0) {
return 0; return 0;
@ -97,6 +128,17 @@ contract GiftableToken {
return true; return true;
} }
// Implements Burner
function burn(uint256 _value) public returns (bool) {
require(msg.sender == owner, 'ERR_ACCESS');
require(balanceOf[msg.sender] >= _value, 'ERR_FUNDS');
balanceOf[msg.sender] -= _value;
burned += _value;
emit Burn(_value);
}
// Implements ERC20 // Implements ERC20
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(applyExpiry() == 0); require(applyExpiry() == 0);
@ -140,6 +182,12 @@ contract GiftableToken {
if (_sum == 0x9493f8b2) { // EIP173 if (_sum == 0x9493f8b2) { // EIP173
return true; return true;
} }
if (_sum == 0xabe1f1f5) { // Writer
return true;
}
if (_sum == 0xfccc2e79) { // Burner
return true;
}
return false; return false;
} }
} }