Beispiel #1
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()
Beispiel #2
0
 def __init__(self, lognote: LogNote):
     self.guy = Address(lognote.usr)
     self.id = Web3.toInt(lognote.arg1)
     self.lot = Wad(Web3.toInt(lognote.arg2))
     self.bid = Rad(Web3.toInt(lognote.get_bytes_at_index(2)))
     self.block = lognote.block
     self.tx_hash = lognote.tx_hash
Beispiel #3
0
    def test_skim(self, mcd, our_address):
        ilk = mcd.collaterals['ETH-A'].ilk

        urn = mcd.vat.urn(ilk, our_address)
        owe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate * mcd.end.tag(ilk)
        assert owe > Ray(0)
        wad = min(Ray(urn.ink), owe)
        print(f"owe={owe} wad={wad}")

        assert mcd.end.skim(ilk, our_address).transact()
        assert mcd.vat.urn(ilk, our_address).art == Wad(0)
        assert mcd.vat.urn(ilk, our_address).ink > Wad(0)
        assert mcd.vat.sin(mcd.vow.address) > Rad(0)

        assert mcd.vat.debt() > Rad(0)
        assert mcd.vat.vice() > Rad(0)
Beispiel #4
0
 def __init__(self, log):
     args = log['args']
     self.id = args['id']
     self.lot = Rad(args['lot'])
     self.bid = Wad(args['bid'])
     self.block = log['blockNumber']
     self.tx_hash = log['transactionHash'].hex()
Beispiel #5
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()
Beispiel #6
0
def kick(web3: Web3, mcd: DssDeployment, gal_address, other_address) -> int:
    joy = mcd.vat.dai(mcd.vow.address)
    woe = (mcd.vat.sin(mcd.vow.address) - mcd.vow.sin()) - mcd.vow.ash()
    print(f'joy={str(joy)[:6]}, woe={str(woe)[:6]}')

    if woe < joy:
        # Bite gal CDP
        c = mcd.collaterals['ETH-B']
        unsafe_cdp = create_unsafe_cdp(mcd, c, Wad.from_number(2), other_address, draw_dai=False)
        flip_kick = bite(mcd, c, unsafe_cdp)

        # Generate some Dai, bid on and win the flip auction without covering all the debt
        reserve_dai(mcd, c, gal_address, Wad.from_number(100), extra_collateral=Wad.from_number(1.1))
        c.flipper.approve(mcd.vat.address, approval_function=hope_directly(from_address=gal_address))
        current_bid = c.flipper.bids(flip_kick)
        bid = Rad.from_number(1.9)
        assert mcd.vat.dai(gal_address) > bid
        assert c.flipper.tend(flip_kick, current_bid.lot, bid).transact(from_address=gal_address)
        time_travel_by(web3, c.flipper.ttl()+1)
        assert c.flipper.deal(flip_kick).transact()

    flog_and_heal(web3, mcd, past_blocks=1200, kiss=False)

    # Kick off the flop auction
    woe = (mcd.vat.sin(mcd.vow.address) - mcd.vow.sin()) - mcd.vow.ash()
    assert mcd.vow.sump() <= woe
    assert mcd.vat.dai(mcd.vow.address) == Rad(0)
    assert mcd.vow.flop().transact(from_address=gal_address)
    return mcd.flopper.kicks()
Beispiel #7
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=None,
                       flopper=self.flopper.address,
                       id=kick))
        # and
        status = model.send_status.call_args[0][0]
        assert status.id == kick
        assert status.flipper is None
        assert status.flapper is None
        assert status.flopper == self.flopper.address
        assert status.bid > Rad.from_number(0)
        assert status.lot == self.mcd.vow.dump()
        assert status.tab is None
        assert status.beg > Wad.from_number(1)
        assert status.guy == self.mcd.vow.address
        assert status.era > 0
        assert status.end < status.era + self.flopper.tau() + 1
        assert status.tic == 0
        assert status.price == Wad(status.bid / Rad(status.lot))
Beispiel #8
0
    def test_should_change_gas_strategy_when_model_output_changes(self, kick):
        # given
        (model, model_factory) = models(self.keeper, kick)
        lot = self.flapper.bids(kick).lot

        # when
        first_bid = Wad.from_number(0.0000009)
        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(0.0000006)
        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 self.flapper.bids(kick).bid == Wad(lot / Rad(second_bid))
        assert self.web3.eth.getBlock('latest', full_transactions=True).transactions[0].gasPrice == \
               self.default_gas_price

        # when
        third_bid = Wad.from_number(0.0000003)
        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 self.flapper.bids(kick).bid == Wad(lot / Rad(third_bid))
        assert self.web3.eth.getBlock(
            'latest',
            full_transactions=True).transactions[0].gasPrice == new_gas_price

        # cleanup
        time_travel_by(self.web3, self.flapper.ttl() + 1)
        assert self.flapper.deal(kick).transact()
Beispiel #9
0
    def validate_frob(self, ilk: Ilk, address: Address, dink: Wad, dart: Wad):
        """Helps diagnose `frob` transaction failures by asserting on `require` conditions in the contract"""
        assert isinstance(ilk, Ilk)
        assert isinstance(address, Address)
        assert isinstance(dink, Wad)
        assert isinstance(dart, Wad)

        urn = self.urn(ilk, address)
        ilk = self.ilk(ilk.name)

        logger.debug(
            f"urn.ink={urn.ink}, urn.art={urn.art}, dink={dink}, dart={dart}, "
            f"ilk.rate={ilk.rate}, debt={str(self.debt())}")
        ink = urn.ink + dink
        art = urn.art + dart
        ilk_art = ilk.art + dart
        rate = ilk.rate

        gem = self.gem(ilk, urn.address) - dink
        dai = self.dai(urn.address) + Rad(rate * dart)
        debt = self.debt() + Rad(rate * dart)

        # stablecoin debt does not increase
        cool = dart <= Wad(0)
        # collateral balance does not decrease
        firm = dink >= Wad(0)
        nice = cool and firm

        # Vault remains under both collateral and total debt ceilings
        under_collateral_debt_ceiling = Rad(ilk_art * rate) <= ilk.line
        if not under_collateral_debt_ceiling:
            logger.warning(
                f"Vault would exceed collateral debt ceiling of {ilk.line}")
        under_total_debt_ceiling = debt < self.line()
        if not under_total_debt_ceiling:
            logger.warning(
                f"Vault would exceed total debt ceiling of {self.line()}")
        calm = under_collateral_debt_ceiling and under_total_debt_ceiling

        safe = (urn.art * rate) <= ink * ilk.spot

        assert calm or cool
        assert nice or safe

        assert Rad(ilk_art * rate) >= ilk.dust or (art == Wad(0))
        assert rate != Ray(0)
        assert self.live()
Beispiel #10
0
 def __init__(self, log):
     self.ilk = Ilk.fromBytes(log['args']['ilk'])
     self.urn = Urn(Address(log['args']['urn']))
     self.ink = Wad(log['args']['ink'])
     self.art = Wad(log['args']['art'])
     self.tab = Rad(log['args']['tab'])
     self.flip = Address(log['args']['flip'])
     self.raw = log
Beispiel #11
0
    def simulate_frob(mcd: DssDeployment, collateral: Collateral,
                      address: Address, dink: Wad, dart: Wad):
        assert isinstance(mcd, DssDeployment)
        assert isinstance(collateral, Collateral)
        assert isinstance(address, Address)
        assert isinstance(dink, Wad)
        assert isinstance(dart, Wad)

        urn = mcd.vat.urn(collateral.ilk, address)
        ilk = mcd.vat.ilk(collateral.ilk.name)

        print(
            f"urn.ink={urn.ink}, urn.art={urn.art}, ilk.art={ilk.art}, dink={dink}, dart={dart}"
        )
        ink = urn.ink + dink
        art = urn.art + dart
        ilk_art = ilk.art + dart
        rate = ilk.rate

        gem = mcd.vat.gem(collateral.ilk, urn.address) - dink
        dai = mcd.vat.dai(urn.address) + Rad(rate * dart)
        debt = mcd.vat.debt() + Rad(rate * dart)

        # stablecoin debt does not increase
        cool = dart <= Wad(0)
        # collateral balance does not decrease
        firm = dink >= Wad(0)
        nice = cool and firm

        # CDP remains under both collateral and total debt ceilings
        under_collateral_debt_ceiling = Rad(ilk_art * rate) <= ilk.line
        if not under_collateral_debt_ceiling:
            print(f"CDP would exceed collateral debt ceiling of {ilk.line}")
        under_total_debt_ceiling = debt < mcd.vat.line()
        if not under_total_debt_ceiling:
            print(f"CDP would exceed total debt ceiling of {mcd.vat.line()}")
        calm = under_collateral_debt_ceiling and under_total_debt_ceiling

        safe = (urn.art * rate) <= ink * ilk.spot

        assert calm or cool
        assert nice or safe

        assert Rad(ilk_art * rate) >= ilk.dust or (art == Wad(0))
        assert rate != Ray(0)
        assert mcd.vat.live()
 def test_pack(self, mcd, our_address):
     assert mcd.end.bag(our_address) == Wad(0)
     assert mcd.end.debt() > Rad(0)
     assert mcd.dai.approve(mcd.end.address).transact()
     assert mcd.vat.dai(our_address) >= Rad.from_number(10)
     # FIXME: `pack` fails, possibly because we're passing 0 to `vat.flux`
     assert mcd.end.pack(Wad.from_number(10)).transact()
     assert mcd.end.bag(our_address) == Wad.from_number(10)
Beispiel #13
0
    def test_gem(self, our_address: Address, d: DssDeployment):
        collateral = d.collaterals[0]

        # when
        assert collateral.adapter.join(Urn(our_address), Wad(10)).transact()

        # then
        assert d.vat.gem(collateral.ilk, our_address) == Rad(Wad(10))
Beispiel #14
0
    def reconcile_debt(self, joy: Rad, ash: Rad, woe: Rad):
        assert isinstance(joy, Rad)
        assert isinstance(ash, Rad)
        assert isinstance(woe, Rad)

        if ash > Rad(0):
            if joy > ash:
                self.vow.kiss(ash).transact(gas_price=self.gas_price)
            else:
                self.vow.kiss(joy).transact(gas_price=self.gas_price)
                return
        if woe > Rad(0):
            joy = self.vat.dai(self.vow.address)
            if joy > woe:
                self.vow.heal(woe).transact(gas_price=self.gas_price)
            else:
                self.vow.heal(joy).transact(gas_price=self.gas_price)
Beispiel #15
0
        def __init__(self, lognote: LogNote):
            assert isinstance(lognote, LogNote)

            self.src = Address(Web3.toHex(lognote.arg1)[26:])
            self.dst = Address(Web3.toHex(lognote.arg2)[26:])
            self.dart = Rad(int.from_bytes(lognote.get_bytes_at_index(2), byteorder="big", signed=True))
            self.block = lognote.block
            self.tx_hash = lognote.tx_hash
Beispiel #16
0
def max_dart(mcd: DssDeployment, collateral: Collateral,
             our_address: Address) -> Wad:
    assert isinstance(mcd, DssDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(our_address, Address)

    urn = mcd.vat.urn(collateral.ilk, our_address)
    ilk = mcd.vat.ilk(collateral.ilk.name)

    # change in art = (collateral balance * collateral price with safety margin) - CDP's stablecoin debt
    dart = urn.ink * ilk.spot - Wad(Ray(urn.art) * ilk.rate)

    # change in debt must also take the rate into account
    dart = dart * Wad(Ray.from_number(1) / ilk.rate)

    # prevent the change in debt from exceeding the collateral debt ceiling
    if (Rad(urn.art) + Rad(dart)) >= ilk.line:
        print("max_dart is avoiding collateral debt ceiling")
        dart = Wad(ilk.line - Rad(urn.art))

    # prevent the change in debt from exceeding the total debt ceiling
    debt = mcd.vat.debt() + Rad(ilk.rate * dart)
    line = Rad(ilk.line)
    if (debt + Rad(dart)) >= line:
        print("max_dart is avoiding total debt ceiling")
        dart = Wad(debt - Rad(urn.art))

    assert dart > Wad(0)
    return dart
Beispiel #17
0
def max_dart(mcd: DssDeployment, collateral: Collateral, our_address: Address) -> Wad:
    """Determines how much stablecoin should be reserved in an `urn` to make it as poorly collateralized as
    possible, such that a small change to the collateral price could trip the liquidation ratio."""
    assert isinstance(mcd, DssDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(our_address, Address)

    urn = mcd.vat.urn(collateral.ilk, our_address)
    ilk = mcd.vat.ilk(collateral.ilk.name)

    # change in art = (collateral balance * collateral price with safety margin) - CDP's stablecoin debt
    dart = urn.ink * ilk.spot - Wad(Ray(urn.art) * ilk.rate)

    # change in debt must also take the rate into account
    dart = dart * Wad(Ray.from_number(1) / ilk.rate)

    # prevent the change in debt from exceeding the collateral debt ceiling
    if (Rad(urn.art) + Rad(dart)) >= ilk.line:
        print("max_dart is avoiding collateral debt ceiling")
        dart = Wad(ilk.line - Rad(urn.art))

    # prevent the change in debt from exceeding the total debt ceiling
    debt = mcd.vat.debt() + Rad(ilk.rate * dart)
    line = Rad(ilk.line)
    if (debt + Rad(dart)) >= line:
        print("max_dart is avoiding total debt ceiling")
        dart = Wad(debt - Rad(urn.art))

    assert dart > Wad(0)
    return dart
Beispiel #18
0
 def __init__(self, log):
     self.ilk = Ilk.fromBytes(log['args']['ilk'])
     self.urn = Urn(Address(log['args']['urn']))
     self.ink = Wad(log['args']['ink'])
     self.art = Wad(log['args']['art'])
     self.due = Rad(log['args']['due'])
     self.clip = Address(log['args']['clip'])
     self.id = int(log['args']['id'])
     self.raw = log
Beispiel #19
0
def mint_dai(mcd: DssDeployment, amount: Wad, ilkName: str, our_address: Address):
    startingAmount = mcd.dai.balance_of(our_address)
    dai = amount
    # Add collateral to our CDP and draw internal Dai
    collateral=mcd.collaterals[ilkName]
    ilk = mcd.vat.ilk(collateral.ilk.name)
    dink = Wad.from_number(1)
    dart = Wad( Rad(dai) / Rad(ilk.rate))
    wrap_eth(mcd, our_address, dink)
    assert collateral.gem.balance_of(our_address) >= dink
    assert collateral.gem.approve(collateral.adapter.address).transact(from_address=our_address)
    assert collateral.adapter.join(our_address, dink).transact(from_address=our_address)
    frob(mcd, collateral, our_address, dink=dink, dart=dart)

    # Exit to Dai Token and make some checks
    assert mcd.vat.hope(mcd.dai_adapter.address).transact(from_address=our_address)
    assert mcd.dai_adapter.exit(our_address, dai).transact(from_address=our_address)
    assert mcd.dai.balance_of(our_address) == dai + startingAmount
Beispiel #20
0
def repay_urn(mcd, c: Collateral, address: Address) -> bool:
    assert isinstance(c, Collateral)
    assert isinstance(address, Address)
    mcd.approve_dai(address)

    urn = mcd.vat.urn(c.ilk, address)
    if urn.art > Wad(0):
        vat_dai = mcd.vat.dai(address)
        tab: Wad = urn.art * c.ilk.rate
        wipe: Wad = mcd.vat.get_wipe_all_dart(c.ilk, address)
        # if we have any Dai, repay all or part of the urn
        if vat_dai > Rad(0):
            vat_dai = vat_dai / Rad(
                c.ilk.rate)  # adjust for Dai available for repayment
            repay_amount = min(wipe, tab, Wad(vat_dai))
            print(f"wipe={wipe}, tab={tab}, vat_dai={vat_dai}")
            print(f"{c.ilk.name} dust is {float(c.ilk.dust)}")
            print(
                f"repaying {repay_amount} Dai on {c.ilk.name} urn {address}; art={urn.art}"
            )
            assert mcd.vat.frob(c.ilk, address, Wad(0), repay_amount *
                                -1).transact(from_address=address)
            urn = mcd.vat.urn(c.ilk, address)
        else:
            print(f"{address} has no Dai to repay tab of {float(tab)}")
    else:
        print(f"{c.ilk.name} urn {address} has no debt")

    min_ink = Wad(Ray(urn.art) * c.ilk.rate / c.ilk.spot) + Wad(1)
    if urn.ink > min_ink:
        ink_to_withdraw = urn.ink - min_ink
        print(
            f"withdrawing {float(ink_to_withdraw)} {c.ilk.name} from urn {address}"
        )
        assert mcd.vat.frob(c.ilk, address, ink_to_withdraw * -1,
                            Wad(0)).transact(from_address=address)
        urn = mcd.vat.urn(c.ilk, address)

    if urn.ink == Wad(0) and urn.art == Wad(0):
        print(f"{c.ilk.name} urn {address} was fully repaid")
        return True
    else:
        print(f"{c.ilk.name} urn {address} left ink={urn.ink} art={urn.art}")
        return False
Beispiel #21
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.flipper.bids(id)

        # dent phase
        if bid.bid == bid.tab:
            our_lot = Wad(bid.bid / Rad(price))
            if our_lot < self.min_lot:
                self.logger.debug(
                    f"dent lot {our_lot} less than minimum {self.min_lot} for auction {id}"
                )
                return None, None, None

            if (our_lot * self.beg <= bid.lot) and (our_lot < bid.lot):
                return price, self.flipper.dent(id, our_lot, bid.bid), bid.bid
            else:
                self.logger.debug(
                    f"dent lot {our_lot} would not exceed the bid increment for auction {id}"
                )
                return None, None, None

        # tend phase
        else:
            if bid.lot < self.min_lot:
                self.logger.debug(
                    f"tend lot {bid.lot} less than minimum {self.min_lot} for auction {id}"
                )
                return None, None, None

            our_bid = Rad.min(Rad(bid.lot) * price, bid.tab)
            our_price = price if our_bid < bid.tab else Wad(bid.bid) / bid.lot

            if (our_bid >= bid.bid * self.beg
                    or our_bid == bid.tab) and our_bid > bid.bid:
                return our_price, self.flipper.tend(id, bid.lot,
                                                    our_bid), Rad(our_bid)
            else:
                self.logger.debug(
                    f"tend bid {our_bid} would not exceed the bid increment for auction {id}"
                )
                return None, None, None
Beispiel #22
0
 def status(self, id: int) -> (bool, Ray, Wad, Rad):
     """Indicates current state of the auction
     Args:
         id: Auction identifier.
     """
     assert isinstance(id, int)
     (needs_redo, price, lot, tab) = self._contract.functions.getStatus(id).call()
     logging.debug(f"Auction {id} {'needs redo ' if needs_redo else ''}with price={float(Ray(price))} " 
                   f"lot={float(Wad(lot))} tab={float(Rad(tab))}")
     return needs_redo, Ray(price), Wad(lot), Rad(tab)
Beispiel #23
0
    def test_ilk(self, mcd):
        assert mcd.vat.ilk('XXX') == Ilk('XXX',
                                         rate=Ray(0), ink=Wad(0), art=Wad(0), spot=Ray(0), line=Rad(0), dust=Rad(0))

        ilk = mcd.collaterals["ETH-C"].ilk
        assert ilk.line == Rad.from_number(15000000)
        assert ilk.dust == Rad(0)

        representation = repr(ilk)
        assert "ETH-C" in representation
Beispiel #24
0
    def test_move(self, mcd, our_address, other_address):
        # given
        collateral = mcd.collaterals['ETH-A']
        collateral.approve(our_address)
        our_urn = mcd.vat.urn(collateral.ilk, our_address)
        wrap_eth(mcd, our_address, Wad(10))
        assert collateral.adapter.join(our_address, Wad(3)).transact()
        assert mcd.vat.frob(collateral.ilk, our_address, Wad(3), Wad(10)).transact()
        other_balance_before = mcd.vat.dai(other_address)

        # when
        assert mcd.vat.move(our_address, other_address, Rad(Wad(10))).transact()

        # then
        other_balance_after = mcd.vat.dai(other_address)
        assert other_balance_before + Rad(Wad(10)) == other_balance_after

        # rollback
        cleanup_urn(mcd, collateral, our_address)
Beispiel #25
0
    def can_bite(self, ilk: Ilk, urn: Urn) -> bool:
        """ Determine whether a vault can be liquidated

        Args:
            ilk: Collateral type
            urn: Identifies the vault holder or proxy
        """
        assert isinstance(ilk, Ilk)
        assert isinstance(urn, Urn)
        ilk = self.vat.ilk(ilk.name)
        urn = self.vat.urn(ilk, urn.address)
        rate = ilk.rate

        # Collateral value should be less than the product of our stablecoin debt and the debt multiplier
        safe = Ray(urn.ink) * ilk.spot >= Ray(urn.art) * rate
        if safe:
            return False

        # Ensure there's room in the litter box
        box: Rad = self.box()
        litter: Rad = self.litter()
        room: Rad = box - litter
        if litter >= box:
            logger.debug(
                f"biting {urn.address} would exceed maximum Dai out for liquidation"
            )
            return False
        if room < ilk.dust:
            return False

        # Prevent null auction (ilk.dunk [Rad], ilk.rate [Ray], ilk.chop [Wad])
        assert self.chop(ilk) > Wad(
            0
        )  # ensure liquidations are enabled and this uses flipper instead of clipper
        dart: Wad = min(
            urn.art,
            Wad(
                min(self.dunk(ilk), room) / Rad(ilk.rate) /
                Rad(self.chop(ilk))))
        dink: Wad = min(urn.ink, urn.ink * dart / urn.art)

        return dart > Wad(0) and dink > Wad(0)
Beispiel #26
0
def print_missed_flops():
    total = 0
    for i in range(mcd.flopper.kicks()):
        auction = mcd.flopper.bids(i)
        if auction.bid != Rad(0):
            total += 1
            print(
                f"id={i}, bid={auction.bid}, lot={auction.lot}, guy={auction.guy}"
            )
    print(
        f"{total} flops were missed, accounting for {str(mcd.vow.sump()*total)[:9]} Dai in debt"
    )
Beispiel #27
0
def open_cdp(mcd: DssDeployment, collateral: Collateral, address: Address, debtMultiplier: int = 1):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(address, Address)

    collateral.approve(address)
    wrap_eth(mcd, address, Wad.from_number(20))
    assert collateral.adapter.join(address, Wad.from_number(20)).transact(from_address=address)
    frob(mcd, collateral, address, Wad.from_number(20), Wad.from_number(20 * debtMultiplier))

    assert mcd.vat.debt() >= Rad(Wad.from_number(20 * debtMultiplier))
    assert mcd.vat.dai(address) >= Rad.from_number(20 * debtMultiplier)
Beispiel #28
0
    def take_with_dai(self, id: int, price: Ray, address: Address):
        assert isinstance(id, int)
        assert isinstance(price, Ray)
        assert isinstance(address, Address)

        lot = self.clipper.sales(id).lot
        assert lot > Wad(0)

        cost = Wad(price * Ray(lot))
        logging.debug(f"reserving {cost} Dai to bid on auction {id}")
        reserve_dai(self.mcd, self.dai_collateral, address, cost)
        assert self.mcd.vat.dai(address) >= Rad(cost)

        logging.debug(f"attempting to take clip {id} at {price}")
        self.clipper.validate_take(id, lot, price, address)
        assert self.clipper.take(id, lot, price, address).transact(from_address=address)

        # confirm that take finished the auction
        (needs_redo, auction_price, lot, tab) = self.clipper.status(id)
        assert not needs_redo
        assert lot == Wad(0) or tab == Rad(0)
Beispiel #29
0
    def can_bite(self, ilk: Ilk, urn: Urn, box: Rad, dunk: Rad, chop: Wad) -> bool:
        # Typechecking intentionally omitted to improve performance
        rate = ilk.rate

        # Collateral value should be less than the product of our stablecoin debt and the debt multiplier
        safe = Ray(urn.ink) * ilk.spot >= Ray(urn.art) * rate
        if safe:
            return False

        # Ensure there's room in the litter box
        litter = self.cat.litter()
        room: Rad = box - litter
        if litter >= box:
            return False
        if room < ilk.dust:
            return False

        # Prevent null auction (ilk.dunk [Rad], ilk.rate [Ray], ilk.chop [Wad])
        dart: Wad = min(urn.art, Wad(min(dunk, room) / Rad(ilk.rate) / Rad(chop)))
        dink: Wad = min(urn.ink, urn.ink * dart / urn.art)
        return dart > Wad(0) and dink > Wad(0)
Beispiel #30
0
    def bids(self, id: int) -> Bid:
        """Returns the auction details.

        Args:
            id: Auction identifier.

        Returns:
            The auction details.
        """
        assert(isinstance(id, int))

        array = self._contract.call().bids(id)

        return Flipper.Bid(bid=Rad(array[0]),
                           lot=Wad(array[1]),
                           guy=Address(array[2]),
                           tic=int(array[3]),
                           end=int(array[4]),
                           usr=Address(array[5]),
                           gal=Address(array[6]),
                           tab=Rad(array[7]))