예제 #1
0
 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
예제 #2
0
    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()
예제 #3
0
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
예제 #4
0
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()
예제 #5
0
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
예제 #6
0
    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()
예제 #7
0
 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
예제 #8
0
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
예제 #9
0
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))
예제 #10
0
 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
예제 #11
0
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
예제 #12
0
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()
예제 #13
0
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
예제 #14
0
 def claim_tokens(auction, bidder):
     txhash = auction.transact({'from': bidder}).claimTokens()
     check_succesful_tx(web3, txhash)
예제 #15
0
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))
예제 #17
0
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)