def test_can_mint_token_and_peg_it_for_everything_in_whitelist( basic_transfer_request: EthereumToSifchainTransferRequest, smart_contracts_dir, bridgebank_address, solidity_json_path, operator_address, ethereum_network, source_ethereum_address, rowan_source): logging.info( "token_refresh needs to use the operator private key, setting that to ETHEREUM_PRIVATE_KEY" ) os.environ["ETHEREUM_PRIVATE_KEY"] = test_utilities.get_required_env_var( "OPERATOR_PRIVATE_KEY") request = copy.deepcopy(basic_transfer_request) request.sifchain_address = rowan_source request.ethereum_address = source_ethereum_address amount_in_tokens = int(test_utilities.get_required_env_var("TOKEN_AMOUNT")) tokens = test_utilities.get_whitelisted_tokens(request) logging.info(f"whitelisted tokens: {tokens}") for t in tokens: destination_symbol = "c" + t["symbol"] if t["symbol"] == "erowan": destination_symbol = "rowan" try: logging.info(f"sending {t}") request.amount = amount_in_tokens * (10**int(t["decimals"])) request.ethereum_symbol = t["token"] request.sifchain_symbol = destination_symbol request.ethereum_address = operator_address test_utilities.mint_tokens(request, operator_address) test_utilities.send_from_ethereum_to_sifchain(request) except Exception as e: # try to get as many tokens across the bridge as you can, # don't stop if one of them fails logging.info(f"failed to mint and send for {t}, error was {e}") logging.info(f"sent new batch of tokens to {rowan_source}") test_utilities.get_sifchain_addr_balance(rowan_source, request.sifnoded_node, "rowan")
def build_request() -> (EthereumToSifchainTransferRequest, SifchaincliCredentials): new_account_key = 'user1' credentials = sifchain_cli_credentials_for_test(new_account_key) new_addr = burn_lock_functions.create_new_sifaddr(credentials=credentials, keyname=new_account_key) credentials.from_key = new_addr["name"] request = EthereumToSifchainTransferRequest( sifchain_address=new_addr["address"], smart_contracts_dir=smart_contracts_dir, ethereum_address=ethereum_address, ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY", bridgebank_address=get_required_env_var("BRIDGE_BANK_ADDRESS"), ethereum_network=(os.environ.get("ETHEREUM_NETWORK") or ""), amount=9 * 10 ** 18, ceth_amount=2 * (10 ** 16) ) return request, credentials
def test_can_create_a_new_token_and_peg_it( basic_transfer_request: EthereumToSifchainTransferRequest, smart_contracts_dir, bridgebank_address, solidity_json_path, operator_address, ethereum_network, source_ethereum_address, ): json_filename = test_utilities.get_required_env_var("TOKENS_FILE") with open(json_filename, mode="r") as json_file: contents = json_file.read() tokens = json.loads(contents) sifaddress, credentials = create_new_sifaddr_and_credentials() request = copy.deepcopy(basic_transfer_request) request.sifchain_address = sifaddress request.ethereum_address = source_ethereum_address amount_in_tokens = 10**9 # one billion of the token; note that this is not 1/(10 **18) of a token for t in tokens["assets"]: if t["symbol"] == "rowan" or t["symbol"] == 'ceth': continue logging.info(f"token is: {t}") try: decimals_int = int(t["decimals"]) amount_in_fractions_of_a_token = amount_in_tokens * (10** decimals_int) new_currency = create_new_currency( amount=amount_in_fractions_of_a_token, symbol=t["symbol"][1:], token_name=t["name"], decimals=decimals_int, smart_contracts_dir=smart_contracts_dir, bridgebank_address=bridgebank_address, solidity_json_path=solidity_json_path, operator_address=operator_address, ethereum_network=ethereum_network) request.amount = amount_in_fractions_of_a_token request.ethereum_symbol = new_currency["newtoken_address"] request.sifchain_symbol = "c" + new_currency["newtoken_symbol"] burn_lock_functions.send_from_ethereum_to_sifchain(request) except Exception as e: # it might already exist, so do nothing logging.info(f"failed to create token {t}, error was {e}")
def test_can_create_a_new_token_and_peg_it( basic_transfer_request: EthereumToSifchainTransferRequest, smart_contracts_dir, bridgebank_address, solidity_json_path, operator_address, ethereum_network, source_ethereum_address, ): json_filename = test_utilities.get_required_env_var("TOKENS_FILE") with open(json_filename, mode="r") as json_file: contents = json_file.read() tokens = json.loads(contents) sifaddress, credentials = create_new_sifaddr_and_credentials() request = copy.deepcopy(basic_transfer_request) request.sifchain_address = sifaddress request.ethereum_address = source_ethereum_address amount_in_tokens = 10 ** 9 # one billion of the token; note that this is not 1/(10 **18) of a token existing_whitelist = test_utilities.get_whitelisted_tokens(request) logging.info(f"existing whitelist: {existing_whitelist}") existing_tokens = set(map(lambda w: "c" + w["symbol"], existing_whitelist)) # ceth is special since we can't just mint it or create an ERC20 contract for it existing_tokens.add("ceth") logging.info(f"requested tokens: {tokens}") for t in tokens["assets"]: if t["symbol"] in existing_tokens or t["symbol"] == "rowan": logging.info(f"token {t} already whitelisted, skipping") continue logging.info(f"whitelisting token {t}") decimals_int = int(t["decimals"]) amount_in_fractions_of_a_token = amount_in_tokens * (10 ** decimals_int) create_new_currency( amount=amount_in_fractions_of_a_token, symbol=t["symbol"][1:], token_name=t["name"], decimals=decimals_int, smart_contracts_dir=smart_contracts_dir, bridgebank_address=bridgebank_address, solidity_json_path=solidity_json_path, operator_address=operator_address, ethereum_network=ethereum_network )
def build_request(new_currency, amount): accounts = ganache_accounts(smart_contracts_dir=smart_contracts_dir) new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_addr = burn_lock_functions.create_new_sifaddr(credentials=credentials, keyname=new_account_key) credentials.from_key = new_addr["name"] request = EthereumToSifchainTransferRequest( ethereum_symbol=new_currency["newtoken_address"], sifchain_symbol="c" + new_currency["newtoken_symbol"], sifchain_address=get_required_env_var("OWNER_ADDR"), smart_contracts_dir=smart_contracts_dir, ethereum_address=accounts["accounts"][0], ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY", bridgebank_address=bridgebank_address, bridgetoken_address=bridgetoken_address, ethereum_network=(os.environ.get("ETHEREUM_NETWORK") or ""), amount=amount, ceth_amount=2 * (10**16)) return (request, credentials)
def test_ceth_receiver_account( basic_transfer_request: EthereumToSifchainTransferRequest, source_ethereum_address: str, rowan_source_integrationtest_env_credentials: SifchaincliCredentials, rowan_source_integrationtest_env_transfer_request: EthereumToSifchainTransferRequest, ethereum_network, smart_contracts_dir, bridgetoken_address, validator_address, ethbridge_module_address, sifchain_admin_account_credentials, ): admin_account = test_utilities.get_required_env_var( "SIFCHAIN_ADMIN_ACCOUNT") ceth_rescue_account, ceth_rescue_account_credentials = integration_env_credentials.create_new_sifaddr_and_credentials( ) basic_transfer_request.sifchain_address = validator_address admin_user_credentials = sifchain_admin_account_credentials test_utilities.update_ceth_receiver_account( receiver_account=ceth_rescue_account, admin_account=admin_account, transfer_request=basic_transfer_request, credentials=admin_user_credentials) test_fee_charged_to_transfer_rowan_to_erowan( basic_transfer_request=basic_transfer_request, source_ethereum_address=source_ethereum_address, rowan_source_integrationtest_env_credentials= rowan_source_integrationtest_env_credentials, rowan_source_integrationtest_env_transfer_request= rowan_source_integrationtest_env_transfer_request, ethereum_network=ethereum_network, smart_contracts_dir=smart_contracts_dir, bridgetoken_address=bridgetoken_address, ) received_ceth_charges = test_utilities.get_sifchain_addr_balance( ceth_rescue_account, basic_transfer_request.sifnoded_node, "ceth") assert received_ceth_charges == test_utilities.burn_gas_cost
def basedir(): return test_utilities.get_required_env_var("BASEDIR")
import logging from copy import deepcopy import burn_lock_functions import test_utilities from burn_lock_functions import EthereumToSifchainTransferRequest from integration_env_credentials import sifchain_cli_credentials_for_test, create_new_sifaddr_and_credentials from test_utilities import get_required_env_var, get_shell_output, SifchaincliCredentials, get_optional_env_var ethereum_network = get_optional_env_var("ETHEREUM_NETWORK", "") amount = int(get_optional_env_var("AMOUNT", "20000")) bridgebank_address = get_required_env_var("BRIDGE_BANK_ADDRESS") def build_request( sifnodecli_node, source_ethereum_address, chain_id, smart_contracts_dir ) -> (EthereumToSifchainTransferRequest, SifchaincliCredentials): new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_addr = burn_lock_functions.create_new_sifaddr(credentials=credentials, keyname=new_account_key) credentials.from_key = new_addr["name"] ceth_fee = 2 * (10**16) request = EthereumToSifchainTransferRequest( sifchain_address=new_addr["address"], smart_contracts_dir=smart_contracts_dir, ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY", bridgebank_address=bridgebank_address, ethereum_network=ethereum_network, amount=amount + ceth_fee, ceth_amount=ceth_fee,
def rowan_source(is_ropsten_testnet): """A sifchain address or key that has rowan and can send that rowan to other address""" return test_utilities.get_required_env_var("ROWAN_SOURCE")
import burn_lock_functions from test_utilities import get_required_env_var if __name__ == "__main__": args = burn_lock_functions.transfer_argument_parser().parse_args() burn_lock_functions.configure_logging(args) logging.debug(f"command line arguments: {sys.argv} {args}") request = burn_lock_functions.args_to_EthereumToSifchainTransferRequest( args) logging.info(f"transferrequestjson: {json.dumps(request.__dict__)}") credentials = burn_lock_functions.SifchaincliCredentials( get_required_env_var("OWNER_PASSWORD"), from_key="user1", homedir=get_required_env_var("CHAINDIR") + "/.sifnodecli") transfer_result = burn_lock_functions.transfer_sifchain_to_sifchain( request, credentials) logging.debug(f"transfer_result is: {transfer_result}") final_balance = transfer_result["sifchain_ending_balance"] result = json.dumps({ "final_balance": final_balance, "final_balance_10_18": float(final_balance) / (10**18), "transfer_request": request.__dict__, "logfile": args.logfile[0], "steps": transfer_result })
def integration_dir(): return test_utilities.get_required_env_var("TEST_INTEGRATION_DIR")
import logging import os from copy import copy, deepcopy from functools import lru_cache from json import JSONDecodeError import pytest import burn_lock_functions from burn_lock_functions import EthereumToSifchainTransferRequest from integration_env_credentials import sifchain_cli_credentials_for_test import test_utilities from test_utilities import get_required_env_var, get_shell_output, SifchaincliCredentials, amount_in_wei, \ get_optional_env_var, ganache_owner_account smart_contracts_dir = get_required_env_var("SMART_CONTRACTS_DIR") ethereum_address = get_optional_env_var( "ETHEREUM_ADDRESS", ganache_owner_account(smart_contracts_dir)) def build_request( ) -> (EthereumToSifchainTransferRequest, SifchaincliCredentials): new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_addr = burn_lock_functions.create_new_sifaddr(credentials=credentials, keyname=new_account_key) credentials.from_key = new_addr["name"] request = EthereumToSifchainTransferRequest( sifchain_address=new_addr["address"], smart_contracts_dir=smart_contracts_dir,
def test_rollback_chain(source_ethereum_address): new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_account = burn_lock_functions.create_new_sifaddr( credentials=credentials, keyname=new_account_key) credentials.from_key = new_account["name"] # Any amount will work amount = 11000 request = EthereumToSifchainTransferRequest( sifchain_address=new_account["address"], smart_contracts_dir=get_required_env_var("SMART_CONTRACTS_DIR"), ethereum_address=source_ethereum_address, ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY", bridgebank_address=get_required_env_var("BRIDGE_BANK_ADDRESS"), ethereum_network=(os.environ.get("ETHEREUM_NETWORK") or ""), amount=amount) logging.info(f"create account with a balance of {request.amount}") burn_lock_functions.transfer_ethereum_to_sifchain(request, 50) new_addr = new_account["address"] snapshot = get_shell_output( f"{test_integration_dir}/snapshot_ganache_chain.sh") logging.info(f"created new account, took ganache snapshot {snapshot}") initial_user_balance = get_sifchain_addr_balance(new_addr, "", request.sifchain_symbol) logging.info(f"initial_user_balance {initial_user_balance}") transfer_1 = send_from_ethereum_to_sifchain(transfer_request=request) logging.info(f"transfer started but it will never complete (by design)") logging.info("advance less than wait blocks") advance_n_ethereum_blocks(n_wait_blocks / 2, request.smart_contracts_dir) # the transaction should not have happened on the sifchain side yet # since we haven't waited for the right number of blocks. # roll back ganache to the snapshot and try another transfer that # should succeed. logging.info( f"apply snapshot {snapshot} - this eliminates transfer_1 (block {transfer_1})" ) get_shell_output( f"{test_integration_dir}/apply_ganache_snapshot.sh {snapshot} 2>&1") logging.info("advance past block wait") advance_n_ethereum_blocks(n_wait_blocks * 2, request.smart_contracts_dir) time.sleep(5) second_user_balance = get_sifchain_addr_balance(new_addr, "", request.sifchain_symbol) if second_user_balance == initial_user_balance: logging.info( f"got expected outcome of no balance change @ {initial_user_balance}" ) else: raise Exception( f"balance should be the same after applying snapshot and rolling forward n_wait_blocks * 2. initial_user_balance: {initial_user_balance} second_user_balance: {second_user_balance}" ) request.amount = 10000 logging.info(f"sending more eth: {request.amount} to {new_addr}") burn_lock_functions.transfer_ethereum_to_sifchain(request) # We want to know that ebrelayer will never do a second transaction. # We can't know that, so just delay a reasonable amount of time. logging.info("delay to give ebrelayer time to make a mistake") time.sleep(10) balance_after_sleep = get_sifchain_addr_balance(new_addr, "", request.sifchain_symbol) logging.info( f"get_sifchain_addr_balance after sleep is {balance_after_sleep} for {new_addr}" ) expected_balance = initial_user_balance + request.amount logging.info(f"look for a balance of {expected_balance}") wait_for_sifchain_addr_balance(new_addr, request.sifchain_symbol, expected_balance, "")
import logging import os import time import burn_lock_functions from integration_env_credentials import sifchain_cli_credentials_for_test from test_utilities import get_shell_output, get_sifchain_addr_balance, \ advance_n_ethereum_blocks, n_wait_blocks, \ send_from_ethereum_to_sifchain from test_utilities import wait_for_sifchain_addr_balance, \ get_required_env_var, \ EthereumToSifchainTransferRequest test_integration_dir = get_required_env_var("TEST_INTEGRATION_DIR") def test_rollback_chain(source_ethereum_address): new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_account = burn_lock_functions.create_new_sifaddr( credentials=credentials, keyname=new_account_key) credentials.from_key = new_account["name"] # Any amount will work amount = 11000 request = EthereumToSifchainTransferRequest( sifchain_address=new_account["address"], smart_contracts_dir=get_required_env_var("SMART_CONTRACTS_DIR"), ethereum_address=source_ethereum_address, ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY",
def sifnode_base_dir(): return test_utilities.get_required_env_var("BASEDIR")
def sifchain_admin_account(): return test_utilities.get_required_env_var("SIFCHAIN_ADMIN_ACCOUNT")
def smart_contracts_dir(): return test_utilities.get_required_env_var("SMART_CONTRACTS_DIR")
import logging from copy import deepcopy import burn_lock_functions import test_utilities from burn_lock_functions import EthereumToSifchainTransferRequest from integration_env_credentials import sifchain_cli_credentials_for_test from test_utilities import get_required_env_var, get_shell_output, SifchaincliCredentials, get_optional_env_var smart_contracts_dir = get_required_env_var("SMART_CONTRACTS_DIR") ethereum_network = get_optional_env_var("ETHEREUM_NETWORK", "") amount = int(get_optional_env_var("AMOUNT", "20000")) bridgebank_address = get_required_env_var("BRIDGE_BANK_ADDRESS") def build_request( sifnodecli_node, source_ethereum_address, chain_id ) -> (EthereumToSifchainTransferRequest, SifchaincliCredentials): new_account_key = get_shell_output("uuidgen") credentials = sifchain_cli_credentials_for_test(new_account_key) new_addr = burn_lock_functions.create_new_sifaddr(credentials=credentials, keyname=new_account_key) credentials.from_key = new_addr["name"] ceth_fee = 2 * (10**16) request = EthereumToSifchainTransferRequest( sifchain_address=new_addr["address"], smart_contracts_dir=smart_contracts_dir, ethereum_address=source_ethereum_address, ethereum_private_key_env_var="ETHEREUM_PRIVATE_KEY", bridgebank_address=bridgebank_address, ethereum_network=ethereum_network,
def bridgebank_address(): return test_utilities.get_required_env_var("BRIDGE_BANK_ADDRESS")
def bridgetoken_address(): return test_utilities.get_required_env_var("BRIDGE_TOKEN_ADDRESS")
def test_bulk_transfers_from_sifchain( basic_transfer_request: EthereumToSifchainTransferRequest, rowan_source_integrationtest_env_credentials: SifchaincliCredentials, rowan_source_integrationtest_env_transfer_request: EthereumToSifchainTransferRequest, smart_contracts_dir, source_ethereum_address, rowan_source, rowan_source_key, bridgebank_address, bridgetoken_address, ethereum_network, sifchain_fees_int, ): test_transfer_amount = 100 # just a tiny number of wei to move to confirm things are working tokens = test_utilities.get_required_env_var("TOKENS", "ceth,rowan").split(",") logging.info(f"tokens to be transferred are: {tokens}") logging.info("create new ethereum and sifchain addresses") basic_transfer_request.ethereum_address = source_ethereum_address n_transfers = int(test_utilities.get_optional_env_var("NTRANSFERS", 2)) n_transactions = n_transfers * len(tokens) new_addresses_and_keys = list(map(lambda x: create_new_sifaddr_and_key(), range(n_transactions))) logging.debug(f"new_addresses_and_keys: {new_addresses_and_keys}") credentials_for_account_with_ceth = SifchaincliCredentials(from_key=rowan_source_key) request: EthereumToSifchainTransferRequest = copy.deepcopy(basic_transfer_request) ceth_amount = n_transactions * (test_utilities.highest_gas_cost + 100) request.amount = ceth_amount request.ethereum_address = source_ethereum_address request.sifchain_address = rowan_source addresses_to_populate = copy.deepcopy(new_addresses_and_keys) test_transfers = [] for a in range(n_transfers): for t in tokens: request.sifchain_destination_address, from_key = addresses_to_populate.pop() # send ceth to pay for the burn request.amount = test_utilities.burn_gas_cost request.sifchain_symbol = "ceth" burn_lock_functions.transfer_sifchain_to_sifchain(request, credentials_for_account_with_ceth) # send rowan to pay the fee request.amount = sifchain_fees_int request.sifchain_symbol = "rowan" burn_lock_functions.transfer_sifchain_to_sifchain(request, credentials_for_account_with_ceth) # send the token itself request.amount = test_transfer_amount request.sifchain_symbol = t burn_lock_functions.transfer_sifchain_to_sifchain(request, credentials_for_account_with_ceth) transfer = (request.sifchain_destination_address, from_key, request.sifchain_symbol, request.amount) test_utilities.get_sifchain_addr_balance(request.sifchain_destination_address, request.sifnodecli_node, t) test_transfers.append(transfer) logging.debug(f"test_transfers is {test_transfers}") text_file = open("pfile.cmds", "w") simple_credentials = SifchaincliCredentials( keyring_passphrase=None, keyring_backend="test", from_key=None, sifnodecli_homedir=None ) logging.info(f"all accounts are on sifchain and have the correct balance") new_eth_addrs = test_utilities.create_ethereum_addresses( smart_contracts_dir, basic_transfer_request.ethereum_network, n_transactions ) logging.debug(f"new eth addrs: {new_eth_addrs}") ethereum_transfers = [] for sifaddr, from_key, sifsymbol, amount in test_transfers: destination_ethereum_address_element = new_eth_addrs.pop() r = copy.deepcopy(basic_transfer_request) r.sifchain_symbol = sifsymbol r.sifchain_address = sifaddr r.ethereum_address = destination_ethereum_address_element["address"] r.amount = amount simple_credentials.from_key = from_key c = test_utilities.send_from_sifchain_to_ethereum_cmd(r, simple_credentials) ethereum_symbol = test_utilities.sifchain_symbol_to_ethereum_symbol(sifsymbol) transfer = (r.ethereum_address, ethereum_symbol, amount) ethereum_transfers.append(transfer) text_file.write(f"{c}\n") text_file.close() test_utilities.get_shell_output("cat pfile.cmds | parallel --trim lr -v {}") whitelist = test_utilities.get_whitelisted_tokens(basic_transfer_request) test_utilities.advance_n_ethereum_blocks(test_utilities.n_wait_blocks, smart_contracts_dir) for ethereum_address, ethereum_symbol, amount in ethereum_transfers: r = copy.deepcopy(basic_transfer_request) r.ethereum_address = ethereum_address r.ethereum_symbol = test_utilities.get_token_ethereum_address( ethereum_symbol, whitelist ) r.amount = amount test_utilities.wait_for_eth_balance( transfer_request=r, target_balance=amount, max_seconds=60 * 60 * 10 )