def get_transaction(cls, tx_hash): tx = web3.eth.getTransaction(tx_hash) contract_instance = cls.erc20_contracts.get(tx.to, None) if contract_instance == None: raise Exception('Not supported contract address for swap:%s' % tx.to) contract = ConciseContract(contract_instance) func, paras = contract_instance.decode_function_input(tx.input) if str(func) != '<Function transfer(address,uint256)>': raise Exception('Unexpect contract method for %s' % tx_hash) if paras['_to'].lower() != config.ETHEREUM_SCAN_ADDRESS.lower(): raise Exception('Unexpect reveive address for %s' % tx_hash) amount, decimals = cls.Wei2Satoshi(paras['_value'], contract.decimals()) totalSupply, _ = cls.Wei2Satoshi(contract.totalSupply(), contract.decimals()) if totalSupply > 0xFFFFFFFFFFFFFFFF: totalSupply = 0xFFFFFFFFFFFFFFFF return contract.symbol(), tx['from'], (amount, totalSupply, decimals)
def send_asset(self, contract_name, to_addr, amount, memo=None): contract_instance = self.erc20_contracts.get(contract_name, None) if contract_instance == None: raise Exception('Not supported contract name for swap:%s' % contract_name) if not web3.isChecksumAddress(to_addr): to_addr = web3.toChecksumAddress(to_addr) contract = ConciseContract(contract_instance) if not web3.personal.unlockAccount(config.ETHEREUM_SCAN_ADDRESS, config.ETHEREUM_SCAN_PASSWD): raise Exception('Failed to unlcok account:' % config.ETHEREUM_SCAN_ADDRESS) amountInWei = self.Satoshi2Wei(amount, contract.decimals())[0] gas_price = web3.eth.gasPrice transact = contract_instance.functions.transferFrom( config.ETHEREUM_SCAN_ADDRESS, to_addr, amountInWei) gas = transact.estimateGas() ret = transact.transact( transaction={ 'from': config.ETHEREUM_SCAN_ADDRESS, 'gas': gas, 'gasPrice': gas_price }) if not ret: raise Exception('Failed to send_asset:[%s, %s, %s]' % (contract_name, to_addr, amount)) return ret.hex()
def test_factory(w3, exchange_template, HAY_token, factory, pad_bytes32, exchange_abi, assert_fail): a0, a1 = w3.eth.accounts[:2] # Can't call initializeFactory on factory twice with raises(TransactionFailed): factory.initializeFactory(HAY_token.address) # Factory initial state assert factory.exchangeTemplate() == exchange_template.address assert factory.getExchange(HAY_token.address) == None # Create Exchange for MRS Token factory.createExchange(HAY_token.address, transact={}) HAY_exchange_address = factory.getExchange(HAY_token.address) assert HAY_exchange_address != None HAY_exchange = ConciseContract( w3.eth.contract(address=HAY_exchange_address, abi=exchange_abi)) assert factory.getToken(HAY_exchange.address) == HAY_token.address assert factory.tokenCount() == 1 assert factory.getTokenWithId(1) == HAY_token.address # Exchange already exists with raises(TransactionFailed): factory.createExchange(HAY_token.address) # Can't call setup on exchange assert_fail(lambda: HAY_exchange.setup(factory.address)) # Exchange initial state assert HAY_exchange.name() == pad_bytes32('Marswap V1') assert HAY_exchange.symbol() == pad_bytes32('MRS-V1') assert HAY_exchange.decimals() == 18 assert HAY_exchange.totalSupply() == 0 assert HAY_exchange.tokenAddress() == HAY_token.address assert HAY_exchange.factoryAddress() == factory.address assert w3.eth.getBalance(HAY_exchange.address) == 0 assert HAY_token.balanceOf(HAY_exchange.address) == 0
def test_factory(w3, exchange_template, HAY_token, exchange_factory, pad_bytes32, exchange_abi): a0, a1 = w3.eth.accounts[:2] # Factory initial state assert exchange_factory.exchangeTemplate() == exchange_template.address assert exchange_factory.getExchange(HAY_token.address) == None # Create Exchange for UNI Token exchange_factory.createExchange(HAY_token.address, transact={}) HAY_exchange_address = exchange_factory.getExchange(HAY_token.address) assert HAY_exchange_address != None HAY_exchange = ConciseContract(w3.eth.contract(address=HAY_exchange_address, abi=exchange_abi)) assert exchange_factory.getToken(HAY_exchange.address) == HAY_token.address assert exchange_factory.tokenCount() == 1 assert exchange_factory.getTokenWithId(1) == HAY_token.address # # Can't call initializeFactory on factory twice # assert_tx_failed(lambda: exchange_factory.initializeFactory(HAY_token.address)) # # Exchange already exists # assert_tx_failed(lambda: exchange_factory.createExchange(HAY_token.address)) # # Can't call setup on exchange # assert_tx_failed(lambda: HAY_exchange.setup(exchange_factory.address)) # # Exchange initial state assert HAY_exchange.name() == pad_bytes32('Uniswap V1') assert HAY_exchange.symbol() == pad_bytes32('UNI-V1') assert HAY_exchange.decimals() == 18 assert HAY_exchange.totalSupply() == 0 assert HAY_exchange.tokenAddress() == HAY_token.address assert HAY_exchange.factoryAddress() == exchange_factory.address assert w3.eth.getBalance(HAY_exchange.address) == 0 assert HAY_token.balanceOf(HAY_exchange.address) == 0
def get_asset_balance(cls, contract_name): contract = cls.erc20_contracts.get(contract_name, None) if contract == None: raise Exception('Not supported contract name for swap:%s' % contract_name) concise = ConciseContract(contract) return cls.Wei2Satoshi(concise.balanceOf(config.ETHEREUM_SCAN_ADDRESS), concise.decimals())[0]
def get_token_precision(self, token_address): token_contract = ConciseContract( self.network.web3.eth.contract( address=Web3.toChecksumAddress(token_address), abi=ERC20_BASIC_ABI, ) ) time.sleep(0.5) # we don't want to spam the API try: return token_contract.decimals() except (OverflowError, BadFunctionCallOutput): return
def get_token_from_token_contract(self, token_address: str) -> Optional[Token]: """ Getting information from token contract and creating Token. Smart contract is taken based on provided address """ token_address = self.unify_address(token_address) token_contract = self.web3.eth.contract(address=token_address, abi=ERC20_BASIC_ABI) concise = ConciseContract(token_contract) try: name = concise.name() symbol = concise.symbol() decimals = concise.decimals() logger.debug(f'Token get from contract with success') except (OverflowError, BadFunctionCallOutput): logger.warning(f'Unable to take token from address: {token_address}') return return Token(name, symbol, token_address, decimals)
def get_token_from_token_contract(self, token_address: str) -> Optional[Token]: ''' Getting information from token contract (remote) Args: token_address (str): address of the token contract Returns: Token, None: Ethereum Token namedtuple or None if there is something goes wrong Raises: RuntimeError: if name or symbol of the token is not defined. Example: >>> from clove.network import EthereumTestnet >>> network = EthereumTestnet() >>> network.get_token_from_token_contract('0x2c76B98079Bb5520FF4BDBC1bf5012AC3E87ddF6') Token(name='PrettyGoodToken', symbol='PGT', address='0x2c76B98079Bb5520FF4BDBC1bf5012AC3E87ddF6', decimals=18) # noqa: E501 ''' token_address = self.unify_address(token_address) token_contract = self.web3.eth.contract(address=token_address, abi=ERC20_BASIC_ABI) concise = ConciseContract(token_contract) try: name = concise.name() symbol = concise.symbol() decimals = concise.decimals() if name == '' or symbol == '': raise RuntimeError( 'Unable to extract token details from token contract') logger.debug(f'Token get from contract with success') except (OverflowError, BadFunctionCallOutput): logger.warning( f'Unable to take token from address: {token_address}') return return Token(name, symbol, token_address, decimals)
def test_deploy( pack_deploy, instantiate, accounts, assert_tx_failed, pack_types, pack_prices, get_receipt, get_logs_for_event, w3, #Parameters bundle_sizes, bundle_caps): BLOCK_GAS_LIMIT = 8e6 # Well over double this now, but a possible concern. # Deploy an oracle and a Link Token (pack, processor, referrals, cards, vault, pack_r, processor_r, referrals_r, cards_r, vault_r) = pack_deploy() receipts = { "pack": (pack, pack_r), "processor": (processor, processor_r), "referrals": (referrals, referrals_r), "cards": (cards, cards_r), "vault": (vault, vault_r) } if DEBUG: print("") # new line for name, r in receipts.items(): if DEBUG: print("Gas used to deploy {}:\t{}".format(name, r[1]['gasUsed'])) assert r[1]['gasUsed'] < BLOCK_GAS_LIMIT, "{} uses more gas than block_gas_limit!".format(name) assert r[0].address != 0, "Address returned not expected for {}".format(name) addPack = cards.functions.addPack(pack.address) assert_tx_failed(addPack, {'from': accounts[1]}) addPack.transact({'from': accounts[0]}) tokens = {} # Now each of the bundle tokens need to be deployed # For each, the pack has to be set to point to the bundle and stipulate it's price and size. for i, (rarity, rarity_value) in enumerate(pack_types.items()): setPack = pack.functions.setPack( rarity_value, pack_prices[rarity], "Genesis {} Bundle".format(rarity), "BND{}".format(rarity[0]), bundle_sizes[i], bundle_caps[i], ) assert_tx_failed(setPack, {'from': accounts[1]}) tx_hash = setPack.transact({'from': accounts[0]}) rcpt = get_receipt(tx_hash) assert len(rcpt['logs']) == 1, "Should have one event emitted." assert rcpt['gasUsed'] < BLOCK_GAS_LIMIT, "Too much gas for block!" logs = get_logs_for_event(pack.events.PackAdded, tx_hash) tokens[rarity] = instantiate(logs[0]['args']['bundle'], abi=None, contract="Bundle") processor.functions.setCanSell(tokens[rarity].address, True).transact({'from': accounts[0]}) if DEBUG: print("Created {} Bundles: Size: {}, Cap: {}, Gas: {}".format( rarity, bundle_sizes[i], bundle_caps[i], rcpt['gasUsed']) ) print("Approval Statuses:") for address in accounts[:5]: print("{}: {}".format(address, processor.functions.approvedSellers(accounts[0]).call())) # For each of the tokens, check their variables and try to purchase a bunch of them, # making sure we can't purchase too many for i, (rarity, token) in enumerate(tokens.items()): c = ConciseContract(token) assert c.totalSupply() == 0, "{} tokens should start with supply of zero".format(rarity) assert c.balanceOf(accounts[0]) == 0, "No user should have balance before mint." assert c.balanceOf(accounts[1]) == 0, "No user should have balance before mint." assert c.name() == "Genesis {} Bundle".format(rarity), "Incorrect token name" assert c.symbol() == "BND{}".format(rarity[0]), "Incorrect token symbol" assert c.decimals() == 0, "Incorrect token decimals" assert c.cap() == bundle_caps[i], "Incorrect cap for token" assert c.packType() == pack_types[rarity], "Incorrect packType for token" BUNDLES_TO_BUY = 6 for _ in range(bundle_caps[i] if bundle_caps[i] > 0 else BUNDLES_TO_BUY): # Shouldn't be able to buy if we send no money assert_tx_failed( token.functions.purchaseFor(accounts[0], 1, accounts[1]), {'from': accounts[0]} ) assert processor.functions.approvedSellers(token.address).call(), "Bundle should be approved to sell." tx_hash = token.functions.purchaseFor(accounts[0], 1, accounts[1])\ .transact({'from': accounts[0], 'value': pack_prices[rarity] * bundle_sizes[i]}) rcpt = get_receipt(tx_hash) assert rcpt['gasUsed'] < BLOCK_GAS_LIMIT, "Too much gas for block!" if DEBUG: print("Account0 {} tokens: {}, vault: {} ({})".format( rarity, token.functions.balanceOf(accounts[0]).call(), (vault.functions.total().call())/10**18, w3.eth.getBalance(vault.address)/10**18)) # Now there shouldn't be any more bundles available to buy if bundle_caps[i] > 0: assert_tx_failed( token.functions.purchaseFor(accounts[0], 1, accounts[1]), {'from': accounts[0]} )