I have a solidity contract like the following:
contract MyToken { string public symbol; string public name; uint8 public decimals; uint public _totalSupply; mapping(address => uint) balances; mapping(address => mapping(address => uint)) allowed; constructor() { symbol = "my"; name = "My Token"; decimals = 18; _totalSupply = 100000000000000000000000000; balances[0x364ca3F935E88Fbc9e041d2032F996CAc69452e6] = _totalSupply / 2; balances[0x5506195d8111B5e150Fb68Ceba2806c546C5a28B] = _totalSupply / 2; Transfer(address(0), 0x364ca3F935E88Fbc9e041d2032F996CAc69452e6, _totalSupply / 2); Transfer(address(0), 0x5506195d8111B5e150Fb68Ceba2806c546C5a28B, _totalSupply / 2); } // ------------------------------------------------------------------------ // Transfer the balance from token owner's account to to account // - Owner's account must have sufficient balance to transfer // - 0 value transfers are allowed // ------------------------------------------------------------------------ function transfer(address to, uint tokens) public returns (bool success) { // this isn't safe for the sake of minimal example balances[msg.sender] -= tokens; balances[to] += tokens; Transfer(msg.sender, to, tokens); return true; } }
I'm using web3py to run tests against this contract but I'm having trouble transferring coins from 0x5506195d8111B5e150Fb68Ceba2806c546C5a28B
to a dummy address which I declare in my tests. My tests are as follows:
import web3 import unittest class TestMycroToken(unittest.TestCase): def setUp(self): self.w3 = web3.Web3(web3.EthereumTesterProvider()) self.contract, self.contract_address, self.contract_instance = self.deploy_contract() def deploy_contract(): compiled_sol = compile_files([]) contract_interface = compiled_sol[f'{PATH_TO_MY_CONTRACT}:MyToken'] # Instantiate and deploy contract contract = self.w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin']) # Get transaction hash from deployed contract tx_hash = contract.constructor().transact({'from': self.w3.eth.accounts[0]}) # Get tx receipt to get contract address tx_receipt = self.w3.eth.getTransactionReceipt(tx_hash) contract_address = tx_receipt['contractAddress'] # Contract instance in concise mode abi = contract_interface['abi'] contract_instance = self.w3.eth.contract(address=contract_address, abi=abi, ContractFactoryClass=web3.contract.ConciseContract) return contract, contract_address, contract_instance def test_transfer(self): DUMMY_USER = "0x1111111111111111111111111111111111111112" USER_ADDRESS = "0x5506195d8111B5e150Fb68Ceba2806c546C5a28B" # this line fails self.contract_instance.transfer(DEFAULT_USER, 10, transact={'from': USER_ADDRESS})
When I try to transfer coins from USER_ADDRESS
(who has coins sent to them during the constructor) I get the following failure:
Error Traceback (most recent call last): File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/backends/pyethereum/v16/main.py", line 137, in _send_evm_transaction sender = tester.keys[tester.accounts.index(transaction['from'])] ValueError: b'U\x06\x19]\x81\x11\xb5\xe1P\xfbh\xce\xba(\x06\xc5F\xc5\xa2\x8b' is not in list During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py", line 59, in testPartExecutor yield File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py", line 605, in run testMethod() File "/Users/paymahn/mycro/tests/test_mycro_token.py", line 129, in test_vote_then_move_balance_is_useless self.contract_instance.transfer(DEFAULT_USER, 10, transact={'from': AARON_ADDRESS}) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/contract.py", line 777, in __call__ return self.__prepared_function(*args, **kwargs) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/contract.py", line 790, in __prepared_function return getattr(self._function(*args), modifier)(modifier_dict) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/contract.py", line 1028, in transact **self.kwargs) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/contract.py", line 1305, in transact_with_contract_function txn_hash = web3.eth.sendTransaction(transact_transaction) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/eth.py", line 247, in sendTransaction get_buffered_gas_estimate(self.web3, transaction), File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/utils/transactions.py", line 72, in get_buffered_gas_estimate gas_estimate = web3.eth.estimateGas(gas_estimate_transaction) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/eth.py", line 288, in estimateGas [transaction], File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/manager.py", line 103, in request_blocking response = self._make_request(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/manager.py", line 86, in _make_request return request_func(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/gas_price_strategy.py", line 18, in middleware return make_request(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/formatting.py", line 21, in middleware response = make_request(method, formatted_params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/attrdict.py", line 18, in middleware response = make_request(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/formatting.py", line 21, in middleware response = make_request(method, formatted_params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/normalize_errors.py", line 9, in middleware result = make_request(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/validation.py", line 44, in middleware return make_request(method, post_validated_params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/formatting.py", line 21, in middleware response = make_request(method, formatted_params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/providers/eth_tester/middleware.py", line 315, in middleware return make_request(method, [filled_transaction] + params[1:]) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/fixture.py", line 12, in middleware return make_request(method, params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/middleware/formatting.py", line 21, in middleware response = make_request(method, formatted_params) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/providers/eth_tester/main.py", line 46, in make_request response = delegator(self.ethereum_tester, params) File "cytoolz/functoolz.pyx", line 232, in cytoolz.functoolz.curry.__call__ File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/web3/providers/eth_tester/defaults.py", line 36, in call_eth_tester return getattr(eth_tester, fn_name)(*fn_args, **fn_kwargs) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/main.py", line 466, in estimate_gas raw_gas_estimate = self.backend.estimate_gas(raw_transaction) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/utils/formatting.py", line 85, in wrapper return to_wrap(*args, **kwargs) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/backends/pyethereum/v16/main.py", line 439, in estimate_gas transaction=transaction, File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/backends/pyethereum/v16/main.py", line 157, in _estimate_evm_transaction return _send_evm_transaction(tester_module, evm, transaction_for_estimate) File "/Users/paymahn/mycro/venv/lib/python3.6/site-packages/eth_tester/backends/pyethereum/v16/main.py", line 139, in _send_evm_transaction sender = evm.extra_accounts[transaction['from']] KeyError: b'U\x06\x19]\x81\x11\xb5\xe1P\xfbh\xce\xba(\x06\xc5F\xc5\xa2\x8b'
This makes sense to me, USER_ADDRESS
was never registered as a sender in the test provider (I'm sure I got some of that terminology wrong). In the deploy_contract
function, I send the constructor transaction from self.w3.eth.accounts[0]
.
My question is: how can I send currency in web3py from an address that gets coins during initialization?