def test_divide(self): assert Rad.from_number(4) / Rad.from_number(2) == Rad.from_number(2) assert Rad(4) / Rad.from_number(2) == Rad(2) assert Rad(3) / Rad.from_number(2) == Rad(1) assert Rad(39) / Rad.from_number(20) == Rad(1) assert Rad(40) / Rad.from_number(20) == Rad(2) assert Rad.from_number(0.2) / Rad.from_number(0.1) == Rad.from_number( 2)
def test_should_start_a_new_model_and_provide_it_with_info_on_auction_start( self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) # when self.keeper.check_all_auctions() wait_for_other_threads() # then model_factory.create_model.assert_called_once_with( Parameters(collateral_auction_house=None, surplus_auction_house=None, debt_auction_house=self.debt_auction_house.address, staked_token_auction_house=None, id=auction_id)) # and status = model.send_status.call_args[0][0] assert status.id == auction_id assert status.collateral_auction_house is None assert status.surplus_auction_house is None assert status.debt_auction_house == self.debt_auction_house.address assert status.bid_amount > Rad.from_number(0) assert status.amount_to_sell == self.geb.accounting_engine.initial_debt_auction_minted_tokens( ) assert status.amount_to_raise is None assert status.bid_decrease > Wad.from_number(1) assert status.high_bidder == self.geb.accounting_engine.address assert status.block_time > 0 assert status.auction_deadline < status.block_time + self.debt_auction_house.total_auction_length( ) + 1 assert status.bid_expiry == 0 assert status.price == Wad(status.bid_amount * self.geb.oracle_relayer.redemption_price() / Rad(status.amount_to_sell))
def test_should_overbid_itself_if_model_has_updated_the_price( self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) # when simulate_model_output(model=model, price=Wad.from_number(100.0)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then assert round( Rad(self.debt_auction_house.bids(auction_id).amount_to_sell), 2) == round(self.debt_auction_bid_size / Rad.from_number(100.0), 2) # when simulate_model_output(model=model, price=Wad.from_number(110.0)) self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then assert self.amount_to_sell_implies_price(auction_id, Wad.from_number(110.0)) # cleanup time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1) assert self.debt_auction_house.settle_auction(auction_id).transact()
def test_should_restart_auction_if_auction_expired_due_to_total_auction_length( self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) # when self.keeper.check_all_auctions() wait_for_other_threads() # then model_factory.create_model.assert_called_once() model.terminate.assert_not_called() # when time_travel_by(self.web3, self.debt_auction_house.total_auction_length() + 1) # and simulate_model_output(model=model, price=Wad.from_number(555.0)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then model.terminate.assert_not_called() auction = self.debt_auction_house.bids(auction_id) assert round( auction.bid_amount * self.geb.oracle_relayer.redemption_price() / Rad(auction.amount_to_sell), 2) == round(Rad.from_number(555.0), 2) # cleanup time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1) model_factory.create_model.assert_called_once() self.keeper.check_all_auctions() model.terminate.assert_called_once()
def test_should_bid_even_if_there_is_already_a_bidder(self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) prot_before = self.geb.prot.balance_of(self.keeper_address) # and amount_to_sell = Wad.from_number(0.000016) assert self.debt_auction_house.decrease_sold_amount( auction_id, amount_to_sell, self.debt_auction_bid_size).transact( from_address=self.other_address) assert self.debt_auction_house.bids( auction_id).amount_to_sell == amount_to_sell # when simulate_model_output(model=model, price=Wad.from_number(825.0)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then auction = self.debt_auction_house.bids(auction_id) assert auction.amount_to_sell != amount_to_sell assert round( auction.bid_amount * self.geb.oracle_relayer.redemption_price() / Rad(auction.amount_to_sell), 2) == round(Rad.from_number(825.0), 2) prot_after = self.geb.prot.balance_of(self.keeper_address) assert prot_before == prot_after # cleanup time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1) assert self.debt_auction_house.settle_auction(auction_id).transact()
def test_should_not_bid_on_rounding_errors_with_small_amounts( self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) # when simulate_model_output(model=model, price=Wad.from_number(1400.0)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then assert self.debt_auction_house.bids(auction_id).amount_to_sell == Wad( self.debt_auction_bid_size * self.geb.oracle_relayer.redemption_price() / Rad.from_number(1400.0)) # when tx_count = self.web3.eth.getTransactionCount( self.keeper_address.address) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then assert self.web3.eth.getTransactionCount( self.keeper_address.address) == tx_count
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 test_prepare_coins_for_redeeming(self, geb, our_address): assert geb.global_settlement.coin_bag(our_address) == Wad(0) assert geb.global_settlement.outstanding_coin_supply() > Rad(0) assert geb.system_coin.approve( geb.global_settlement.address).transact() assert geb.safe_engine.coin_balance(our_address) >= Rad.from_number(10) # FIXME: `prepareCoinsForRedeeming` fails, possibly because we're passing 0 to `safeEngine.transfer_collateral` assert geb.global_settlement.prepare_coins_for_redeeming( Wad.from_number(10)).transact() assert geb.global_settlement.coin_bag(our_address) == Wad.from_number( 10)
def test_should_cast_to_int(self): assert int(Rad.from_number(-4.5)) == -4 assert int(Rad.from_number(0.99)) == 0 assert int(Rad.from_number(1)) == 1 assert int(Rad.from_number(1.0)) == 1 assert int(Rad.from_number(1.5)) == 1 assert int(Rad.from_number(1.9999999999)) == 1
def test_should_cast_to_float(self): assert float(Rad.from_number(-4.5)) == -4.5 assert float(Rad.from_number(0.99)) == 0.99 assert float(Rad.from_number(1)) == 1.0 assert float(Rad.from_number(1.0)) == 1.0 assert float(Rad.from_number(1.5)) == 1.5 assert float(Rad.from_number(1.9999999999)) == 1.9999999999
def pop_debt_and_settle_debt(web3: Web3, geb: GfDeployment, past_blocks=8, cancel_auctioned_debt=True, require_settle_debt=True): # Raise debt from the queue (note that accounting_engine.wait is 0 on our testchain) liquidations = geb.liquidation_engine.past_liquidations(past_blocks) for liquidation in liquidations: block_time_liquidation = liquidation.block_time(web3) debt_queue = geb.accounting_engine.debt_queue_of( block_time_liquidation) if debt_queue > Rad(0): print( f'popping debt era={block_time_liquidation} from block={liquidation.raw["blockNumber"]} ' f'with debt_queue={str(geb.accounting_engine.debt_queue_of(block_time_liquidation))}' ) assert geb.accounting_engine.pop_debt_from_queue( block_time_liquidation).transact() assert geb.accounting_engine.debt_queue_of( block_time_liquidation) == Rad(0) # Ensure there is no on-auction debt which a previous test failed to clean up if cancel_auctioned_debt and geb.accounting_engine.total_on_auction_debt( ) > Rad.from_number(0): assert geb.accounting_engine.cancel_auctioned_debt_with_surplus( geb.accounting_engine.total_on_auction_debt()).transact() assert geb.accounting_engine.total_on_auction_debt( ) == Rad.from_number(0) # Cancel out surplus and debt total_surplus = geb.safe_engine.coin_balance(geb.accounting_engine.address) unqueued_unauctioned_debt = geb.accounting_engine.unqueued_unauctioned_debt( ) if require_settle_debt: assert total_surplus <= unqueued_unauctioned_debt if total_surplus <= unqueued_unauctioned_debt: assert geb.accounting_engine.settle_debt(total_surplus).transact()
def open_safe(geb: GfDeployment, collateral: Collateral, address: Address): assert isinstance(geb, GfDeployment) assert isinstance(collateral, Collateral) assert isinstance(address, Address) collateral.approve(address) wrap_eth(geb, address, Wad.from_number(10)) assert collateral.adapter.join( address, Wad.from_number(10)).transact(from_address=address) wrap_modify_safe_collateralization(geb, collateral, address, Wad.from_number(10), Wad.from_number(15)) assert geb.safe_engine.global_debt() >= Rad(Wad.from_number(15)) assert geb.safe_engine.coin_balance(address) >= Rad.from_number(10)
class MockDebtAuctionHouse: bid_amount = Rad.from_number(50000) debt_auction_bid_size = Wad.from_number(50000) def __init__(self): self.total_auction_length = 259200 self.bid_duration = 21600 self.amount_to_sell = self.debt_auction_bid_size pass def bids(self, id: int): return DebtAuctionHouse.Bid( id=id, bid_amount=self.bid_amount, amount_to_sell=self.amount_to_sell, high_bidder=Address("0x0000000000000000000000000000000000000000"), bid_expiry=0, auction_deadline=int(datetime.now(tz=timezone.utc).timestamp()) + self.total_auction_length)
def test_balance_added_after_startup(self, mocker): try: # given collateral balances after starting keeper token_balance_before = self.get_system_coin_token_balance() self.create_keeper(mocker) time.sleep(6) # wait for keeper to join everything on startup safe_engine_balance_before = self.get_system_coin_safe_engine_balance( ) assert self.get_system_coin_token_balance() == Wad(0) assert safe_engine_balance_before == Wad(0) # when adding SystemCoin purchase_system_coin(Wad.from_number(77), self.keeper_address) assert self.get_system_coin_token_balance() == Wad.from_number(77) # and pretending there's a bid which requires SystemCoin reservoir = Reservoir( self.keeper.safe_engine.coin_balance(self.keeper_address)) assert self.keeper.check_bid_cost(id=1, cost=Rad.from_number(20), reservoir=reservoir) # then ensure all SystemCoin is joined assert self.get_system_coin_token_balance() == Wad(0) assert self.get_system_coin_safe_engine_balance( ) == Wad.from_number(77) # when adding more SystemCoin and pretending there's a bid we cannot cover purchase_system_coin(Wad.from_number(23), self.keeper_address) assert self.get_system_coin_token_balance() == Wad.from_number(23) reservoir = Reservoir( self.keeper.safe_engine.coin_balance(self.keeper_address)) assert not self.keeper.check_bid_cost( id=2, cost=Rad(Wad.from_number(120)), reservoir=reservoir) # then ensure the added SystemCoin was joined anyway assert self.get_system_coin_token_balance() == Wad(0) assert self.get_system_coin_safe_engine_balance( ) == Wad.from_number(100) finally: self.shutdown_keeper() self.give_away_system_coin()
def test_fixed_system_coin_target(self, mocker): try: # given a keeper configured to maintained a fixed amount of SystemCoin target = Wad.from_number(100) purchase_system_coin(target * 2, self.keeper_address) assert self.get_system_coin_token_balance() == Wad.from_number(200) self.create_keeper(mocker, target) time.sleep(6) # wait for keeper to join 100 on startup safe_engine_balance_before = self.get_system_coin_safe_engine_balance( ) assert safe_engine_balance_before == target # when spending SystemCoin assert self.keeper.system_coin_join.exit( self.keeper_address, Wad.from_number(22)).transact() assert self.get_system_coin_safe_engine_balance( ) == Wad.from_number(78) # and pretending there's a bid which requires more SystemCoin reservoir = Reservoir( self.keeper.safe_engine.coin_balance(self.keeper_address)) assert self.keeper.check_bid_cost(id=3, cost=Rad.from_number(79), reservoir=reservoir) # then ensure SystemCoin was joined up to the target assert self.get_system_coin_safe_engine_balance() == target # when pretending there's a bid which we have plenty of SystemCoin to cover reservoir = Reservoir( self.keeper.safe_engine.coin_balance(self.keeper_address)) assert self.keeper.check_bid_cost(id=4, cost=Rad(Wad.from_number(1)), reservoir=reservoir) # then ensure SystemCoin levels haven't changed assert self.get_system_coin_safe_engine_balance() == target finally: self.shutdown_keeper()
def test_should_make_initial_bid(self): # given auction_id = self.debt_auction_house.auctions_started() (model, model_factory) = models(self.keeper, auction_id) prot_before = self.geb.prot.balance_of(self.keeper_address) # when simulate_model_output(model=model, price=Wad.from_number(575.0)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # then auction = self.debt_auction_house.bids(auction_id) assert round( auction.bid_amount * self.geb.oracle_relayer.redemption_price() / Rad(auction.amount_to_sell), 2) == round(Rad.from_number(575.0), 2) prot_after = self.geb.prot.balance_of(self.keeper_address) assert prot_before == prot_after # cleanup time_travel_by(self.web3, self.debt_auction_house.bid_duration() + 1) assert self.debt_auction_house.settle_auction(auction_id).transact()
def test_healthy_safe(self, web3, geb, our_address): collateral = geb.collaterals['ETH-B'] collateral_type = collateral.collateral_type TestSAFEEngine.ensure_clean_safe(geb, collateral, our_address) initial_system_coin = geb.safe_engine.coin_balance(our_address) wrap_eth(geb, our_address, Wad.from_number(90)) # Ensure our collateral enters the safe collateral_balance_before = collateral.collateral.balance_of( our_address) collateral.approve(our_address) assert collateral.adapter.join(our_address, Wad.from_number(90)).transact() assert collateral.collateral.balance_of( our_address) == collateral_balance_before - Wad.from_number(90) # Add collateral without generating system coin wrap_modify_safe_collateralization( geb, collateral, our_address, delta_collateral=Wad.from_number(30), delta_debt=Wad(0)) print( f"After adding collateral: {geb.safe_engine.safe(collateral_type, our_address)}" ) assert geb.safe_engine.safe( collateral_type, our_address).locked_collateral == Wad.from_number(30) assert geb.safe_engine.safe(collateral_type, our_address).generated_debt == Wad(0) assert geb.safe_engine.token_collateral( collateral_type, our_address) == Wad.from_number(90) - geb.safe_engine.safe( collateral_type, our_address).locked_collateral assert geb.safe_engine.coin_balance(our_address) == initial_system_coin # Generate some system coin wrap_modify_safe_collateralization(geb, collateral, our_address, delta_collateral=Wad(0), delta_debt=Wad.from_number(153)) return print( f"After generating system_coin: {geb.safe_engine.safe(collateral_type, our_address)}" ) assert geb.safe_engine.safe( collateral_type, our_address).locked_collateral == Wad.from_number(30) assert geb.safe_engine.safe( collateral_type, our_address).generated_debt == Wad.from_number(153) assert geb.safe_engine.coin_balance( our_address) == initial_system_coin + Rad.from_number(153) # Add collateral and generate some more system coin wrap_modify_safe_collateralization( geb, collateral, our_address, delta_collateral=Wad.from_number(60), delta_debt=Wad.from_number(180)) print( f"After adding collateral and system_coin: {geb.safe_engine.safe(collateral_type, our_address)}" ) assert geb.safe_engine.safe( collateral_type, our_address).locked_collateral == Wad.from_number(90) assert geb.safe_engine.token_collateral(collateral_type, our_address) == Wad(0) assert geb.safe_engine.safe( collateral_type, our_address).generated_debt == Wad.from_number(333) assert geb.safe_engine.coin_balance( our_address) == initial_system_coin + Rad.from_number(333) # Mint and withdraw our system coin system_coin_balance_before = geb.system_coin.balance_of(our_address) geb.approve_system_coin(our_address) assert isinstance(geb.system_coin_adapter, CoinJoin) assert geb.system_coin_adapter.exit(our_address, Wad.from_number(333)).transact() assert geb.system_coin.balance_of( our_address) == system_coin_balance_before + Wad.from_number(333) assert geb.safe_engine.coin_balance(our_address) == initial_system_coin assert geb.safe_engine.global_debt( ) >= initial_system_coin + Rad.from_number(333) # Repay (and burn) our system coin assert geb.system_coin_adapter.join(our_address, Wad.from_number(333)).transact() assert geb.system_coin.balance_of(our_address) == Wad(0) assert geb.safe_engine.coin_balance( our_address) == initial_system_coin + Rad.from_number(333) # Withdraw our collateral wrap_modify_safe_collateralization(geb, collateral, our_address, delta_collateral=Wad(0), delta_debt=Wad.from_number(-333)) wrap_modify_safe_collateralization( geb, collateral, our_address, delta_collateral=Wad.from_number(-90), delta_debt=Wad(0)) assert geb.safe_engine.token_collateral( collateral_type, our_address) == Wad.from_number(90) assert collateral.adapter.exit(our_address, Wad.from_number(90)).transact() collateral_balance_after = collateral.collateral.balance_of( our_address) assert collateral_balance_before == collateral_balance_after # Cleanup cleanup_safe(geb, collateral, our_address)
auction_state = json.loads(auction_input) # If we are already the high bidder, do nothing if auction_state['high_bidder'] == os.environ['KEEPER_ADDRESS']: continue # Ensure our custom bid increase is at least the minimum allowed MY_BID_DECREASE = max(Wad.from_number(MY_BID_DECREASE), Wad.from_number(auction_state['bid_decrease'])) # Add slight amount to account for possible redemption price change between the time of model output and bid placement MY_BID_DECREASE += Wad.from_number(1e-4) # Bid price using `MY_BID_INCREASE` my_bid_amount = Wad.from_number(auction_state['amount_to_sell']) / MY_BID_DECREASE # Round up from Rad to Wad my_bid_price = Wad(Rad.from_number(auction_state['bid_amount']) * redemption_price / Rad(my_bid_amount)) + Wad(1) # Bid price using minimum bid increase allowed min_bid_amount = Wad.from_number(auction_state['amount_to_sell']) / Wad.from_number(auction_state['bid_decrease']) # Round up from Rad to Wad min_bid_price = Wad(Rad.from_number(auction_state['bid_amount']) * redemption_price / Rad(min_bid_amount)) + Wad(1) # Try our bid increase first # If price is too low, then try minimum bid increase if my_bid_price <= Wad.from_number(MAXIMUM_FLX_MULTIPLIER * current_flx_usd_price): bid = {'price': str(my_bid_price)} print(json.dumps(bid), flush=True) elif min_bid_price <= Wad.from_number(MAXIMUM_FLX_MULTIPLIER * current_flx_usd_price): bid = {'price': str(min_bid_price)} print(json.dumps(bid), flush=True)
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 test_should_instantiate_from_a_wad(self): assert Rad(Wad(10000000000000000000)) == Rad.from_number(10)
def test_should_instantiate_from_a_ray(self): assert Rad(Ray.from_number(10)) == Rad.from_number(10)
def test_multiply(self): assert Rad.from_number(2) * Rad.from_number(3) == Rad.from_number(6) assert Rad.from_number(2) * Rad(3) == Rad(6) assert Rad.from_number(2.5) * Rad(3) == Rad(7) assert Rad.from_number(2.99999) * Rad(3) == Rad(8)
def test_should_have_nice_printable_representation(self): for ray in [Rad(1), Rad(100), Rad.from_number(2.5), Rad(-1)]: assert repr(ray) == f"Rad({ray.value})"
def test_multiply_by_wad(self): assert Rad.from_number(2) * Wad.from_number(3) == Rad.from_number(6) assert Rad.from_number(2) * Wad(3) == Rad(6000000000000000000000000000) assert Rad(2) * Wad(3) == Rad(0) assert Rad(2) * Wad(999999999999999999) == Rad(1) assert Rad(2) * Wad(1000000000000000000) == Rad(2)
def test_multiply_by_ray(self): assert Rad.from_number(2) * Ray.from_number(3) == Rad.from_number(6) assert Rad.from_number(2) * Ray(3) == Rad(6000000000000000000) assert Rad(2) * Ray(3) == Rad(0) assert Rad(2) * Ray(999999999999999999999999999) == Rad(1) assert Rad(2) * Ray(1000000000000000000000000000) == Rad(2)
def test_multiply_by_int(self): assert Rad.from_number(2) * 3 == Rad.from_number(6) assert Rad.from_number(2) * 1 == Rad.from_number(2)
def test_should_provide_model_with_updated_info_after_our_partial_bid(self, auction_id): # 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() initial_status = collateral_auction_house.bids(model.id) # then assert model.send_status.call_count == 1 # when bidding less than the full amount our_balance = Wad(initial_status.amount_to_raise) / Wad.from_number(2) reserve_system_coin(self.geb, self.collateral, self.keeper_address, our_balance) assert initial_status.amount_to_raise != Rad(0) assert self.geb.safe_engine.coin_balance(self.keeper_address) > Rad(0) # Make our balance lte half of the auction size half_amount_to_raise = initial_status.amount_to_raise / Rad.from_number(2) if self.geb.safe_engine.coin_balance(self.keeper_address) >= half_amount_to_raise: burn_amount = self.geb.safe_engine.coin_balance(self.keeper_address) - half_amount_to_raise assert burn_amount < self.geb.safe_engine.coin_balance(self.keeper_address) self.geb.safe_engine.transfer_internal_coins(self.keeper_address, Address("0x0000000000000000000000000000000000000000"), burn_amount).transact() assert self.geb.safe_engine.coin_balance(self.keeper_address) <= half_amount_to_raise assert self.geb.safe_engine.coin_balance(self.keeper_address) > Rad(0) simulate_model_output(model=model, price=None) self.keeper.check_for_bids() # and checking auction status and sending auction status to model self.keeper.check_all_auctions() wait_for_other_threads() # and self.keeper.check_all_auctions() wait_for_other_threads() # then assert model.send_status.call_count > 1 # ensure our bid was processed current_status = collateral_auction_house.bids(model.id) assert current_status.amount_to_raise == initial_status.amount_to_raise assert current_status.amount_to_sell == initial_status.amount_to_sell assert current_status.auction_deadline == initial_status.auction_deadline assert current_status.raised_amount == Rad(our_balance) # and the last status sent to our model reflects our bid 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.amount_to_sell == initial_status.amount_to_sell assert status.amount_to_raise == initial_status.amount_to_raise assert status.raised_amount == Rad(our_balance) assert status.auction_deadline == initial_status.auction_deadline # and auction is still active final_status = collateral_auction_house.bids(model.id) assert final_status.amount_to_raise == initial_status.amount_to_raise assert final_status.amount_to_sell == initial_status.amount_to_sell assert final_status.auction_deadline == initial_status.auction_deadline assert final_status.raised_amount == Rad(our_balance) #cleanup our_balance = Wad(initial_status.amount_to_raise) + Wad(1) reserve_system_coin(self.geb, self.collateral, self.keeper_address, our_balance) assert self.geb.safe_engine.coin_balance(self.keeper_address) >= initial_status.amount_to_raise simulate_model_output(model=model, price=None) self.keeper.check_for_bids() self.keeper.check_all_auctions() wait_for_other_threads() # ensure auction has been deleted current_status = collateral_auction_house.bids(model.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 test_should_replace_pending_transactions_if_model_raises_bid_and_increases_gas_price(self, auction_id): # given (model, model_factory) = models(self.keeper, auction_id) amount_to_sell = self.surplus_auction_house.bids(auction_id).amount_to_sell # when simulate_model_output(model=model, price=Wad.from_number(9.0), gas_price=10) # and self.start_ignoring_transactions() # and self.keeper.check_all_auctions() self.keeper.check_for_bids() # and self.end_ignoring_transactions() # and simulate_model_output(model=model, price=Wad.from_number(8.0), gas_price=15) # and self.keeper.check_for_bids() wait_for_other_threads() # then assert round(self.surplus_auction_house.bids(auction_id).bid_amount, 2) == round(Wad(amount_to_sell / Rad.from_number(8.0)), 2) assert self.web3.eth.getBlock('latest', full_transactions=True).transactions[0].gasPrice == 15 # cleanup time_travel_by(self.web3, self.surplus_auction_house.bid_duration() + 1) assert self.surplus_auction_house.settle_auction(auction_id).transact()
def test_round(self): assert round(Rad.from_number(123.4567), 2) == Rad.from_number(123.46) assert round(Rad.from_number(123.4567), 0) == Rad.from_number(123.0) assert round(Rad.from_number(123.4567), -2) == Rad.from_number(100.0)
def test_should_provide_model_with_updated_info_after_our_own_bid(self): # given auction_id = self.surplus_auction_house.auctions_started() (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 simulate_model_output(model=model, price=Wad.from_number(9)) # and self.keeper.check_all_auctions() self.keeper.check_for_bids() wait_for_other_threads() # 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 is None assert status.surplus_auction_house == self.surplus_auction_house.address assert status.debt_auction_house is None assert status.bid_amount == Wad(self.surplus_auction_house.bids(auction_id).amount_to_sell * self.geb.oracle_relayer.redemption_price() / Rad.from_number(9)) assert status.amount_to_sell == self.geb.accounting_engine.surplus_auction_amount_to_sell() assert status.amount_to_raise is None assert status.bid_increase == self.geb.surplus_auction_house.bid_increase() assert status.high_bidder == self.keeper_address assert status.block_time > 0 assert status.auction_deadline > status.block_time assert status.bid_expiry > status.block_time assert round(status.price, 2) == round(Wad.from_number(9), 2) # cleanup time_travel_by(self.web3, self.surplus_auction_house.bid_duration() + 1) assert self.surplus_auction_house.settle_auction(auction_id).transact()