Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3, Ethereum - how to send ERC20 Tokens?

i have some script using to sending Ethers from address to addres. Im using Parity, and Python 3.6. It is using Flask looks like:

from flask import Flask, render_template, json, request
import urllib
import requests
import binascii
from decimal import *
app = Flask(__name__)

def Eth(method,params=[]):
    data = {"method":method,"params":params,"id":1,"jsonrpc":"2.0"}
    headers = {'Content-type': 'application/json'}
    r = requests.post(ethrpc, data=json.dumps(data), headers=headers)
    r = r.text
    response = json.loads(r)
    return(response)
hot = str("XXXXXXX")
@app.route('/')
def index():
    ethnumbers = int(10)**int(18)
    hot = str("XXXXX")
    balance = Eth("eth_getBalance",[hot,'latest'])
    balance = balance["result"]
    balance = int(balance, 16)
    balance = float(balance)
    balance = balance / ethnumbers
    balance = str(balance)
    return render_template('index.html',hot = hot,balance=balance)


@app.route('/send/',methods=['POST','GET'])
def send():
    getcontext().prec = 28
    ethnumbers = Decimal(10)**Decimal(18)
    print(ethnumbers)
    if request.method == "POST":    
        _myaddress = request.form['_myaddress']
        _youraddress = request.form['_youraddress']
        _amount = request.form['_amount']
        _gas = request.form['_gas']
        _gas = hex(int(_gas))
        passy = str("XXXXXXXXX")
        getcontext().prec = 28
        _amount = Decimal(_amount)
        getcontext().prec = 28
        _amount = _amount * ethnumbers
        getcontext().prec = 28
        _amount = int(_amount)
        _amount = hex(_amount)
        r = [{'from':_myaddress,"to":_youraddress,"value":_amount,"gas":_gas,},str("XXXXXXXXXX!")]
        print(r)
        json.dumps(r)
        resultio = Eth("personal_sendTransaction",r)
        try: 
            resultio["result"]
            return render_template('sent.html',resultio=resultio["result"])
        except: KeyError
        return render_template('sent.html',resultio=resultio["error"]["message"])

    else:
        return render_template('index.html')







if __name__ == "__main__":
    app.run()

Im pretty sure, that i have to use "data" to do this, but i have no idea how to send via this script ERC20 tokens. Structure of tokens transaction looks like "my address -> token address -> token receiver".

Any ideas?

like image 810
Kamil Avatar asked Jan 24 '18 22:01

Kamil


2 Answers

Guys it was simpler than it looks like. You just have to put:

contract address

as receiver and make a long "data" field, it represents string as:

// method name, its constans in erc20

0xa9059cbb

//receiver address (you have to do it without "0x" because its needed only when
//you have to tell "im using hexadecimal". You did it above, in method field.
//so, receiver address:

5b7b3b499fb69c40c365343cb0dc842fe8c23887

// and fill it with zeros, it have to be lenght 64. So fill rest of address 

0000000000000000000000005b7b3b499fb69c40c365343cb0dc842fe8c23887

// then you need amount, please convert it to hexadecimal, delete "0x" and 
// remember, you need to integer first, so if token has 18 "decimals" it need
// to be amount / 10**18 first!!
//1e27786570c272000 and fill that with zeros, like above:

000000000000000000000000000000000000000000000001e27786570c272000

//just add string, to string, to string, and you have data field: 

0xa9059cbb0000000000000000000000005b7b3b499fb69c40c365343cb0dc842fe8c23887000000000000000000000000000000000000000000000001e27786570c272000

Sample transaction: https://etherscan.io/tx/0x9c27df8af24e06edb819a8d7a380f548fad637de5edddd6155d15087d1619964

like image 89
Kamil Avatar answered Oct 05 '22 09:10

Kamil


web3.py is definitely the way to go. If you want to do it by hand and you just want to call the standard ERC-20 transfer method, the from address should stay the same, the to address should be the token contract, and then the data should be the following concatenated together and formatted as hexadecimal:

  1. The first 4 bytes of the keccak256 hash of "transfer(address,uint256)", which is the function's signature.
  2. The address of the recipient, left-zero-padded to be 32 bytes.
  3. The amount to be transferred. (Be sure to take into account the token's decimals... 1 token is often 10**18, but the number of decimal places varies from token to token and can be retrieved by calling the decimals() function.) This should also be formatted as a 32-byte number (so left-zero-padded).

web3.py would be much easier. :-) Something like:

web3.eth.contract(address, abi=standard_token_abi).sendTransaction({
    'from': from_address
}).transfer(to_address, amount)
like image 21
user94559 Avatar answered Oct 05 '22 09:10

user94559