Last active
December 6, 2022 23:45
-
-
Save 30mb1/6467e8136ababa3c3398d0e36ce0fa94 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from web3.contract import ConciseContract | |
from web3 import Web3, HTTPProvider | |
from zero_ex.order_utils import asset_data_utils, sign_hash | |
from zero_ex.order_utils import generate_order_hash_hex | |
import time | |
from random import randint | |
from eth_abi import encode_single | |
from binascii import unhexlify | |
# swap token number to its solidity representation | |
def to_base_unit(quantity, decimals): | |
return quantity * 10**decimals | |
def wait_txn_success(tx_hash): | |
while True: | |
res = w3.eth.waitForTransactionReceipt(tx_hash) | |
if res['status'] != 1: | |
raise Exception('Transaction execution failed.') | |
return | |
def get_random_future_date(): | |
return int(time.time() + randint(10, 1000)) | |
def encode_order(order, taker_asset_amount): | |
abi_encoding = '((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),uint256,bytes)' | |
encoded_data = encode_single( | |
abi_encoding, | |
((order['makerAddress'], | |
order['takerAddress'], | |
order['feeRecipientAddress'], | |
order['senderAddress'], | |
int(order['makerAssetAmount']), | |
int(order['takerAssetAmount']), | |
int(order['makerFee']), | |
int(order['takerFee']), | |
int(order['expirationTimeSeconds']), | |
int(order['salt']), | |
unhexlify(order['makerAssetData'][2:]), | |
unhexlify(order['takerAssetData'][2:])), | |
taker_asset_amount, | |
unhexlify(order['signature'][2:])) | |
) | |
return encoded_data | |
MAX_UINT_256 = 2**256 - 1 | |
NULL_ADDRESS = "0x0000000000000000000000000000000000000000" | |
with open('erc20.abi.json', 'r') as f: | |
erc20_abi = json.load(f) | |
with open('exchange.abi.json', 'r') as f: | |
exchange_abi = json.load(f) | |
with open('erc20proxy.abi.json', 'r') as f: | |
erc20proxy_abi = json.load(f) | |
# setting web3 instance | |
provider = HTTPProvider('http://127.0.0.1:8545') | |
w3 = Web3(provider) | |
erc_20_1_address = w3.toChecksumAddress('0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f') | |
erc_20_2_address = w3.toChecksumAddress('0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db') | |
erc_20_proxy_address = w3.toChecksumAddress('0x1dc4c1cefef38a777b15aa20260a54e584b16c48') | |
exchange_address = w3.toChecksumAddress('0x48bacb9266a570d521063ef5dd96e61686dbe788') | |
# creating contracts instances | |
# 2 dummy tokens and exchage contract | |
erc20_1_contract = w3.eth.contract( | |
abi=erc20_abi, | |
address=erc_20_1_address, | |
ContractFactoryClass=ConciseContract | |
) | |
erc20_2_contract = w3.eth.contract( | |
abi=erc20_abi, | |
address=erc_20_2_address, | |
ContractFactoryClass=ConciseContract | |
) | |
exchange_contract = w3.eth.contract( | |
abi=exchange_abi, | |
address=exchange_address, | |
ContractFactoryClass=ConciseContract | |
) | |
erc20proxy_contract = w3.eth.contract( | |
abi=erc20proxy_abi, | |
address=erc_20_proxy_address, | |
ContractFactoryClass=ConciseContract | |
) | |
# getting available accounts | |
accounts = w3.personal.listAccounts | |
# declaring maker and taker | |
maker, taker = accounts[:2] | |
# 1st account 1000000000000000000000000000 tokens by defualt | |
# we need to send some to taker | |
tx_hash = erc20_2_contract.transfer(taker, to_base_unit(1000, 18), transact={'from':maker}) | |
wait_txn_success(tx_hash) | |
# these values will be used later for creating order | |
maker_asset_data = asset_data_utils.encode_erc20_asset_data(erc_20_1_address) | |
taker_asset_data = asset_data_utils.encode_erc20_asset_data(erc_20_2_address) | |
# both tokens have 18 decimals | |
# we will swap 10 erc1 tokens for 20 erc2 tokens | |
maker_asset_amount = to_base_unit(10, 18) | |
taker_asset_amount = to_base_unit(20, 18) | |
# required initial setup | |
# we need to approve 0x contracts to move our funds through allowance | |
# in fact, we give unlimited allowance to 0x erc20proxy contract | |
tx_hash = erc20_1_contract.approve(erc_20_proxy_address, MAX_UINT_256, transact={'from':maker}) | |
wait_txn_success(tx_hash) | |
tx_hash = erc20_2_contract.approve(erc_20_proxy_address, MAX_UINT_256, transact={'from':taker}) | |
wait_txn_success(tx_hash) | |
# creating order | |
order = { | |
'exchangeAddress':exchange_address.lower(), | |
'makerAddress':maker.lower(), | |
'takerAddress':NULL_ADDRESS, | |
'senderAddress':NULL_ADDRESS, | |
'feeRecipientAddress':NULL_ADDRESS, | |
'expirationTimeSeconds':str(get_random_future_date()), | |
'salt':str(randint(1, 2**256)), | |
'makerAssetAmount':str(maker_asset_amount), | |
'takerAssetAmount':str(taker_asset_amount), | |
'makerAssetData':maker_asset_data, | |
'takerAssetData':taker_asset_data, | |
'makerFee':"0", | |
'takerFee':"0" | |
} | |
# generate the order hash and sign it | |
order_hash_hex = generate_order_hash_hex(order) | |
# now we need to sign order | |
signature = sign_hash(provider, maker, order_hash_hex) | |
signed_order = { **order, 'signature' : signature } | |
# in real situation we need to validate order (e.g check signature, amounts ans etc.) | |
# but this is a test case, we will send order right away | |
encoded_order = encode_order(signed_order, taker_asset_amount) | |
fn_selector = Web3.sha3(text='fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),uint256,bytes)')[:4] | |
tx_hash = w3.eth.sendTransaction({ | |
'to':exchange_address, | |
'from':taker, | |
'data':fn_selector + encoded_order, | |
'gas':2000000 | |
}) | |
wait_txn_success(tx_hash) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment