def test_should_ignore_orders_owned_by_others(self, deployment: Deployment): # given keeper = OasisMarketMakerCancel(args=args(f"--eth-from {deployment.web3.eth.defaultAccount} " f"--oasis-address {deployment.otc.address}"), web3=deployment.web3) # and DSToken(web3=deployment.web3, address=deployment.gem.address).mint(Wad.from_number(1000)).transact() DSToken(web3=deployment.web3, address=deployment.sai.address).mint(Wad.from_number(1000)).transact() # and deployment.gem.transfer(Address(deployment.web3.eth.accounts[1]), Wad.from_number(500)).transact() deployment.sai.transfer(Address(deployment.web3.eth.accounts[1]), Wad.from_number(500)).transact() # and deployment.otc.approve([deployment.gem, deployment.sai], directly()) deployment.otc.make(deployment.gem.address, Wad.from_number(10), deployment.sai.address, Wad.from_number(5)).transact() # and deployment.web3.eth.defaultAccount = deployment.web3.eth.accounts[1] deployment.otc.approve([deployment.gem, deployment.sai], directly()) deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(12)).transact() deployment.web3.eth.defaultAccount = deployment.web3.eth.accounts[0] # and assert len(deployment.otc.get_orders()) == 2 # when keeper.main() # then assert len(deployment.otc.get_orders()) == 1 assert deployment.otc.get_orders()[0].maker == Address(deployment.web3.eth.accounts[1])
def test_should_cancel_all_orders_but_not_terminate_if_market_gets_closed(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # when deployment.otc._contract.transact().stop() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 0 assert not keeper.lifecycle.terminated_internally
def test_should_cancel_orders_on_shutdown(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 # when keeper.shutdown() # then assert len(deployment.otc.get_orders()) == 0
def test_should_use_specified_gas_price_for_all_transactions(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file} " f"--gas-price 70000000000"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and start_block_number = deployment.web3.eth.blockNumber # when keeper.approve() self.synchronize_orders_twice(keeper) keeper.shutdown() # then for block_number in range(start_block_number+1, deployment.web3.eth.blockNumber+1): for transaction in deployment.web3.eth.getBlock(block_number, full_transactions=True).transactions: assert transaction.gasPrice == 70000000000
def test_should_not_create_any_orders_but_not_terminate_if_eth_balance_before_minimum(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.two_adjacent_bands_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file} " f"--min-eth-balance 100.0"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and self.leave_only_some_eth(deployment, Wad.from_number(10.0)) # there is a 5.0 ETH block reward even in testrpc, # that's why `--min-eth-balance` is higher than 10 # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 0 assert not keeper.lifecycle.terminated_internally
def test_should_support_config_files_with_variables(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.with_variables_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 1 # and assert self.orders_by_token(deployment, deployment.gem)[0].maker == deployment.our_address assert self.orders_by_token(deployment, deployment.gem)[0].pay_amount == Wad.from_number(5.0) assert self.orders_by_token(deployment, deployment.gem)[0].pay_token == deployment.gem.address assert self.orders_by_token(deployment, deployment.gem)[0].buy_amount == Wad.from_number(520) assert self.orders_by_token(deployment, deployment.gem)[0].buy_token == deployment.sai.address
def test_should_place_extra_order_only_if_order_brought_below_min(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 sai_order_id = self.orders_by_token(deployment, deployment.sai)[0].order_id # when deployment.otc.take(sai_order_id, Wad.from_number(20)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # when deployment.otc.take(sai_order_id, Wad.from_number(5)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # when deployment.otc.take(sai_order_id, Wad.from_number(1)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 3 assert deployment.otc.get_orders()[2].pay_amount == Wad.from_number(26) assert deployment.otc.get_orders()[2].pay_token == deployment.sai.address assert deployment.otc.get_orders()[2].buy_amount == Wad(270833333333333333) assert deployment.otc.get_orders()[2].buy_token == deployment.gem.address
def test_should_cancel_selected_sell_orders_to_bring_the_band_total_below_max_and_closest_to_it(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 # when [7.5+2.0 = 9.5] deployment.otc.make(deployment.gem.address, Wad.from_number(2), deployment.sai.address, Wad.from_number(208)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 3 # when [9.5+0.5 = 10] deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(52)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 4 # when [10+0.1 = 10.1] --> above max! deployment.otc.make(deployment.gem.address, Wad.from_number(0.1), deployment.sai.address, Wad.from_number(10.4)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 4 assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(deployment, deployment.gem)), Wad(0)) \ == Wad.from_number(10.0)
def test_should_cancel_the_only_buy_order_and_place_a_new_one_if_above_max( self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() # and # [one artificially created order above the max band threshold] deployment.otc.make(deployment.sai.address, Wad.from_number(170), deployment.gem.address, Wad.from_number(1.770805)).transact() # when self.synchronize_orders_twice(keeper) # then # [the artificial order gets cancelled, a new one gets created instead] assert len(deployment.otc.get_orders()) == 2 assert self.orders_by_token( deployment, deployment.sai)[0].maker == deployment.our_address assert self.orders_by_token( deployment, deployment.sai)[0].pay_amount == Wad.from_number(75) assert self.orders_by_token( deployment, deployment.sai)[0].pay_token == deployment.sai.address assert self.orders_by_token( deployment, deployment.sai)[0].buy_amount == Wad.from_number(0.78125) assert self.orders_by_token( deployment, deployment.sai)[0].buy_token == deployment.gem.address
def test_should_support_config_files_with_variables( self, deployment: Deployment, tmpdir: py.path.local): # given config_file = BandConfig.with_variables_config(tmpdir) # and keeper = EtherDeltaMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} --config {config_file}" f" --tub-address {deployment.tub.address}" f" --etherdelta-address {deployment.etherdelta.address}" f" --etherdelta-socket https://127.0.0.1:99999/" f" --order-age 3600 --eth-reserve 10" f" --min-eth-deposit 1 --min-sai-deposit 400" f" --cancel-on-shutdown --withdraw-on-shutdown"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) keeper.etherdelta_api.publish_order = MagicMock() # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed # then assert len(self.orders(keeper)) == 1 # and assert self.orders_by_token( keeper, EtherDelta.ETH_TOKEN)[0].maker == deployment.our_address assert self.orders_by_token( keeper, EtherDelta.ETH_TOKEN)[0].pay_amount == Wad.from_number(5.0) assert self.orders_by_token( keeper, EtherDelta.ETH_TOKEN)[0].pay_token == EtherDelta.ETH_TOKEN assert self.orders_by_token( keeper, EtherDelta.ETH_TOKEN)[0].buy_amount == Wad.from_number(520) assert self.orders_by_token( keeper, EtherDelta.ETH_TOKEN)[0].buy_token == deployment.sai.address
def test_should_cancel_all_orders_outside_bands(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 # when deployment.otc.make( deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0538)).transact() #price=92.936802973977695 deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0505)).transact() #price=99.0 deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(50.5)).transact() #price=101 deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(53.5)).transact() #price=107 assert len(deployment.otc.get_orders()) == 6 # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2
def setup_method(self): self.web3 = web3() self.our_address = our_address(self.web3) self.keeper_address = keeper_address(self.web3) self.other_address = other_address(self.web3) self.gal_address = gal_address(self.web3) self.mcd = mcd(self.web3) self.flapper = self.mcd.flapper self.flapper.approve(self.mcd.mkr.address, directly(from_address=self.other_address)) self.keeper = AuctionKeeper(args=args(f"--eth-from {self.keeper_address} " f"--type flap " f"--from-block 1 " f"--bid-check-interval 0.05 " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() mint_mkr(self.mcd.mkr, self.keeper_address, Wad.from_number(50000)) mint_mkr(self.mcd.mkr, self.other_address, Wad.from_number(50000))
def test_should_bite_unsafe_cups_only(self, deployment: Deployment): # given keeper = BiteKeeper(args=args( f"--eth-from {deployment.web3.eth.defaultAccount} --tub-address {deployment.tub.address}" ), web3=deployment.web3) # and deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # and assert deployment.tub.safe(1) # when keeper.check_all_cups() # then assert deployment.tub.safe(1) assert deployment.tub.tab(1) == Wad.from_number(1000) # when DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(150).value).transact() # and assert not deployment.tub.safe(1) # and keeper.check_all_cups() # then assert deployment.tub.safe(1) assert deployment.tub.tab(1) == Wad.from_number(0)
def test_should_cancel_all_orders_but_not_terminate_if_eth_balance_before_minimum( self, deployment: Deployment, tmpdir: py.path.local): # given config_file = BandConfig.two_adjacent_bands_config(tmpdir) # and keeper = EtherDeltaMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} --config {config_file}" f" --tub-address {deployment.tub.address}" f" --etherdelta-address {deployment.etherdelta.address}" f" --etherdelta-socket https://127.0.0.1:99999/" f" --order-age 3600 --eth-reserve 200" f" --min-eth-balance 100.0" f" --min-eth-deposit 1 --min-sai-deposit 400"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) keeper.etherdelta_api.publish_order = MagicMock() # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed # then assert len(self.orders(keeper)) == 2 # when self.leave_only_some_eth(deployment, Wad.from_number( 10.0)) # there is a 5.0 ETH block reward even in testrpc, # that's why `--min-eth-balance` is higher than 10 # and keeper.synchronize_orders() # then assert len(self.orders(keeper)) == 0 assert not keeper.lifecycle.terminated_internally
def create_keeper(self, exit_dai_on_shutdown: bool, exit_gem_on_shutdown: bool): assert isinstance(exit_dai_on_shutdown, bool) assert isinstance(exit_gem_on_shutdown, bool) vat_dai_behavior = "" if exit_dai_on_shutdown else "--keep-dai-in-vat-on-exit" vat_gem_behavior = "" if exit_gem_on_shutdown else "--keep-gem-in-vat-on-exit" keeper = AuctionKeeper(args=args(f"--eth-from {self.keeper_address} " f"--type flop " f"--network testnet " f"{vat_dai_behavior} " f"{vat_gem_behavior} " f"--model ./bogus-model.sh"), web3=self.web3) assert self.web3.eth.defaultAccount == self.keeper_address.address assert keeper.arguments.exit_dai_on_shutdown == exit_dai_on_shutdown keeper.startup() return keeper
def test_should_reload_config_file_if_changed(self, deployment: Deployment, tmpdir: py.path.local): # given config_file = BandConfig.with_variables_config(tmpdir) # and keeper = EtherDeltaMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} --config {config_file}" f" --tub-address {deployment.tub.address}" f" --etherdelta-address {deployment.etherdelta.address}" f" --etherdelta-socket https://127.0.0.1:99999/" f" --order-age 3600 --eth-reserve 10" f" --min-eth-deposit 1 --min-sai-deposit 400"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) keeper.etherdelta_api.publish_order = MagicMock() # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed # then assert len(self.orders(keeper)) == 1 # when second_config_file = BandConfig.sample_config(tmpdir) shutil.copyfile(second_config_file, config_file) # and keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed # then assert len(self.orders(keeper)) == 2
def test_should_cancel_selected_sell_orders_to_bring_the_band_total_below_max_and_closest_to_it(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 # when [7.5+2.0 = 9.5] deployment.otc.make(deployment.gem.address, Wad.from_number(2), deployment.sai.address, Wad.from_number(208)).transact() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 3 # when [9.5+0.5 = 10] deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(52)).transact() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 4 # when [10+0.1 = 10.1] --> above max! deployment.otc.make(deployment.gem.address, Wad.from_number(0.1), deployment.sai.address, Wad.from_number(10.4)).transact() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 4 assert reduce(Wad.__add__, map(lambda order: order.pay_amount, self.orders_by_token(deployment, deployment.gem)), Wad(0)) \ == Wad.from_number(10.0)
def test_should_not_do_anything_if_no_arbitrage_opportunities( self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 1.0 --max-engagement 1000.0"), web3=deployment.web3) DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tap.mold_gap(Wad.from_number(1.05)).transact() # when keeper.approve() keeper.process_block()
def create_keeper(self, exit_dai_on_shutdown: bool, exit_gem_on_shutdown: bool): assert isinstance(exit_dai_on_shutdown, bool) assert isinstance(exit_gem_on_shutdown, bool) vat_dai_behavior = "" if exit_dai_on_shutdown else "--keep-dai-in-vat-on-exit" vat_gem_behavior = "" if exit_gem_on_shutdown else "--keep-gem-in-vat-on-exit" keeper = AuctionKeeper(args=args(f"--eth-from {self.keeper_address} " f"--type flip --ilk {self.collateral.ilk.name} " f"--from-block 1 " f"{vat_dai_behavior} " f"{vat_gem_behavior} " f"--model ./bogus-model.sh"), web3=self.web3) self.web3 = keeper.web3 self.mcd = keeper.mcd assert self.web3.eth.defaultAccount == self.keeper_address.address assert keeper.arguments.exit_dai_on_shutdown == exit_dai_on_shutdown assert keeper.arguments.exit_gem_on_shutdown == exit_gem_on_shutdown keeper.startup() return keeper
def test_should_cancel_orders_on_shutdown_and_withdraw_if_asked_to_do_so( self, deployment: Deployment, tmpdir: py.path.local): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = EtherDeltaMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} --config {config_file}" f" --tub-address {deployment.tub.address}" f" --etherdelta-address {deployment.etherdelta.address}" f" --etherdelta-socket https://127.0.0.1:99999/" f" --order-age 3600 --eth-reserve 10" f" --min-eth-deposit 1 --min-sai-deposit 400" f" --cancel-on-shutdown --withdraw-on-shutdown"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) keeper.etherdelta_api.publish_order = MagicMock() # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed assert len(self.orders(keeper)) == 2 # when keeper.shutdown() # then assert len(self.orders(keeper)) == 0 # and assert deployment.etherdelta.balance_of( deployment.our_address) == Wad(0) assert deployment.etherdelta.balance_of_token( deployment.sai.address, deployment.our_address) == Wad(0)
def create_keeper(self, mocker, dai_target="all"): # Create a keeper mocker.patch("web3.net.Net.peer_count", return_value=1) self.keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--type flip --ilk ETH-C --bid-only " f"--vat-dai-target {dai_target} " f"--return-gem-interval 3 " f"--model ./bogus-model.sh"), web3=self.web3) assert self.web3.eth.defaultAccount == self.keeper_address.address self.web3 = self.keeper.web3 self.mcd = self.keeper.mcd assert self.keeper.auctions # Changed the collateral to ETH-C because our testchain didn't have dust set for ETH-A or ETH-B self.collateral = self.keeper.collateral self.collateral.approve(self.keeper_address) self.thread = threading.Thread(target=self.keeper.main, daemon=True) self.thread.start() return self.keeper
def test_should_cancel_orders_owned_by_us(self, deployment: Deployment): # given keeper = OasisMarketMakerCancel(args=args(f"--eth-from {deployment.web3.eth.defaultAccount} " f"--oasis-address {deployment.otc.address}"), web3=deployment.web3) # and DSToken(web3=deployment.web3, address=deployment.gem.address).mint(Wad.from_number(1000)).transact() DSToken(web3=deployment.web3, address=deployment.sai.address).mint(Wad.from_number(1000)).transact() # and deployment.otc.approve([deployment.gem, deployment.sai], directly()) deployment.otc.make(deployment.gem.address, Wad.from_number(10), deployment.sai.address, Wad.from_number(5)).transact() deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(12)).transact() assert len(deployment.otc.get_orders()) == 2 # when keeper.main() # then assert len(deployment.otc.get_orders()) == 0
def setup_method(self): self.web3 = web3() self.our_address = our_address(self.web3) self.keeper_address = keeper_address(self.web3) self.other_address = other_address(self.web3) self.gal_address = gal_address(self.web3) self.mcd = mcd(self.web3) self.flopper = self.mcd.flopper self.flopper.approve(self.mcd.vat.address, approval_function=hope_directly(from_address=self.keeper_address)) self.flopper.approve(self.mcd.vat.address, approval_function=hope_directly(from_address=self.other_address)) self.keeper = AuctionKeeper(args=args(f"--eth-from {self.keeper_address} " f"--type flop " f"--network testnet " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() reserve_dai(self.mcd, self.mcd.collaterals['ETH-C'], self.keeper_address, Wad.from_number(200.00000)) reserve_dai(self.mcd, self.mcd.collaterals['ETH-C'], self.other_address, Wad.from_number(200.00000)) self.sump = self.mcd.vow.sump() # Rad
def test_default_gas_config(self, web3, keeper_address): keeper = AuctionKeeper(args=args(f"--eth-from {keeper_address} " f"--type flop --from-block 1 " f"--model ./bogus-model.sh"), web3=web3) assert isinstance(keeper.gas_price, DynamicGasPrice) assert keeper.gas_price.initial_multiplier == 1.0 assert keeper.gas_price.reactive_multiplier == 1.125 assert keeper.gas_price.gas_maximum == default_max_gas * GWEI default_initial_gas = get_node_gas_price(web3) assert keeper.gas_price.get_gas_price(0) == default_initial_gas assert keeper.gas_price.get_gas_price( 1 + every_secs) == default_initial_gas * 1.125 assert keeper.gas_price.get_gas_price( 1 + every_secs * 2) == default_initial_gas * 1.125**2 assert keeper.gas_price.get_gas_price( 1 + every_secs * 3) == default_initial_gas * 1.125**3 assert keeper.gas_price.get_gas_price(every_secs * 80) == default_max_gas * GWEI
def test_fixed_with_explicit_max(self, web3, keeper_address): keeper = AuctionKeeper(args=args(f"--eth-from {keeper_address} " f"--type flap " f"--fixed-gas 100 " f'--gas-maximum 4000 ' f"--model ./bogus-model.sh"), web3=web3) assert isinstance(keeper.gas_price, DynamicGasPrice) assert keeper.gas_price.fixed_gas == 100 * GWEI assert keeper.gas_price.reactive_multiplier == 1.125 assert keeper.gas_price.gas_maximum == 4000 * GWEI assert keeper.gas_price.get_gas_price(0) == 100 * GWEI assert keeper.gas_price.get_gas_price(1 + every_secs) == 100 * GWEI * 1.125 assert keeper.gas_price.get_gas_price(1 + every_secs * 2) == 100 * GWEI * 1.125**2 assert keeper.gas_price.get_gas_price(1 + every_secs * 3) == 100 * GWEI * 1.125**3 assert keeper.gas_price.get_gas_price(every_secs * 60) == 4000 * GWEI
def test_should_cancel_all_orders_but_not_terminate_if_eth_balance_below_minimum( self, deployment: Deployment, tmpdir): # given config_file = BandConfig.two_adjacent_bands_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file} " f"--min-eth-balance 100.0"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # when self.leave_only_some_eth(deployment, Wad.from_number( 10.0)) # there is a 5.0 ETH block reward even in testrpc, # that's why `--min-eth-balance` is higher than 10 # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 0 assert not keeper.lifecycle.terminated_internally
def test_should_use_specified_gas_price_for_all_transactions( self, deployment: Deployment, tmpdir: py.path.local): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = EtherDeltaMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} --config {config_file}" f" --tub-address {deployment.tub.address}" f" --etherdelta-address {deployment.etherdelta.address}" f" --etherdelta-socket https://127.0.0.1:99999/" f" --order-age 3600 --eth-reserve 10" f" --min-eth-deposit 1 --min-sai-deposit 400" f" --cancel-on-shutdown" f" --gas-price 69000000000"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) keeper.etherdelta_api.publish_order = MagicMock() # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and start_block_number = deployment.web3.eth.blockNumber # when keeper.approve() keeper.synchronize_orders( ) # ... first call is so it can made deposits keeper.synchronize_orders( ) # ... second call is so the actual orders can get placed keeper.shutdown() # then for block_number in range(start_block_number + 1, deployment.web3.eth.blockNumber + 1): for transaction in deployment.web3.eth.getBlock( block_number, full_transactions=True).transactions: assert transaction.gasPrice == 69000000000
def test_should_create_orders_in_multiple_bands(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.two_adjacent_bands_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # and assert self.orders_sorted(deployment.otc.get_orders())[0].maker == deployment.our_address assert self.orders_sorted(deployment.otc.get_orders())[0].pay_amount == Wad.from_number(7.5) assert self.orders_sorted(deployment.otc.get_orders())[0].pay_token == deployment.gem.address assert self.orders_sorted(deployment.otc.get_orders())[0].buy_amount == Wad.from_number(780) assert self.orders_sorted(deployment.otc.get_orders())[0].buy_token == deployment.sai.address # and assert self.orders_sorted(deployment.otc.get_orders())[1].maker == deployment.our_address assert self.orders_sorted(deployment.otc.get_orders())[1].pay_amount == Wad.from_number(9.5) assert self.orders_sorted(deployment.otc.get_orders())[1].pay_token == deployment.gem.address assert self.orders_sorted(deployment.otc.get_orders())[1].buy_amount == Wad.from_number(1026) assert self.orders_sorted(deployment.otc.get_orders())[1].buy_token == deployment.sai.address
def test_should_create_orders_in_multiple_bands(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.two_adjacent_bands_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed eth_dai-tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # and assert self.orders_sorted(deployment.otc.get_orders())[0].maker == deployment.our_address assert self.orders_sorted(deployment.otc.get_orders())[0].pay_amount == Wad.from_number(7.5) assert self.orders_sorted(deployment.otc.get_orders())[0].pay_token == deployment.gem.address assert self.orders_sorted(deployment.otc.get_orders())[0].buy_amount == Wad.from_number(780) assert self.orders_sorted(deployment.otc.get_orders())[0].buy_token == deployment.sai.address # and assert self.orders_sorted(deployment.otc.get_orders())[1].maker == deployment.our_address assert self.orders_sorted(deployment.otc.get_orders())[1].pay_amount == Wad.from_number(9.5) assert self.orders_sorted(deployment.otc.get_orders())[1].pay_token == deployment.gem.address assert self.orders_sorted(deployment.otc.get_orders())[1].buy_amount == Wad.from_number(1026) assert self.orders_sorted(deployment.otc.get_orders())[1].buy_token == deployment.sai.address
def test_should_fail_to_operate_if_bands_overlap(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.bands_overlapping_invalid_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Web3Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() # expect with pytest.raises(Exception): self.synchronize_orders_twice(keeper)
def setup_class(cls): super().setup_class() assert cls.collateral.clipper assert not cls.collateral.flipper cls.keeper = AuctionKeeper(args=args(f"--eth-from {cls.keeper_address.address} " f"--type clip " f"--from-block 1 " f"--ilk {cls.collateral.ilk.name} " f"--model ./bogus-model.sh"), web3=cls.mcd.web3) cls.keeper.approve() # Clean up the urn used for bark testing such that it doesn't impact our flip tests assert get_collateral_price(cls.collateral) == Wad.from_number(200) if not repay_urn(cls.mcd, cls.collateral, cls.gal_address): liquidate_urn(cls.mcd, cls.collateral, cls.gal_address, cls.keeper_address) # approve another taker cls.collateral.approve(cls.other_address) cls.collateral.clipper.approve(cls.mcd.vat.address, hope_directly(from_address=cls.other_address)) assert isinstance(cls.keeper.gas_price, DynamicGasPrice) cls.default_gas_price = cls.keeper.gas_price.get_gas_price(0)
def setup_method(self): self.web3 = web3() self.our_address = our_address(self.web3) self.keeper_address = keeper_address(self.web3) self.other_address = other_address(self.web3) self.gal_address = gal_address(self.web3) self.mcd = mcd(self.web3) self.flapper = self.mcd.flapper self.flapper.approve(self.mcd.mkr.address, directly(from_address=self.other_address)) self.keeper = AuctionKeeper(args=args(f"--eth-from {self.keeper_address} " f"--type flap " f"--from-block 1 " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() mint_mkr(self.mcd.mkr, self.keeper_address, Wad.from_number(50000)) mint_mkr(self.mcd.mkr, self.other_address, Wad.from_number(50000)) assert isinstance(self.keeper.gas_price, DynamicGasPrice) # Since no args were assigned, gas strategy should return a GeometricGasPrice starting at the node gas price self.default_gas_price = get_node_gas_price(self.web3)
def setup_method(self): self.web3 = Web3(HTTPProvider("http://localhost:8555")) self.web3.eth.defaultAccount = self.web3.eth.accounts[0] self.keeper_address = Address(self.web3.eth.defaultAccount) self.gal_address = Address(self.web3.eth.accounts[1]) self.other_address = Address(self.web3.eth.accounts[2]) # GemMock version of DSToken with push(bytes32, uint function) an hope(address) gem_abi = Contract._load_abi(__name__, '../lib/pymaker/tests/abi/GemMock.abi') gem_bin = Contract._load_bin(__name__, '../lib/pymaker/tests/abi/GemMock.bin') self.dai_addr = Contract._deploy(self.web3, gem_abi, gem_bin, [b'DAI']) self.dai = DSToken(web3=self.web3, address=self.dai_addr) self.dai.mint(Wad.from_number(10000000)).transact() self.dai.transfer(self.other_address, Wad.from_number(1000000)).transact() self.mkr = DSToken.deploy(self.web3, 'MKR') self.flopper = Flopper.deploy(self.web3, self.dai.address, self.mkr.address) # so the Flopper can mint MKR dad = DSGuard.deploy(self.web3) dad.permit(self.flopper.address, self.mkr.address, DSGuard.ANY).transact() self.mkr.set_authority(dad.address).transact() self.keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--flopper {self.flopper.address} " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() self.model = MagicMock() self.model.get_stance = MagicMock(return_value=None) self.model_factory = self.keeper.auctions.model_factory self.model_factory.create_model = MagicMock(return_value=self.model)
def test_should_cancel_all_orders_but_not_terminate_if_config_file_becomes_invalid( self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2 # when second_config_file = BandConfig.bands_overlapping_invalid_config( tmpdir) shutil.copyfile(second_config_file, config_file) # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 0 assert not keeper.lifecycle.terminated_internally
def test_should_support_config_files_with_variables( self, deployment: Deployment, tmpdir): # given config_file = BandConfig.with_variables_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args( f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # when keeper.approve() self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 1 # and assert self.orders_by_token( deployment, deployment.gem)[0].maker == deployment.our_address assert self.orders_by_token( deployment, deployment.gem)[0].pay_amount == Wad.from_number(5.0) assert self.orders_by_token( deployment, deployment.gem)[0].pay_token == deployment.gem.address assert self.orders_by_token( deployment, deployment.gem)[0].buy_amount == Wad.from_number(520) assert self.orders_by_token( deployment, deployment.gem)[0].buy_token == deployment.sai.address
def test_should_cancel_the_only_sell_order_and_place_a_new_one_if_above_max(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() # and # [one artificially created order above the max band threshold] deployment.otc.make(deployment.gem.address, Wad.from_number(20), deployment.sai.address, Wad.from_number(2080)).transact() # and keeper.order_book_manager.wait_for_order_book_refresh() # when self.synchronize_orders_twice(keeper) # then # [the artificial order gets cancelled, a new one gets created instead] assert len(deployment.otc.get_orders()) == 2 assert self.orders_by_token(deployment, deployment.gem)[0].maker == deployment.our_address assert self.orders_by_token(deployment, deployment.gem)[0].pay_amount == Wad.from_number(7.5) assert self.orders_by_token(deployment, deployment.gem)[0].pay_token == deployment.gem.address assert self.orders_by_token(deployment, deployment.gem)[0].buy_amount == Wad.from_number(780) assert self.orders_by_token(deployment, deployment.gem)[0].buy_token == deployment.sai.address
def test_should_use_gas_price_specified(self, deployment: Deployment): # given some_gas_price = 15000000000 keeper = OasisMarketMakerCancel(args=args(f"--eth-from {deployment.web3.eth.defaultAccount} " f"--oasis-address {deployment.otc.address} " f"--gas-price {some_gas_price}"), web3=deployment.web3) # and DSToken(web3=deployment.web3, address=deployment.gem.address).mint(Wad.from_number(1000)).transact() DSToken(web3=deployment.web3, address=deployment.sai.address).mint(Wad.from_number(1000)).transact() # and deployment.otc.approve([deployment.gem, deployment.sai], directly()) deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(12)).transact() assert len(deployment.otc.get_orders()) == 1 # when keeper.main() # then assert len(deployment.otc.get_orders()) == 0 assert deployment.web3.eth.getBlock('latest', True)['transactions'][0]['gasPrice'] == some_gas_price
def test_no_api_non_fixed(self, mcd, keeper_address): c = mcd.collaterals['ETH-A'] reactive_multipler = 1.125 * 3 keeper = AuctionKeeper(args=args( f"--eth-from {keeper_address} " f"--type flip " f"--from-block 1 " f"--ilk {c.ilk.name} " f"--gas-reactive-multiplier {reactive_multipler} " f"--model ./bogus-model.sh"), web3=mcd.web3) initial_amount = get_node_gas_price(mcd.web3) assert keeper.gas_price.get_gas_price(0) == initial_amount assert keeper.gas_price.get_gas_price( 1 + every_secs) == initial_amount * reactive_multipler assert keeper.gas_price.get_gas_price( 1 + every_secs * 2) == initial_amount * reactive_multipler**2 assert keeper.gas_price.get_gas_price( 1 + every_secs * 3) == initial_amount * reactive_multipler**3 assert keeper.gas_price.get_gas_price(every_secs * 12) == default_max_gas * GWEI
def create_keeper(self, exit_system_coin_on_shutdown: bool, exit_collateral_on_shutdown: bool): assert isinstance(exit_system_coin_on_shutdown, bool) assert isinstance(exit_collateral_on_shutdown, bool) safe_engine_system_coin_behavior = "" if exit_system_coin_on_shutdown else "--keep-system-coin-in-safe-engine-on-exit" safe_engine_collateral_behavior = "" if exit_collateral_on_shutdown else "--keep-collateral-in-safe-engine-on-exit" keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--type collateral --collateral-type {self.collateral.collateral_type.name} " f"--from-block 1 " f"{safe_engine_system_coin_behavior} " f"{safe_engine_collateral_behavior} " f"--model ./bogus-model.sh"), web3=self.web3) self.web3 = keeper.web3 self.geb = keeper.geb assert self.web3.eth.defaultAccount == self.keeper_address.address assert keeper.arguments.exit_system_coin_on_shutdown == exit_system_coin_on_shutdown assert keeper.arguments.exit_collateral_on_shutdown == exit_collateral_on_shutdown keeper.startup() return keeper
def create_keeper(self, mocker, system_coin_target="all"): # Create a keeper mocker.patch("web3.net.Net.peer_count", return_value=1) self.keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--type collateral --collateral-type ETH-B --bid-only " f"--safe-engine-system-coin-target {system_coin_target} " f"--return-collateral-interval 3 " f"--swap-collateral " f"--max-swap-slippage 0.00001 " f"--model ./bogus-model.sh"), web3=self.web3) assert self.web3.eth.defaultAccount == self.keeper_address.address self.web3 = self.keeper.web3 self.geb = self.keeper.geb assert self.keeper.auctions # Changed the collateral to ETH-C because our testchain didn't have dust set for ETH-A or ETH-B self.collateral = self.keeper.collateral self.collateral.approve(self.keeper_address) self.thread = threading.Thread(target=self.keeper.main, daemon=True) self.thread.start() return self.keeper
def test_should_cancel_all_orders_outside_bands(self, deployment: Deployment, tmpdir): # given config_file = BandConfig.sample_config(tmpdir) # and keeper = OasisMarketMakerKeeper(args=args(f"--eth-from {deployment.our_address} " f"--tub-address {deployment.tub.address} " f"--oasis-address {deployment.otc.address} " f"--buy-token-address {deployment.sai.address} " f"--sell-token-address {deployment.gem.address} " f"--price-feed tub " f"--config {config_file}"), web3=deployment.web3) keeper.lifecycle = Lifecycle(web3=keeper.web3) # and self.mint_tokens(deployment) self.set_price(deployment, Wad.from_number(100)) # and keeper.approve() self.synchronize_orders_twice(keeper) assert len(deployment.otc.get_orders()) == 2 # when deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0538)).transact() #price=92.936802973977695 deployment.otc.make(deployment.sai.address, Wad.from_number(5), deployment.gem.address, Wad.from_number(0.0505)).transact() #price=99.0 deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(50.5)).transact() #price=101 deployment.otc.make(deployment.gem.address, Wad.from_number(0.5), deployment.sai.address, Wad.from_number(53.5)).transact() #price=107 assert len(deployment.otc.get_orders()) == 6 # and keeper.order_book_manager.wait_for_order_book_refresh() # and self.synchronize_orders_twice(keeper) # then assert len(deployment.otc.get_orders()) == 2