diff --git a/python/eth_erc20/erc20.py b/python/eth_erc20/erc20.py index 00725c4..3bec684 100644 --- a/python/eth_erc20/erc20.py +++ b/python/eth_erc20/erc20.py @@ -7,7 +7,6 @@ from hexathon import ( add_0x, strip_0x, ) -from crypto_dev_signer.eth.transaction import EIP155Transaction # external imports from chainlib.hash import ( diff --git a/python/eth_erc20/runnable/approve.py b/python/eth_erc20/runnable/approve.py new file mode 100644 index 0000000..53eeb9d --- /dev/null +++ b/python/eth_erc20/runnable/approve.py @@ -0,0 +1,99 @@ +#!python3 + +"""Token transfer script + +.. moduleauthor:: Louis Holbrook +.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 + +""" + +# SPDX-License-Identifier: GPL-3.0-or-later + +# standard imports +import os +import io +import json +import argparse +import logging + +# external imports +from hexathon import ( + add_0x, + strip_0x, + ) +from chainlib.eth.connection import EthHTTPConnection +from chainlib.chain import ChainSpec +from chainlib.eth.runnable.util import decode_for_puny_humans +from chainlib.eth.address import to_checksum_address +import chainlib.eth.cli + +# local imports +from eth_erc20 import ERC20 + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.WALLET +argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_positional('amount', type=int, help='Token amount to send') +args = argparser.parse_args() +extra_args = { + 'amount': None, + } +config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=100000) + +block_all = args.ww +block_last = args.w or block_all + +wallet = chainlib.eth.cli.Wallet() +wallet.from_config(config) + +rpc = chainlib.eth.cli.Rpc(wallet=wallet) +conn = rpc.connect_by_config(config) + +chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) + +value = config.get('_AMOUNT') + +send = config.true('_RPC_SEND') + +def main(): + + signer = rpc.get_signer() + signer_address = rpc.get_sender_address() + + gas_oracle = rpc.get_gas_oracle() + nonce_oracle = rpc.get_nonce_oracle() + + g = ERC20(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) + + recipient = to_checksum_address(config.get('_RECIPIENT')) + if not config.true('_UNSAFE') and recipient != add_0x(config.get('_RECIPIENT')): + raise ValueError('invalid checksum address for recipient') + + token_address = to_checksum_address(config.get('_EXEC_ADDRESS')) + if not config.true('_UNSAFE') and token_address != add_0x(config.get('_EXEC_ADDRESS')): + raise ValueError('invalid checksum address for contract') + + (tx_hash_hex, o) = g.approve(token_address, signer_address, recipient, value, id_generator=rpc.id_generator) + + if send: + conn.do(o) + if block_last: + r = conn.wait(tx_hash_hex) + if logg.isEnabledFor(logging.DEBUG): + sender_balance = balance(g, token_address, signer_address, id_generator=rpc.id_generator) + recipient_balance = balance(g, token_address, recipient, id_generator=rpc.id_generator) + logg.debug('sender {} balance after: {}'.format(signer_address, sender_balance)) + logg.debug('recipient {} balance after: {}'.format(recipient, recipient_balance)) + if r['status'] == 0: + logg.critical('VM revert. Wish I could tell you more') + sys.exit(1) + print(tx_hash_hex) + + else: + print(o['params'][0]) + + +if __name__ == '__main__': + main() diff --git a/python/requirements.txt b/python/requirements.txt index b2de75f..b8e7803 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1,4 +1,3 @@ confini>=0.3.6rc3,<0.5.0 -crypto-dev-signer>=0.4.15a1,<=0.4.15 chainlib-eth>=0.0.9a9,<=0.1.0 potaahto~=0.0.1a2 diff --git a/solidity/GiftableToken.sol b/solidity/GiftableToken.sol index e1f8629..3c11757 100644 --- a/solidity/GiftableToken.sol +++ b/solidity/GiftableToken.sol @@ -23,7 +23,7 @@ contract GiftableToken { event Transfer(address indexed _from, address indexed _to, uint256 _value); event TransferFrom(address indexed _from, address indexed _to, address indexed _spender, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value); - event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value); + event Mint(address indexed _minter, address indexed _beneficiary, uint256 _value); // Minter constructor(string memory _name, string memory _symbol, uint8 _decimals) public { owner = msg.sender; @@ -33,6 +33,7 @@ contract GiftableToken { minters[msg.sender] = true; } + // Implements Minter function mintTo(address _to, uint256 _value) public returns (bool) { require(minters[msg.sender]); @@ -52,6 +53,11 @@ contract GiftableToken { return true; } + // Implements Writer + function addWriter(address _minter) public returns (bool) { + return addMinter(_minter); + } + function removeMinter(address _minter) public returns (bool) { require(msg.sender == owner || msg.sender == _minter); @@ -60,6 +66,11 @@ contract GiftableToken { return true; } + // Implements Writer + function deleteWriter(address _minter) public returns (bool) { + return removeMinter(_minter); + } + // Implements ERC20 function transfer(address _to, uint256 _value) public returns (bool) { require(balanceOf[msg.sender] >= _value); @@ -101,6 +112,9 @@ contract GiftableToken { if (_sum == 0x01ffc9a7) { // EIP165 return true; } + if (_sum == 0x80c84bd6) { // Writer + return true; + } return false; } }