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()
Beispiel #2
0
    def test_process_safe(self, geb, our_address):
        collateral_type = geb.collaterals['ETH-A'].collateral_type

        safe = geb.safe_engine.safe(collateral_type, our_address)
        assert safe.generated_debt > Wad(0)
        assert geb.safe_engine.collateral_type(
            collateral_type.name).accumulated_rate > Ray(0)
        assert geb.global_settlement.final_coin_per_collateral_price(
            collateral_type) > Ray(0)

        owe = Ray(safe.generated_debt) * geb.safe_engine.collateral_type(
            collateral_type.name
        ).accumulated_rate * geb.global_settlement.final_coin_per_collateral_price(
            collateral_type)

        assert owe > Ray(0)
        wad = min(Ray(safe.locked_collateral), owe)
        print(f"owe={owe} wad={wad}")

        assert geb.global_settlement.process_safe(collateral_type,
                                                  our_address).transact()
        assert geb.safe_engine.safe(collateral_type,
                                    our_address).generated_debt == Wad(0)
        assert geb.safe_engine.safe(collateral_type,
                                    our_address).locked_collateral > Wad(0)
        assert geb.safe_engine.debt_balance(
            geb.accounting_engine.address) > Rad(0)

        assert geb.safe_engine.global_debt() > Rad(0)
        assert geb.safe_engine.global_unbacked_debt() > Rad(0)
    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()
Beispiel #4
0
    def test_transfer_internal_coins(self, geb, our_address, other_address):
        # given
        collateral = geb.collaterals['ETH-A']
        collateral.approve(our_address)
        our_safe = geb.safe_engine.safe(collateral.collateral_type,
                                        our_address)
        wrap_eth(geb, our_address, Wad.from_number(60))

        assert collateral.adapter.join(our_address,
                                       Wad.from_number(60)).transact()
        assert geb.safe_engine.modify_safe_collateralization(
            collateral.collateral_type, our_address, Wad.from_number(60),
            Wad.from_number(20)).transact()
        other_balance_before = geb.safe_engine.coin_balance(other_address)

        # when
        assert geb.safe_engine.transfer_internal_coins(
            our_address, other_address, Rad(Wad.from_number(20))).transact()

        # then
        other_balance_after = geb.safe_engine.coin_balance(other_address)
        assert other_balance_before + Rad(
            Wad.from_number(20)) == other_balance_after

        # rollback
        cleanup_safe(geb, collateral, our_address)
Beispiel #5
0
    def get_input(self, id: int) -> Status:
        assert isinstance(id, int)

        # Read auction state
        bid = self.staked_token_auction_house.bids(id)

        # get latest redemption price
        redemption_price = self.geb.oracle_relayer.redemption_price()

        # Prepare the model input from auction state
        return Status(
            id=id,
            collateral_auction_house=None,
            surplus_auction_house=None,
            debt_auction_house=None,
            staked_token_auction_house=self.staked_token_auction_house.address,
            bid_amount=bid.bid_amount,
            amount_to_sell=bid.amount_to_sell,
            amount_to_raise=None,
            sold_amount=None,
            raised_amount=None,
            bid_increase=self.bid_increase,
            bid_decrease=None,
            high_bidder=bid.high_bidder,
            block_time=block_time(self.staked_token_auction_house.web3),
            bid_expiry=bid.bid_expiry,
            auction_deadline=bid.auction_deadline,
            price=Wad(bid.bid_amount * Rad(redemption_price) /
                      Rad(bid.amount_to_sell))
            if Rad(bid.amount_to_sell) != Rad(0) else None)
    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()
    def test_flash_proxy_settle_auction(self, c: Collateral, web3, geb,
                                        auction_id, other_address):
        # given
        collateral_auction_house = self.collateral.collateral_auction_house
        if not isinstance(collateral_auction_house,
                          FixedDiscountCollateralAuctionHouse):
            return

        set_collateral_price(geb, c, Wad.from_number(100))
        eth_before = self.web3.eth.getBalance(self.keeper_address.address)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()

        assert self.web3.eth.getBalance(
            self.keeper_address.address) > eth_before

        current_status = collateral_auction_house.bids(auction_id)
        assert current_status.raised_amount == Rad(0)
        assert current_status.sold_amount == Wad(0)
        assert current_status.amount_to_raise == Rad(0)
        assert current_status.amount_to_sell == Wad(0)
        assert current_status.auction_deadline == 0
        assert current_status.raised_amount == Rad(0)
    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_flash_proxy_liquidate_and_settle_auction(self, c: Collateral,
                                                      web3, geb, auction_id,
                                                      other_address):
        # given
        collateral_auction_house = self.collateral.collateral_auction_house
        if not isinstance(collateral_auction_house,
                          FixedDiscountCollateralAuctionHouse):
            return

        set_collateral_price(geb, c, Wad.from_number(100))
        eth_before = self.web3.eth.getBalance(self.keeper_address.address)
        auctions_started = collateral_auction_house.auctions_started()

        # when
        critical_safe = create_critical_safe(geb, c, bid_size, other_address)
        self.keeper.check_safes()
        wait_for_other_threads()
        assert self.web3.eth.getBalance(
            self.keeper_address.address) > eth_before
        assert collateral_auction_house.auctions_started(
        ) == auctions_started + 1

        auction_status = collateral_auction_house.bids(auctions_started + 1)
        assert auction_status.raised_amount == Rad(0)
        assert auction_status.sold_amount == Wad(0)
        assert auction_status.amount_to_raise == Rad(0)
        assert auction_status.amount_to_sell == Wad(0)
        assert auction_status.auction_deadline == 0
        assert auction_status.raised_amount == Rad(0)
def auction_id(web3: Web3, geb: GfDeployment, auction_income_recipient_address,
               other_address) -> int:

    total_surplus = geb.safe_engine.coin_balance(geb.accounting_engine.address)
    unqueued_unauctioned_debt = (
        geb.safe_engine.debt_balance(geb.accounting_engine.address) -
        geb.accounting_engine.total_queued_debt()
    ) - geb.accounting_engine.total_on_auction_debt()
    print(
        f'total_surplus={str(total_surplus)[:6]}, unqueued_unauctioned_debt={str(unqueued_unauctioned_debt)[:6]}'
    )

    if unqueued_unauctioned_debt < total_surplus or (
            unqueued_unauctioned_debt == Rad(0) and total_surplus == Rad(0)):
        # Liquidate SAFE
        c = geb.collaterals['ETH-B']
        critical_safe = create_critical_safe(geb,
                                             c,
                                             Wad.from_number(2),
                                             other_address,
                                             draw_system_coin=False)
        collateral_auction_id = liquidate(geb, c, critical_safe)

        # Generate some system coin, bid on and win the collateral auction without covering all the debt
        reserve_system_coin(geb,
                            c,
                            auction_income_recipient_address,
                            Wad.from_number(100),
                            extra_collateral=Wad.from_number(1.1))
        c.collateral_auction_house.approve(
            geb.safe_engine.address,
            approval_function=approve_safe_modification_directly(
                from_address=auction_income_recipient_address))
        current_bid = c.collateral_auction_house.bids(collateral_auction_id)
        bid_amount = Rad.from_number(1.9)
        assert geb.safe_engine.coin_balance(
            auction_income_recipient_address) > bid_amount
        #assert c.collateral_auction_house.increase_bid_size(collateral_auction_id, current_bid.amount_to_sell, bid_amount).transact(from_address=auction_income_recipient_address)
        #time_travel_by(web3, c.collateral_auction_house.bid_duration()+1)
        #assert c.collateral_auction_house.settle_auction(collateral_auction_id).transact()

    pop_debt_and_settle_debt(web3,
                             geb,
                             past_blocks=1200,
                             cancel_auctioned_debt=False)

    # Start the debt auction
    unqueued_unauctioned_debt = (
        geb.safe_engine.debt_balance(geb.accounting_engine.address) -
        geb.accounting_engine.total_queued_debt()
    ) - geb.accounting_engine.total_on_auction_debt()
    assert geb.accounting_engine.debt_auction_bid_size(
    ) <= unqueued_unauctioned_debt
    assert geb.safe_engine.coin_balance(
        geb.accounting_engine.address) == Rad(0)
    assert geb.accounting_engine.auction_debt().transact(
        from_address=auction_income_recipient_address)
    return geb.debt_auction_house.auctions_started()
Beispiel #11
0
 def test_prepare_coins_for_redeeming(self, geb, our_address):
     assert geb.global_settlement.coin_bag(our_address) == Wad(0)
     assert geb.global_settlement.outstanding_coin_supply() > Rad(0)
     assert geb.system_coin.approve(
         geb.global_settlement.address).transact()
     assert geb.safe_engine.coin_balance(our_address) >= Rad.from_number(10)
     # FIXME: `prepareCoinsForRedeeming` fails, possibly because we're passing 0 to `safeEngine.transfer_collateral`
     assert geb.global_settlement.prepare_coins_for_redeeming(
         Wad.from_number(10)).transact()
     assert geb.global_settlement.coin_bag(our_address) == Wad.from_number(
         10)
    def eliminate_queued_debt(cls, web3, geb, keeper_address):
        if geb.safe_engine.debt_balance(
                geb.accounting_engine.address) == Rad(0):
            return

        # given the existence of queued debt
        c = geb.collaterals['ETH-A']
        auction_id = c.collateral_auction_house.auctions_started()
        last_liquidation = geb.liquidation_engine.past_liquidations(10)[0]

        # when a bid covers the SAFE debt
        auction = c.collateral_auction_house.bids(auction_id)
        reserve_system_coin(geb, c, keeper_address,
                            Wad(auction.amount_to_raise) + Wad(1))
        c.collateral_auction_house.approve(
            c.collateral_auction_house.safe_engine(),
            approval_function=approve_safe_modification_directly(
                from_address=keeper_address))
        c.approve(keeper_address)

        if isinstance(c.collateral_auction_house,
                      EnglishCollateralAuctionHouse):
            assert c.collateral_auction_house.increase_bid_size(
                auction_id, auction.amount_to_sell,
                auction.amount_to_raise).transact(from_address=keeper_address)
            time_travel_by(web3, c.collateral_auction_house.bid_duration() + 1)
            assert c.collateral_auction_house.settle_auction(
                auction_id).transact()
        elif isinstance(c.collateral_auction_house,
                        FixedDiscountCollateralAuctionHouse):
            assert c.collateral_auction_house.buy_collateral(
                auction_id,
                Wad(auction.amount_to_raise) +
                Wad(1)).transact(from_address=keeper_address)
        elif isinstance(c.collateral_auction_house,
                        IncreasingDiscountCollateralAuctionHouse):
            assert c.collateral_auction_house.buy_collateral(
                auction_id,
                Wad(auction.amount_to_raise) +
                Wad(1)).transact(from_address=keeper_address)

        # when a bid covers the vow debt
        assert geb.accounting_engine.debt_queue_of(
            last_liquidation.block_time(web3)) > Rad(0)
        assert geb.accounting_engine.pop_debt_from_queue(
            last_liquidation.block_time(web3)).transact(
                from_address=keeper_address)
        assert geb.accounting_engine.settle_debt(
            geb.safe_engine.debt_balance(
                geb.accounting_engine.address)).transact()

        # then ensure queued debt has been auctioned off
        assert geb.safe_engine.debt_balance(
            geb.accounting_engine.address) == Rad(0)
def wipe_debt(geb: GfDeployment, collateral: Collateral, address: Address):
    safe = geb.safe_engine.safe(collateral.collateral_type, address)
    assert Rad(safe.generated_debt) >= geb.safe_engine.coin_balance(address)
    delta_collateral = Ray(geb.safe_engine.coin_balance(
        address)) / geb.safe_engine.collateral_type(
            collateral.collateral_type.name).accumulated_rate
    wrap_modify_safe_collateralization(
        geb, collateral, address, Wad(0),
        Wad(delta_collateral) *
        -1)  #because there is residual state on the testchain
    assert geb.safe_engine.coin_balance(address) <= Rad(
        Wad(1))  # pesky dust amount in Dai amount
Beispiel #14
0
 def __init__(self, log):
     args = log['args']
     self.id = int(args['id'])
     self.amount_to_sell = Wad(args['amountToSell'])
     self.bid_amount = Rad(args['initialBid'])
     self.amount_to_raise = Rad(args['amountToRaise'])
     self.forgone_collateral_receiver = Address(
         args['forgoneCollateralReceiver'])
     self.auction_income_recipient = Address(
         args['auctionIncomeRecipient'])
     self.block = log['blockNumber']
     self.tx_hash = log['transactionHash'].hex()
    def test_should_change_gas_strategy_when_model_output_changes(
            self, auction_id):
        # given
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        first_bid = Wad.from_number(90)
        simulate_model_output(model=model, price=first_bid, gas_price=2000)
        # and
        self.keeper.check_all_auctions()
        self.keeper.check_for_bids()
        wait_for_other_threads()
        # then
        assert self.web3.eth.getBlock(
            'latest', full_transactions=True).transactions[0].gasPrice == 2000

        # when
        second_bid = Wad.from_number(100)
        simulate_model_output(model=model, price=second_bid)
        # 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(second_bid), 2)
        assert self.web3.eth.getBlock('latest', full_transactions=True).transactions[0].gasPrice == \
               self.default_gas_price

        # when
        third_bid = Wad.from_number(110)
        new_gas_price = int(self.default_gas_price * 1.25)
        simulate_model_output(model=model,
                              price=third_bid,
                              gas_price=new_gas_price)
        # 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(third_bid), 2)
        assert self.web3.eth.getBlock(
            'latest',
            full_transactions=True).transactions[0].gasPrice == new_gas_price

        # cleanup
        time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1)
        assert self.debt_auction_house.settle_auction(auction_id).transact()
Beispiel #16
0
    def test_init(self, geb, deployment_address, our_address):
        assert geb.esm is not None
        assert isinstance(geb.esm, ESM)
        assert isinstance(geb.esm.address, Address)
        assert geb.esm.trigger_threshold() > Wad(0)
        assert not geb.esm.settled()

        coin_balance = geb.safe_engine.coin_balance(
            geb.accounting_engine.address)
        awe = geb.safe_engine.debt_balance(geb.accounting_engine.address)
        # If `test_shutdown.py` is run in isolation, create a surplus auction to exercise `terminate_auction_prematurely`
        if coin_balance == Rad(0) and awe == Rad(0):
            create_surplus_auction(geb, deployment_address, our_address,
                                   geb.collaterals['ETH-A'])
Beispiel #17
0
    def test_collateral_type(self, geb):
        assert geb.safe_engine.collateral_type('XXX') == CollateralType(
            'XXX',
            accumulated_rate=Ray(0),
            safe_collateral=Wad(0),
            safe_debt=Wad(0),
            safety_price=Ray(0),
            debt_ceiling=Rad(0),
            debt_floor=Rad(0))

        collateral_type = geb.collaterals["ETH-C"].collateral_type

        representation = repr(collateral_type)
        assert "ETH-C" in representation
Beispiel #18
0
def open_safe(geb: GfDeployment, collateral: Collateral, address: Address):
    assert isinstance(geb, GfDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(address, Address)

    collateral.approve(address)
    wrap_eth(geb, address, Wad.from_number(10))
    assert collateral.adapter.join(
        address, Wad.from_number(10)).transact(from_address=address)
    wrap_modify_safe_collateralization(geb, collateral, address,
                                       Wad.from_number(10),
                                       Wad.from_number(15))

    assert geb.safe_engine.global_debt() >= Rad(Wad.from_number(15))
    assert geb.safe_engine.coin_balance(address) >= Rad.from_number(10)
Beispiel #19
0
def create_surplus_auction(geb: GfDeployment, deployment_address: Address,
                           our_address: Address, collateral: Collateral):
    assert isinstance(geb, GfDeployment)
    assert isinstance(deployment_address, Address)
    assert isinstance(our_address, Address)

    surplus_auction_house = geb.surplus_auction_house
    create_surplus(geb, surplus_auction_house, deployment_address, collateral)
    coin_balance = geb.safe_engine.coin_balance(geb.accounting_engine.address)
    assert coin_balance > geb.safe_engine.debt_balance(
        geb.accounting_engine.address
    ) + geb.accounting_engine.surplus_auction_amount_to_sell(
    ) + geb.accounting_engine.surplus_buffer()
    assert (geb.safe_engine.debt_balance(geb.accounting_engine.address) -
            geb.accounting_engine.total_queued_debt()
            ) - geb.accounting_engine.total_on_auction_debt() == Rad(0)
    assert geb.accounting_engine.auction_surplus().transact()

    mint_prot(geb.prot, our_address, Wad.from_number(10))
    surplus_auction_house.approve(geb.prot.address,
                                  directly(from_address=our_address))
    bid = Wad.from_number(0.001)
    assert geb.prot.balance_of(our_address) > bid
    assert surplus_auction_house.increase_bid_size(
        surplus_auction_house.auctions_started(),
        geb.accounting_engine.surplus_auction_amount_to_sell(),
        bid).transact(from_address=our_address)
    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
Beispiel #21
0
    def settlement_active_auctions(self, parent_obj) -> List:
        """ Returns auctions that meet the requiremenets to be called by
            GlobalSettlement.fastTrackAuction, SurplusAuctionHouse.terminateAuctionPrematurely and 
            DebtAuctionHouse.terminateAuctionPrematurely
        """
        active_auctions = []
        auction_count = parent_obj.auctions_started()

        # english collateral auction
        if isinstance(parent_obj, EnglishCollateralAuctionHouse):
            for index in range(auction_count + 1):
                bid = parent_obj._bids(index)
                if bid.high_bidder != Address(
                        "0x0000000000000000000000000000000000000000"):
                    if bid.bid_amount < bid.amount_to_raise:
                        active_auctions.append(bid)

        # fixed discount collateral auction
        elif isinstance(parent_obj, FixedDiscountCollateralAuctionHouse):
            for index in range(auction_count + 1):
                bid = parent_obj._bids(index)
                if bid.amount_to_sell != Wad(0) and bid.amount_to_raise != Rad(
                        0):
                    active_auctions.append(bid)

        # surplus and debt auctions
        else:
            for index in range(auction_count + 1):
                bid = parent_obj._bids(index)
                if bid.high_bidder != Address(
                        "0x0000000000000000000000000000000000000000"):
                    active_auctions.append(bid)

        return active_auctions
    def test_should_provide_model_with_updated_info_after_somebody_else_partial_bids(self, auction_id, other_address):
        # given
        collateral_auction_house = self.collateral.collateral_auction_house
        if not isinstance(collateral_auction_house, FixedDiscountCollateralAuctionHouse):
            return
        (model, model_factory) = models(self.keeper, auction_id)

        # when
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        assert model.send_status.call_count == 1

        # when
        collateral_auction_house.approve(collateral_auction_house.safe_engine(),
                                         approval_function=approve_safe_modification_directly(from_address=other_address))
        previous_bid = collateral_auction_house.bids(auction_id)
        new_bid_amount = Wad.from_number(30)
        self.buy_collateral_with_system_coin(self.geb, self.collateral, collateral_auction_house, model.id, other_address, new_bid_amount)
        # and
        self.keeper.check_all_auctions()
        wait_for_other_threads()
        # then
        assert model.send_status.call_count > 1
        # and
        status = model.send_status.call_args[0][0]
        assert status.id == auction_id
        assert status.collateral_auction_house == collateral_auction_house.address
        assert status.surplus_auction_house is None
        assert status.debt_auction_house is None
        assert status.raised_amount == Rad(new_bid_amount)
        assert status.amount_to_sell == previous_bid.amount_to_sell
        assert status.amount_to_raise == previous_bid.amount_to_raise
        assert status.block_time > 0
        assert status.auction_deadline > status.block_time
def increase_bid_size(collateral_auction_house: EnglishCollateralAuctionHouse,
                      id: int, address: Address, amount_to_sell: Wad,
                      bid_amount: Rad):
    assert (isinstance(collateral_auction_house,
                       EnglishCollateralAuctionHouse))
    assert (isinstance(id, int))
    assert (isinstance(amount_to_sell, Wad))
    assert (isinstance(bid_amount, Rad))

    current_bid = collateral_auction_house.bids(id)
    assert current_bid.high_bidder != Address(
        "0x0000000000000000000000000000000000000000")
    assert current_bid.bid_expiry > datetime.now().timestamp(
    ) or current_bid.bid_expiry == 0
    assert current_bid.auction_deadline > datetime.now().timestamp()

    assert amount_to_sell == current_bid.amount_to_sell
    assert bid_amount <= current_bid.amount_to_raise
    assert bid_amount > current_bid.bid_amount
    assert (bid_amount >= Rad(collateral_auction_house.bid_increase()) *
            current_bid.bid_amount) or (bid_amount
                                        == current_bid.amount_to_raise)

    assert collateral_auction_house.increase_bid_size(
        id, amount_to_sell, bid_amount).transact(from_address=address)
Beispiel #24
0
    def bid(self, id: int
            ) -> Tuple[Optional[Wad], Optional[Transact], Optional[Rad]]:
        assert isinstance(id, int)

        bid = self.collateral_auction_house.bids(id)
        remaining_to_raise = bid.amount_to_raise - bid.raised_amount
        remaining_to_sell = bid.amount_to_sell - bid.sold_amount

        if remaining_to_sell < self.min_amount_to_sell:
            self.logger.debug(
                f"remaining_to_sell {remaining_to_sell} less than minimum {self.min_amount_to_sell} for auction {id}"
            )
            return None, None, None

        # Always bid our entire balance.  If auction amount_to_raise is less, FixedDiscountCollateralAuctionHouse will reduce it.
        our_bid = Wad(self.geb.safe_engine.coin_balance(self.our_address))
        if our_bid <= self.collateral_auction_house.minimum_bid():
            self.logger.info(
                f"Our system coin balance is less than FixedDiscountCollateralAuctionHouse.minimum_bid(). Not bidding"
            )
            return None, None, None

        approximate_collateral, our_adjusted_bid = self.collateral_auction_house.get_approximate_collateral_bought(
            id, our_bid)

        if approximate_collateral == Wad(0):
            self.logger.info(
                f"Approximate collateral bought for auction {id} would be Wad(0). Not bidding"
            )
            return None, None, None
        our_approximate_price = our_adjusted_bid / approximate_collateral

        return our_approximate_price, self.collateral_auction_house.buy_collateral(
            id, our_bid), Rad(our_bid)
    def test_active_auctions(self, geb: GfDeployment, keeper: SettlementKeeper,
                             our_address: Address, other_address: Address,
                             deployment_address: Address):
        print_out("test_active_auctions")
        print(
            f"debt balance: {geb.safe_engine.debt_balance(geb.accounting_engine.address)}"
        )
        print(
            f"system coin: {geb.safe_engine.coin_balance(geb.accounting_engine.address)}"
        )

        create_surplus_auction(geb, deployment_address, our_address)
        create_debt_auction(geb, deployment_address, other_address)

        # this collateral auction sets the collateral back to a price that makes the guy's vault underwater again.
        # 49 to make it underwater, and create_collateral_auction sets it to 33
        create_collateral_auction(geb, deployment_address, our_address)

        auctions = keeper.all_active_auctions()
        assert "collateral_auctions" in auctions
        assert "debt_auctions" in auctions
        assert "surplus_auctions" in auctions

        nobody = Address("0x0000000000000000000000000000000000000000")

        # All auctions active before terminations
        for collateral_type in auctions["collateral_auctions"].keys():
            # pyflex create_debt() doesn't bid/settle on collateral auction.
            # so one extra auction is present
            #assert len(auctions["collateral_auctions"][collateral_type]) == 1
            for auction in auctions["collateral_auctions"][collateral_type]:
                if isinstance(
                        geb.collaterals[collateral_type].
                        collateral_auction_house,
                        EnglishCollateralAuctionHouse):
                    assert auction.id > 0
                    assert auction.bid_amount < auction.amount_to_raise
                    assert auction.high_bidder != nobody
                    #assert auction.high_bidder == our_address
                elif isinstance(
                        geb.collaterals[collateral_type].
                        collateral_auction_house,
                        FixedDiscountCollateralAuctionHouse):
                    assert auction.amount_to_sell != Wad(
                        0) and auction.amount_to_raise != Rad(0)

        assert len(auctions["surplus_auctions"]) == 1
        for auction in auctions["surplus_auctions"]:
            assert auction.id > 0
            assert auction.high_bidder != nobody
            assert auction.high_bidder == our_address

        assert len(auctions["debt_auctions"]) == 1
        for auction in auctions["debt_auctions"]:
            assert auction.id > 0
            assert auction.high_bidder != nobody
            assert auction.high_bidder == other_address

        pytest.global_auctions = auctions
Beispiel #26
0
    def bid(self, id: int, price: Wad
            ) -> Tuple[Optional[Wad], Optional[Transact], Optional[Rad]]:
        assert isinstance(id, int)
        assert isinstance(price, Wad)

        bid = self.staked_token_auction_house.bids(id)
        redemption_price = self.geb.oracle_relayer.redemption_price()

        our_bid = Rad(price) * Rad(bid.amount_to_sell) / Rad(redemption_price)

        if our_bid > bid.bid_amount * self.bid_increase:
            return price, self.staked_token_auction_house.increase_bid_size(
                id, bid.amount_to_sell, our_bid), bid.bid_amount
        else:
            self.logger.debug(
                f"our_bid {our_bid} at price {price} would not exceed the min bid increase {self.bid_increase} over bid_amount {bid.bid_amount} for amount to sell {bid.amount_to_sell} for auction {id} and redemption price {redemption_price}"
            )
            return None, None, None
Beispiel #27
0
 def __init__(self, log):
     args = log['args']
     self.id = int(args['id'])
     self.high_bidder = Address(args['highBidder'])
     self.amount_to_buy = Wad(args['amountToBuy'])
     self.bid = Rad(args['bid'])
     self.bid_expiry = int(args['bidExpiry'])
     self.block = log['blockNumber']
     self.tx_hash = log['transactionHash'].hex()
Beispiel #28
0
    def bid(self, id: int, price: Wad
            ) -> Tuple[Optional[Wad], Optional[Transact], Optional[Rad]]:
        assert isinstance(id, int)
        assert isinstance(price, Wad)

        bid = self.debt_auction_house.bids(id)
        redemption_price = self.geb.oracle_relayer.redemption_price()
        our_amount = bid.bid_amount * redemption_price / Rad(price)

        if Ray(our_amount) * self.bid_decrease <= Ray(
                bid.amount_to_sell) and our_amount < Rad(bid.amount_to_sell):
            return price, self.debt_auction_house.decrease_sold_amount(
                id, Wad(our_amount), bid.bid_amount), bid.bid_amount
        else:
            self.logger.debug(
                f"our_amount {our_amount} at price {price} would not exceed the bid decrease {self.bid_decrease} for amount to sell {bid.amount_to_sell} for auction {id} and redemption price {redemption_price}"
            )
            return None, None, None
Beispiel #29
0
def create_almost_risky_safe():
    # Create a safe close to the liquidation ratio
    if is_critical_safe(
            geb.safe_engine.collateral_type(collateral.collateral_type.name),
            safe):
        logging.info("SAFE is already critical; no action taken")
    else:
        collateral_amount = Wad(
            collateral_type.debt_floor /
            (Rad(osm_price) / Rad(redemption_price)) *
            Rad(geb.oracle_relayer.safety_c_ratio(collateral_type)) *
            Rad(collateral_type.accumulated_rate)) + flub_amount
        logging.info(
            f"Opening/adjusting safe with {collateral_amount} {collateral_type.name}"
        )
        create_almost_risky_safe(geb, collateral, collateral_amount,
                                 our_address, False)
        logging.info("Created almost risky safe")
Beispiel #30
0
    def active_auctions(self) -> list:
        active_auctions = []
        auction_count = self.auctions_started()
        for index in range(1, auction_count + 1):
            bid = self._bids(index)
            if bid.amount_to_sell > Wad(0) and bid.amount_to_raise > Rad(0):
                active_auctions.append(bid)

        return active_auctions