Пример #1
0
def create_surplus(mcd: DssDeployment, flapper: Flapper,
                   deployment_address: Address):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(flapper, Flapper)
    assert isinstance(deployment_address, Address)

    joy = mcd.vat.dai(mcd.vow.address)
    if joy < mcd.vat.sin(mcd.vow.address) + mcd.vow.hump() + mcd.vow.bump():
        print('Creating a vault with surplus')
        collateral = mcd.collaterals['ETH-C']
        ink = Wad.from_number(200)
        wrap_eth(mcd, deployment_address, ink)
        collateral.approve(deployment_address)
        assert collateral.adapter.join(
            deployment_address, ink).transact(from_address=deployment_address)
        frob(mcd,
             collateral,
             deployment_address,
             dink=ink,
             dart=Wad.from_number(15000))
        assert mcd.jug.drip(
            collateral.ilk).transact(from_address=deployment_address)
        joy = mcd.vat.dai(mcd.vow.address)
        # total surplus > total debt + surplus auction lot size + surplus buffer
        assert float(joy) > float(mcd.vat.sin(mcd.vow.address)) + float(
            mcd.vow.bump()) + float(mcd.vow.hump())
    else:
        print(f'Surplus of {joy} already exists; skipping CDP creation')
def create_dai_token(mcd: DssDeployment, our_address: Address):
    collateral = mcd.collaterals['ETH-B']
    ilk = collateral.ilk
    # TestVat.ensure_clean_urn(mcd, collateral, our_address)
    initial_dai = mcd.vat.dai(our_address)
    wrap_eth(mcd, our_address, Wad.from_number(9))

    # Ensure our collateral enters the urn
    collateral_balance_before = collateral.gem.balance_of(our_address)
    collateral.approve(our_address)
    assert collateral.adapter.join(our_address, Wad.from_number(9)).transact()
    assert collateral.gem.balance_of(our_address) == collateral_balance_before - Wad.from_number(9)

    # Add collateral without generating Dai
    frob(mcd, collateral, our_address, dink=Wad.from_number(3), dart=Wad(0))
    print(f"After adding collateral:         {mcd.vat.urn(ilk, our_address)}")
    assert mcd.vat.urn(ilk, our_address).ink == Wad.from_number(3)
    assert mcd.vat.urn(ilk, our_address).art == Wad(0)
    assert mcd.vat.gem(ilk, our_address) == Wad.from_number(9) - mcd.vat.urn(ilk, our_address).ink
    assert mcd.vat.dai(our_address) == initial_dai

    # Generate some Dai
    frob(mcd, collateral, our_address, dink=Wad(0), dart=Wad.from_number(153))
    print(f"After generating dai:            {mcd.vat.urn(ilk, our_address)}")
    assert mcd.vat.urn(ilk, our_address).ink == Wad.from_number(3)
    assert mcd.vat.urn(ilk, our_address).art == Wad.from_number(153)
    assert mcd.vat.dai(our_address) == initial_dai + Rad.from_number(153)
    assert mcd.vat.hope(mcd.dai_adapter.address).transact(from_address=our_address)
    assert mcd.dai_adapter.exit(our_address, Wad.from_number(153)).transact(from_address=our_address)
    assert mcd.dai.balance_of(our_address) == Wad.from_number(153)
Пример #3
0
def create_surplus(mcd: DssDeployment, flapper: Flapper,
                   deployment_address: Address):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(flapper, Flapper)
    assert isinstance(deployment_address, Address)

    joy = mcd.vat.dai(mcd.vow.address)

    if joy < mcd.vow.hump() + mcd.vow.bump():
        # Create a CDP with surplus
        print('Creating a CDP with surplus')
        collateral = mcd.collaterals['ETH-B']
        assert flapper.kicks() == 0
        wrap_eth(mcd, deployment_address, Wad.from_number(0.1))
        collateral.approve(deployment_address)
        assert collateral.adapter.join(
            deployment_address,
            Wad.from_number(0.1)).transact(from_address=deployment_address)
        frob(mcd,
             collateral,
             deployment_address,
             dink=Wad.from_number(0.1),
             dart=Wad.from_number(10))
        assert mcd.jug.drip(
            collateral.ilk).transact(from_address=deployment_address)
        joy = mcd.vat.dai(mcd.vow.address)
        assert joy >= mcd.vow.hump() + mcd.vow.bump()
    else:
        print(f'Surplus of {joy} already exists; skipping CDP creation')
Пример #4
0
def wipe_debt(mcd: DssDeployment, collateral: Collateral, address: Address):
    urn = mcd.vat.urn(collateral.ilk, address)
    assert Rad(urn.art) >= mcd.vat.dai(address)
    dink = Ray(mcd.vat.dai(address)) / mcd.vat.ilk(collateral.ilk.name).rate
    frob(mcd, collateral, address, Wad(0),
         Wad(dink) * -1)  #because there is residual state on the testchain
    assert mcd.vat.dai(address) <= Rad(
        Wad(1))  # pesky dust amount in Dai amount
Пример #5
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)
def test_join_and_exit(dsr):
    proxy = dsr.get_proxy()
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)

    mcd = dsr.mcd

    # Create a CDP
    collateral = mcd.collaterals['ETH-A']
    wrap_eth(mcd, dsr.owner, Wad.from_number(1))
    collateral.approve(dsr.owner)
    assert collateral.adapter.join(
        dsr.owner, Wad.from_number(1)).transact(from_address=dsr.owner)
    frob(mcd, collateral, dsr.owner, dink=Wad.from_number(1), dart=Wad(0))
    dart = max_dart(mcd, collateral, dsr.owner) - Wad(1)
    frob(mcd, collateral, dsr.owner, dink=Wad(0), dart=dart)

    # Mint and withdraw all the Dai
    mcd.approve_dai(dsr.owner)
    assert mcd.dai_adapter.exit(dsr.owner,
                                dart).transact(from_address=dsr.owner)
    assert mcd.dai.balance_of(dsr.owner) == dart

    intial_dai_balance = mcd.dai.balance_of(dsr.owner)
    assert intial_dai_balance > Wad.from_number(0)
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)

    # approve Proxy to use 100 DAI from account
    mcd.dai.approve(proxy.address,
                    Wad.from_number(100)).transact(from_address=dsr.owner)

    # join 100 DAI in DSR
    dsr.join(Wad.from_number(100), proxy).transact(from_address=dsr.owner)
    assert mcd.dai.balance_of(
        dsr.owner) == intial_dai_balance - Wad.from_number(100)
    assert round(dsr.get_balance(proxy.address)) == Wad.from_number(100)

    # exit 33 DAI from DSR
    dsr.exit(Wad.from_number(33), proxy).transact(from_address=dsr.owner)
    assert round(
        mcd.dai.balance_of(dsr.owner)
    ) == round(intial_dai_balance) - Wad.from_number(100) + Wad.from_number(33)
    assert round(dsr.get_balance(proxy.address)) == Wad.from_number(67)

    # exit remaining DAI from DSR
    dsr.exit_all(proxy).transact(from_address=dsr.owner)
    assert round(mcd.dai.balance_of(dsr.owner)) == round(intial_dai_balance)
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)
Пример #7
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
Пример #8
0
def create_debt(web3: Web3, mcd: DssDeployment, our_address: Address, deployment_address: Address):
    assert isinstance(web3, Web3)
    assert isinstance(mcd, DssDeployment)
    assert isinstance(our_address, Address)
    assert isinstance(deployment_address, Address)

    # Create a vault
    collateral = mcd.collaterals['ETH-A']
    ilk = collateral.ilk
    wrap_eth(mcd, deployment_address, Wad.from_number(1))
    collateral.approve(deployment_address)
    assert collateral.adapter.join(deployment_address, Wad.from_number(1)).transact(
        from_address=deployment_address)
    frob(mcd, collateral, deployment_address, dink=Wad.from_number(1), dart=Wad(0))
    dart = max_dart(mcd, collateral, deployment_address) - Wad(1)
    frob(mcd, collateral, deployment_address, dink=Wad(0), dart=dart)
    assert not mcd.cat.can_bite(ilk, mcd.vat.urn(collateral.ilk, deployment_address))

    # Undercollateralize by dropping the spot price, and then bite the vault
    to_price = Wad(Web3.toInt(collateral.pip.read())) / Wad.from_number(2)
    set_collateral_price(mcd, collateral, to_price)
    urn = mcd.vat.urn(collateral.ilk, deployment_address)
    assert urn.ink is not None and urn.art is not None
    assert ilk.spot is not None
    safe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate <= Ray(urn.ink) * ilk.spot
    assert not safe
    assert mcd.cat.can_bite(collateral.ilk, urn)
    assert mcd.cat.bite(collateral.ilk, urn).transact()
    flip_kick = collateral.flipper.kicks()

    # Generate some Dai, bid on and win the flip auction without covering all the debt
    wrap_eth(mcd, our_address, Wad.from_number(10))
    collateral.approve(our_address)
    assert collateral.adapter.join(our_address, Wad.from_number(10)).transact(from_address=our_address)
    web3.eth.defaultAccount = our_address.address
    frob(mcd, collateral, our_address, dink=Wad.from_number(10), dart=Wad.from_number(200))
    collateral.flipper.approve(mcd.vat.address, approval_function=hope_directly())
    current_bid = collateral.flipper.bids(flip_kick)
    urn = mcd.vat.urn(collateral.ilk, our_address)
    assert Rad(urn.art) > current_bid.tab
    bid = Rad.from_number(6)
    TestFlipper.tend(collateral.flipper, flip_kick, our_address, current_bid.lot, bid)
    mcd.vat.can(our_address, collateral.flipper.address)
    wait(mcd, our_address, collateral.flipper.ttl()+1)
    assert collateral.flipper.deal(flip_kick).transact()

    # Raise debt from the queue (note that vow.wait is 0 on our testchain)
    bites = mcd.cat.past_bites(100)
    for bite in bites:
        era_bite = bite.era(web3)
        assert era_bite > int(datetime.now().timestamp()) - 120
        assert mcd.vow.sin_of(era_bite) > Rad(0)
        assert mcd.vow.flog(era_bite).transact()
        assert mcd.vow.sin_of(era_bite) == Rad(0)
    # Cancel out surplus and debt
    dai_vow = mcd.vat.dai(mcd.vow.address)
    assert dai_vow <= mcd.vow.woe()
    assert mcd.vow.heal(dai_vow).transact()
    assert mcd.vow.woe() >= mcd.vow.sump()
Пример #9
0
def create_flip_auction(mcd: DssDeployment, deployment_address: Address,
                        our_address: Address):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(our_address, Address)
    assert isinstance(deployment_address, Address)

    # Create a CDP
    collateral = mcd.collaterals['ETH-A']
    ilk = collateral.ilk
    wrap_eth(mcd, deployment_address, Wad.from_number(1))
    collateral.approve(deployment_address)
    assert collateral.adapter.join(
        deployment_address,
        Wad.from_number(1)).transact(from_address=deployment_address)
    frob(mcd,
         collateral,
         deployment_address,
         dink=Wad.from_number(1),
         dart=Wad(0))
    dart = max_dart(mcd, collateral, deployment_address) - Wad(1)
    frob(mcd, collateral, deployment_address, dink=Wad(0), dart=dart)

    # Undercollateralize and bite the CDP
    to_price = Wad(mcd.web3.toInt(collateral.pip.read())) / Wad.from_number(2)
    set_collateral_price(mcd, collateral, to_price)
    urn = mcd.vat.urn(collateral.ilk, deployment_address)
    ilk = mcd.vat.ilk(ilk.name)
    safe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate <= Ray(urn.ink) * ilk.spot
    assert not safe
    assert mcd.cat.can_bite(collateral.ilk, Urn(deployment_address))
    assert mcd.cat.bite(collateral.ilk, Urn(deployment_address)).transact()
    flip_kick = collateral.flipper.kicks()

    # Generate some Dai, bid on the flip auction without covering all the debt
    wrap_eth(mcd, our_address, Wad.from_number(10))
    collateral.approve(our_address)
    assert collateral.adapter.join(
        our_address, Wad.from_number(10)).transact(from_address=our_address)
    mcd.web3.eth.defaultAccount = our_address.address
    frob(mcd,
         collateral,
         our_address,
         dink=Wad.from_number(10),
         dart=Wad.from_number(200))
    collateral.flipper.approve(mcd.vat.address,
                               approval_function=hope_directly())
    current_bid = collateral.flipper.bids(flip_kick)
    urn = mcd.vat.urn(collateral.ilk, our_address)
    assert Rad(urn.art) > current_bid.tab
    bid = Rad.from_number(6)
    tend(collateral.flipper, flip_kick, our_address, current_bid.lot, bid)
Пример #10
0
def test_join_and_exit(dsr):
    proxy = dsr.get_proxy()
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)

    mcd = dsr.mcd

    # create a vault
    collateral = mcd.collaterals['ETH-C']
    wrap_eth(mcd, dsr.owner, Wad.from_number(2))
    collateral.approve(dsr.owner)
    assert collateral.adapter.join(dsr.owner, Wad.from_number(2)).transact(from_address=dsr.owner)
    frob(mcd, collateral, dsr.owner, dink=Wad.from_number(2), dart=Wad(0))
    dart = Wad.from_number(100)
    frob(mcd, collateral, dsr.owner, dink=Wad(0), dart=dart)

    # mint and withdraw all the Dai
    mcd.approve_dai(dsr.owner)
    assert mcd.dai_adapter.exit(dsr.owner, dart).transact(from_address=dsr.owner)
    assert mcd.dai.balance_of(dsr.owner) == dart

    initial_dai_balance = mcd.dai.balance_of(dsr.owner)
    assert initial_dai_balance >= Wad.from_number(100)
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)

    # approve Proxy to use 100 DAI from account
    mcd.dai.approve(proxy.address, Wad.from_number(100)).transact(from_address=dsr.owner)

    # join 100 DAI in DSR
    assert dsr.join(Wad.from_number(100), proxy).transact(from_address=dsr.owner)
    assert mcd.dai.balance_of(dsr.owner) == initial_dai_balance - Wad.from_number(100)
    assert round(dsr.get_balance(proxy.address)) == Wad.from_number(100)
    assert mcd.pot.drip().transact()

    # exit 33 DAI from DSR
    assert dsr.exit(Wad.from_number(33), proxy).transact(from_address=dsr.owner)
    assert round(mcd.dai.balance_of(dsr.owner)) == round(initial_dai_balance) - Wad.from_number(100) + Wad.from_number(33)
    assert round(dsr.get_balance(proxy.address)) == Wad.from_number(67)
    assert mcd.pot.drip().transact()

    # exit remaining DAI from DSR and join to vat
    assert dsr.exit_all(proxy).transact(from_address=dsr.owner)
    assert round(mcd.dai.balance_of(dsr.owner)) == round(initial_dai_balance)
    assert dsr.get_balance(proxy.address) == Wad.from_number(0)
    assert mcd.dai_adapter.join(dsr.owner, mcd.dai.balance_of(dsr.owner)).transact(from_address=dsr.owner)

    # repay the vault
    assert collateral.ilk.dust == Rad(0)
    wipe: Wad = mcd.vat.get_wipe_all_dart(collateral.ilk, dsr.owner)
    frob(mcd, collateral, dsr.owner, dink=Wad(0), dart=wipe*-1)
Пример #11
0
    def test_scenario(self, web3, mcd, collateral, clipper, our_address,
                      other_address, deployment_address):
        dirt_before = mcd.dog.dog_dirt()
        vice_before = mcd.vat.vice()
        sin_before = mcd.vow.sin()

        # Create a vault
        ilk = collateral.ilk
        ink = Wad.from_number(1)
        wrap_eth(mcd, deployment_address, ink)
        collateral.approve(deployment_address)
        assert collateral.adapter.join(
            deployment_address, ink).transact(from_address=deployment_address)
        frob(mcd, collateral, deployment_address, dink=ink, dart=Wad(0))
        dart = max_dart(mcd, collateral, deployment_address) - Wad(1)
        frob(mcd, collateral, deployment_address, dink=Wad(0), dart=dart)

        # Mint and withdraw all the Dai
        mcd.approve_dai(deployment_address)
        assert mcd.dai_adapter.exit(
            deployment_address, dart).transact(from_address=deployment_address)

        # Undercollateralize the vault
        to_price = Wad(Web3.toInt(collateral.pip.read())) / Wad.from_number(2)
        set_collateral_price(mcd, collateral, to_price)
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        ilk = mcd.vat.ilk(ilk.name)
        safe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate <= Ray(
            urn.ink) * ilk.spot
        assert not safe
        assert clipper.active_count() == 0

        # Bark the vault, which moves debt to the vow and kicks the clipper
        dai_before_bark: Rad = mcd.vat.dai(our_address)
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        assert urn.ink > Wad(0)
        tab = urn.art * ilk.rate  # Wad
        assert tab == dart
        assert mcd.dog.bark(ilk, urn).transact()
        barks = mcd.dog.past_barks(1)
        assert len(barks) == 1
        last_bite = barks[0]
        assert last_bite.due > Rad(0)
        assert clipper.active_count() == 1
        kick = clipper.kicks()
        assert kick == 1
        assert len(clipper.active_auctions()) == 1
        assert clipper.active_auctions()[0].id == 1
        assert mcd.active_auctions()['clips']['ETH-B'][0].id == 1
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        (needs_redo, price, lot, tab) = clipper.status(kick)
        assert not needs_redo
        assert price == Ray.from_number(172.5)
        assert lot == ink
        assert float(tab) == 105.0
        # Check vat, vow, and dog
        assert urn.ink == Wad(0)
        assert vice_before < mcd.vat.vice()
        assert sin_before < mcd.vow.sin()
        assert dirt_before < mcd.dog.dog_dirt()
        # Check the clipper
        current_sale = clipper.sales(kick)
        assert isinstance(current_sale, Clipper.Sale)
        assert current_sale.pos == 0
        assert float(current_sale.tab) == 105.0
        assert current_sale.lot == ink
        assert current_sale.usr == deployment_address
        assert current_sale.tic > 0
        assert round(current_sale.top, 1) == price
        coin = Rad(clipper.tip() + (current_sale.tab * clipper.chip()))
        # Confirm we received our liquidation reward
        dai_after_bark: Rad = mcd.vat.dai(our_address)
        assert dai_after_bark == dai_before_bark + coin
        kick_log = self.last_log(clipper)
        assert isinstance(kick_log, Clipper.KickLog)
        assert kick_log.id == kick
        assert kick_log.top == current_sale.top
        assert kick_log.tab == current_sale.tab
        assert kick_log.lot == current_sale.lot
        assert kick_log.usr == deployment_address
        assert kick_log.kpr == our_address
        assert kick_log.coin == coin

        # Wrap some eth and handle approvals before bidding
        eth_required = Wad(
            current_sale.tab / Rad(ilk.spot)) * Wad.from_number(1.1)
        wrap_eth(mcd, our_address, eth_required)
        collateral.approve(our_address)
        assert collateral.adapter.join(
            our_address, eth_required).transact(from_address=our_address)
        clipper.approve(
            mcd.vat.address,
            approval_function=hope_directly(from_address=our_address))

        # Ensure we cannot take collateral below the current price
        (needs_redo, price, lot, tab) = clipper.status(kick)
        with pytest.raises(AssertionError):
            clipper.validate_take(kick, ink, price - Ray.from_number(1))
        assert not clipper.take(
            kick, ink, Ray.from_number(140)).transact(from_address=our_address)

        # Take some collateral with max above the top price
        clipper.validate_take(kick, Wad.from_number(0.07),
                              Ray.from_number(180))
        assert web3.eth.defaultAccount == our_address.address
        assert clipper.take(
            kick, Wad.from_number(0.07),
            Ray.from_number(180)).transact(from_address=our_address)
        (needs_redo, price, lot, tab) = clipper.status(kick)
        assert not needs_redo
        current_sale = clipper.sales(kick)
        assert current_sale.lot > Wad(0)
        assert current_sale.top > price
        assert Rad(0) < current_sale.tab < kick_log.tab
        first_take_log = self.last_log(clipper)
        assert first_take_log.id == 1
        assert first_take_log.max == Ray.from_number(180)
        assert first_take_log.price == price
        assert first_take_log.lot == current_sale.lot
        assert first_take_log.usr == deployment_address
        assert first_take_log.sender == our_address
        assert round(first_take_log.owe,
                     18) == round(Rad.from_number(0.07) * Rad(price), 18)

        # Allow the auction to expire, and then resurrect it
        # TODO: If abaci contract is ever wrapped, read tau from it
        time_travel_by(web3, 24)
        (needs_redo, price, lot, tab) = clipper.status(kick)
        assert needs_redo
        assert len(clipper.active_auctions()) == clipper.active_count()
        assert clipper.redo(kick, our_address).transact()
        (needs_redo, price, lot, tab) = clipper.status(kick)
        assert not needs_redo
        current_sale = clipper.sales(kick)
        assert current_sale.lot > Wad(0)
        redo_log = self.last_log(clipper)
        assert isinstance(redo_log, Clipper.RedoLog)
        assert redo_log.id == kick
        assert redo_log.top == current_sale.top
        assert redo_log.tab == current_sale.tab
        assert redo_log.lot == current_sale.lot
        assert redo_log.usr == deployment_address
        assert redo_log.kpr == our_address
        coin = Rad(clipper.tip() + (current_sale.tab * clipper.chip()))
        assert round(float(redo_log.coin), 18) == round(float(coin), 18)

        # Sleep until price has gone down enough to bid with remaining Dai
        dai = mcd.vat.dai(our_address)
        last_price = price
        print(
            f"Bid cost={float(price * Ray(current_sale.lot))}, Dai balance={float(dai)}"
        )
        while price * Ray(current_sale.lot) > Ray(dai):
            print(
                f"Bid cost {price * Ray(current_sale.lot)} exceeds Dai balance {dai}"
            )
            time_travel_by(web3, 2)
            (needs_redo, price, lot, tab) = clipper.status(kick)
            assert price < last_price
            assert not needs_redo
            last_price = price
        clipper.validate_take(kick, current_sale.lot, price)
        assert clipper.take(kick, current_sale.lot,
                            price).transact(from_address=our_address)
        current_sale = clipper.sales(kick)
        assert current_sale.lot == Wad(0)
        assert current_sale.tab == Rad(0)
        assert clipper.active_count() == 0
        assert len(clipper.active_auctions()) == 0

        # Ensure we can retrieve our collateral
        collateral_before = collateral.gem.balance_of(our_address)
        assert collateral.adapter.exit(our_address,
                                       ink).transact(from_address=our_address)
        collateral_after = collateral.gem.balance_of(our_address)
        assert collateral_before < collateral_after

        # Cleanup
        set_collateral_price(mcd, collateral, Wad.from_number(230))
        cleanup_urn(mcd, collateral, our_address)
Пример #12
0
    def test_scenario(self, web3, mcd, collateral, flipper, our_address,
                      other_address, deployment_address):
        # Create a vault
        kicks_before = flipper.kicks()
        ilk = collateral.ilk
        ink = Wad.from_number(0.5)
        wrap_eth(mcd, deployment_address, ink)
        collateral.approve(deployment_address)
        assert collateral.adapter.join(
            deployment_address, ink).transact(from_address=deployment_address)
        frob(mcd, collateral, deployment_address, dink=ink, dart=Wad(0))
        dart = max_dart(mcd, collateral, deployment_address) - Wad(1)
        frob(mcd, collateral, deployment_address, dink=Wad(0), dart=dart)

        # Mint and withdraw all the Dai
        mcd.approve_dai(deployment_address)
        assert mcd.dai_adapter.exit(
            deployment_address, dart).transact(from_address=deployment_address)
        assert mcd.dai.balance_of(deployment_address) == dart

        # Undercollateralize the vault
        to_price = Wad(Web3.toInt(collateral.pip.read())) / Wad.from_number(2)
        set_collateral_price(mcd, collateral, to_price)
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        ilk = mcd.vat.ilk(ilk.name)
        assert ilk.rate is not None
        assert ilk.spot is not None
        safe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate <= Ray(
            urn.ink) * ilk.spot
        assert not safe
        assert len(flipper.active_auctions()) == 0
        litter_before = mcd.cat.litter()

        # Bite the vault, which moves debt to the vow and kicks the flipper
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        assert urn.ink > Wad(0)
        art = min(urn.art, Wad(mcd.cat.dunk(ilk)))  # Wad
        tab = art * ilk.rate  # Wad
        assert tab == dart
        assert mcd.cat.can_bite(ilk, urn)
        assert mcd.cat.bite(ilk, urn).transact()
        kick = flipper.kicks()
        assert kick == kicks_before + 1
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        # Check vat, vow, and cat
        assert urn.ink == Wad(0)
        assert urn.art == dart - art
        assert mcd.vat.vice() > Rad(0)
        assert mcd.vow.sin() == Rad(tab)
        bites = mcd.cat.past_bites(1)
        assert len(bites) == 1
        last_bite = bites[0]
        assert last_bite.tab > Rad(0)
        assert last_bite.id == 1
        litter_after = mcd.cat.litter()
        assert litter_before < litter_after
        # Check the flipper
        current_bid = flipper.bids(kick)
        assert isinstance(current_bid, Flipper.Bid)
        assert current_bid.lot > Wad(0)
        assert current_bid.tab > Rad(0)
        assert current_bid.bid == Rad(0)
        # Cat doesn't incorporate the liquidation penalty (chop), but the kicker includes it.
        # Awaiting word from @dc why this is so.
        #assert last_bite.tab == current_bid.tab
        log = self.last_log(flipper)
        assert isinstance(log, Flipper.KickLog)
        assert log.id == kick
        assert log.lot == current_bid.lot
        assert log.bid == current_bid.bid
        assert log.tab == current_bid.tab
        assert log.usr == deployment_address
        assert log.gal == mcd.vow.address

        # Allow the auction to expire, and then resurrect it
        time_travel_by(web3, flipper.tau() + 1)
        assert flipper.tick(kick).transact()

        # Wrap some eth and handle approvals before bidding
        eth_required = Wad(
            current_bid.tab / Rad(ilk.spot)) * Wad.from_number(1.13)
        wrap_eth(mcd, other_address, eth_required)
        collateral.approve(other_address)
        assert collateral.adapter.join(
            other_address, eth_required).transact(from_address=other_address)
        wrap_eth(mcd, our_address, eth_required)
        collateral.approve(our_address)
        assert collateral.adapter.join(
            our_address, eth_required).transact(from_address=our_address)

        # Test the _tend_ phase of the auction
        flipper.approve(
            mcd.vat.address,
            approval_function=hope_directly(from_address=other_address))
        # Add Wad(1) to counter precision error converting tab from Rad to Wad
        frob(mcd,
             collateral,
             other_address,
             dink=eth_required,
             dart=Wad(current_bid.tab) + Wad(1))
        urn = mcd.vat.urn(collateral.ilk, other_address)
        assert Rad(urn.art) >= current_bid.tab
        # Bid the tab to instantly transition to dent stage
        TestFlipper.tend(flipper, kick, other_address, current_bid.lot,
                         current_bid.tab)
        current_bid = flipper.bids(kick)
        assert current_bid.guy == other_address
        assert current_bid.bid == current_bid.tab
        assert len(flipper.active_auctions()) == 1
        check_active_auctions(flipper)
        log = self.last_log(flipper)
        assert isinstance(log, Flipper.TendLog)
        assert log.guy == current_bid.guy
        assert log.id == current_bid.id
        assert log.lot == current_bid.lot
        assert log.bid == current_bid.bid

        # Test the _dent_ phase of the auction
        flipper.approve(
            mcd.vat.address,
            approval_function=hope_directly(from_address=our_address))
        frob(mcd,
             collateral,
             our_address,
             dink=eth_required,
             dart=Wad(current_bid.tab) + Wad(1))
        lot = current_bid.lot - Wad.from_number(0.3)
        assert flipper.beg() * lot <= current_bid.lot
        TestFlipper.dent(flipper, kick, our_address, lot, current_bid.tab)
        current_bid = flipper.bids(kick)
        assert current_bid.guy == our_address
        assert current_bid.bid == current_bid.tab
        assert current_bid.lot == lot
        log = self.last_log(flipper)
        assert isinstance(log, Flipper.DentLog)
        assert log.guy == current_bid.guy
        assert log.id == current_bid.id
        assert log.lot == current_bid.lot
        assert log.bid == current_bid.bid

        # Exercise _deal_ after bid has expired
        time_travel_by(web3, flipper.ttl() + 1)
        now = datetime.now().timestamp()
        assert 0 < current_bid.tic < now or current_bid.end < now
        assert flipper.deal(kick).transact(from_address=our_address)
        assert len(flipper.active_auctions()) == 0
        log = self.last_log(flipper)
        assert isinstance(log, Flipper.DealLog)
        assert log.usr == our_address

        # Grab our collateral
        collateral_before = collateral.gem.balance_of(our_address)
        assert collateral.adapter.exit(
            our_address, current_bid.lot).transact(from_address=our_address)
        collateral_after = collateral.gem.balance_of(our_address)
        assert collateral_before < collateral_after

        # Cleanup
        set_collateral_price(mcd, collateral, Wad.from_number(230))
        cleanup_urn(mcd, collateral, other_address)
Пример #13
0
])
mcd = DssDeployment.from_node(web3)
deployment_address = Address("0x00a329c0648769A73afAc7F9381E08FB43dBEA72")

joy = mcd.vat.dai(mcd.vow.address)

if joy < mcd.vow.hump() + mcd.vow.bump():
    # Create a CDP with surplus
    print('Creating a CDP with surplus')
    collateral = mcd.collaterals['ETH-B']
    wrap_eth(mcd, deployment_address, Wad.from_number(0.1))
    collateral.approve(deployment_address)
    assert collateral.adapter.join(
        deployment_address,
        Wad.from_number(0.1)).transact(from_address=deployment_address)
    frob(mcd,
         collateral,
         deployment_address,
         dink=Wad.from_number(0.1),
         dart=Wad.from_number(10))
    assert mcd.jug.drip(
        collateral.ilk).transact(from_address=deployment_address)
    joy = mcd.vat.dai(mcd.vow.address)
    assert joy >= mcd.vow.hump() + mcd.vow.bump()
else:
    print(f'Surplus of {joy} already exists; skipping CDP creation')

mcd.vow.flap().transact()
kick = mcd.flapper.kicks()
print(f"There are {kick} flap auctions kicked")
Пример #14
0
    def test_scenario(self, web3, mcd, collateral, flipper, our_address,
                      other_address, deployment_address):
        # Create a CDP
        collateral = mcd.collaterals['ETH-A']
        kicks_before = flipper.kicks()
        ilk = collateral.ilk
        wrap_eth(mcd, deployment_address, Wad.from_number(1))
        collateral.approve(deployment_address)
        assert collateral.adapter.join(
            deployment_address,
            Wad.from_number(1)).transact(from_address=deployment_address)
        frob(mcd,
             collateral,
             deployment_address,
             dink=Wad.from_number(1),
             dart=Wad(0))
        dart = max_dart(mcd, collateral, deployment_address) - Wad(1)
        frob(mcd, collateral, deployment_address, dink=Wad(0), dart=dart)

        # Mint and withdraw all the Dai
        mcd.approve_dai(deployment_address)
        assert mcd.dai_adapter.exit(
            deployment_address, dart).transact(from_address=deployment_address)
        assert mcd.dai.balance_of(deployment_address) == dart
        assert mcd.vat.dai(deployment_address) == Rad(0)

        # Undercollateralize the CDP
        to_price = Wad(Web3.toInt(collateral.pip.read())) / Wad.from_number(2)
        set_collateral_price(mcd, collateral, to_price)
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        ilk = mcd.vat.ilk(ilk.name)
        assert ilk.rate is not None
        assert ilk.spot is not None
        safe = Ray(urn.art) * mcd.vat.ilk(ilk.name).rate <= Ray(
            urn.ink) * ilk.spot
        assert not safe
        assert len(flipper.active_auctions()) == 0

        # Bite the CDP, which moves debt to the vow and kicks the flipper
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        assert urn.ink > Wad(0)
        lot = min(urn.ink, mcd.cat.lump(ilk))  # Wad
        art = min(urn.art, (lot * urn.art) / urn.ink)  # Wad
        tab = art * ilk.rate  # Wad
        assert tab == dart
        simulate_bite(mcd, collateral, deployment_address)
        assert mcd.cat.bite(collateral.ilk, Urn(deployment_address)).transact()
        kick = flipper.kicks()
        assert kick == kicks_before + 1
        urn = mcd.vat.urn(collateral.ilk, deployment_address)
        # Check vat, vow, and cat
        assert urn.ink == Wad(0)
        assert urn.art == dart - art
        assert mcd.vat.vice() > Rad(0)
        assert mcd.vow.sin() == Rad(tab)
        bites = mcd.cat.past_bite(10)
        assert len(bites) == 1
        last_bite = bites[0]
        assert last_bite.tab > Rad(0)
        # Check the flipper
        current_bid = flipper.bids(kick)
        assert isinstance(current_bid, Flipper.Bid)
        assert current_bid.lot > Wad(0)
        assert current_bid.tab > Rad(0)
        assert current_bid.bid == Rad(0)
        # Cat doesn't incorporate the liquidation penalty (chop), but the kicker includes it.
        # Awaiting word from @dc why this is so.
        #assert last_bite.tab == current_bid.tab

        # Wrap some eth and handle approvals before bidding
        eth_required = Wad(
            current_bid.tab / Rad(ilk.spot)) * Wad.from_number(1.1)
        wrap_eth(mcd, other_address, eth_required)
        collateral.approve(other_address)
        assert collateral.adapter.join(
            other_address, eth_required).transact(from_address=other_address)
        wrap_eth(mcd, our_address, eth_required)
        collateral.approve(our_address)
        assert collateral.adapter.join(
            our_address, eth_required).transact(from_address=our_address)

        # Test the _tend_ phase of the auction
        flipper.approve(
            mcd.vat.address,
            approval_function=hope_directly(from_address=other_address))
        # Add Wad(1) to counter precision error converting tab from Rad to Wad
        frob(mcd,
             collateral,
             other_address,
             dink=eth_required,
             dart=Wad(current_bid.tab) + Wad(1))
        urn = mcd.vat.urn(collateral.ilk, other_address)
        assert Rad(urn.art) >= current_bid.tab
        # Bid the tab to instantly transition to dent stage
        TestFlipper.tend(flipper, kick, other_address, current_bid.lot,
                         current_bid.tab)
        current_bid = flipper.bids(kick)
        assert current_bid.guy == other_address
        assert current_bid.bid == current_bid.tab

        # Test the _dent_ phase of the auction
        flipper.approve(
            mcd.vat.address,
            approval_function=hope_directly(from_address=our_address))
        frob(mcd,
             collateral,
             our_address,
             dink=eth_required,
             dart=Wad(current_bid.tab) + Wad(1))
        lot = current_bid.lot - Wad.from_number(0.2)
        assert flipper.beg() * Ray(lot) <= Ray(current_bid.lot)
        assert mcd.vat.can(our_address, flipper.address)
        TestFlipper.dent(flipper, kick, our_address, lot, current_bid.tab)
        current_bid = flipper.bids(kick)
        assert current_bid.guy == our_address
        assert current_bid.bid == current_bid.tab
        assert current_bid.lot == lot

        # Exercise _deal_ after bid has expired
        wait(mcd, our_address, flipper.ttl() + 1)
        now = datetime.now().timestamp()
        assert 0 < current_bid.tic < now or current_bid.end < now
        assert flipper.deal(kick).transact(from_address=our_address)
        assert len(flipper.active_auctions()) == 0

        # Grab our collateral
        collateral_before = collateral.gem.balance_of(our_address)
        assert collateral.adapter.exit(
            our_address, current_bid.lot).transact(from_address=our_address)
        collateral_after = collateral.gem.balance_of(our_address)
        assert collateral_before < collateral_after

        # Cleanup
        set_collateral_price(mcd, collateral, Wad.from_number(230))
        # TODO: Determine why frobbing the art away fails
        # cleanup_urn(mcd, collateral, our_address)
        cleanup_urn(mcd, collateral, other_address)
Пример #15
0
    def test_scenario(self, web3, mcd, flapper, our_address, other_address,
                      deployment_address):
        joy = mcd.vat.dai(mcd.vow.address)

        if joy == Rad(0):
            # Create a CDP with surplus
            print('Creating a CDP with surplus')
            collateral = mcd.collaterals['ETH-B']
            assert flapper.kicks() == 0
            wrap_eth(mcd, deployment_address, Wad.from_number(0.1))
            collateral.approve(deployment_address)
            assert collateral.adapter.join(
                deployment_address,
                Wad.from_number(0.1)).transact(from_address=deployment_address)
            frob(mcd,
                 collateral,
                 deployment_address,
                 dink=Wad.from_number(0.1),
                 dart=Wad.from_number(10))
            assert mcd.jug.drip(
                collateral.ilk).transact(from_address=deployment_address)
        else:
            print('Surplus already exists; skipping CDP creation')
        joy_before = mcd.vat.dai(mcd.vow.address)
        # total surplus > total debt + surplus auction lot size + surplus buffer
        assert joy_before > mcd.vat.sin(
            mcd.vow.address) + mcd.vow.bump() + mcd.vow.hump()
        assert (mcd.vat.sin(mcd.vow.address) -
                mcd.vow.sin()) - mcd.vow.ash() == Rad(0)
        assert mcd.vow.flap().transact()
        kick = flapper.kicks()
        assert kick == 1
        assert len(flapper.active_auctions()) == 1
        current_bid = flapper.bids(1)
        assert current_bid.lot > Rad(0)

        # Bid on the surplus
        mint_mkr(mcd.mkr, deployment_address, our_address, Wad.from_number(10))
        flapper.approve(mcd.mkr.address, directly(from_address=our_address))
        bid = Wad.from_number(0.001)
        assert mcd.mkr.balance_of(our_address) > bid
        TestFlapper.tend(flapper, kick, our_address, current_bid.lot, bid)
        current_bid = flapper.bids(kick)
        assert current_bid.bid == bid
        assert current_bid.guy == our_address

        # Exercise _deal_ after bid has expired
        wait(mcd, our_address, flapper.ttl() + 1)
        now = datetime.now().timestamp()
        assert 0 < current_bid.tic < now or current_bid.end < now
        assert flapper.deal(kick).transact(from_address=our_address)
        joy_after = mcd.vat.dai(mcd.vow.address)
        print(f'joy_before={str(joy_before)}, joy_after={str(joy_after)}')
        assert joy_before - joy_after == mcd.vow.bump()

        # Grab our dai
        mcd.approve_dai(our_address)
        assert mcd.dai_adapter.exit(our_address, Wad(
            current_bid.lot)).transact(from_address=our_address)
        assert mcd.dai.balance_of(our_address) >= Wad(current_bid.lot)
        assert (mcd.vat.sin(mcd.vow.address) -
                mcd.vow.sin()) - mcd.vow.ash() == Rad(0)