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)
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])
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)
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)
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']
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']
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'])
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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 ])
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
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']))
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
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()))
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)
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]
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()
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())
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)
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
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()
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))