Esempio n. 1
0
    def test_should_reload_config_file_if_changed(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"--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

        # when
        second_config_file = BandConfig.sample_config(tmpdir)
        shutil.copyfile(second_config_file, config_file)

        # and
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 2
    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"--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
Esempio n. 3
0
    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"--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_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_not_create_orders_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"--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()

        # when
        self.synchronize_orders_twice(keeper)

        # then
        assert len(deployment.otc.get_orders()) == 0
    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_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_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_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