def unfreeze(aergo_to: herapy.Aergo, receiver: str, lock_proof: AttributeDict, bridge_to: str, gas_limit: int, gas_price: int) -> Tuple[str, Transaction]: """ Unlock the receiver's deposit balance on aergo_to. """ if not is_aergo_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Aergo address".format(receiver)) ap = format_proof_for_lua(lock_proof.storageProof[0].proof) balance = int.from_bytes(lock_proof.storageProof[0].value, "big") ubig_balance = {'_bignum': str(balance)} # call unlock on aergo_to with the burn proof from aergo_from tx, result = aergo_to.call_sc(bridge_to, "unfreeze", args=[receiver, ubig_balance, ap], gas_limit=gas_limit, gas_price=gas_price) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Unfreeze asset Tx commit failed : {}".format(result)) result = aergo_to.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Unfreeze asset Tx execution failed : {}".format(result)) logger.info("\u26fd Unfreeze tx fee paid: %s", result.fee_used) logger.info("\u26fd Aergo gas used: %s", result.gas_used) return str(tx.tx_hash), result
def mint(aergo_to: herapy.Aergo, receiver: str, lock_proof: AttributeDict, token_origin: str, bridge_to: str, gas_limit: int, gas_price: int) -> Tuple[str, str, Transaction]: """ Unlock the receiver's deposit balance on aergo_to. """ if not is_aergo_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Aergo address".format(receiver)) if not is_ethereum_address(token_origin): raise InvalidArgumentsError( "token_origin {} must be an Ethereum address".format(token_origin)) ap = format_proof_for_lua(lock_proof.storageProof[0].proof) balance = int.from_bytes(lock_proof.storageProof[0].value, "big") ubig_balance = {'_bignum': str(balance)} # call unlock on aergo_to with the burn proof from aergo_from tx, result = aergo_to.call_sc( bridge_to, "mint", args=[receiver, ubig_balance, token_origin[2:].lower(), ap], gas_limit=gas_limit, gas_price=gas_price) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Mint asset Tx commit failed : {}".format(result)) result = aergo_to.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Mint asset Tx execution failed : {}".format(result)) logger.info("\u26fd Aergo gas used: %s", result.gas_used) token_pegged = json.loads(result.detail)[0] return token_pegged, str(tx.tx_hash), result
def freeze( aergo_from: herapy.Aergo, bridge_from: str, receiver: str, value: int, gas_limit: int, gas_price: int, ) -> Tuple[int, str, Transaction]: """ Freeze aergo native """ if not is_ethereum_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Ethereum address".format(receiver)) args = (receiver[2:].lower(), {"_bignum": str(value)}) tx, result = aergo_from.call_sc(bridge_from, "freeze", amount=value, args=args, gas_limit=gas_limit, gas_price=gas_price) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Freeze asset Tx commit failed : {}".format(result)) # Check freeze success result = aergo_from.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Freeze Aer Tx execution failed : {}".format(result)) logger.info("\u26fd Aergo gas used: %s", result.gas_used) # get precise burn height tx_detail = aergo_from.get_tx(tx.tx_hash) freeze_height = tx_detail.block.height return freeze_height, str(tx.tx_hash), tx_detail
def burn( aergo_from: herapy.Aergo, bridge_from: str, receiver: str, value: int, token_pegged: str, gas_limit: int, gas_price: int, ) -> Tuple[int, str, Transaction]: """ Burn a minted token on a sidechain. """ if not is_ethereum_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Ethereum address".format(receiver)) if not is_aergo_address(token_pegged): raise InvalidArgumentsError( "token_pegged {} must be an Aergo address".format(token_pegged)) args = (receiver[2:].lower(), {"_bignum": str(value)}, token_pegged) tx, result = aergo_from.call_sc(bridge_from, "burn", args=args, gas_limit=gas_limit, gas_price=gas_price) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Burn asset Tx commit failed : {}".format(result)) # Check burn success result = aergo_from.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Burn asset Tx execution failed : {}".format(result)) logger.info("\u26fd Aergo gas used: %s", result.gas_used) # get precise burn height tx_detail = aergo_from.get_tx(tx.tx_hash) burn_height = tx_detail.block.height return burn_height, str(tx.tx_hash), tx_detail
def mint( aergo_to: herapy.Aergo, receiver: str, lock_proof: herapy.obj.sc_state.SCState, token_origin: str, bridge_to: str, gas_limit: int, gas_price: int ) -> Tuple[str, str]: """ Mint the receiver's deposit balance on aergo_to. """ if not is_aergo_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Aergo address".format(receiver) ) auditPath = lock_proof.var_proofs[0].auditPath ap = [node.hex() for node in auditPath] balance = lock_proof.var_proofs[0].value.decode('utf-8')[1:-1] ubig_balance = {'_bignum': str(balance)} # call mint on aergo_to with the lock proof from aergo_from tx, result = aergo_to.call_sc( bridge_to, "mint", args=[receiver, ubig_balance, token_origin, ap], gas_limit=gas_limit, gas_price=gas_price ) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Mint asset Tx commit failed : {}".format(result)) result = aergo_to.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Mint asset Tx execution failed : {}".format(result)) logger.info("\u26fd gas used: %s", result.gas_used) token_pegged = json.loads(result.detail)[0] return token_pegged, str(tx.tx_hash)
def burn(w3: Web3, signer_acct, receiver: str, amount: int, bridge_from: str, bridge_from_abi: str, token_pegged: str, gas_limit: int, gas_price: int) -> Tuple[int, str, AttributeDict]: """ Burn a token that was minted on ethereum. """ if not is_aergo_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Aergo address".format(receiver)) if not is_ethereum_address(token_pegged): raise InvalidArgumentsError( "token_pegged {} must be an Ethereum address".format(token_pegged)) bridge_from = Web3.toChecksumAddress(bridge_from) eth_bridge = w3.eth.contract(address=bridge_from, abi=bridge_from_abi) construct_txn = eth_bridge.functions.burn( receiver, amount, token_pegged).buildTransaction({ 'chainId': w3.eth.chainId, 'from': signer_acct.address, 'nonce': w3.eth.getTransactionCount(signer_acct.address), 'gas': gas_limit, 'gasPrice': w3.toWei(gas_price, 'gwei') }) signed = signer_acct.sign_transaction(construct_txn) tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction) receipt = w3.eth.waitForTransactionReceipt(tx_hash) if receipt.status != 1: raise TxError("Burn asset Tx execution failed: {}".format(receipt)) logger.info("\u26fd Eth Gas used: %s", receipt.gasUsed) return receipt.blockNumber, tx_hash.hex(), receipt
def increase_approval(spender: str, asset_addr: str, amount: int, w3: Web3, erc20_abi: str, signer_acct, gas_limit: int, gas_price: int) -> Tuple[int, str]: """ Increase approval increases the amount of tokens that spender can withdraw. For older tokens without the increaseApproval function in the abi, approval should be set to 0 and then to amount. Newer tokens with increaseAllowance should also be suported """ asset_addr = Web3.toChecksumAddress(asset_addr) spender = Web3.toChecksumAddress(spender) function = get_abi_function(w3, asset_addr, erc20_abi, spender, amount) approval_nonce = w3.eth.getTransactionCount(signer_acct.address) construct_txn = function.buildTransaction({ 'chainId': w3.eth.chainId, 'from': signer_acct.address, 'nonce': approval_nonce, 'gas': gas_limit, 'gasPrice': w3.toWei(gas_price, 'gwei') }) signed = signer_acct.sign_transaction(construct_txn) tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction) receipt = w3.eth.waitForTransactionReceipt(tx_hash) if receipt.status != 1: raise TxError( "Increase approval Tx execution failed {}".format(receipt)) return approval_nonce + 1, tx_hash.hex()
def deploy_token(payload_str: str, aergo: herapy.Aergo, receiver: str, total_supply: int, fee_limit: int, fee_price: int) -> str: """ Deploy a token contract payload and give the total supply to the deployer """ payload = herapy.utils.decode_address(payload_str) tx, result = aergo.deploy_sc(amount=0, payload=payload, args=[{ "_bignum": str(total_supply) }, receiver]) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Token deployment Tx commit failed : {}".format(result)) result = aergo.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.CREATED: raise TxError( "Token deployment Tx execution failed : {}".format(result)) sc_address = result.contract_address return sc_address
def lock( aergo_from: herapy.Aergo, bridge_from: str, receiver: str, value: int, asset: str, gas_limit: int, gas_price: int, ) -> Tuple[int, str, Transaction]: """ Lock can be called to lock aer or tokens. it supports delegated transfers when tx broadcaster is not the same as the token owner """ if not is_ethereum_address(receiver): raise InvalidArgumentsError( "receiver {} must be an Ethereum address".format(receiver)) if not is_aergo_address(asset): raise InvalidArgumentsError( "asset {} must be an Aergo address".format(asset)) args = (bridge_from, {"_bignum": str(value)}, receiver[2:].lower()) tx, result = aergo_from.call_sc(asset, "transfer", args=args, amount=0, gas_limit=gas_limit, gas_price=gas_price) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Lock asset Tx commit failed : {}".format(result)) # Check lock success result = aergo_from.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Lock asset Tx execution failed : {}".format(result)) logger.info("\u26fd Aergo gas used: %s", result.gas_used) # get precise lock height tx_detail = aergo_from.get_tx(tx.tx_hash) lock_height = tx_detail.block.height return lock_height, str(tx.tx_hash), tx_detail
def transfer( value: int, to: str, asset_addr: str, aergo: herapy.Aergo, sender: str, fee_limit: int, fee_price: int, ) -> str: """ Support 3 types of transfers : simple aer transfers, token transfer, and signed token transfers (token owner != tx signer) """ if not is_aergo_address(to): raise InvalidArgumentsError( "Receiver {} must be an Aergo address".format(to)) aergo.get_account() # get the latest nonce for making tx if asset_addr == "aergo": # transfer aer on network_name tx, result = aergo.send_payload(to_address=to, amount=value, payload=None) else: # transfer token (issued or pegged) on network_name tx, result = aergo.call_sc(asset_addr, "transfer", args=[to, { "_bignum": str(value) }], amount=0) if result.status != herapy.CommitStatus.TX_OK: raise TxError("Transfer asset Tx commit failed : {}".format(result)) # Check lock success result = aergo.wait_tx_result(tx.tx_hash) if result.status != herapy.TxResultStatus.SUCCESS: raise TxError("Transfer asset Tx execution failed : {}".format(result)) return str(tx.tx_hash)
def mint( w3: Web3, signer_acct, receiver: str, lock_proof: herapy.obj.sc_state.SCState, token_origin: str, bridge_to: str, bridge_to_abi: str, gas_limit: int, gas_price: int ) -> Tuple[str, str, AttributeDict]: """ Mint the receiver's deposit balance on aergo_to. """ if not is_ethereum_address(receiver): raise InvalidArgumentsError( "Receiver {} must be an Ethereum address".format(receiver) ) if not is_aergo_address(token_origin): raise InvalidArgumentsError( "token_origin {} must be an Aergo address".format(token_origin) ) receiver = Web3.toChecksumAddress(receiver) balance = int(lock_proof.var_proofs[0].value.decode('utf-8')[1:-1]) ap = lock_proof.var_proofs[0].auditPath bitmap = lock_proof.var_proofs[0].bitmap leaf_height = lock_proof.var_proofs[0].height # call mint on ethereum with the lock proof from aergo_from eth_bridge = w3.eth.contract( address=bridge_to, abi=bridge_to_abi ) construct_txn = eth_bridge.functions.mint( receiver, balance, token_origin, ap, bitmap, leaf_height ).buildTransaction({ 'chainId': w3.eth.chainId, 'from': signer_acct.address, 'nonce': w3.eth.getTransactionCount( signer_acct.address ), 'gas': gas_limit, 'gasPrice': w3.toWei(gas_price, 'gwei') }) signed = signer_acct.sign_transaction(construct_txn) tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction) receipt = w3.eth.waitForTransactionReceipt(tx_hash) if receipt.status != 1: raise TxError("Mint asset Tx execution failed: {}".format(receipt)) logger.info("\u26fd Eth Gas used: %s", receipt.gasUsed) events = eth_bridge.events.mintEvent().processReceipt(receipt) token_pegged = events[0]['args']['tokenAddress'] return token_pegged, tx_hash.hex(), receipt