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)
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')
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
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)
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
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()
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)
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)
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)
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)
]) 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")
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)
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)