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)
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)
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)
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")
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 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)
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