def bid(self): missing_funds = self.auction_contract.call().missingFundsToEndAuction() if missing_funds == 0: return if missing_funds <= self.last_missing_funds: log.warning('missing funds <= last missing: %d < %d' % (missing_funds, self.last_missing_funds)) self.last_missing_funds = missing_funds balance = self.web3.eth.getBalance(self.address) unlocked = self.web3.personal.unlockAccount(self.address, passphrase) assert unlocked is True amount = self.get_random_bid(missing_funds, balance) log.info('BID bidder=%s, missing_funds=%.2e, balance=%d, amount=%s' % (self.address, missing_funds, balance, amount_format(self.web3, amount))) try: txhash = self.auction_contract.transact({ 'from': self.address, "value": amount }).bid() receipt, success = check_succesful_tx(self.web3, txhash) except ValueError as e: log.warn(str(e)) if self.retries >= self.max_retries: raise e self.retries += 1
def distribute(self): with Timeout() as timeout: while (not self.distribution_ended and (not self.auction_ended or not len(self.addresses_claimable))): timeout.sleep(2) log.info('Auction ended. We should have all the addresses. %s, %s' % (len(self.addresses_claimable), self.addresses_claimable)) # 82495 gas / claimTokens # Call the distributor contract with batches of bidder addresses while len(self.addresses_claimable): batch_number = min(self.batch_number, len(self.addresses_claimable)) batch = self.addresses_claimable[:batch_number] self.addresses_claimable = self.addresses_claimable[batch_number:] self.claimed = self.claimed + batch print('Distributing tokens to {0} addresses: {1}'.format( batch_number, batch)) txhash = self.distributor.transact({ 'gas': 4000000 }).distribute(batch) receipt, success = check_succesful_tx(self.web3, txhash) assert success is True assert receipt is not None self.distribution_ended_checks()
def auction_simulation(web3, token, auction, owner, bidders, kwargs): log.info('owner={owner} balance={balance}'.format( owner=owner, balance=amount_format(web3, web3.eth.getBalance(owner)))) # Start the auction if kwargs['start_auction'] is True: log.info('Start auction owner balance %s' % amount_format(web3, web3.eth.getBalance(owner))) txhash = auction.transact({'from': owner}).startAuction() receipt = check_succesful_tx(web3, txhash, tx_timeout) assert auction.call().stage() == 2 # AuctionStarted assert auction.call().price_start() > 0 assert isinstance(auction.call().price_constant(), int) assert isinstance(auction.call().price_exponent(), int) assert token.call().decimals() > 0 # deploy bidders # this will return when auction ends deploy_bidders(bidders, web3, auction, kwargs) # check if there are no funds remaining ret = auction.call({'from': owner}).missingFundsToEndAuction() assert ret == 0 log.info('missing funds %s' % auction.call({ 'from': owner }).missingFundsToEndAuction()) # Owner calls finalizeAuction txhash = auction.transact({'from': owner}).finalizeAuction() receipt = check_succesful_tx(web3, txhash) assert receipt is not None assert auction.call().stage() == 3 # AuctionEnded if kwargs['claim_tokens'] is True: event_lst = [ gevent.spawn(claim_tokens, auction, x, web3) for x in bidders ] gevent.joinall(event_lst) event_lst = [gevent.spawn(get_balance, token, x) for x in bidders] gevent.joinall(event_lst) total_balance = sum([ev.value for ev in event_lst]) assert auction.call().stage() == 4 # TokensDistributed return total_balance
def main(**kwargs): project = Project() chain_name = kwargs['chain'] account = kwargs['account'] distributor_address = kwargs['distributor'] auction_address = kwargs['auction'] auction_tx = kwargs['auction_tx'] batch_number = kwargs['batch_number'] to_file = kwargs['to_file'] claims_file = None if to_file: claims_file = 'build/claimed_tokens_{}_{}.csv'.format( chain_name, time()) if batch_number: batch_number = int(batch_number) with project.get_chain(chain_name) as chain: web3 = chain.web3 log.info('Web3 provider is %s' % (web3.currentProvider)) account = account or chain.web3.eth.accounts[0] Auction = chain.provider.get_contract_factory('DutchAuction') Distributor = chain.provider.get_contract_factory('Distributor') # Load Populus contract proxy classes auction = Auction(address=auction_address) end_time = auction.call().end_time() waiting = auction.call().token_claim_waiting_period() token_claim_ok_time = end_time + waiting now = web3.eth.getBlock('latest')['timestamp'] if token_claim_ok_time > now: log.warning('Token claim waiting period is not over') log.warning('Remaining: %s seconds' % (token_claim_ok_time - now)) sys.exit() if not distributor_address: distributor_tx = Distributor.deploy(transaction={'from': account}, args=[auction_address]) log.info('DISTRIBUTOR tx hash: ' + distributor_tx) receipt, success = check_succesful_tx(web3, distributor_tx) assert success is True assert receipt is not None distributor_address = receipt['contractAddress'] log.info('DISTRIBUTOR contract address ' + distributor_address) distributor = Distributor(address=distributor_address) assert distributor is not None distrib = DistributorScript(web3, account, auction, auction_tx, auction.abi, distributor, batch_number, claims_file) distrib.distribute()
def start_auction(auction, owner, web3): if auction.call().stage() >= AUCTION_STARTED: log.info( 'requested startAuction(), but auction has started already. skipping.' ) return log.info('Start auction owner balance %s' % amount_format(web3, web3.eth.getBalance(owner))) txhash = auction.transact({'from': owner}).startAuction() receipt = check_succesful_tx(web3, txhash, tx_timeout) assert receipt is not None
def distribute(self): with Timeout() as timeout: while (not self.distribution_ended and (not self.auction_ended or not len(self.addresses_unclaimed))): timeout.sleep(2) unclaimed_number = len(self.addresses_unclaimed) log.info('Auction ended. We should have all the addresses: %s' % (len(self.bidder_addresses.keys()))) log.info('Unclaimed tokens - addresses: %s' % (unclaimed_number)) # 87380 gas / claimTokens # We need to calculate from gas estimation if unclaimed_number > 0 and not self.batch_number: valid_bid_address = self.addresses_unclaimed[0] claim_tx_gas = self.auction.estimateGas({ 'from': self.account }).proxyClaimTokens(valid_bid_address) # claim_tx_gas = 50000 log.info('ESTIMATED claimTokens tx GAS: %s', (claim_tx_gas)) self.batch_number = int(self.total_distribute_tx_gas // claim_tx_gas) log.info('BATCH number: %s', (self.batch_number)) # Call the distributor contract with batches of bidder addresses while len(self.addresses_unclaimed): batch_number = min(self.batch_number, len(self.addresses_unclaimed)) batch = self.addresses_unclaimed[:batch_number] self.addresses_unclaimed = self.addresses_unclaimed[batch_number:] self.addresses_claimed = self.addresses_claimed + batch log.info('Distributing tokens to %s addresses: %s' % (batch_number, ','.join(batch))) # Send the distribute transaction tx = { 'from': self.account, 'gas': int(self.total_distribute_tx_gas) } if self.gas_price: tx['gas_price'] = int(self.gas_price) txhash = self.distributor.transact(tx).distribute(batch) if self.wait: receipt, success = check_succesful_tx(self.web3, txhash) assert success is True assert receipt is not None self.distribution_ended_checks()
def bid(self): missing_funds = self.auction_contract.call().missingFundsToEndAuction() balance = self.web3.eth.getBalance(self.address) max_bid = int(missing_funds * 0.6 * random.random()) amount = int(max(0, min(balance - self.approx_bid_txn_cost, max_bid))) if amount == 0: amount = 1 unlocked = self.web3.personal.unlockAccount(self.address, passphrase) assert unlocked is True log.info('bidder=%s, missing_funds=%d, balance=%d, amount=%s' % (self.address, missing_funds, balance, amount_format(self.web3, amount))) txhash = self.auction_contract.transact({'from': self.address, "value": amount}).bid() receipt = check_succesful_tx(self.web3, txhash) assert receipt is not None
def successful_bid(web3, auction, bidder, amount): bid_successful = False while not bid_successful and amount > 0: try: txhash = auction.transact({'from': bidder, "value": amount}).bid() receipt = check_succesful_tx(web3, txhash) assert receipt is not None log.info('BID successful from=%s value=%d' % (bidder, amount)) bid_successful = amount except: amount = auction.call().missingFundsToEndAuction() if (amount > 10): amount = amount // 7 log.info( 'Bid > missing funds, trying with {0} WEI ({bidder})'.format( amount, bidder=bidder)) return amount
def claim_tokens(auction, bidder, web3): unlocked = web3.personal.unlockAccount(bidder, passphrase) assert unlocked is True try: txhash = auction.transact({'from': bidder}).claimTokens() except ValueError as e: # method call failed: there are probably no tokens to claim if e.args[0]['code'] != -32015: raise e log.warn( 'claimTokens() failed for bidder ({0}). ' 'Most likely this bidder owns no tokens or waiting perios hasn\'t expired. ({1})' .format(bidder, str(e))) return receipt, success = check_succesful_tx(web3, txhash) if success is False: log.info('claimTokens(%s) failed for tx %s. This is either an error, ' 'or funds have been claimed already' % (bidder, txhash))
def bid(self): missing_funds = self.auction_contract.call().missingFundsToEndAuction() if missing_funds == 0: return assert missing_funds <= self.last_missing_funds self.last_missing_funds = missing_funds balance = self.web3.eth.getBalance(self.address) unlocked = self.web3.personal.unlockAccount(self.address, passphrase) assert unlocked is True amount = self.get_random_bid(missing_funds, balance) log.info('BID bidder=%s, missing_funds=%.2e, balance=%d, amount=%s' % (self.address, missing_funds, balance, amount_format(self.web3, amount))) txhash = self.auction_contract.transact({ 'from': self.address, "value": amount }).bid() receipt = check_succesful_tx(self.web3, txhash) assert receipt is not None
def finalize_auction(auction, owner, web3): # check if there are no funds remaining if auction.call().stage() >= AUCTION_ENDED: log.warning( "requested finalizeAuction(), but auction has ended already. Skipping this." ) return ret = auction.call({'from': owner}).missingFundsToEndAuction() assert ret == 0 log.info('missing funds %s' % auction.call({ 'from': owner }).missingFundsToEndAuction()) # Owner calls finalizeAuction txhash = auction.transact({'from': owner}).finalizeAuction() receipt, success = check_succesful_tx(web3, txhash) assert receipt is not None assert success is True assert auction.call().stage() == 3 # AuctionEnded
def main(**kwargs): project = Project() chain_name = kwargs['chain'] distributor_address = kwargs['distributor'] distributor_tx = kwargs['distributor_tx'] auction_address = kwargs['auction'] auction_tx = kwargs['auction_tx'] claims = kwargs['claims'] with project.get_chain(chain_name) as chain: web3 = chain.web3 print("Web3 provider is", web3.currentProvider) owner = chain.web3.eth.accounts[0] Auction = chain.provider.get_contract_factory('DutchAuction') Distributor = chain.provider.get_contract_factory('Distributor') # Load Populus contract proxy classes auction = Auction(address=auction_address) if not distributor_address: distributor_tx = Distributor.deploy(transaction={"from": owner}, args=[auction_address]) log.info("Deploying distributor, tx hash is " + distributor_tx) print("Deploying distributor, tx hash is ", distributor_tx) receipt, success = check_succesful_tx(web3, distributor_tx) assert success is True distributor_address = receipt["contractAddress"] log.info("Distributor contract address " + distributor_address) print("Distributor contract address ", distributor_address) distributor = Distributor(address=distributor_address) assert distributor is not None distrib = DistributorScript(web3, auction, auction_tx, auction.abi, distributor, distributor_tx, claims) distrib.distribute()
def auction_simulation(web3, wallet, token, auction, owner, bidders, bid_interval=None, bid_start_price=None, sim_claim_tokens=False): print_all_logs(token, auction) log.info('{owner} {balance}'.format(owner=owner, balance=amount_format( web3, web3.eth.getBalance(owner)))) # Start the auction log.info('Start auction owner balance %s' % amount_format(web3, web3.eth.getBalance(owner))) txhash = auction.transact({'from': owner}).startAuction() receipt = check_succesful_tx(web3, txhash, tx_timeout) assert auction.call().stage() == 2 # AuctionStarted # Make the bids # Timeout until price is = bid_start_price price_start = auction.call().price_start() assert price_start > 0 price_constant = auction.call().price_constant() assert isinstance(price_constant, int) price_exponent = auction.call().price_exponent() assert isinstance(price_exponent, int) decimals = token.call().decimals() multiplier = 10**decimals assert multiplier > 0 ''' # Delay in seconds if we want to start the first bid at a certain price if bid_start_price: initial_bid_delay = elapsedAtPrice(bid_start_price, price_factor, price_constant, multiplier) assert initial_bid_delay >= 0, 'Price for first bid was set too high' log.info('Elapsed time until the first bid is made', initial_bid_delay ''' # noqa log.info('Timeout between bids {0}'.format(bid_interval or ' is random.')) from deploy.bidder import Bidder import gevent bidder_objs = [Bidder(web3, auction, addr) for addr in bidders] bidder_gevents = [gevent.spawn(b.run) for b in bidder_objs] gevent.joinall(bidder_gevents) del bidder_gevents assert auction.call({'from': owner}).missingFundsToEndAuction() == 0 log.info('missing funds from=%s' % auction.call({ 'from': owner }).missingFundsToEndAuction()) # Owner calls finalizeAuction txhash = auction.transact({'from': owner}).finalizeAuction() receipt = check_succesful_tx(web3, txhash) assert receipt is not None assert auction.call().stage() == 3 # AuctionEnded # distribute tokens def claim_tokens(auction, bidder): txhash = auction.transact({'from': bidder}).claimTokens() check_succesful_tx(web3, txhash) def get_balance(token, bidder): token_balance = token.call().balanceOf(bidder) log.info('{bidder} {tokens}'.format(bidder=bidder, tokens=token_balance)) return token_balance if sim_claim_tokens is True: event_lst = [gevent.spawn(claim_tokens, auction, x) for x in bidders] gevent.joinall(event_lst) event_lst = [gevent.spawn(get_balance, token, x) for x in bidders] gevent.joinall(event_lst) total_balance = sum([ev.value for ev in event_lst]) assert auction.call().stage() == 4 # TokensDistributed return total_balance
def claim_tokens(auction, bidder): txhash = auction.transact({'from': bidder}).claimTokens() check_succesful_tx(web3, txhash)
def main(ctx, **kwargs): project = Project() chain_name = kwargs['chain'] owner = kwargs['owner'] wallet_address = kwargs['wallet'] supply = kwargs['supply'] price_start = kwargs['price_start'] price_constant = kwargs['price_constant'] price_exponent = kwargs['price_exponent'] multiplier = 10**18 supply *= multiplier print( "Make sure {} chain is running, you can connect to it and it is synced, " "or you'll get timeout".format(chain_name)) with project.get_chain(chain_name) as chain: web3 = chain.web3 set_connection_pool_size(web3, 100, 100) owner = owner or web3.eth.accounts[0] wallet_address = wallet_address or web3.personal.newAccount(passphrase) print("Web3 provider is", web3.currentProvider) assert owner, "Make sure owner account is created" assert wallet_address, "Make sure wallet account is created" print('Owner', owner) print('Wallet', wallet_address) print('Auction start price:', price_start) print('Auction price constant:', price_constant) print('Auction price exponent:', price_exponent) # Load Populus contract proxy classes Auction = chain.provider.get_contract_factory('DutchAuction') Token = chain.provider.get_contract_factory('RaidenToken') Distributor = chain.provider.get_contract_factory('Distributor') # Deploy Auction auction_txhash = Auction.deploy( transaction={"from": owner}, args=[wallet_address, price_start, price_constant, price_exponent]) print("Deploying auction, tx hash is", auction_txhash) receipt = check_succesful_tx(web3, auction_txhash) auction_address = receipt["contractAddress"] print("Auction contract address is", auction_address) # Deploy token token_txhash = Token.deploy( transaction={"from": owner}, args=[auction_address, wallet_address, supply]) print("Deploying token, tx hash is", token_txhash) receipt = check_succesful_tx(web3, token_txhash) token_address = receipt["contractAddress"] print("Token contract address is", token_address) # Deploy Distributor contract distributor_txhash = Distributor.deploy(transaction={"from": owner}, args=[auction_address]) print("Deploying distributor, tx hash is", distributor_txhash) receipt = check_succesful_tx(web3, distributor_txhash) distributor_address = receipt["contractAddress"] print("Distributor contract address is", distributor_address) # Make contracts aware of each other print("Initializing contracts") auction = Auction(address=auction_address) token = Token(address=token_address) distributor = Distributor(address=distributor_address) assert distributor is not None txhash = auction.transact({"from": owner}).setup(token_address) check_succesful_tx(web3, txhash) # Do some contract reads to see everything looks ok print("Token total supply is {0} Tei = {1} TKN".format( token.call().totalSupply(), int(token.call().totalSupply() / multiplier))) print( "Auction price at 0 seconds (elapsed) is {0} WEI = {1} ETH".format( auction.call().price(), web3.fromWei(auction.call().price(), 'ether'))) ctx.obj = Web3Context(web3, auction, token, owner, wallet_address, auction_address)
def deploy(ctx, **kwargs): owner = ctx.obj['owner'] wallet_address = kwargs['wallet'] supply = kwargs['supply'] price_start = kwargs['price_start'] price_constant = kwargs['price_constant'] price_exponent = kwargs['price_exponent'] whitelister = kwargs['whitelister'] multiplier = 10**18 supply *= multiplier chain = ctx.obj['chain'] web3 = chain.web3 wallet_address = wallet_address or web3.personal.newAccount(passphrase) log.info("Web3 provider is %s" % (web3.currentProvider)) assert owner, "Make sure owner account is created" assert wallet_address, "Make sure wallet account is created" log.info('owner=%s wallet=%s' % (owner, wallet_address)) log.info('auction start_price=%d constant=%d exponent=%d' % (price_start, price_constant, price_exponent)) # Load Populus contract proxy classes Auction = chain.provider.get_contract_factory('DutchAuction') Token = chain.provider.get_contract_factory('RaidenToken') # Deploy Auction auction_txhash = Auction.deploy(transaction={"from": owner}, args=[ wallet_address, whitelister, price_start, price_constant, price_exponent ]) log.info("Deploying auction, tx hash " + auction_txhash) receipt, success = check_succesful_tx(web3, auction_txhash) assert success is True auction_address = receipt["contractAddress"] log.info("Auction contract address " + auction_address) # Deploy token token_txhash = Token.deploy(transaction={"from": owner}, args=[auction_address, wallet_address, supply]) log.info("Deploying token, tx hash " + token_txhash) receipt, success = check_succesful_tx(web3, token_txhash) assert success is True token_address = receipt["contractAddress"] log.info("Token contract address " + token_address) # Make contracts aware of each other log.info("Initializing contracts") auction = Auction(address=auction_address) token = Token(address=token_address) txhash = auction.transact({"from": owner}).setup(token_address) check_succesful_tx(web3, txhash) # Do some contract reads to see everything looks ok log.info("Token total supply is {0} Tei = {1} TKN".format( token.call().totalSupply(), int(token.call().totalSupply() / multiplier))) log.info( "Auction price at 0 seconds (elapsed) is {0} WEI = {1} ETH".format( auction.call().price(), web3.fromWei(auction.call().price(), 'ether'))) ctx.obj['token_contract_address'] = token_address ctx.obj['auction_contract_address'] = auction_address ctx.obj['total_supply'] = supply log.info("contracts deployed: --auction-contract %s --token-contract %s" % (auction_address, token_address))
def claim_tokens(auction, bidder, web3): unlocked = web3.personal.unlockAccount(bidder, passphrase) assert unlocked is True txhash = auction.transact({'from': bidder}).claimTokens() check_succesful_tx(web3, txhash)