def test_flash_proxy_liquidate_and_settle_auction(self, c: Collateral, web3, geb, auction_id, other_address): # given collateral_auction_house = self.collateral.collateral_auction_house if not isinstance(collateral_auction_house, FixedDiscountCollateralAuctionHouse): return set_collateral_price(geb, c, Wad.from_number(100)) eth_before = self.web3.eth.getBalance(self.keeper_address.address) auctions_started = collateral_auction_house.auctions_started() # when critical_safe = create_critical_safe(geb, c, bid_size, other_address) self.keeper.check_safes() wait_for_other_threads() assert self.web3.eth.getBalance( self.keeper_address.address) > eth_before assert collateral_auction_house.auctions_started( ) == auctions_started + 1 auction_status = collateral_auction_house.bids(auctions_started + 1) assert auction_status.raised_amount == Rad(0) assert auction_status.sold_amount == Wad(0) assert auction_status.amount_to_raise == Rad(0) assert auction_status.amount_to_sell == Wad(0) assert auction_status.auction_deadline == 0 assert auction_status.raised_amount == Rad(0)
def liquidate_urn(cls, web3, mcd, c, gal_address, our_address): # Ensure the CDP isn't safe urn = mcd.vat.urn(c.ilk, gal_address) dart = max_dart(mcd, c, gal_address) - Wad.from_number(1) assert mcd.vat.frob(c.ilk, gal_address, Wad(0), dart).transact(from_address=gal_address) set_collateral_price(mcd, c, Wad.from_number(66)) assert not is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn) # Bite and kick off the auction kick = bite(mcd, c, urn) assert kick > 0 # Bid on and win the auction auction = c.flipper.bids(kick) bid = Wad(auction.tab) + Wad(1) reserve_dai(mcd, c, our_address, bid) c.flipper.approve( mcd.vat.address, approval_function=hope_directly(from_address=our_address)) assert c.flipper.tend(kick, auction.lot, auction.tab).transact(from_address=our_address) time_travel_by(web3, c.flipper.ttl() + 1) assert c.flipper.deal(kick).transact() set_collateral_price(mcd, c, Wad.from_number(200)) urn = mcd.vat.urn(c.ilk, gal_address) assert urn.ink == Wad(0) assert urn.art == Wad(0)
def liquidate_urn(cls, web3, mcd, c, gal_address, our_address): # Ensure the CDP isn't safe urn = mcd.vat.urn(c.ilk, gal_address) dart = max_dart(mcd, c, gal_address) - Wad.from_number(1) assert mcd.vat.frob(c.ilk, gal_address, Wad(0), dart).transact(from_address=gal_address) set_collateral_price(mcd, c, Wad.from_number(66)) assert not is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn) # Determine how many bites will be required dunk = Wad(mcd.cat.dunk(c.ilk)) urn = mcd.vat.urn(c.ilk, gal_address) bites_required = math.ceil(urn.art / dunk) print(f"art={urn.art} and dunk={dunk} so {bites_required} bites are required") c.flipper.approve(mcd.vat.address, approval_function=hope_directly(from_address=our_address)) first_kick = c.flipper.kicks() + 1 # Bite and bid on each auction for i in range(bites_required): kick = bite(mcd, c, urn) assert kick > 0 auction = c.flipper.bids(kick) print(f"biting {i} of {bites_required} and bidding tab of {auction.tab}") bid = Wad(auction.tab) + Wad(1) reserve_dai(mcd, c, our_address, bid) print(f"bidding tab of {auction.tab}") assert c.flipper.tend(kick, auction.lot, auction.tab).transact(from_address=our_address) time_travel_by(web3, c.flipper.ttl()) for kick in range(first_kick, c.flipper.kicks()): assert c.flipper.deal(kick).transact() set_collateral_price(mcd, c, Wad.from_number(200)) urn = mcd.vat.urn(c.ilk, gal_address)
def liquidate_safe(cls, web3, geb, c, auction_income_recipient_address, our_address): safe = geb.safe_engine.safe(c.collateral_type, auction_income_recipient_address) delta_debt = max_delta_debt(geb, c, auction_income_recipient_address) - Wad.from_number(1) assert geb.safe_engine.modify_safe_collateralization(c.collateral_type, auction_income_recipient_address, Wad(0), delta_debt).transact(from_address=auction_income_recipient_address) safe = geb.safe_engine.safe(c.collateral_type, auction_income_recipient_address) set_collateral_price(geb, c, Wad.from_number(10)) # Ensure the SAFE isn't safe assert not is_safe_safe(geb.safe_engine.collateral_type(c.collateral_type.name), safe) # Determine how many liquidations will be required liquidation_quantity = Wad(geb.liquidation_engine.liquidation_quantity(c.collateral_type)) liquidations_required = math.ceil(safe.generated_debt / liquidation_quantity) print(f"locked_collateral={safe.locked_collateral} generated_debt={safe.generated_debt} so {liquidations_required} liquidations are required") c.collateral_auction_house.approve(geb.safe_engine.address, approval_function=approve_safe_modification_directly(from_address=our_address)) # First auction that will be started first_auction_id = c.collateral_auction_house.auctions_started() + 1 # liquidate and bid on each auction for _ in range(liquidations_required): auction_id = liquidate(geb, c, safe) assert auction_id > 0 auction = c.collateral_auction_house.bids(auction_id) bid_amount = Wad(auction.amount_to_raise) + Wad(1) reserve_system_coin(geb, c, our_address, bid_amount) assert c.collateral_auction_house.increase_bid_size(auction_id, auction.amount_to_sell, auction.amount_to_raise).transact(from_address=our_address) time_travel_by(web3, c.collateral_auction_house.total_auction_length()+1) for auction_id in range(first_auction_id, c.collateral_auction_house.auctions_started()+1): assert c.collateral_auction_house.settle_auction(auction_id).transact() set_collateral_price(geb, c, Wad.from_number(200)) safe = geb.safe_engine.safe(c.collateral_type, auction_income_recipient_address)
def test_flash_proxy_settle_auction(self, c: Collateral, web3, geb, auction_id, other_address): # given collateral_auction_house = self.collateral.collateral_auction_house if not isinstance(collateral_auction_house, FixedDiscountCollateralAuctionHouse): return set_collateral_price(geb, c, Wad.from_number(100)) eth_before = self.web3.eth.getBalance(self.keeper_address.address) # when self.keeper.check_all_auctions() wait_for_other_threads() assert self.web3.eth.getBalance( self.keeper_address.address) > eth_before current_status = collateral_auction_house.bids(auction_id) assert current_status.raised_amount == Rad(0) assert current_status.sold_amount == Wad(0) assert current_status.amount_to_raise == Rad(0) assert current_status.amount_to_sell == Wad(0) assert current_status.auction_deadline == 0 assert current_status.raised_amount == Rad(0)
def auction_id(geb, c: Collateral, auction_income_recipient_address) -> int: # set to pymaker price set_collateral_price(geb, c, Wad.from_number(500)) # Ensure we start with a clean safe safe = geb.safe_engine.safe(c.collateral_type, auction_income_recipient_address) assert safe.locked_collateral == Wad(0) assert safe.generated_debt == Wad(0) # liquidate SAFE critical_safe = create_critical_safe(geb, c, bid_size, auction_income_recipient_address) return liquidate(geb, c, critical_safe)
def auction_id(geb, c: Collateral, auction_income_recipient_address) -> int: set_collateral_price(geb, c, Wad.from_number(200)) create_safe_with_surplus(geb, c, auction_income_recipient_address) assert geb.accounting_engine.auction_surplus().transact(from_address=auction_income_recipient_address) auction_id = geb.surplus_auction_house.auctions_started() assert auction_id > 0 current_bid = geb.surplus_auction_house.bids(auction_id) assert current_bid.amount_to_sell == geb.accounting_engine.surplus_auction_amount_to_sell() return auction_id
def test_liquidation_and_collateral_auction( self, web3, geb, auction_income_recipient_address, keeper_address): # given c = geb.collaterals['ETH-A'] set_collateral_price(geb, c, Wad.from_number(500)) keeper = AuctionKeeper(args=args( f"--eth-from {keeper_address} " f"--type collateral " f"--from-block 1 " f"--collateral-type {c.collateral_type.name} " f"--model ./bogus-model.sh"), web3=geb.web3) keeper.approve() unsafe_safe = create_critical_safe(geb, c, Wad.from_number(1.2), auction_income_recipient_address) assert len(geb.active_auctions()["collateral_auctions"][ c.collateral_type.name]) == 0 # Keeper won't bid with a 0 system coin balance purchase_system_coin(Wad.from_number(20), keeper_address) assert geb.system_coin_adapter.join( keeper_address, Wad.from_number(20)).transact(from_address=keeper_address) # when keeper.check_safes() wait_for_other_threads() # then assert len(geb.liquidation_engine.past_liquidations(10)) > 0 safe = geb.safe_engine.safe(unsafe_safe.collateral_type, unsafe_safe.address) assert safe.generated_debt == Wad(0) # unsafe safe has been liquidated assert safe.locked_collateral == Wad(0) # unsafe safe is now safe ... assert c.collateral_auction_house.auctions_started( ) == 1 # One auction started
# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys from pyflex.numeric import Wad, Ray, Rad from tests.conftest import geb, set_collateral_price, web3 geb = geb(web3()) price = Wad.from_number(float( sys.argv[1])) if len(sys.argv) > 1 else Wad.from_number(200) collateral_type_name = str(sys.argv[2]) if len(sys.argv) > 2 else 'ETH-A' set_collateral_price(geb, geb.collaterals[collateral_type_name], price) print( f"safety_price={str(geb.safe_engine.collateral_type(collateral_type_name).safety_price)[:9]}" ) print( f"liquidation_price={str(geb.safe_engine.collateral_type(collateral_type_name).liquidation_price)[:9]}" )
def teardown_method(self): set_collateral_price(self.mcd, self.collateral, Wad.from_number(200.00))
def teardown_class(cls): set_collateral_price(cls.mcd, cls.collateral, Wad.from_number(200.00))
# This file is part of Maker Keeper Framework. # # Copyright (C) 2019 EdNoepel # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys from pymaker.numeric import Wad, Ray, Rad from tests.conftest import mcd, set_collateral_price, web3 mcd = mcd(web3()) price = Wad.from_number(float( sys.argv[1])) if len(sys.argv) > 1 else Wad.from_number(200) ilk_name = str(sys.argv[2]) if len(sys.argv) > 2 else 'ETH-A' set_collateral_price(mcd, mcd.collaterals[ilk_name], price) print(f"spot={str(mcd.vat.ilk(ilk_name).spot)[:9]}")
def teardown_method(self): c = self.mcd.collaterals['ETH-A'] set_collateral_price(self.mcd, c, Wad.from_number(200.00))