Пример #1
0
def cleanup_urn(mcd: DssDeployment, collateral: Collateral, address: Address):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(address, Address)
    urn = mcd.vat.urn(collateral.ilk, address)
    ilk = mcd.vat.ilk(collateral.ilk.name)

    # If jug.drip has been called, we won't have sufficient dai to repay the CDP
    if ilk.rate > Ray.from_number(1):
        return

    # Repay borrowed Dai
    mcd.approve_dai(address)
    # Put all the user's Dai back into the vat
    if mcd.dai.balance_of(address) >= Wad(0):
        assert mcd.dai_adapter.join(address, mcd.dai.balance_of(address)).transact(from_address=address)
    # tab = Ray(urn.art) * ilk.rate
    # print(f'tab={str(tab)}, rate={str(ilk.rate)}, dai={str(mcd.vat.dai(address))}')
    if urn.art > Wad(0) and mcd.vat.dai(address) >= Rad(urn.art):
        frob(mcd, collateral, address, Wad(0), urn.art * -1)

    # Withdraw collateral
    collateral.approve(address)
    urn = mcd.vat.urn(collateral.ilk, address)
    # dink = Wad((Ray(urn.art) * ilk.rate) / ilk.spot)
    # print(f'dink={str(dink)}, ink={str(urn.ink)}')
    if urn.art == Wad(0) and urn.ink > Wad(0):
        frob(mcd, collateral, address, urn.ink * -1, Wad(0))
    assert collateral.adapter.exit(address, mcd.vat.gem(collateral.ilk, address)).transact(from_address=address)
Пример #2
0
def create_cdp_with_surplus(mcd: DssDeployment, c: Collateral,
                            gal_address: Address) -> Urn:
    assert isinstance(mcd, DssDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(gal_address, Address)

    # Ensure there is no debt which a previous test failed to clean up
    assert mcd.vat.sin(mcd.vow.address) == Rad(0)

    ink = Wad.from_number(10)
    art = Wad.from_number(500)
    wrap_eth(mcd, gal_address, ink)
    c.approve(gal_address)
    assert c.adapter.join(gal_address, ink).transact(from_address=gal_address)
    simulate_frob(mcd, c, gal_address, ink, art)
    assert mcd.vat.frob(c.ilk, gal_address, dink=ink,
                        dart=art).transact(from_address=gal_address)
    assert mcd.jug.drip(c.ilk).transact(from_address=gal_address)
    # total surplus > total debt + surplus auction lot size + surplus buffer
    print(
        f"dai(vow)={str(mcd.vat.dai(mcd.vow.address))} >? sin(vow)={str(mcd.vat.sin(mcd.vow.address))} "
        f"+ vow.bump={str(mcd.vow.bump())} + vow.hump={str(mcd.vow.hump())}")
    assert mcd.vat.dai(mcd.vow.address) > mcd.vat.sin(
        mcd.vow.address) + mcd.vow.bump() + mcd.vow.hump()
    return mcd.vat.urn(c.ilk, gal_address)
Пример #3
0
def reserve_dai(mcd: DssDeployment,
                c: Collateral,
                usr: Address,
                amount: Wad,
                extra_collateral=Wad.from_number(1)):
    assert isinstance(mcd, DssDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(usr, Address)
    assert isinstance(amount, Wad)
    assert amount > Wad(0)

    # Determine how much collateral is needed
    ilk = mcd.vat.ilk(c.ilk.name)
    rate = ilk.rate  # Ray
    spot = ilk.spot  # Ray
    assert rate >= Ray.from_number(1)
    collateral_required = Wad(
        (Ray(amount) / spot) * rate) * extra_collateral + Wad(1)
    print(
        f'collateral_required for {str(amount)} dai is {str(collateral_required)}'
    )

    wrap_eth(mcd, usr, collateral_required)
    c.approve(usr)
    assert c.adapter.join(usr, collateral_required).transact(from_address=usr)
    assert mcd.vat.frob(c.ilk, usr, collateral_required,
                        amount).transact(from_address=usr)
    assert mcd.vat.urn(c.ilk, usr).art >= Wad(amount)
Пример #4
0
    def deploy_collateral(self, collateral: Collateral,
                          debt_ceiling: Wad, penalty: Ray, flop_lot: Wad, ratio: Ray, initial_price: Wad):

        collateral.pip = DSValue.deploy(web3=self.web3)
        assert collateral.pip.poke_with_int(initial_price.value).transact()  # Initial price

        collateral.flipper = Flipper.deploy(web3=self.web3, dai=self.dai_move.address, gem=collateral.mover.address)

        collateral.spotter = Spotter.deploy(web3=self.web3, pit=self.pit.address, ilk=collateral.ilk)
        collateral.spotter.file_pip(collateral.pip.address).transact()
        collateral.spotter.file_mat(ratio).transact()  # Liquidation ratio

        assert collateral.gem.approve(collateral.adapter.address).transact()

        assert self.cat.file_flip(collateral.ilk, collateral.flipper).transact()
        assert self.cat.file_lump(collateral.ilk, flop_lot).transact()  # Liquidation Quantity
        assert self.cat.file_chop(collateral.ilk, penalty).transact()  # Liquidation Penalty
        assert self.vat.init(collateral.ilk).transact()
        assert self.drip.init(collateral.ilk).transact()

        assert self.vat.rely(collateral.flipper.address).transact()
        assert self.vat.rely(collateral.adapter.address).transact()
        assert self.vat.rely(collateral.mover.address).transact()
        assert self.pit.rely(collateral.spotter.address).transact()

        assert self.pit.file_line(collateral.ilk, debt_ceiling).transact()  # Collateral debt Ceiling
        assert collateral.spotter.poke().transact()

        self.collaterals.append(collateral)
Пример #5
0
def create_risky_cdp(mcd: DssDeployment,
                     c: Collateral,
                     collateral_amount: Wad,
                     gal_address: Address,
                     draw_dai=True) -> Urn:
    assert isinstance(mcd, DssDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(gal_address, Address)

    # Ensure vault isn't already unsafe (if so, this shouldn't be called)
    urn = mcd.vat.urn(c.ilk, gal_address)
    assert is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn)

    # Add collateral to gal vault if necessary
    c.approve(gal_address)
    token = Token(c.ilk.name, c.gem.address, c.adapter.dec())
    print(f"collateral_amount={collateral_amount} ink={urn.ink}")
    dink = collateral_amount - urn.ink
    if dink > Wad(0):
        vat_balance = mcd.vat.gem(c.ilk, gal_address)
        balance = token.normalize_amount(c.gem.balance_of(gal_address))
        print(
            f"before join: dink={dink} vat_balance={vat_balance} balance={balance} vat_gap={dink - vat_balance}"
        )
        if vat_balance < dink:
            vat_gap = dink - vat_balance
            if balance < vat_gap:
                if c.ilk.name.startswith("ETH"):
                    wrap_eth(mcd, gal_address, vat_gap)
                else:
                    raise RuntimeError("Insufficient collateral balance")
            amount_to_join = token.unnormalize_amount(vat_gap)
            if amount_to_join == Wad(
                    0):  # handle dusty balances with non-18-decimal tokens
                amount_to_join += token.unnormalize_amount(token.min_amount)
            assert c.adapter.join(
                gal_address, amount_to_join).transact(from_address=gal_address)
        vat_balance = mcd.vat.gem(c.ilk, gal_address)
        print(
            f"after join: dink={dink} vat_balance={vat_balance} balance={balance} vat_gap={dink - vat_balance}"
        )
        assert vat_balance >= dink
        assert mcd.vat.frob(c.ilk, gal_address, dink,
                            Wad(0)).transact(from_address=gal_address)

    # Put gal CDP at max possible debt
    dart = max_dart(mcd, c, gal_address) - Wad(1)
    if dart > Wad(0):
        print(f"Attempting to frob with dart={dart}")
        assert mcd.vat.frob(c.ilk, gal_address, Wad(0),
                            dart).transact(from_address=gal_address)

    # Draw our Dai, simulating the usual behavior
    urn = mcd.vat.urn(c.ilk, gal_address)
    if draw_dai and urn.art > Wad(0):
        mcd.approve_dai(gal_address)
        assert mcd.dai_adapter.exit(gal_address,
                                    urn.art).transact(from_address=gal_address)
        print(f"Exited {urn.art} Dai from urn")
Пример #6
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)
Пример #7
0
    def tend_with_dai(mcd: DssDeployment, c: Collateral, flipper: Flipper, id: int, address: Address, bid: Rad):
        assert (isinstance(mcd, DssDeployment))
        assert (isinstance(c, Collateral))
        assert (isinstance(flipper, Flipper))
        assert (isinstance(id, int))
        assert (isinstance(bid, Rad))

        flipper.approve(flipper.vat(), approval_function=hope_directly(from_address=address))
        previous_bid = flipper.bids(id)
        c.approve(address)
        reserve_dai(mcd, c, address, Wad(bid), extra_collateral=Wad.from_number(2))
        TestAuctionKeeperFlipper.tend(flipper, id, address, previous_bid.lot, bid)
Пример #8
0
 def from_json(web3: Web3, conf: str):
     conf = json.loads(conf)
     mom = DSGuard(web3, Address(conf['MCD_MOM']))
     vat = Vat(web3, Address(conf['MCD_VAT']))
     vow = Vow(web3, Address(conf['MCD_VOW']))
     drip = Drip(web3, Address(conf['MCD_DRIP']))
     pit = Pit(web3, Address(conf['MCD_PIT']))
     cat = Cat(web3, Address(conf['MCD_CAT']))
     flap = Flapper(web3, Address(conf['MCD_FLAP']))
     flop = Flopper(web3, Address(conf['MCD_FLOP']))
     dai = DSToken(web3, Address(conf['MCD_DAI']))
     dai_adapter = DaiAdapter(web3, Address(conf['MCD_JOIN_DAI']))
     dai_move = DaiVat(web3, Address(conf['MCD_MOVE_DAI']))
     mkr = DSToken(web3, Address(conf['MCD_GOV']))
     collaterals = []
     for name in conf['COLLATERALS']:
         collateral = Collateral(Ilk(name))
         collateral.gem = DSToken(web3, Address(conf[name]))
         collateral.adapter = GemAdapter(web3, Address(conf[f'MCD_JOIN_{name}']))
         collateral.mover = GemVat(web3, Address(conf[f'MCD_MOVE_{name}']))
         collateral.flipper = Flipper(web3, Address(conf[f'MCD_FLIP_{name}']))
         collateral.pip = DSValue(web3, Address(conf[f'PIP_{name}']))
         collateral.spotter = Spotter(web3, Address(conf[f'MCD_SPOT_{name}']))
         collaterals.append(collateral)
     return DssDeployment.Config(mom, vat, vow, drip, pit, cat, flap, flop, dai, dai_adapter, dai_move, mkr,
                                 collaterals)
Пример #9
0
        def from_json(web3: Web3, conf: str):
            conf = json.loads(conf)
            pause = DSPause(web3, Address(conf['MCD_PAUSE']))
            vat = Vat(web3, Address(conf['MCD_VAT']))
            vow = Vow(web3, Address(conf['MCD_VOW']))
            jug = Jug(web3, Address(conf['MCD_JUG']))
            cat = Cat(web3, Address(conf['MCD_CAT']))
            dai = DSToken(web3, Address(conf['MCD_DAI']))
            dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI']))
            flapper = Flapper(web3, Address(conf['MCD_FLAP']))
            flopper = Flopper(web3, Address(conf['MCD_FLOP']))
            mkr = DSToken(web3, Address(conf['MCD_GOV']))
            spotter = Spotter(web3, Address(conf['MCD_SPOT']))

            collaterals = {}
            for name in DssDeployment.Config._infer_collaterals_from_addresses(conf.keys()):
                ilk = Ilk(name[0].replace('_', '-'))
                if name[1] == "ETH":
                    gem = DSEthToken(web3, Address(conf[name[1]]))
                else:
                    gem = DSToken(web3, Address(conf[name[1]]))

                # TODO: If problematic, skip pip for deployments which use a medianizer.
                collateral = Collateral(ilk=ilk, gem=gem,
                                        adapter=GemJoin(web3, Address(conf[f'MCD_JOIN_{name[0]}'])),
                                        flipper=Flipper(web3, Address(conf[f'MCD_FLIP_{name[0]}'])),
                                        pip=DSValue(web3, Address(conf[f'PIP_{name[1]}'])))
                collaterals[ilk.name] = collateral

            return DssDeployment.Config(pause, vat, vow, jug, cat, flapper, flopper,
                                        dai, dai_adapter, mkr, spotter, collaterals)
Пример #10
0
def create_unsafe_cdp(mcd: DssDeployment,
                      c: Collateral,
                      collateral_amount: Wad,
                      gal_address: Address,
                      draw_dai=True) -> Urn:
    assert isinstance(mcd, DssDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(gal_address, Address)

    # Ensure CDP isn't already unsafe (if so, this shouldn't be called)
    urn = mcd.vat.urn(c.ilk, gal_address)
    assert is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn)

    # Add collateral to gal CDP if necessary
    c.approve(gal_address)
    dink = collateral_amount - urn.ink
    if dink > Wad(0):
        balance = c.gem.balance_of(gal_address)
        if balance < dink:
            wrap_eth(mcd, gal_address, dink - balance)
            assert c.adapter.join(gal_address, dink -
                                  balance).transact(from_address=gal_address)
        simulate_frob(mcd, c, gal_address, dink, Wad(0))
        assert mcd.vat.frob(c.ilk, gal_address, dink,
                            Wad(0)).transact(from_address=gal_address)

    # Put gal CDP at max possible debt
    dart = max_dart(mcd, c, gal_address) - Wad(1)
    simulate_frob(mcd, c, gal_address, Wad(0), dart)
    assert mcd.vat.frob(c.ilk, gal_address, Wad(0),
                        dart).transact(from_address=gal_address)

    # Draw our Dai, simulating the usual behavior
    urn = mcd.vat.urn(c.ilk, gal_address)
    if draw_dai and urn.art > Wad(0):
        mcd.approve_dai(gal_address)
        assert mcd.dai_adapter.exit(gal_address,
                                    urn.art).transact(from_address=gal_address)
        print(f"Exited {urn.art} Dai from urn")

    # Manipulate price to make gal CDP underwater
    to_price = Wad(c.pip.read_as_int()) - Wad.from_number(1)
    set_collateral_price(mcd, c, to_price)

    # Ensure the CDP is unsafe
    assert not is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn)
    return urn
Пример #11
0
        def from_json(web3: Web3, conf: str):
            conf = json.loads(conf)
            pause = DSPause(web3, Address(conf['MCD_PAUSE']))
            vat = Vat(web3, Address(conf['MCD_VAT']))
            vow = Vow(web3, Address(conf['MCD_VOW']))
            jug = Jug(web3, Address(conf['MCD_JUG']))
            cat = Cat(web3, Address(conf['MCD_CAT']))
            dai = DSToken(web3, Address(conf['MCD_DAI']))
            dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI']))
            flapper = Flapper(web3, Address(conf['MCD_FLAP']))
            flopper = Flopper(web3, Address(conf['MCD_FLOP']))
            pot = Pot(web3, Address(conf['MCD_POT']))
            mkr = DSToken(web3, Address(conf['MCD_GOV']))
            spotter = Spotter(web3, Address(conf['MCD_SPOT']))
            ds_chief = DSChief(web3, Address(conf['MCD_ADM']))
            esm = ShutdownModule(web3, Address(conf['MCD_ESM']))
            end = End(web3, Address(conf['MCD_END']))
            proxy_registry = ProxyRegistry(web3,
                                           Address(conf['PROXY_REGISTRY']))
            dss_proxy_actions = DssProxyActionsDsr(
                web3, Address(conf['PROXY_ACTIONS_DSR']))

            collaterals = {}
            for name in DssDeployment.Config._infer_collaterals_from_addresses(
                    conf.keys()):
                ilk = Ilk(name[0].replace('_', '-'))
                if name[1] == "ETH":
                    gem = DSEthToken(web3, Address(conf[name[1]]))
                else:
                    gem = DSToken(web3, Address(conf[name[1]]))

                # PIP contract may be a DSValue, OSM, or bogus address.
                pip_address = Address(conf[f'PIP_{name[1]}'])
                network = DssDeployment.NETWORKS.get(web3.net.version,
                                                     "testnet")
                if network == "testnet":
                    pip = DSValue(web3, pip_address)
                else:
                    pip = OSM(web3, pip_address)

                collateral = Collateral(
                    ilk=ilk,
                    gem=gem,
                    adapter=GemJoin(web3,
                                    Address(conf[f'MCD_JOIN_{name[0]}'])),
                    flipper=Flipper(web3,
                                    Address(conf[f'MCD_FLIP_{name[0]}'])),
                    pip=pip)
                collaterals[ilk.name] = collateral

            return DssDeployment.Config(pause, vat, vow, jug, cat, flapper,
                                        flopper, pot, dai, dai_adapter, mkr,
                                        spotter, ds_chief, esm, end,
                                        proxy_registry, dss_proxy_actions,
                                        collaterals)
Пример #12
0
    def deploy(web3: Web3, debt_ceiling: Wad):
        assert isinstance(web3, Web3)

        vat = Vat.deploy(web3=web3)

        pit = Pit.deploy(web3=web3, vat=vat.address)
        assert pit.file_global_line(debt_ceiling).transact()  # Global debt Ceiling
        assert vat.rely(pit.address).transact()

        dai = DSToken.deploy(web3=web3, symbol='DAI')
        dai_adapter = DaiAdapter.deploy(web3=web3, vat=vat.address, dai=dai.address)
        dai_move = DaiVat.deploy(web3=web3, vat=vat.address)
        assert vat.rely(dai_adapter.address).transact()
        assert vat.rely(dai_move.address).transact()

        mkr = DSToken.deploy(web3=web3, symbol='MKR')

        # TODO: use a DSProxy
        mom = DSGuard.deploy(web3)
        assert mom.permit(DSGuard.ANY, DSGuard.ANY, DSGuard.ANY).transact()
        assert dai.set_authority(mom.address).transact()
        assert mkr.set_authority(mom.address).transact()

        vow = Vow.deploy(web3=web3)
        drip = Drip.deploy(web3=web3, vat=vat.address)
        flap = Flapper.deploy(web3=web3, dai=dai_move.address, gem=mkr.address)

        assert vow.file_vat(vat).transact()
        assert vow.file_flap(flap).transact()
        assert vow.file_bump(Wad.from_number(1000)).transact()
        assert vow.file_sump(Wad.from_number(10)).transact()
        assert drip.file_vow(vow).transact()

        assert vat.rely(vow.address).transact()
        assert vat.rely(drip.address).transact()
        assert vat.rely(flap.address).transact()

        cat = Cat.deploy(web3=web3, vat=vat.address)
        assert cat.file_vow(vow).transact()
        assert cat.file_pit(pit).transact()

        flop = Flopper.deploy(web3=web3, dai=dai_move.address, gem=mkr.address)

        assert vow.file_flop(flop).transact()

        assert vat.rely(cat.address).transact()
        assert vat.rely(flop.address).transact()
        assert vow.rely(cat.address).transact()
        assert flop.rely(vow.address).transact()

        config = DssDeployment.Config(mom, vat, vow, drip, pit, cat, flap, flop, dai, dai_adapter, dai_move, mkr)
        deployment = DssDeployment(web3, config)

        collateral = Collateral.deploy(web3=web3, name='WETH', vat=vat)
        deployment.deploy_collateral(collateral,
                                     debt_ceiling=Wad.from_number(100000),
                                     penalty=Ray.from_number(1),
                                     flop_lot=Wad.from_number(10000),
                                     ratio=Ray.from_number(1.5),
                                     initial_price=Wad.from_number(219))

        return deployment