예제 #1
0
    def test_should_take_if_model_price_updated(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        (needs_redo, price, initial_lot, initial_tab) = self.clipper.status(kick)

        # when initial model price is too low
        bad_price = price - Ray.from_number(30)
        self.simulate_model_bid(model, bad_price)
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()

        # then ensure no bid was submitted
        (needs_redo, price, lot, tab) = self.clipper.status(kick)
        assert lot == initial_lot
        assert tab == initial_tab

        # when model price becomes appropriate
        good_price = price + Ray.from_number(30)
        self.simulate_model_bid(model, good_price)
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()

        # then ensure our bid was submitted
        our_take: Clipper.TakeLog = self.last_log()
        assert our_take.id == kick
        assert our_take.price <= good_price
        # and that the auction finished
        (needs_redo, price, lot, tab) = self.clipper.status(kick)
        assert not needs_redo
        assert lot == Wad(0) or tab == Rad(0)
예제 #2
0
    def test_should_overbid_itself_if_model_has_updated_the_price(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        lot = self.flapper.bids(kick).lot

        # when
        first_bid = Wad.from_number(0.0000004)
        simulate_model_output(model=model, price=first_bid)
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.flapper.bids(kick).bid == Wad(lot / Rad(first_bid))

        # when
        second_bid = Wad.from_number(0.0000003)
        simulate_model_output(model=model, price=second_bid)
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.flapper.bids(kick).bid == Wad(lot / Rad(second_bid))

        # cleanup
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        assert self.flapper.deal(kick).transact()
예제 #3
0
    def test_should_not_bid_on_rounding_errors_with_small_amounts(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        lot = self.flapper.bids(kick).lot

        # when
        price = Wad.from_number(9.0)-Wad(5)
        simulate_model_output(model=model, price=price)
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.flapper.bids(kick).bid == Wad(lot) / Wad(price)

        # when
        tx_count = self.web3.eth.getTransactionCount(self.keeper_address.address)
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.web3.eth.getTransactionCount(self.keeper_address.address) == tx_count

        # cleanup
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        assert self.flapper.deal(kick).transact()
예제 #4
0
    def test_should_not_tend_on_rounding_errors_with_small_amounts(
            self, mcd, c, kick_small_lot, keeper):
        # given
        (model, model_factory) = models(keeper, kick_small_lot)
        flipper = c.flipper

        # when
        bid_price = Wad.from_number(3.0)
        self.simulate_model_bid(mcd, c, model, bid_price)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert flipper.bids(kick_small_lot).bid == Rad(bid_price *
                                                       tend_small_lot)

        # when
        tx_count = self.web3.eth.getTransactionCount(
            self.keeper_address.address)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.web3.eth.getTransactionCount(
            self.keeper_address.address) == tx_count
예제 #5
0
    def test_should_tick_if_auction_expired_due_to_tau(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        time_travel_by(self.web3, self.flapper.tau() + 1)
        # and
        simulate_model_output(model=model, price=Wad.from_number(9.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        model.terminate.assert_not_called()
        auction = self.flapper.bids(kick)
        assert round(Wad(auction.lot) / auction.bid, 2) == round(Wad.from_number(9.0), 2)

        # cleanup
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        model_factory.create_model.assert_called_once()
        self.keeper.check_all_auctions()
        model.terminate.assert_called_once()
예제 #6
0
    def test_should_use_most_up_to_date_price_for_dent_even_if_it_gets_updated_during_tend(
            self, mcd, c, kick, keeper, keeper_address):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        first_bid_price = Wad.from_number(140)
        self.simulate_model_bid(mcd, c, model, first_bid_price)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        auction = flipper.bids(kick)
        assert auction.bid == auction.tab
        assert auction.lot == tend_lot

        # when
        second_bid_price = Wad.from_number(150)
        self.simulate_model_bid(mcd, c, model, second_bid_price)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        auction = flipper.bids(kick)
        assert auction.bid == auction.tab
        assert auction.lot == Wad(auction.bid / Rad(second_bid_price))

        # cleanup
        time_travel_by(self.web3, flipper.ttl() + 1)
        assert flipper.deal(kick).transact()
예제 #7
0
    def test_should_overbid_itself_if_model_has_updated_the_price(
            self, mcd, c, kick, keeper, keeper_address):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        first_bid = Wad.from_number(15.0)
        self.simulate_model_bid(mcd, c, model, first_bid)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert flipper.bids(kick).bid == Rad(first_bid * tend_lot)

        # when
        second_bid = Wad.from_number(20.0)
        self.simulate_model_bid(mcd, c, model, second_bid)
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert flipper.bids(kick).bid == Rad(second_bid * tend_lot)

        # cleanup
        time_travel_by(self.web3, flipper.ttl() + 1)
        assert flipper.deal(kick).transact()
    def test_should_start_a_new_model_and_provide_it_with_info_on_auction_start(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once_with(
            Parameters(collateral_auction_house=None,
                       surplus_auction_house=None,
                       debt_auction_house=self.debt_auction_house.address,
                       staked_token_auction_house=None,
                       id=auction_id))
        # and
        status = model.send_status.call_args[0][0]
        assert status.id == auction_id
        assert status.collateral_auction_house is None
        assert status.surplus_auction_house is None
        assert status.debt_auction_house == self.debt_auction_house.address
        assert status.bid_amount > Rad.from_number(0)
        assert status.amount_to_sell == self.geb.accounting_engine.initial_debt_auction_minted_tokens(
        )
        assert status.amount_to_raise is None
        assert status.bid_decrease > Wad.from_number(1)
        assert status.high_bidder == self.geb.accounting_engine.address
        assert status.block_time > 0
        assert status.auction_deadline < status.block_time + self.debt_auction_house.total_auction_length(
        ) + 1
        assert status.bid_expiry == 0
        assert status.price == Wad(status.bid_amount *
                                   self.geb.oracle_relayer.redemption_price() /
                                   Rad(status.amount_to_sell))
    def test_should_restart_auction_if_auction_expired_due_to_total_auction_length(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        time_travel_by(self.web3,
                       self.debt_auction_house.total_auction_length() + 1)
        # and
        simulate_model_output(model=model, price=Wad.from_number(555.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        model.terminate.assert_not_called()
        auction = self.debt_auction_house.bids(auction_id)
        assert round(
            auction.bid_amount * self.geb.oracle_relayer.redemption_price() /
            Rad(auction.amount_to_sell), 2) == round(Rad.from_number(555.0), 2)

        # cleanup
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        model_factory.create_model.assert_called_once()
        self.keeper.check_all_auctions()
        model.terminate.assert_called_once()
예제 #10
0
    def test_should_overbid_itself_if_model_has_updated_the_price(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        simulate_model_output(model=model, price=Wad.from_number(100.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert round(Rad(self.flopper.bids(kick).lot),
                     2) == round(self.sump / Rad.from_number(100.0), 2)

        # when
        simulate_model_output(model=model, price=Wad.from_number(110.0))
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.lot_implies_price(kick, Wad.from_number(110.0))

        # cleanup
        time_travel_by(self.web3, self.flopper.ttl() + 1)
        assert self.flopper.deal(kick).transact()
예제 #11
0
    def test_should_increase_gas_price_of_pending_transactions_if_model_increases_gas_price(
            self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        simulate_model_output(model=model,
                              price=Wad.from_number(120.0),
                              gas_price=10)
        # and
        self.start_ignoring_transactions()
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        # and
        time.sleep(2)
        # and
        self.end_ignoring_transactions()
        # and
        simulate_model_output(model=model,
                              price=Wad.from_number(120.0),
                              gas_price=15)
        # and
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.lot_implies_price(kick, Wad.from_number(120.0))
        assert self.web3.eth.getBlock(
            'latest', full_transactions=True).transactions[0].gasPrice == 15

        # cleanup
        time_travel_by(self.web3, self.flopper.ttl() + 1)
        assert self.flopper.deal(kick).transact()
예제 #12
0
    def test_should_bid_even_if_there_is_already_a_bidder(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        mkr_before = self.mcd.mkr.balance_of(self.keeper_address)
        # and
        lot = Wad.from_number(0.000016)
        assert self.flopper.dent(
            kick, lot, self.sump).transact(from_address=self.other_address)
        assert self.flopper.bids(kick).lot == lot

        # when
        simulate_model_output(model=model, price=Wad.from_number(825.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        auction = self.flopper.bids(kick)
        assert auction.lot != lot
        assert round(auction.bid / Rad(auction.lot),
                     2) == round(Rad.from_number(825.0), 2)
        mkr_after = self.mcd.mkr.balance_of(self.keeper_address)
        assert mkr_before == mkr_after

        # cleanup
        time_travel_by(self.web3, self.flopper.ttl() + 1)
        assert self.flopper.deal(kick).transact()
예제 #13
0
    def test_should_terminate_model_if_auction_expired_due_to_ttl_and_somebody_else_won_it(
            self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        self.dent(kick, self.other_address, Wad.from_number(0.000015),
                  self.sump)
        # and
        time_travel_by(self.web3, self.flopper.ttl() + 1)
        # and
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()

        # cleanup
        assert self.flopper.deal(kick).transact()
예제 #14
0
    def test_should_take_partial_if_insufficient_dai_available(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        (needs_redo, price, initial_lot, initial_tab) = self.clipper.status(kick)
        assert initial_lot == Wad.from_number(1)
        # and we exit all Dai out of the Vat
        assert self.mcd.dai_adapter.exit(self.keeper_address, Wad(self.mcd.vat.dai(self.keeper_address)))\
            .transact(from_address=self.keeper_address)

        # when we have less Dai than we need to cover the auction
        our_price = Ray.from_number(187)
        assert our_price < price
        dai_needed = initial_lot * Wad(our_price)
        half_dai = dai_needed / Wad.from_number(2)
        initial_dai_balance = Wad(self.mcd.vat.dai(self.keeper_address))
        if initial_dai_balance < half_dai:
            print(f"Reserving {half_dai - initial_dai_balance} Dai to get balance of {half_dai}")
            reserve_dai(self.mcd, self.dai_collateral, self.keeper_address, half_dai - initial_dai_balance)
        else:
            print(f"Abandoning {initial_dai_balance - half_dai} Dai to get balance of {half_dai}")
            self.mcd.vat.move(self.keeper_address, self.gal_address, Rad(initial_dai_balance - half_dai))\
                .transact(from_address=keeper_address)
        dai_balance_before_take = Wad(self.mcd.vat.dai(self.keeper_address))
        assert Wad(0) < dai_balance_before_take < dai_needed

        # then ensure we don't bid when the price is too high
        self.simulate_model_bid(model, our_price, reserve_dai_for_bid=False)
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        (needs_redo, price, lot, tab) = self.clipper.status(kick)
        assert lot == initial_lot
        assert tab == initial_tab

        # when we wait for the price to become appropriate
        while lot > Wad(0):
            time_travel_by(self.web3, 1)
            (needs_redo, auction_price, lot, tab) = self.clipper.status(kick)
            if auction_price < our_price:
                break

        # then ensure our bid is submitted using available Dai
        # self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        (needs_redo, price, lot, tab) = self.clipper.status(kick)
        assert Wad(0) < lot < initial_lot
        our_take = self.last_log()
        assert isinstance(our_take, Clipper.TakeLog)
        assert Wad(self.mcd.vat.dai(self.keeper_address)) < dai_balance_before_take

        # and ensure we don't place a subsequent dusty bid afterward
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        our_take2 = self.last_log()
        assert our_take.tx_hash == our_take2.tx_hash

        # cleanup
        self.take_below_price(kick, price, self.keeper_address)
예제 #15
0
    def test_should_terminate_model_if_auction_expired_due_to_ttl_and_somebody_else_won_it(
            self, mcd, c, kick, other_address, keeper):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        flipper.approve(
            flipper.vat(),
            approval_function=hope_directly(from_address=other_address))
        new_bid_amount = Rad.from_number(85)
        self.tend_with_dai(mcd, c, flipper, kick, other_address,
                           new_bid_amount)
        # and
        time_travel_by(self.web3, flipper.ttl() + 1)
        # and
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()

        # cleanup
        assert flipper.deal(kick).transact()
    def test_should_terminate_model_if_auction_is_settled(self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        self.decrease_sold_amount(auction_id, self.other_address,
                                  Wad.from_number(0.000016),
                                  self.debt_auction_bid_size)
        # and
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        # and
        self.debt_auction_house.settle_auction(auction_id).transact(
            from_address=self.other_address)
        # and
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()
예제 #17
0
    def test_should_terminate_model_if_auction_is_dealt(
            self, mcd, c, kick, other_address, keeper):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        self.tend_with_dai(mcd, c, flipper, kick, other_address,
                           Rad.from_number(90))
        # and
        time_travel_by(self.web3, flipper.ttl() + 1)
        # and
        flipper.deal(kick).transact(from_address=other_address)
        # and
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()
    def test_should_bid_even_if_there_is_already_a_bidder(self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)
        prot_before = self.geb.prot.balance_of(self.keeper_address)
        # and
        amount_to_sell = Wad.from_number(0.000016)
        assert self.debt_auction_house.decrease_sold_amount(
            auction_id, amount_to_sell, self.debt_auction_bid_size).transact(
                from_address=self.other_address)
        assert self.debt_auction_house.bids(
            auction_id).amount_to_sell == amount_to_sell

        # when
        simulate_model_output(model=model, price=Wad.from_number(825.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        auction = self.debt_auction_house.bids(auction_id)
        assert auction.amount_to_sell != amount_to_sell
        assert round(
            auction.bid_amount * self.geb.oracle_relayer.redemption_price() /
            Rad(auction.amount_to_sell), 2) == round(Rad.from_number(825.0), 2)
        prot_after = self.geb.prot.balance_of(self.keeper_address)
        assert prot_before == prot_after

        # cleanup
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        assert self.debt_auction_house.settle_auction(auction_id).transact()
예제 #19
0
    def test_should_only_tend_if_bid_is_only_slightly_above_tab(
            self, mcd, c, kick, keeper, keeper_address):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        auction = flipper.bids(kick)
        bid_price = Wad(auction.tab) + Wad.from_number(0.1)
        self.simulate_model_bid(mcd, c, model, bid_price)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        auction = flipper.bids(kick)
        assert auction.bid == auction.tab
        assert auction.lot == tend_lot

        # when
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        auction = flipper.bids(kick)
        assert auction.bid == auction.tab
        assert auction.lot == tend_lot

        # cleanup
        time_travel_by(self.web3, flipper.ttl() + 1)
        assert flipper.deal(kick).transact()
    def test_should_overbid_itself_if_model_has_updated_the_price(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        simulate_model_output(model=model, price=Wad.from_number(100.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert round(
            Rad(self.debt_auction_house.bids(auction_id).amount_to_sell),
            2) == round(self.debt_auction_bid_size / Rad.from_number(100.0), 2)

        # when
        simulate_model_output(model=model, price=Wad.from_number(110.0))
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.amount_to_sell_implies_price(auction_id,
                                                 Wad.from_number(110.0))

        # cleanup
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        assert self.debt_auction_house.settle_auction(auction_id).transact()
예제 #21
0
    def test_should_increase_gas_price_of_pending_transactions_if_model_increases_gas_price(
            self, mcd, c, kick, keeper):
        # given
        (model, model_factory) = models(keeper, kick)
        flipper = c.flipper

        # when
        bid_price = Wad.from_number(20.0)
        reserve_dai(mcd, c, self.keeper_address, bid_price * tend_lot * 2)
        simulate_model_output(model=model, price=bid_price, gas_price=10)
        # and
        self.start_ignoring_transactions()
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        # and
        simulate_model_output(model=model, price=bid_price, gas_price=15)
        # and
        self.end_ignoring_transactions()
        # and
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert flipper.bids(kick).bid == Rad(bid_price * tend_lot)
        assert self.web3.eth.getBlock(
            'latest', full_transactions=True).transactions[0].gasPrice == 15

        # cleanup
        time_travel_by(self.web3, flipper.ttl() + 1)
        assert flipper.deal(kick).transact()
    def test_should_replace_pending_transactions_if_model_lowers_bid_and_increases_gas_price(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        simulate_model_output(model=model,
                              price=Wad.from_number(80.0),
                              gas_price=10)
        # and
        self.start_ignoring_transactions()
        # and
        self.keeper.check_all_auctions()
        # and
        time.sleep(2)
        # and
        self.end_ignoring_transactions()
        # and
        simulate_model_output(model=model,
                              price=Wad.from_number(70.0),
                              gas_price=15)
        # and
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.amount_to_sell_implies_price(auction_id,
                                                 Wad.from_number(70.0))
        assert self.web3.eth.getBlock(
            'latest', full_transactions=True).transactions[0].gasPrice == 15

        # cleanup
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        assert self.debt_auction_house.settle_auction(auction_id).transact()
예제 #23
0
    def test_should_not_dent_on_rounding_errors_with_small_amounts(
            self, mcd, c, keeper):
        # given
        flipper = c.flipper
        kick_small_lot = flipper.kicks()
        (model, model_factory) = models(keeper, kick_small_lot)

        # when
        auction = flipper.bids(kick_small_lot)
        bid_price = Wad(auction.tab / Rad(tend_small_lot))
        self.simulate_model_bid(mcd, c, model, bid_price)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert flipper.bids(kick_small_lot).lot == auction.lot

        # when
        tx_count = self.web3.eth.getTransactionCount(
            self.keeper_address.address)
        # and
        keeper.check_all_auctions()
        keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.web3.eth.getTransactionCount(
            self.keeper_address.address) == tx_count
    def test_should_not_bid_on_rounding_errors_with_small_amounts(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        simulate_model_output(model=model, price=Wad.from_number(1400.0))
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.debt_auction_house.bids(auction_id).amount_to_sell == Wad(
            self.debt_auction_bid_size *
            self.geb.oracle_relayer.redemption_price() /
            Rad.from_number(1400.0))

        # when
        tx_count = self.web3.eth.getTransactionCount(
            self.keeper_address.address)
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.web3.eth.getTransactionCount(
            self.keeper_address.address) == tx_count
예제 #25
0
    def test_should_terminate_model_if_auction_is_dealt(self, kick):
        # given
        kick = self.flapper.kicks()
        (model, model_factory) = models(self.keeper, kick)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        auction = self.flapper.bids(kick)
        assert self.flapper.tend(kick, auction.lot, Wad.from_number(40)).transact(from_address=self.other_address)
        # and
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        # and
        assert self.flapper.deal(kick).transact(from_address=self.other_address)
        # and
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()
예제 #26
0
    def test_should_start_a_new_model_and_provide_it_with_info_on_auction_kick(
            self, c, kick, mcd, keeper):
        # given
        (model, model_factory) = models(keeper, kick)

        # when
        keeper.check_all_auctions()
        wait_for_other_threads()
        initial_bid = c.flipper.bids(kick)
        # then
        model_factory.create_model.assert_called_once_with(
            Parameters(flipper=c.flipper.address,
                       flapper=None,
                       flopper=None,
                       id=kick))
        # and
        status = model.send_status.call_args[0][0]
        assert status.id == kick
        assert status.flipper == c.flipper.address
        assert status.flapper is None
        assert status.flopper is None
        assert status.bid == Rad.from_number(0)
        assert status.lot == initial_bid.lot
        assert status.tab == initial_bid.tab
        assert status.beg > Wad.from_number(1)
        assert status.guy == mcd.cat.address
        assert status.era > 0
        assert status.end < status.era + c.flipper.tau() + 1
        assert status.tic == 0
        assert status.price == Wad(0)
예제 #27
0
    def test_should_replace_pending_transactions_if_model_lowers_bid_and_increases_gas_price(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        lot = self.flapper.bids(kick).lot

        # when
        simulate_model_output(model=model, price=Wad.from_number(10.0), gas_price=10)
        # and
        self.start_ignoring_transactions()
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        # and
        self.end_ignoring_transactions()
        # and
        simulate_model_output(model=model, price=Wad.from_number(8.0), gas_price=15)
        # and
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.flapper.bids(kick).bid == Wad(lot) / Wad.from_number(8.0)
        assert self.web3.eth.getBlock('latest', full_transactions=True).transactions[0].gasPrice == 15

        # cleanup
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        assert self.flapper.deal(kick).transact()
예제 #28
0
    def test_should_terminate_model_if_auction_expired_due_to_tau(
            self, c, keeper):
        # given
        flipper = c.flipper
        kick = flipper.kicks()
        (model, model_factory) = models(keeper, kick)

        # when
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_not_called()

        # when
        time_travel_by(self.web3, flipper.tau() + 1)
        # and
        keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once()
        model.terminate.assert_called_once()

        # cleanup
        assert flipper.deal(kick).transact()
예제 #29
0
    def test_should_start_a_new_model_and_provide_it_with_info_on_auction_kick(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        model_factory.create_model.assert_called_once_with(Parameters(flipper=None,
                                                                      flapper=self.flapper.address,
                                                                      flopper=None,
                                                                      id=kick))
        # and
        status = model.send_status.call_args[0][0]
        assert status.id == kick
        assert status.flipper is None
        assert status.flapper == self.flapper.address
        assert status.flopper is None
        assert status.bid == Wad(0)
        assert status.lot == self.mcd.vow.bump()
        assert status.tab is None
        assert status.beg == Wad.from_number(1.05)
        assert status.guy == self.mcd.vow.address
        assert status.era > 0
        assert status.end < status.era + self.flapper.tau() + 1
        assert status.tic == 0
        assert status.price is None
예제 #30
0
    def test_should_take_when_price_appropriate(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)

        # when
        our_price = Ray.from_number(153)
        self.simulate_model_bid(model, our_price)

        while True:
            time_travel_by(self.web3, 1)
            self.keeper.check_all_auctions()
            self.keeper.check_for_bids()
            wait_for_other_threads()
            lot = self.clipper.sales(kick).lot
            (needs_redo, auction_price, lot, tab) = self.clipper.status(kick)

            # when auction price is unacceptable
            if auction_price > our_price:
                # then ensure no action is taken
                assert self.clipper.sales(kick).lot > Wad(0)
                assert not needs_redo
            # when auction price is acceptable
            else:
                # then ensure take was called
                assert self.clipper.sales(kick).lot == Wad(0)
                break

        # and ensure the take price was appropriate
        our_take = self.last_log()
        assert isinstance(our_take, Clipper.TakeLog)
        assert our_take.price <= our_price