Skip to content

Instantly share code, notes, and snippets.

@30mb1
Last active December 6, 2022 23:45
Show Gist options
  • Save 30mb1/6467e8136ababa3c3398d0e36ce0fa94 to your computer and use it in GitHub Desktop.
Save 30mb1/6467e8136ababa3c3398d0e36ce0fa94 to your computer and use it in GitHub Desktop.
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