def test_modify_safe_collateralization_other_account( self, web3, geb, other_address): # given collateral = geb.collaterals['ETH-A'] collateral.approve(other_address) geb.system_coin_adapter.approve( approve_safe_modification_directly(from_address=other_address), geb.safe_engine.address) safe = geb.safe_engine.safe(collateral.collateral_type, other_address) assert safe.address == other_address # when wrap_eth(geb, other_address, Wad.from_number(100)) assert collateral.collateral.balance_of( other_address) >= Wad.from_number(100) assert collateral.collateral == collateral.adapter.collateral() collateral.collateral.approve(collateral.adapter.address) assert collateral.adapter.join( other_address, Wad.from_number(30)).transact(from_address=other_address) assert geb.safe_engine.modify_safe_collateralization( collateral.collateral_type, other_address, Wad.from_number(30), Wad.from_number(20)).transact(from_address=other_address) # then assert geb.safe_engine.safe( collateral.collateral_type, other_address ).generated_debt == safe.generated_debt + Wad.from_number(20) # rollback cleanup_safe(geb, collateral, other_address)
def test_should_provide_model_with_updated_info_after_somebody_else_partial_bids(self, auction_id, other_address): # given collateral_auction_house = self.collateral.collateral_auction_house if not isinstance(collateral_auction_house, FixedDiscountCollateralAuctionHouse): return (model, model_factory) = models(self.keeper, auction_id) # when self.keeper.check_all_auctions() wait_for_other_threads() # then assert model.send_status.call_count == 1 # when collateral_auction_house.approve(collateral_auction_house.safe_engine(), approval_function=approve_safe_modification_directly(from_address=other_address)) previous_bid = collateral_auction_house.bids(auction_id) new_bid_amount = Wad.from_number(30) self.buy_collateral_with_system_coin(self.geb, self.collateral, collateral_auction_house, model.id, other_address, new_bid_amount) # and self.keeper.check_all_auctions() wait_for_other_threads() # then assert model.send_status.call_count > 1 # and status = model.send_status.call_args[0][0] assert status.id == auction_id assert status.collateral_auction_house == collateral_auction_house.address assert status.surplus_auction_house is None assert status.debt_auction_house is None assert status.raised_amount == Rad(new_bid_amount) assert status.amount_to_sell == previous_bid.amount_to_sell assert status.amount_to_raise == previous_bid.amount_to_raise assert status.block_time > 0 assert status.auction_deadline > status.block_time
def buy_collateral_with_system_coin( geb: GfDeployment, c: Collateral, collateral_auction_house: FixedDiscountCollateralAuctionHouse, id: int, address: Address, bid_amount: Wad): assert (isinstance(geb, GfDeployment)) assert (isinstance(c, Collateral)) assert (isinstance(collateral_auction_house, FixedDiscountCollateralAuctionHouse)) assert (isinstance(id, int)) assert (isinstance(bid_amount, Wad)) collateral_auction_house.approve( collateral_auction_house.safe_engine(), approval_function=approve_safe_modification_directly( from_address=address)) previous_bid = collateral_auction_house.bids(id) c.approve(address) reserve_system_coin(geb, c, address, bid_amount, extra_collateral=Wad.from_number(2)) TestAuctionKeeperCollateralFlashSwap.buy_collateral( collateral_auction_house, id, address, bid_amount)
def auction_id(web3: Web3, geb: GfDeployment, auction_income_recipient_address, other_address) -> int: total_surplus = geb.safe_engine.coin_balance(geb.accounting_engine.address) unqueued_unauctioned_debt = ( geb.safe_engine.debt_balance(geb.accounting_engine.address) - geb.accounting_engine.total_queued_debt() ) - geb.accounting_engine.total_on_auction_debt() print( f'total_surplus={str(total_surplus)[:6]}, unqueued_unauctioned_debt={str(unqueued_unauctioned_debt)[:6]}' ) if unqueued_unauctioned_debt < total_surplus or ( unqueued_unauctioned_debt == Rad(0) and total_surplus == Rad(0)): # Liquidate SAFE c = geb.collaterals['ETH-B'] critical_safe = create_critical_safe(geb, c, Wad.from_number(2), other_address, draw_system_coin=False) collateral_auction_id = liquidate(geb, c, critical_safe) # Generate some system coin, bid on and win the collateral auction without covering all the debt reserve_system_coin(geb, c, auction_income_recipient_address, Wad.from_number(100), extra_collateral=Wad.from_number(1.1)) c.collateral_auction_house.approve( geb.safe_engine.address, approval_function=approve_safe_modification_directly( from_address=auction_income_recipient_address)) current_bid = c.collateral_auction_house.bids(collateral_auction_id) bid_amount = Rad.from_number(1.9) assert geb.safe_engine.coin_balance( auction_income_recipient_address) > bid_amount #assert c.collateral_auction_house.increase_bid_size(collateral_auction_id, current_bid.amount_to_sell, bid_amount).transact(from_address=auction_income_recipient_address) #time_travel_by(web3, c.collateral_auction_house.bid_duration()+1) #assert c.collateral_auction_house.settle_auction(collateral_auction_id).transact() pop_debt_and_settle_debt(web3, geb, past_blocks=1200, cancel_auctioned_debt=False) # Start the debt auction unqueued_unauctioned_debt = ( geb.safe_engine.debt_balance(geb.accounting_engine.address) - geb.accounting_engine.total_queued_debt() ) - geb.accounting_engine.total_on_auction_debt() assert geb.accounting_engine.debt_auction_bid_size( ) <= unqueued_unauctioned_debt assert geb.safe_engine.coin_balance( geb.accounting_engine.address) == Rad(0) assert geb.accounting_engine.auction_debt().transact( from_address=auction_income_recipient_address) return geb.debt_auction_house.auctions_started()
def create_debt_auction(geb: GfDeployment, deployment_address: Address, our_address: Address): assert isinstance(geb, GfDeployment) assert isinstance(deployment_address, Address) assert isinstance(our_address, Address) debt_auction_house = geb.debt_auction_house print( f"Before Debt: {geb.safe_engine.debt_balance(geb.accounting_engine.address)}" ) if geb.accounting_engine.unqueued_unauctioned_debt( ) <= geb.accounting_engine.debt_auction_bid_size(): create_debt(geb.web3, geb, our_address, deployment_address, geb.collaterals['ETH-A']) print( f"After Debt: {geb.safe_engine.debt_balance(geb.accounting_engine.address)}" ) # start debt auction auction_id = debt_auction_house.auctions_started() assert auction_id == 0 assert len(debt_auction_house.active_auctions()) == 0 assert geb.safe_engine.coin_balance( geb.accounting_engine.address) == Rad(0) assert geb.accounting_engine.auction_debt().transact() auction_id = debt_auction_house.auctions_started() assert auction_id == 1 assert len(debt_auction_house.active_auctions()) == 1 check_active_auctions(debt_auction_house) current_bid = debt_auction_house.bids(auction_id) amount_to_sell = Wad.from_number(0.000005) # current_bid.bid_amount = 0.001 # current_bid.amount_to_sell = 0.0001 debt_auction_house.approve( geb.safe_engine.address, approval_function=approve_safe_modification_directly( from_address=our_address)) assert geb.safe_engine.safe_rights(our_address, debt_auction_house.address) collateral = geb.collaterals['ETH-A'] wrap_eth(geb, our_address, Wad.from_number(1)) collateral.approve(our_address) assert collateral.adapter.join( our_address, Wad.from_number(1)).transact(from_address=our_address) #web3.eth.defaultAccount = our_address.address wrap_modify_safe_collateralization(geb, collateral, our_address, delta_collateral=Wad.from_number(1), delta_debt=Wad.from_number(10)) assert geb.safe_engine.coin_balance(our_address) >= current_bid.bid_amount decrease_sold_amount(debt_auction_house, auction_id, our_address, amount_to_sell, current_bid.bid_amount) current_bid = debt_auction_house.bids(auction_id) assert current_bid.high_bidder == our_address
def eliminate_queued_debt(cls, web3, geb, keeper_address): if geb.safe_engine.debt_balance( geb.accounting_engine.address) == Rad(0): return # given the existence of queued debt c = geb.collaterals['ETH-A'] auction_id = c.collateral_auction_house.auctions_started() last_liquidation = geb.liquidation_engine.past_liquidations(10)[0] # when a bid covers the SAFE debt auction = c.collateral_auction_house.bids(auction_id) reserve_system_coin(geb, c, keeper_address, Wad(auction.amount_to_raise) + Wad(1)) c.collateral_auction_house.approve( c.collateral_auction_house.safe_engine(), approval_function=approve_safe_modification_directly( from_address=keeper_address)) c.approve(keeper_address) if isinstance(c.collateral_auction_house, EnglishCollateralAuctionHouse): assert c.collateral_auction_house.increase_bid_size( auction_id, auction.amount_to_sell, auction.amount_to_raise).transact(from_address=keeper_address) time_travel_by(web3, c.collateral_auction_house.bid_duration() + 1) assert c.collateral_auction_house.settle_auction( auction_id).transact() elif isinstance(c.collateral_auction_house, FixedDiscountCollateralAuctionHouse): assert c.collateral_auction_house.buy_collateral( auction_id, Wad(auction.amount_to_raise) + Wad(1)).transact(from_address=keeper_address) elif isinstance(c.collateral_auction_house, IncreasingDiscountCollateralAuctionHouse): assert c.collateral_auction_house.buy_collateral( auction_id, Wad(auction.amount_to_raise) + Wad(1)).transact(from_address=keeper_address) # when a bid covers the vow debt assert geb.accounting_engine.debt_queue_of( last_liquidation.block_time(web3)) > Rad(0) assert geb.accounting_engine.pop_debt_from_queue( last_liquidation.block_time(web3)).transact( from_address=keeper_address) assert geb.accounting_engine.settle_debt( geb.safe_engine.debt_balance( geb.accounting_engine.address)).transact() # then ensure queued debt has been auctioned off assert geb.safe_engine.debt_balance( geb.accounting_engine.address) == Rad(0)
def setup_method(self): self.web3 = get_web3() self.our_address = get_our_address(self.web3) self.keeper_address = get_keeper_address(self.web3) self.other_address = get_other_address(self.web3) self.auction_income_recipient_address = get_auction_income_recipient_address( self.web3) self.geb = get_geb(self.web3) self.debt_auction_house = self.geb.debt_auction_house self.debt_auction_house.approve( self.geb.safe_engine.address, approval_function=approve_safe_modification_directly( from_address=self.keeper_address)) self.debt_auction_house.approve( self.geb.safe_engine.address, approval_function=approve_safe_modification_directly( from_address=self.other_address)) self.keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--type debt " f"--from-block 1 " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() assert isinstance(self.keeper.gas_price, DynamicGasPrice) self.default_gas_price = self.keeper.gas_price.get_gas_price(0) reserve_system_coin(self.geb, self.geb.collaterals['ETH-C'], self.keeper_address, Wad.from_number(200.00000)) reserve_system_coin(self.geb, self.geb.collaterals['ETH-C'], self.other_address, Wad.from_number(200.00000)) self.debt_auction_bid_size = self.geb.accounting_engine.debt_auction_bid_size( ) # Rad
def approve_system_coin(self, address: Address, **kwargs): """ Allows the user to draw system coin from and repay system coin to their SAFEs. Args address: Recipient of system coin from one or more SAFEs """ assert isinstance(address, Address) gas_price = kwargs[ 'gas_price'] if 'gas_price' in kwargs else DefaultGasPrice() self.system_coin_adapter.approve( approval_function=approve_safe_modification_directly( from_address=address, gas_price=gas_price), source=self.safe_engine.address) self.system_coin.approve(self.system_coin_adapter.address).transact( from_address=address, gas_price=gas_price)
def approve(self, gas_price: GasPrice): assert isinstance(gas_price, GasPrice) #self.collateral_auction_house.approve(self.collateral_auction_house.safe_engine(), approve_safe_modification_directly(gas_price=gas_price)) self.collateral_auction_house.approve( self.collateral_auction_house.safe_engine(), approve_safe_modification_directly())
def approve(self, gas_price: GasPrice): self.staked_token_auction_house.approve( self.staked_token_auction_house.safe_engine(), approve_safe_modification_directly(gas_price=gas_price))
def create_collateral_auction(geb: GfDeployment, deployment_address: Address, our_address: Address): assert isinstance(geb, GfDeployment) assert isinstance(our_address, Address) assert isinstance(deployment_address, Address) # Create a SAFE collateral = geb.collaterals['ETH-A'] collateral_type = collateral.collateral_type wrap_eth(geb, 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) wrap_modify_safe_collateralization(geb, collateral, deployment_address, delta_collateral=Wad.from_number(1), delta_debt=Wad(0)) delta_debt = max_delta_debt(geb, collateral, deployment_address) - Wad(1) wrap_modify_safe_collateralization(geb, collateral, deployment_address, delta_collateral=Wad(0), delta_debt=delta_debt) # Undercollateralize and bite the SAFE to_price = Wad(geb.web3.toInt(collateral.osm.read())) / Wad.from_number(2) set_collateral_price(geb, collateral, to_price) safe = geb.safe_engine.safe(collateral.collateral_type, deployment_address) collateral_type = geb.safe_engine.collateral_type(collateral_type.name) safe = Ray(safe.generated_debt) * geb.safe_engine.collateral_type( collateral_type.name).accumulated_rate <= Ray( safe.locked_collateral) * collateral_type.safety_price assert not safe assert geb.liquidation_engine.can_liquidate(collateral.collateral_type, SAFE(deployment_address)) assert geb.liquidation_engine.liquidate_safe( collateral.collateral_type, SAFE(deployment_address)).transact() auction_id = collateral.collateral_auction_house.auctions_started() # Generate some system coin, bid on the collateral auction without covering all the debt wrap_eth(geb, 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) geb.web3.eth.defaultAccount = our_address.address wrap_modify_safe_collateralization(geb, collateral, our_address, delta_collateral=Wad.from_number(10), delta_debt=Wad.from_number(50)) collateral.collateral_auction_house.approve( geb.safe_engine.address, approval_function=approve_safe_modification_directly()) current_bid = collateral.collateral_auction_house.bids(auction_id) safe = geb.safe_engine.safe(collateral.collateral_type, our_address) assert Rad(safe.generated_debt) > current_bid.amount_to_raise bid_amount = Rad.from_number(6) if isinstance(collateral.collateral_auction_house, EnglishCollateralAuctionHouse): increase_bid_size(collateral.collateral_auction_house, auction_id, our_address, current_bid.amount_to_sell, bid_amount) elif isinstance(collateral.collateral_auction_house, FixedDiscountCollateralAuctionHouse): assert collateral.collateral_auction_house.get_collateral_bought( auction_id, Wad(bid_amount)).transact(from_address=our_address) assert collateral.collateral_auction_house.buy_collateral( auction_id, Wad(bid_amount)).transact(from_address=our_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)