Beispiel #1
0
 def test_multiply_by_ray(self):
     assert Wad.from_number(2) * Ray.from_number(3) == Wad.from_number(6)
     assert Wad.from_number(2) * Ray(3) == Wad(0)
     assert Wad(2) * Ray(499999999999999999999999999) == Wad(0)
     assert Wad(2) * Ray(500000000000000000000000000) == Wad(1)
     assert Wad(2) * Ray(999999999999999999999999999) == Wad(1)
     assert Wad(2) * Ray(1000000000000000000000000000) == Wad(2)
Beispiel #2
0
 def __init__(self, otc: SimpleMarket, offer: OfferInfo):
     self.otc = otc
     self.offer = offer
     super().__init__(source_token=offer.buy_which_token,
                      target_token=offer.sell_which_token,
                      rate=Ray(offer.sell_how_much) /
                      Ray(offer.buy_how_much),
                      max_source_amount=offer.buy_how_much,
                      method=f"opc.take({self.offer.offer_id})")
Beispiel #3
0
    def test_crop_and_tax(self, sai: SaiDeployment):
        # given
        assert sai.tub.tax() == Ray.from_number(1)

        # when
        sai.tub.crop(Ray(1000000000000000020000000000)).transact()

        # then
        assert sai.tub.tax() == Ray(1000000000000000020000000000)
Beispiel #4
0
    def test_coax_and_way(self, sai: SaiDeployment):
        # given
        assert sai.tub.way() == Ray.from_number(1)

        # when
        sai.tub.coax(Ray(1000000000000000070000000000)).transact()

        # then
        assert sai.tub.way() == Ray(1000000000000000070000000000)
Beispiel #5
0
 def test_divide(self):
     assert Ray.from_number(4) / Ray.from_number(2) == Ray.from_number(2)
     assert Ray(4) / Ray.from_number(2) == Ray(2)
     assert Ray(3) / Ray.from_number(2) == Ray(1)
     assert Ray(39) / Ray.from_number(20) == Ray(1)
     assert Ray(40) / Ray.from_number(20) == Ray(2)
     assert Ray.from_number(0.2) / Ray.from_number(0.1) == Ray.from_number(
         2)
Beispiel #6
0
    def tax(self) -> Ray:
        """Get the stability fee.

        Returns:
            Per-second value of the stability fee. `1.0` means no stability fee.
        """
        return Ray(self._contractTub.call().tax())
Beispiel #7
0
    def fit(self) -> Ray:
        """Get the GEM per SKR settlement price.

        Returns:
            The GEM per SKR settlement (kill) price.
        """
        return Ray(self._contractTub.call().fit())
Beispiel #8
0
    def jar_bid(self) -> Ray:
        """Get the current `exit()` price (GEM per SKR).

        Returns:
            The GEM per SKR price that will be used on `exit()`.
        """
        return Ray(self._contractJar.call().bid())
Beispiel #9
0
    def jar_ask(self) -> Ray:
        """Get the current `join()` price (GEM per SKR).

        Returns:
            The GEM per SKR price that will be used on `join()`.
        """
        return Ray(self._contractJar.call().ask())
Beispiel #10
0
    def way(self) -> Ray:
        """Get the holder fee (interest rate).

        Returns:
            Per-second value of the holder fee. `1.0` means no holder fee.
        """
        return Ray(self._contractTip.call().way())
Beispiel #11
0
    def axe(self) -> Ray:
        """Get the liquidation penalty.

        Returns:
            The liquidation penalty. `1.0` means no penalty. `1.2` means 20% penalty.
        """
        return Ray(self._contractTub.call().axe())
Beispiel #12
0
    def mat(self) -> Ray:
        """Get the liquidation ratio.

        Returns:
            The liquidation ratio. `1.5` means the liquidation ratio is 150%.
        """
        return Ray(self._contractTub.call().mat())
Beispiel #13
0
    def fix(self) -> Ray:
        """Get the GEM per SAI settlement price.

        Returns:
            The GEM per SAI settlement (kill) price.
        """
        return Ray(self._contract.call().fix())
Beispiel #14
0
    def per(self) -> Ray:
        """Get the lps per ref ratio.

        Returns:
            The current lps per ref ratio.
        """
        return Ray(self._contract.call().per())
Beispiel #15
0
    def test_joy_and_boom(self, sai: SaiDeployment):
        # given
        sai.tub.join(Wad.from_number(10)).transact()
        sai.tub.cork(Wad.from_number(100000)).transact()
        sai.tub.crop(Ray(1000100000000000000000000000)).transact()
        DSValue(web3=sai.web3, address=sai.tub.pip()).poke_with_int(
            Wad.from_number(250).value).transact()

        # and
        sai.tub.open().transact()
        sai.tub.lock(1, Wad.from_number(4)).transact()
        sai.tub.draw(1, Wad.from_number(1000)).transact()

        # when
        sai.tub.drip().transact()
        sai.tub.warp(3600).transact()
        sai.tub.drip().transact()

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

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

        # then
        assert sai.skr.balance_of(sai.our_address) == Wad.from_number(5)
        assert sai.tap.joy() == Wad(183303616582911495481)
Beispiel #16
0
 def __init__(self, tub: Tub, tap: Tap):
     self.tub = tub
     self.tap = tap
     super().__init__(source_token=self.tub.sai(),
                      target_token=self.tub.skr(),
                      rate=(Ray.from_number(1) / Ray(tap.ask())),
                      max_source_amount=self.bustable_amount_in_sai(tap),
                      method="tub.bust()")
Beispiel #17
0
 def __init__(self, tub: Tub, tap: Tap):
     self.tub = tub
     self.tap = tap
     super().__init__(source_token=self.tub.skr(),
                      target_token=self.tub.sai(),
                      rate=Ray(tap.bid()),
                      max_source_amount=self.boomable_amount_in_skr(tap),
                      method="tub.boom()")
Beispiel #18
0
    def per(self) -> Ray:
        """Get the current average entry/exit price (GEM per SKR).

        In order to get the price that will be actually used on `join()` or `exit()`, see
        `jar_ask()` and `jar_bid()` respectively.

        Returns:
            The current GEM per SKR price.
        """
        return Ray(self._contractJar.call().per())
Beispiel #19
0
 def test_should_calculate_tx_costs(self, token1):
     # expect the tx_costs to be non negative and to increase with the number of steps
     steps = []
     prev_tx_costs = Wad.from_number(0)
     for i in range(10):
         steps.append(Conversion(token1, token1, Ray(0), Wad(0), 'met'))
         opportunity = Sequence(steps)
         tx_costs = opportunity.tx_costs()
         assert (tx_costs > prev_tx_costs)
         prev_tx_costs = tx_costs
Beispiel #20
0
    def chi(self) -> Ray:
        """Get the internal debt price.

        Every invocation of this method calls `drip()` internally, so the value you receive is always up-to-date.
        But as calling it doesn't result in an Ethereum transaction, the actual `_chi` value in the smart
        contract storage does not get updated.

        Returns:
            The internal debt price in SAI.
        """
        return Ray(self._contractTub.call().chi())
Beispiel #21
0
 def required_top_up(self, cup):
     pro = cup.ink * self.tub.tag()
     tab = self.tub.tab(cup.cup_id)
     if tab > Wad(0):
         current_ratio = Ray(pro / tab)
         if current_ratio < self.minimum_ratio:
             return tab * (Wad(self.target_ratio - current_ratio) /
                           self.tub.tag())
         else:
             return None
     else:
         return None
Beispiel #22
0
 def __init__(self, lpc: Lpc):
     self.lpc = lpc
     rate = Ray(self.lpc.par() / (self.lpc.tag() * self.lpc.gap()))
     #TODO we always leave 0.000001 in the liquidity pool, in case of some rounding errors
     max_entry_ref = Wad.max(
         (ERC20Token(web3=lpc.web3, address=lpc.alt()).balance_of(
             lpc.address) / Wad(rate)) - Wad.from_number(0.000001),
         Wad.from_number(0))
     super().__init__(source_token=self.lpc.ref(),
                      target_token=self.lpc.alt(),
                      rate=rate,
                      max_source_amount=max_entry_ref,
                      method="lpc.take(alt)")
Beispiel #23
0
    def test_prod_and_par_and_tau(self, sai: SaiDeployment):
        # given
        sai.tub.coax(Ray(1000000000000000070000000000)).transact()
        old_par = sai.tub.par()
        old_tau = sai.tub.tau()

        # when
        sai.tub.warp(1000).transact()
        sai.tub.prod().transact()

        # then
        assert sai.tub.par() > old_par
        assert sai.tub.tau() > old_tau
Beispiel #24
0
    def test_drip_and_chi_and_rho(self, sai: SaiDeployment):
        # given
        sai.tub.crop(Ray(1000000000000000020000000000)).transact()
        old_chi = sai.tub.chi()
        old_rho = sai.tub.rho()

        # when
        sai.tub.warp(1000).transact()
        sai.tub.drip().transact()

        # then
        assert sai.tub.chi() > old_chi
        assert sai.tub.rho() > old_rho
Beispiel #25
0
 def test_should_reject_comparison_with_ints(self):
     with pytest.raises(ArithmeticError):
         assert Ray(1000) == 100
     with pytest.raises(ArithmeticError):
         assert Ray(1000) != 999
     with pytest.raises(ArithmeticError):
         assert Ray(1000) > 999
     with pytest.raises(ArithmeticError):
         assert Ray(999) < 1000
     with pytest.raises(ArithmeticError):
         assert Ray(999) <= 1000
     with pytest.raises(ArithmeticError):
         assert Ray(1000) <= 1000
     with pytest.raises(ArithmeticError):
         assert Ray(1000) >= 1000
     with pytest.raises(ArithmeticError):
         assert Ray(1000) >= 999
Beispiel #26
0
 def test_should_reject_comparison_with_rays(self):
     with pytest.raises(ArithmeticError):
         assert Wad(1000) == Ray(1000)
     with pytest.raises(ArithmeticError):
         assert Wad(1000) != Ray(999)
     with pytest.raises(ArithmeticError):
         assert Wad(1000) > Ray(999)
     with pytest.raises(ArithmeticError):
         assert Wad(999) < Ray(1000)
     with pytest.raises(ArithmeticError):
         assert Wad(999) <= Ray(1000)
     with pytest.raises(ArithmeticError):
         assert Wad(1000) <= Ray(1000)
     with pytest.raises(ArithmeticError):
         assert Wad(1000) >= Ray(1000)
     with pytest.raises(ArithmeticError):
         assert Wad(1000) >= Ray(999)
Beispiel #27
0
 def test_should_reject_comparison_with_wads(self):
     with pytest.raises(ArithmeticError):
         assert Ray(1000) == Wad(1000)
     with pytest.raises(ArithmeticError):
         assert Ray(1000) != Wad(999)
     with pytest.raises(ArithmeticError):
         assert Ray(1000) > Wad(999)
     with pytest.raises(ArithmeticError):
         assert Ray(999) < Wad(1000)
     with pytest.raises(ArithmeticError):
         assert Ray(999) <= Wad(1000)
     with pytest.raises(ArithmeticError):
         assert Ray(1000) <= Wad(1000)
     with pytest.raises(ArithmeticError):
         assert Ray(1000) >= Wad(1000)
     with pytest.raises(ArithmeticError):
         assert Ray(1000) >= Wad(999)
Beispiel #28
0
 def test_should_format_to_string_nicely(self):
     assert str(Ray(1)) == "0.000000000000000000000000001"
     assert str(Ray(
         500000000000000000000000000)) == "0.500000000000000000000000000"
     assert str(Ray(
         1500000000000000000000000000)) == "1.500000000000000000000000000"
     assert str(Ray(
         -1500000000000000000000000000)) == "-1.500000000000000000000000000"
     assert str(Ray(
         -500000000000000000000000000)) == "-0.500000000000000000000000000"
     assert str(Ray(-1)) == "-0.000000000000000000000000001"
Beispiel #29
0
    def set_amounts(self, initial_amount: Wad):
        def recalculate_previous_amounts(from_step_id: int):
            for id in range(from_step_id, -1, -1):
                self.steps[id].target_amount = self.steps[id + 1].source_amount
                self.steps[id].source_amount = Wad(
                    Ray(self.steps[id].target_amount) / self.steps[id].rate)

        assert (isinstance(initial_amount, Wad))
        for i in range(len(self.steps)):
            if i == 0:
                self.steps[0].source_amount = initial_amount
            else:
                self.steps[i].source_amount = self.steps[i - 1].target_amount
            if self.steps[i].source_amount > self.steps[i].max_source_amount:
                self.steps[i].source_amount = self.steps[i].max_source_amount
                recalculate_previous_amounts(i - 1)
            self.steps[i].target_amount = Wad(
                Ray(self.steps[i].source_amount) * self.steps[i].rate)
Beispiel #30
0
 def recalculate_previous_amounts(from_step_id: int):
     for id in range(from_step_id, -1, -1):
         self.steps[id].target_amount = self.steps[id + 1].source_amount
         self.steps[id].source_amount = Wad(
             Ray(self.steps[id].target_amount) / self.steps[id].rate)