Exemple #1
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)
Exemple #2
0
    def get_offer(self, offer_id: int) -> Optional[OfferInfo]:
        """Get the offer details.

        Args:
            offer_id: The id of the offer to get the details of.

        Returns:
            An instance of `OfferInfo` if the offer is still active, or `None` if the offer has been
            already completely taken.
        """

        # if an offer is None, it won't become not-None again for the same OTC instance
        if offer_id in self._none_offers:
            return None

        array = self._contract.call().offers(offer_id)
        if array[5] is not True:
            self._none_offers.add(offer_id)
            return None
        else:
            return OfferInfo(offer_id=offer_id,
                             sell_how_much=Wad(array[0]),
                             sell_which_token=Address(array[1]),
                             buy_how_much=Wad(array[2]),
                             buy_which_token=Address(array[3]),
                             owner=Address(array[4]),
                             timestamp=array[6])
Exemple #3
0
    def test_transfer(self):
        # when
        self.token.transfer(self.second_address, Wad(500)).transact()

        # then
        assert self.token.balance_of(self.our_address) == Wad(999500)
        assert self.token.balance_of(self.second_address) == Wad(500)
Exemple #4
0
    def test_approve(self):
        # when
        self.token.approve(self.second_address, Wad(2000)).transact()

        # then
        assert self.token.allowance_of(self.our_address,
                                       self.second_address) == Wad(2000)
Exemple #5
0
 def __init__(self, args):
     self.id = bytes_to_int(args['id'])
     self.maker = Address(args['maker'])
     self.have_token = Address(args['haveToken'])
     self.have_amount = Wad(args['haveAmount'])
     self.want_token = Address(args['wantToken'])
     self.want_amount = Wad(args['wantAmount'])
     self.timestamp = args['timestamp']
Exemple #6
0
 def __init__(self, args):
     self.id = bytes_to_int(args['id'])
     self.maker = Address(args['maker'])
     self.pay_token = Address(args['pay_gem'])
     self.pay_amount = Wad(args['pay_amt'])
     self.buy_token = Address(args['buy_gem'])
     self.buy_amount = Wad(args['buy_amt'])
     self.timestamp = args['timestamp']
Exemple #7
0
 def __init__(self, args):
     self.token_get = Address(args['tokenGet'])
     self.amount_get = Wad(args['amountGet'])
     self.token_give = Address(args['tokenGive'])
     self.amount_give = Wad(args['amountGive'])
     self.expires = args['expires']
     self.nonce = args['nonce']
     self.user = Address(args['user'])
Exemple #8
0
    def test_cups(self, sai: SaiDeployment):
        # when
        sai.tub.open().transact()

        # then
        assert sai.tub.cups(1).art == Wad(0)
        assert sai.tub.cups(1).ink == Wad(0)
        assert sai.tub.cups(1).lad == sai.our_address
Exemple #9
0
 def _net_value(self, transfer: Transfer, our_address: Address):
     if transfer.from_address == our_address and transfer.to_address == our_address:
         return Wad(0)
     elif transfer.from_address == our_address:
         return Wad(0) - transfer.value
     elif transfer.to_address == our_address:
         return transfer.value
     else:
         return Wad(0)
Exemple #10
0
    def test_transfer_out_of_gas(self):
        # when
        receipt = self.token.transfer(self.second_address,
                                      Wad(500)).transact(gas=15000)

        # then
        assert receipt is None
        assert self.token.balance_of(self.our_address) == Wad(1000000)
        assert self.token.balance_of(self.second_address) == Wad(0)
Exemple #11
0
    def test_burn(self):
        # given
        self.dstoken.mint(Wad(100000)).transact()

        # when
        self.dstoken.burn(Wad(40000)).transact()

        # then
        assert self.dstoken.balance_of(self.our_address) == Wad(60000)
Exemple #12
0
    def withdraw_everything(self):
        eth_balance = self.etherdelta.balance_of(self.our_address)
        if eth_balance > Wad(0):
            self.etherdelta.withdraw(eth_balance)

        sai_balance = self.etherdelta.balance_of_token(self.sai.address,
                                                       self.our_address)
        if sai_balance > Wad(0):
            self.etherdelta.withdraw_token(self.sai.address, sai_balance)
Exemple #13
0
    def test_withdraw(self):
        # given
        self.dsethtoken.deposit(Wad(100000)).transact()

        # when
        self.dsethtoken.withdraw(Wad(40000)).transact()

        # then
        assert self.dsethtoken.balance_of(self.our_address) == Wad(60000)
Exemple #14
0
 def deposit_for_buy_orders(self):
     order_total = self.total_amount(self.our_buy_orders())
     currently_deposited = self.etherdelta.balance_of(self.our_address)
     if order_total > currently_deposited:
         depositable_eth = Wad.max(
             self.eth_balance(self.our_address) - self.eth_reserve, Wad(0))
         additional_deposit = Wad.min(order_total - currently_deposited,
                                      depositable_eth)
         if additional_deposit > Wad(0):
             self.etherdelta.deposit(additional_deposit)
Exemple #15
0
    def test_transfer_async(self):
        # when
        synchronize([
            self.token.transfer(self.second_address,
                                Wad(750)).transact_async()
        ])

        # then
        assert self.token.balance_of(self.our_address) == Wad(999250)
        assert self.token.balance_of(self.second_address) == Wad(750)
Exemple #16
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)
Exemple #17
0
    def test_transfer_out_of_gas_async(self):
        # when
        receipt = synchronize([
            self.token.transfer(self.second_address,
                                Wad(500)).transact_async(gas=15000)
        ])[0]

        # then
        assert receipt is None
        assert self.token.balance_of(self.our_address) == Wad(1000000)
        assert self.token.balance_of(self.second_address) == Wad(0)
Exemple #18
0
    def make(self,
             have_token: Address,
             have_amount: Wad,
             want_token: Address,
             want_amount: Wad,
             pos: int = None) -> Transact:
        """Create a new offer.

        The `have_amount` of `have_token` token will be taken from you on offer creation and deposited
        in the market contract. Allowance needs to be set first. Refer to the `approve()` method
        in the `ERC20Token` class.

        The `MatchingMarket` contract maintains an internal ordered linked list of offers, which allows the contract
        to do automated matching. Client placing a new offer can either let the contract find the correct
        position in the linked list (by passing `0` as the `pos` argument of `make`) or calculate the position
        itself and just pass the right value to the contract (this will happen if you omit the `pos`
        argument of `make`). The latter should always use less gas. If the client decides not to calculate the
        position or it does get it wrong and the number of open orders is high at the same time, the new offer
        may not even be placed at all as the attempt to calculate the position by the contract will likely fail
        due to high gas usage.

        Args:
            have_token: Address of the ERC20 token you want to put on sale.
            have_amount: Amount of the `have_token` token you want to put on sale.
            want_token: Address of the ERC20 token you want to be paid with.
            want_amount: Amount of the `want_token` you want to receive.
            pos: The position to insert the order at in the sorted list.
                If `None`, the optimal position will automatically get calculated.

        Returns:
            A :py:class:`keeper.api.Transact` instance, which can be used to trigger the transaction.
        """
        assert (isinstance(have_token, Address))
        assert (isinstance(have_amount, Wad))
        assert (isinstance(want_token, Address))
        assert (isinstance(want_amount, Wad))
        assert (isinstance(pos, int) or (pos is None))
        assert (have_amount > Wad(0))
        assert (want_amount > Wad(0))

        if pos is None:
            pos = self.position(have_token=have_token,
                                have_amount=have_amount,
                                want_token=want_token,
                                want_amount=want_amount)
        else:
            assert (pos >= 0)

        return Transact(self, self.web3, self.abi, self.address,
                        self._contract, 'offer', [
                            have_amount.value, have_token.address,
                            want_amount.value, want_token.address, pos
                        ])
Exemple #19
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
Exemple #20
0
 def from_json(data: dict):
     assert(isinstance(data, dict))
     return OffChainOrder(token_get=Address(data['tokenGet']),
                          amount_get=Wad(int(data['amountGet'])),
                          token_give=Address(data['tokenGive']),
                          amount_give=Wad(int(data['amountGive'])),
                          expires=int(data['expires']),
                          nonce=int(data['nonce']),
                          v=int(data['v']),
                          r=hexstring_to_bytes(data['r']),
                          s=hexstring_to_bytes(data['s']),
                          user=Address(data['user']))
Exemple #21
0
 def __init__(self, auction_manager, auctionlet_id, auctionlet_info,
              is_expired):
     self._auction_manager = auction_manager
     self._auction = None
     self.auctionlet_id = auctionlet_id
     self.auction_id = auctionlet_info[0]
     self.last_bidder = Address(auctionlet_info[1])
     self.last_bid_time = datetime.datetime.fromtimestamp(
         auctionlet_info[2])
     self.buy_amount = Wad(auctionlet_info[3])
     self.sell_amount = Wad(auctionlet_info[4])
     self.unclaimed = auctionlet_info[5]
     self.base = auctionlet_info[6]
     self.expired = is_expired
Exemple #22
0
    def test_should_bid_on_newly_created_auctions(self):
        # given
        # (newly created auction)

        # when
        strategy = BasicForwardAuctionStrategy(self.dai_token, self.mkr_token,
                                               0.05, 0.5, Wad(1))
        result = strategy.perform(self.auctionlet, self.context)

        # then
        self.assertEqual(
            "Placed a new bid at 100.500000000000000000 MKR, bid was successful. Our maximum bid on this auctionlet is 200.000000000000000000 MKR",
            result.description)
        self.assertFalse(result.forget)
        self.auctionlet.bid.assert_called_once_with(Wad(100.5 * self.wei()))
Exemple #23
0
 def test_divide(self):
     assert Wad.from_number(4) / Wad.from_number(2) == Wad.from_number(2)
     assert Wad(4) / Wad.from_number(2) == Wad(2)
     assert Wad(3) / Wad.from_number(2) == Wad(1)
     assert Wad(39) / Wad.from_number(20) == Wad(1)
     assert Wad(40) / Wad.from_number(20) == Wad(2)
     assert Wad.from_number(0.2) / Wad.from_number(0.1) == Wad.from_number(
         2)
Exemple #24
0
 def __init__(self, auction_manager, auction_id, auction_info):
     self._auction_manager = auction_manager
     self.auction_id = auction_id
     self.creator = Address(auction_info[0])
     self.selling = ERC20Token(web3=auction_manager.web3,
                               address=Address(auction_info[1]))
     self.buying = ERC20Token(web3=auction_manager.web3,
                              address=Address(auction_info[2]))
     self.start_bid = Wad(auction_info[3])
     self.min_increase = auction_info[4]
     self.min_decrease = auction_info[5]
     self.sell_amount = Wad(auction_info[6])
     self.ttl = auction_info[7]
     self.reversed = auction_info[8]
     self.unsold = auction_info[9]
Exemple #25
0
 def setup_method(self):
     self.web3 = Web3(EthereumTesterProvider())
     self.web3.eth.defaultAccount = self.web3.eth.accounts[0]
     self.our_address = Address(self.web3.eth.defaultAccount)
     self.second_address = Address(self.web3.eth.accounts[1])
     self.token = DSToken.deploy(self.web3, 'ABC')
     self.token.mint(Wad(1000000)).transact()
Exemple #26
0
 def total_supply(self) -> Wad:
     """Returns the total supply of the token.
     
     Returns:
         The total supply of the token.
     """
     return Wad(self._contract.call().totalSupply())
Exemple #27
0
 def create_new_sell_order(self):
     """If our SAI engagement is below the minimum amount, create a new offer up to the maximum amount"""
     total_amount = self.total_amount(self.our_sell_orders())
     if total_amount < self.min_sai_amount:
         our_balance = self.sai.balance_of(
             self.our_address) + self.etherdelta.balance_of_token(
                 self.sai.address, self.our_address)
         have_amount = Wad.min(self.max_sai_amount,
                               our_balance) - total_amount
         if have_amount > Wad(0):
             want_amount = have_amount * self.apply_sell_margin(
                 self.target_rate(), self.avg_margin)
             if self.offchain:
                 self.etherdelta.place_order_offchain(
                     token_get=EtherDelta.ETH_TOKEN,
                     amount_get=want_amount,
                     token_give=self.sai.address,
                     amount_give=have_amount,
                     expires=self.web3.eth.blockNumber + self.order_age)
             else:
                 self.etherdelta.place_order_onchain(
                     token_get=EtherDelta.ETH_TOKEN,
                     amount_get=want_amount,
                     token_give=self.sai.address,
                     amount_give=have_amount,
                     expires=self.web3.eth.blockNumber + self.order_age)
Exemple #28
0
    def __init__(self, receipt):
        self.transaction_hash = receipt['transactionHash']
        self.gas_used = receipt['gasUsed']
        self.transfers = []

        receipt_logs = receipt['logs']
        if (receipt_logs is not None) and (len(receipt_logs) > 0):
            self.successful = True
            for receipt_log in receipt_logs:
                if len(receipt_log['topics']) > 0 and receipt_log['topics'][
                        0] == '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef':
                    from keeper.api.token import ERC20Token
                    transfer_abi = [
                        abi for abi in ERC20Token.abi
                        if abi.get('name') == 'Transfer'
                    ][0]
                    event_data = get_event_data(transfer_abi, receipt_log)
                    self.transfers.append(
                        Transfer(token_address=Address(event_data['address']),
                                 from_address=Address(
                                     event_data['args']['from']),
                                 to_address=Address(event_data['args']['to']),
                                 value=Wad(event_data['args']['value'])))
        else:
            self.successful = False
Exemple #29
0
    def test_should_not_bid_over_max_price(self):
        # given
        self.auctionlet.buy_amount = Wad(200 * self.wei())
        self.auctionlet.last_bidder = self.competitor_address

        # when
        strategy = BasicForwardAuctionStrategy(self.dai_token, self.mkr_token,
                                               0.05, 0.5, Wad(1))
        result = strategy.perform(self.auctionlet, self.context)

        # then
        self.assertEqual(
            "Our maximum possible bid (200.000000000000000000 MKR) reached",
            result.description)
        self.assertFalse(result.forget)
        self.auctionlet.bid.assert_not_called()
Exemple #30
0
 def test_round_inequality(self):
     # should hold for all x, ndigits
     x = Wad.from_number(7654.321)
     ndigits = 1
     round_difference = x - round(x, ndigits)
     round_distance = Wad(abs(round_difference.value))
     assert round_distance <= Wad.from_number(0.5 * 10**(-ndigits))