示例#1
0
    def test_fog_and_woe_and_bust(self, deployment: Deployment):
        # given
        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
        DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(150).value).transact()

        # when
        deployment.tub.bite(1).transact()

        # then
        assert deployment.tap.fog() == Wad.from_number(4)
        assert deployment.tap.woe() == Wad.from_number(1000)
        assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(6)
        assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(1000)

        # when
        deployment.tap.bust(Wad.from_number(2)).transact()
        assert deployment.tap.fog() == Wad.from_number(2)
        assert deployment.tap.woe() == Wad.from_number(700)
        assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(8)
        assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(700)
示例#2
0
    def test_bite_and_safe(self, deployment: Deployment):
        # given
        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()

        # when
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(4)).transact()
        deployment.tub.draw(1, Wad.from_number(1000)).transact()

        # then
        assert deployment.tub.safe(1)

        # when
        DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(150).value).transact()

        # then
        assert not deployment.tub.safe(1)

        # when
        deployment.tub.bite(1).transact()

        # then
        assert deployment.tub.safe(1)
示例#3
0
    def prepare_unsafe_cup(deployment: Deployment):
        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()

        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(4)).transact()
        deployment.tub.draw(1, Wad.from_number(1000)).transact()

        # price goes down, the cup becomes unsafe
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(150).value).transact()
示例#4
0
 def from_json(web3: Web3, conf: str):
     conf = json.loads(conf)
     mom = DSGuard(web3, Address(conf['MCD_MOM']))
     vat = Vat(web3, Address(conf['MCD_VAT']))
     vow = Vow(web3, Address(conf['MCD_VOW']))
     drip = Drip(web3, Address(conf['MCD_DRIP']))
     pit = Pit(web3, Address(conf['MCD_PIT']))
     cat = Cat(web3, Address(conf['MCD_CAT']))
     flap = Flapper(web3, Address(conf['MCD_FLAP']))
     flop = Flopper(web3, Address(conf['MCD_FLOP']))
     dai = DSToken(web3, Address(conf['MCD_DAI']))
     dai_adapter = DaiAdapter(web3, Address(conf['MCD_JOIN_DAI']))
     dai_move = DaiVat(web3, Address(conf['MCD_MOVE_DAI']))
     mkr = DSToken(web3, Address(conf['MCD_GOV']))
     collaterals = []
     for name in conf['COLLATERALS']:
         collateral = Collateral(Ilk(name))
         collateral.gem = DSToken(web3, Address(conf[name]))
         collateral.adapter = GemAdapter(web3, Address(conf[f'MCD_JOIN_{name}']))
         collateral.mover = GemVat(web3, Address(conf[f'MCD_MOVE_{name}']))
         collateral.flipper = Flipper(web3, Address(conf[f'MCD_FLIP_{name}']))
         collateral.pip = DSValue(web3, Address(conf[f'PIP_{name}']))
         collateral.spotter = Spotter(web3, Address(conf[f'MCD_SPOT_{name}']))
         collaterals.append(collateral)
     return DssDeployment.Config(mom, vat, vow, drip, pit, cat, flap, flop, dai, dai_adapter, dai_move, mkr,
                                 collaterals)
示例#5
0
    def test_cash(self, deployment: Deployment):
        # given
        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
        gem_before = deployment.gem.balance_of(deployment.our_address)

        # when
        deployment.top.cage().transact()
        deployment.tap.cash(Wad.from_number(500)).transact()

        # then
        gem_after = deployment.gem.balance_of(deployment.our_address)
        assert gem_after - gem_before == Wad.from_number(2)

        # when
        deployment.tap.cash(Wad.from_number(500)).transact()

        # then
        gem_after = deployment.gem.balance_of(deployment.our_address)
        assert gem_after - gem_before == Wad.from_number(4)
示例#6
0
        def from_json(web3: Web3, conf: str):
            conf = json.loads(conf)
            pause = DSPause(web3, Address(conf['MCD_PAUSE']))
            vat = Vat(web3, Address(conf['MCD_VAT']))
            vow = Vow(web3, Address(conf['MCD_VOW']))
            jug = Jug(web3, Address(conf['MCD_JUG']))
            cat = Cat(web3, Address(conf['MCD_CAT']))
            dai = DSToken(web3, Address(conf['MCD_DAI']))
            dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI']))
            flapper = Flapper(web3, Address(conf['MCD_FLAP']))
            flopper = Flopper(web3, Address(conf['MCD_FLOP']))
            mkr = DSToken(web3, Address(conf['MCD_GOV']))
            spotter = Spotter(web3, Address(conf['MCD_SPOT']))

            collaterals = {}
            for name in DssDeployment.Config._infer_collaterals_from_addresses(conf.keys()):
                ilk = Ilk(name[0].replace('_', '-'))
                if name[1] == "ETH":
                    gem = DSEthToken(web3, Address(conf[name[1]]))
                else:
                    gem = DSToken(web3, Address(conf[name[1]]))

                # TODO: If problematic, skip pip for deployments which use a medianizer.
                collateral = Collateral(ilk=ilk, gem=gem,
                                        adapter=GemJoin(web3, Address(conf[f'MCD_JOIN_{name[0]}'])),
                                        flipper=Flipper(web3, Address(conf[f'MCD_FLIP_{name[0]}'])),
                                        pip=DSValue(web3, Address(conf[f'PIP_{name[1]}'])))
                collaterals[ilk.name] = collateral

            return DssDeployment.Config(pause, vat, vow, jug, cat, flapper, flopper,
                                        dai, dai_adapter, mkr, spotter, collaterals)
示例#7
0
    def test_joy_and_boom(self, deployment: Deployment):
        # given
        deployment.tub.join(Wad.from_number(10)).transact()
        deployment.tub.mold_cap(Wad.from_number(100000)).transact()
        deployment.tub.mold_tax(Ray(1000100000000000000000000000)).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()

        # when
        deployment.time_travel_by(3600)
        deployment.tub.drip().transact()

        # then
        assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(6)
        assert deployment.tap.joy() == Wad(433303616582911495481)

        # when
        deployment.tap.boom(Wad.from_number(1)).transact()

        # then
        assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(5)
        assert deployment.tap.joy() == Wad(183303616582911495481)
示例#8
0
    def test_draw_and_tab_and_din_and_wipe(self, deployment: Deployment):
        # given
        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.45).value).transact()

        # and
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(5)).transact()

        # when
        deployment.tub.draw(1, Wad.from_number(50)).transact()

        # then
        assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(50)
        assert deployment.tub.tab(1) == Wad.from_number(50)
        assert deployment.tub.din() == Wad.from_number(50)

        # when
        deployment.tub.wipe(1, Wad.from_number(30)).transact()

        # then
        assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(20)
        assert deployment.tub.tab(1) == Wad.from_number(20)
        assert deployment.tub.din() == Wad.from_number(20)
    def test_should_execute_arbitrage_in_one_transaction_if_tx_manager_configured(
            self, deployment: Deployment):
        # given
        tx_manager = TxManager.deploy(deployment.web3)

        # and
        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 13.0 --max-engagement 100.0"
            f" --tx-manager {tx_manager.address}"),
                                 web3=deployment.web3)

        # and
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        deployment.tub.mold_gap(Wad.from_number(1.05)).transact()
        deployment.tub.join(Wad.from_number(1000)).transact()
        deployment.tap.mold_gap(Wad.from_number(1.05)).transact()

        # and
        deployment.sai.mint(Wad.from_number(1000)).transact()

        # and
        deployment.otc.approve(
            [deployment.gem, deployment.sai, deployment.skr], directly())
        deployment.otc.add_token_pair_whitelist(
            deployment.sai.address, deployment.skr.address).transact()
        deployment.otc.add_token_pair_whitelist(
            deployment.skr.address, deployment.gem.address).transact()
        deployment.otc.add_token_pair_whitelist(
            deployment.gem.address, deployment.sai.address).transact()
        deployment.otc.make(deployment.skr.address,
                            Wad.from_number(105), deployment.sai.address,
                            Wad.from_number(100)).transact()
        deployment.otc.make(deployment.gem.address,
                            Wad.from_number(110), deployment.skr.address,
                            Wad.from_number(105)).transact()
        deployment.otc.make(deployment.sai.address,
                            Wad.from_number(115), deployment.gem.address,
                            Wad.from_number(110)).transact()
        assert len(deployment.otc.get_orders()) == 3

        # when
        keeper.approve()
        block_number_before = deployment.web3.eth.blockNumber
        keeper.process_block()
        block_number_after = deployment.web3.eth.blockNumber

        # then
        assert len(deployment.otc.get_orders()) == 0

        # and
        # [keeper used only one transaction, as TxManager is configured]
        assert (block_number_after - block_number_before) == 1
示例#10
0
    def test_tag(self, deployment: Deployment):
        # when
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(250.45).value).transact()

        # then
        assert deployment.tub.tag() == Ray.from_number(250.45)
示例#11
0
    def test_s2s_and_bid_and_ask(self, deployment: Deployment):
        # when
        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()

        # then
        assert deployment.tap.bid(Wad.from_number(2)) == Wad.from_number(475)*Wad.from_number(2)
        assert deployment.tap.s2s() == Ray.from_number(500)
        assert deployment.tap.ask(Wad.from_number(2)) == Wad.from_number(525)*Wad.from_number(2)
示例#12
0
    def test_shut(self, deployment: Deployment):
        # given
        DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact()
        deployment.tub.open().transact()

        # when
        deployment.tub.shut(1).transact()

        # then
        assert deployment.tub.lad(1) == Address('0x0000000000000000000000000000000000000000')
示例#13
0
    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)
示例#14
0
        def from_json(web3: Web3, conf: str):
            conf = json.loads(conf)
            pause = DSPause(web3, Address(conf['MCD_PAUSE']))
            vat = Vat(web3, Address(conf['MCD_VAT']))
            vow = Vow(web3, Address(conf['MCD_VOW']))
            jug = Jug(web3, Address(conf['MCD_JUG']))
            cat = Cat(web3, Address(conf['MCD_CAT']))
            dai = DSToken(web3, Address(conf['MCD_DAI']))
            dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI']))
            flapper = Flapper(web3, Address(conf['MCD_FLAP']))
            flopper = Flopper(web3, Address(conf['MCD_FLOP']))
            pot = Pot(web3, Address(conf['MCD_POT']))
            mkr = DSToken(web3, Address(conf['MCD_GOV']))
            spotter = Spotter(web3, Address(conf['MCD_SPOT']))
            ds_chief = DSChief(web3, Address(conf['MCD_ADM']))
            esm = ShutdownModule(web3, Address(conf['MCD_ESM']))
            end = End(web3, Address(conf['MCD_END']))
            proxy_registry = ProxyRegistry(web3,
                                           Address(conf['PROXY_REGISTRY']))
            dss_proxy_actions = DssProxyActionsDsr(
                web3, Address(conf['PROXY_ACTIONS_DSR']))

            collaterals = {}
            for name in DssDeployment.Config._infer_collaterals_from_addresses(
                    conf.keys()):
                ilk = Ilk(name[0].replace('_', '-'))
                if name[1] == "ETH":
                    gem = DSEthToken(web3, Address(conf[name[1]]))
                else:
                    gem = DSToken(web3, Address(conf[name[1]]))

                # PIP contract may be a DSValue, OSM, or bogus address.
                pip_address = Address(conf[f'PIP_{name[1]}'])
                network = DssDeployment.NETWORKS.get(web3.net.version,
                                                     "testnet")
                if network == "testnet":
                    pip = DSValue(web3, pip_address)
                else:
                    pip = OSM(web3, pip_address)

                collateral = Collateral(
                    ilk=ilk,
                    gem=gem,
                    adapter=GemJoin(web3,
                                    Address(conf[f'MCD_JOIN_{name[0]}'])),
                    flipper=Flipper(web3,
                                    Address(conf[f'MCD_FLIP_{name[0]}'])),
                    pip=pip)
                collaterals[ilk.name] = collateral

            return DssDeployment.Config(pause, vat, vow, jug, cat, flapper,
                                        flopper, pot, dai, dai_adapter, mkr,
                                        spotter, ds_chief, esm, end,
                                        proxy_registry, dss_proxy_actions,
                                        collaterals)
示例#15
0
    def test_safe(self, deployment: Deployment):
        # given
        deployment.tub.mold_mat(Ray.from_number(1.5)).transact()
        deployment.tub.mold_axe(Ray.from_number(1.2)).transact()
        DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact()

        # when
        deployment.tub.open().transact()

        # then
        assert deployment.tub.safe(1)
    def test_should_obey_min_profit(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 16.0 --max-engagement 1000.0"),
                                 web3=deployment.web3)

        # and
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        deployment.tub.mold_gap(Wad.from_number(1.05)).transact()
        deployment.tub.join(Wad.from_number(1000)).transact()
        deployment.tap.mold_gap(Wad.from_number(1.05)).transact()

        # and
        deployment.sai.mint(Wad.from_number(1000)).transact()

        # and
        deployment.otc.approve(
            [deployment.gem, deployment.sai, deployment.skr], directly())
        deployment.otc.add_token_pair_whitelist(
            deployment.sai.address, deployment.skr.address).transact()
        deployment.otc.add_token_pair_whitelist(
            deployment.skr.address, deployment.gem.address).transact()
        deployment.otc.add_token_pair_whitelist(
            deployment.gem.address, deployment.sai.address).transact()
        deployment.otc.make(deployment.skr.address,
                            Wad.from_number(105), deployment.sai.address,
                            Wad.from_number(100)).transact()
        deployment.otc.make(deployment.gem.address,
                            Wad.from_number(110), deployment.skr.address,
                            Wad.from_number(105)).transact()
        deployment.otc.make(deployment.sai.address,
                            Wad.from_number(115), deployment.gem.address,
                            Wad.from_number(110)).transact()
        assert len(deployment.otc.get_orders()) == 3

        # when
        keeper.approve()
        keeper.process_block()

        # then
        assert len(deployment.otc.get_orders()) == 3
        assert deployment.otc.get_orders()[0].buy_amount == Wad.from_number(
            100)
        assert deployment.otc.get_orders()[1].buy_amount == Wad.from_number(
            105)
        assert deployment.otc.get_orders()[2].buy_amount == Wad.from_number(
            110)
    def test_should_identify_arbitrage_against_oasis_and_exit(
            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.gem.address}"
            f" --min-profit 5.0 --max-engagement 100.0"),
                                 web3=deployment.web3)

        # and
        # [a price is set, so the arbitrage keeper knows prices of `boom` and `bust`]
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()

        # and
        # [we have 100 WETH]
        deployment.gem.mint(Wad.from_number(100)).transact()

        # and
        # [somebody else placed an order on OASIS offering 110 SKR for 100 WETH]
        second_address = Address(deployment.web3.eth.accounts[1])

        deployment.gem.mint(Wad.from_number(110)).transact()
        deployment.tub.join(Wad.from_number(110)).transact()
        deployment.skr.transfer(second_address,
                                Wad.from_number(110)).transact()
        deployment.otc.add_token_pair_whitelist(
            deployment.skr.address, deployment.gem.address).transact()
        deployment.otc.approve([deployment.gem, deployment.skr],
                               directly(from_address=second_address))
        deployment.otc.make(
            deployment.skr.address, Wad.from_number(110),
            deployment.gem.address,
            Wad.from_number(100)).transact(from_address=second_address)
        assert deployment.skr.total_supply() == Wad.from_number(110)
        assert len(deployment.otc.get_orders()) == 1

        # when
        keeper.approve()
        keeper.process_block()

        # then
        # [the order on Oasis has been taken by the keeper]
        assert len(deployment.otc.get_orders()) == 0

        # and
        # [the total supply of SKR has decreased, so we know the keeper did call exit('110.0')]
        assert deployment.skr.total_supply() == Wad.from_number(0)
示例#18
0
    def test_not_empty_cups(self, deployment: Deployment):
        # given
        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.45).value).transact()

        # and
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(3)).transact()

        # when
        deployment.tub.draw(1, Wad.from_number(50)).transact()

        # then
        assert deployment.tub.cups(1).art == Wad.from_number(50)
        assert deployment.tub.cups(1).ink == Wad.from_number(3)
示例#19
0
    def test_cage(self, deployment: Deployment):
        # given
        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()

        # when
        deployment.top.cage().transact()

        # then
        assert deployment.top.fix() == Ray.from_number(0.004)
    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()
示例#21
0
    def test_lock_and_free(self, deployment: Deployment):
        # given
        DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact()
        deployment.tub.open().transact()
        deployment.tub.join(Wad.from_number(10)).transact()

        # when
        print(deployment.tub.cupi())
        deployment.tub.lock(1, Wad.from_number(5)).transact()

        # then
        assert deployment.tub.ink(1) == Wad.from_number(5)
        assert deployment.tub.air() == Wad.from_number(5)

        # when
        deployment.tub.free(1, Wad.from_number(3)).transact()

        # then
        assert deployment.tub.ink(1) == Wad.from_number(2)
        assert deployment.tub.air() == Wad.from_number(2)
示例#22
0
    def __init__(self, tub: Tub):
        assert(isinstance(tub, Tub))

        self.ds_value = DSValue(web3=tub.web3, address=tub.pip())
示例#23
0
        def from_json(web3: Web3, conf: str):
            def address_in_configs(key: str, conf: str) -> bool:
                if key not in conf:
                    return False
                elif not conf[key]:
                    return False
                elif conf[key] == "0x0000000000000000000000000000000000000000":
                    return False
                else:
                    return True

            conf = json.loads(conf)
            pause = DSPause(web3, Address(conf['MCD_PAUSE']))
            vat = Vat(web3, Address(conf['MCD_VAT']))
            vow = Vow(web3, Address(conf['MCD_VOW']))
            jug = Jug(web3, Address(conf['MCD_JUG']))
            cat = Cat(web3, Address(conf['MCD_CAT'])) if address_in_configs(
                'MCD_CAT', conf) else None
            dog = Dog(web3, Address(conf['MCD_DOG'])) if address_in_configs(
                'MCD_DOG', conf) else None
            dai = DSToken(web3, Address(conf['MCD_DAI']))
            dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI']))
            flapper = Flapper(web3, Address(conf['MCD_FLAP']))
            flopper = Flopper(web3, Address(conf['MCD_FLOP']))
            pot = Pot(web3, Address(conf['MCD_POT']))
            mkr = DSToken(web3, Address(conf['MCD_GOV']))
            spotter = Spotter(web3, Address(conf['MCD_SPOT']))
            ds_chief = DSChief(web3, Address(conf['MCD_ADM']))
            esm = ShutdownModule(web3, Address(conf['MCD_ESM']))
            end = End(web3, Address(conf['MCD_END']))
            proxy_registry = ProxyRegistry(web3,
                                           Address(conf['PROXY_REGISTRY']))
            dss_proxy_actions = DssProxyActionsDsr(
                web3, Address(conf['PROXY_ACTIONS_DSR']))
            cdp_manager = CdpManager(web3, Address(conf['CDP_MANAGER']))
            dsr_manager = DsrManager(web3, Address(conf['DSR_MANAGER']))
            faucet = TokenFaucet(
                web3, Address(conf['FAUCET'])) if address_in_configs(
                    'FAUCET', conf) else None

            collaterals = {}
            for name in DssDeployment.Config._infer_collaterals_from_addresses(
                    conf.keys()):
                ilk = vat.ilk(name[0].replace('_', '-'))
                if name[1] == "ETH":
                    gem = DSEthToken(web3, Address(conf[name[1]]))
                else:
                    gem = DSToken(web3, Address(conf[name[1]]))

                if name[1] in [
                        'USDC', 'WBTC', 'TUSD', 'USDT', 'GUSD', 'RENBTC'
                ]:
                    adapter = GemJoin5(web3,
                                       Address(conf[f'MCD_JOIN_{name[0]}']))
                else:
                    adapter = GemJoin(web3,
                                      Address(conf[f'MCD_JOIN_{name[0]}']))

                # PIP contract may be a DSValue, OSM, or bogus address.
                pip_name = f'PIP_{name[1]}'
                pip_address = Address(
                    conf[pip_name]
                ) if pip_name in conf and conf[pip_name] else None
                val_name = f'VAL_{name[1]}'
                val_address = Address(
                    conf[val_name]
                ) if val_name in conf and conf[val_name] else None
                if pip_address:  # Configure OSM as price source
                    if name[1].startswith('UNIV2'):
                        pip = Univ2LpOSM(web3, pip_address)
                    else:
                        pip = OSM(web3, pip_address)
                elif val_address:  # Configure price using DSValue
                    pip = DSValue(web3, val_address)
                else:
                    pip = None

                auction = None
                if f'MCD_FLIP_{name[0]}' in conf:
                    auction = Flipper(web3,
                                      Address(conf[f'MCD_FLIP_{name[0]}']))
                elif f'MCD_CLIP_{name[0]}' in conf:
                    auction = Clipper(web3,
                                      Address(conf[f'MCD_CLIP_{name[0]}']))

                collateral = Collateral(ilk=ilk,
                                        gem=gem,
                                        adapter=adapter,
                                        auction=auction,
                                        pip=pip,
                                        vat=vat)
                collaterals[ilk.name] = collateral

            return DssDeployment.Config(pause, vat, vow, jug, cat, dog,
                                        flapper, flopper, pot, dai,
                                        dai_adapter, mkr, spotter, ds_chief,
                                        esm, end, proxy_registry,
                                        dss_proxy_actions, cdp_manager,
                                        dsr_manager, faucet, collaterals)
示例#24
0
 def set_price(deployment: Deployment, price: Wad):
     DSValue(web3=deployment.web3,
             address=deployment.tub.pip()).poke_with_int(
                 price.value).transact()
    def test_should_identify_arbitrage_against_oasis_and_boom(
            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 100.0 --max-engagement 500000.0"),
                                 web3=deployment.web3)

        # and
        # [we generate some Dai surplus available for `boom`]
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        deployment.tub.mold_cap(Wad.from_number(10000000000)).transact()
        deployment.tub.mold_mat(Ray.from_number(1.5)).transact()
        deployment.tub.mold_axe(Ray.from_number(1.2)).transact()
        deployment.tub.mold_tax(Ray.from_number(1.0000000001)).transact()
        deployment.gem.mint(Wad.from_number(1000000)).transact()
        deployment.tub.join(Wad.from_number(1000000)).transact()
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(1000000)).transact()
        deployment.tub.draw(1, Wad.from_number(250000000)).transact()
        time_travel_by(deployment.web3, 60 * 60 * 24 * 180)
        deployment.tub.wipe(1, Wad.from_number(250000000)).transact()
        print(deployment.tap.joy())
        assert Wad.from_number(
            389102) < deployment.tap.joy() < Wad.from_number(389103)

        # and
        # [we add a boom/bust spread to make calculations a bit more difficult]
        deployment.tap.mold_gap(Wad.from_number(0.95)).transact()
        assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0)
        assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0)

        # and
        # [we have lots of SAI to invest]
        deployment.sai.mint(Wad.from_number(5000000.00)).transact()

        # [we have some SKR to cover rounding errors]
        deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact()

        # and
        # [we should now have 389102.xx SAI available for 741.14 SKR on `boom`]
        # [now lets pretend somebody else placed an order on OASIS offering 1000 GEM for 500000 SAI]
        second_address = Address(deployment.web3.eth.accounts[1])

        deployment.gem.mint(Wad.from_number(1000)).transact()
        deployment.gem.transfer(second_address,
                                Wad.from_number(1000)).transact()
        deployment.otc.approve([deployment.sai, deployment.gem],
                               directly(from_address=second_address))
        deployment.otc.make(
            deployment.gem.address,
            Wad.from_number(1000), deployment.sai.address,
            Wad.from_number(500000)).transact(from_address=second_address)
        assert len(deployment.otc.get_orders()) == 1

        # when
        keeper.approve()
        keeper.process_block()

        # and
        # [the amount of surplus is almost zero, so we know the keeper did call boom()]
        # [the inequality below is to cater for rounding errors]
        assert deployment.tap.joy() < Wad.from_number(0.1)
    def test_should_identify_arbitrage_against_oasis_and_bust(
            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 950.0 --max-engagement 14250.0"),
                                 web3=deployment.web3)

        # and
        # [we generate some bad debt available for `bust`]
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        deployment.tub.mold_cap(Wad.from_number(1000000)).transact()
        deployment.tub.mold_mat(Ray.from_number(2.0)).transact()
        deployment.tub.mold_axe(Ray.from_number(2.0)).transact()
        deployment.gem.mint(Wad.from_number(100)).transact()
        deployment.tub.join(Wad.from_number(100)).transact()
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(100)).transact()
        deployment.tub.draw(1, Wad.from_number(25000)).transact()
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(400).value).transact()
        deployment.tub.bite(1).transact()
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        assert deployment.tap.woe() == Wad.from_number(25000)
        assert deployment.tap.fog() == Wad.from_number(100)

        # and
        # [we add a boom/bust spread to make calculations a bit more difficult]
        deployment.tap.mold_gap(Wad.from_number(0.95)).transact()
        assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0)
        assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0)

        # and
        # [we have some SKR to cover rounding errors]
        deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact()

        # and
        # [we should now have 30 SKR available for 14250 SAI on `bust`]
        # [now lets pretend somebody else placed an order on OASIS offering 15250 SAI for 30 GEM]
        # [this will be an arbitrage opportunity which can make the bot earn 1000 SAI]
        second_address = Address(deployment.web3.eth.accounts[1])

        deployment.sai.mint(Wad.from_number(15250)).transact()
        deployment.sai.transfer(second_address,
                                Wad.from_number(15250)).transact()
        deployment.otc.approve([deployment.sai, deployment.gem],
                               directly(from_address=second_address))
        deployment.otc.make(
            deployment.sai.address, Wad.from_number(15250),
            deployment.gem.address,
            Wad.from_number(30)).transact(from_address=second_address)
        assert len(deployment.otc.get_orders()) == 1

        # when
        keeper.approve()
        keeper.process_block()

        # then
        # [the order on Oasis has been taken by the keeper]
        assert len(deployment.otc.get_orders()) == 0

        # and
        # [the amount of bad debt has decreased, so we know the keeper did call bust('14250.0')]
        # [the inequality below is to cater for rounding errors]
        assert deployment.tap.woe() < Wad.from_number(10800.0)
    def test_should_identify_arbitrage_against_0x_and_bust(
            self, deployment: Deployment):
        # given
        # [0x protocol is in place]
        zrx_token = ERC20Token(web3=deployment.web3,
                               address=deploy_contract(deployment.web3,
                                                       'ZRXToken'))
        token_transfer_proxy_address = deploy_contract(deployment.web3,
                                                       'TokenTransferProxy')
        exchange = ZrxExchange.deploy(deployment.web3, zrx_token.address,
                                      token_transfer_proxy_address)
        deployment.web3.eth.contract(abi=json.loads(
            pkg_resources.resource_string(
                'pymaker.deployment', f'abi/TokenTransferProxy.abi')))(
                    address=token_transfer_proxy_address.address).transact(
                    ).addAuthorizedAddress(exchange.address.address)

        # and
        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" --exchange-address {exchange.address}"
            f" --relayer-api-server http://127.0.0.1:9999/sra/v0"
            f" --base-token {deployment.sai.address}"
            f" --min-profit 950.0 --max-engagement 14250.0"),
                                 web3=deployment.web3)

        # and
        # [we generate some bad debt available for `bust`]
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        deployment.tub.mold_cap(Wad.from_number(1000000)).transact()
        deployment.tub.mold_mat(Ray.from_number(2.0)).transact()
        deployment.tub.mold_axe(Ray.from_number(2.0)).transact()
        deployment.gem.mint(Wad.from_number(100)).transact()
        deployment.tub.join(Wad.from_number(100)).transact()
        deployment.tub.open().transact()
        deployment.tub.lock(1, Wad.from_number(100)).transact()
        deployment.tub.draw(1, Wad.from_number(25000)).transact()
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(400).value).transact()
        deployment.tub.bite(1).transact()
        DSValue(web3=deployment.web3,
                address=deployment.tub.pip()).poke_with_int(
                    Wad.from_number(500).value).transact()
        assert deployment.tap.woe() == Wad.from_number(25000)
        assert deployment.tap.fog() == Wad.from_number(100)

        # and
        # [we add a boom/bust spread to make calculations a bit more difficult]
        deployment.tap.mold_gap(Wad.from_number(0.95)).transact()
        assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0)
        assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0)

        # and
        # [we have some SKR to cover rounding errors]
        deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact()

        # and
        # [we should now have 30 SKR available for 14250 SAI on `bust`]
        # [now lets pretend we placed an order on 0x offering 15250 SAI for 30 GEM]
        # [this will be an arbitrage opportunity which can make the bot earn 1000 SAI]
        deployment.sai.mint(Wad.from_number(15250)).transact()
        exchange.approve([deployment.sai, deployment.gem], directly())
        zrx_order = exchange.sign_order(
            exchange.create_order(pay_token=deployment.sai.address,
                                  pay_amount=Wad.from_number(15250),
                                  buy_token=deployment.gem.address,
                                  buy_amount=Wad.from_number(30),
                                  expiration=int(time.time() + 3600)))
        keeper.zrx_orders = lambda tokens: [zrx_order]

        # when
        keeper.approve()
        keeper.process_block()

        # then
        # [the 0x order has been taken by the keeper]
        assert exchange.get_unavailable_buy_amount(
            zrx_order) == Wad.from_number(30)

        # and
        # [the amount of bad debt has decreased, so we know the keeper did call bust('14250.0')]
        # [the inequality below is to cater for rounding errors]
        assert deployment.tap.woe() < Wad.from_number(10800.0)
示例#28
0
 def test_fail_when_no_contract_under_that_address(self):
     # expect
     with pytest.raises(Exception):
         DSValue(web3=self.web3, address=Address('0xdeadadd1e5500000000000000000000000000000'))
示例#29
0
 def set_price(deployment: Deployment, new_price):
     DSValue(web3=deployment.web3,
             address=deployment.tub.pip()).poke_with_int(
                 Wad.from_number(new_price).value).transact()