ETH Price: $2,031.03 (+2.79%)

Transaction Decoder

Block:
9714629 at Mar-21-2020 11:06:28 AM +UTC
Transaction Fee:
0.000464796 ETH $0.94
Gas Used:
116,199 Gas / 4 Gwei

Emitted Events:

132 RLC.Transfer( from=[Sender] 0xefea7656b79d8f5cdd4efe28ddf71855d9c7f447, to=[Receiver] Vyper_contract, value=162876766400 )
133 Dai.Transfer( src=Vyper_contract, dst=[Sender] 0xefea7656b79d8f5cdd4efe28ddf71855d9c7f447, wad=42000000000000000000 )
134 Vyper_contract.TokenPurchase( buyer=[Receiver] Vyper_contract, eth_sold=334554398216574880, tokens_bought=42000000000000000000 )
135 Vyper_contract.EthPurchase( buyer=[Sender] 0xefea7656b79d8f5cdd4efe28ddf71855d9c7f447, tokens_sold=162876766400, eth_bought=334554398216574880 )

Account State Difference:

  Address   Before After State Difference Code
0x2a1530C4...7b7158667 13,169.22316065628429608 Eth13,169.55771505450087096 Eth0.33455439821657488
0x607F4C5B...1544a7375
0x6B175474...495271d0F
0xA825CAE0...b520c8642 292.774796043126195462 Eth292.440241644909620582 Eth0.33455439821657488
5,847.622418446486902775 Eth5,847.622883242486902775 Eth0.000464796
0xEFEA7656...5d9C7F447
0.031643643479391742 Eth
Nonce: 522
0.031178847479391742 Eth
Nonce: 523
0.000464796

Execution Trace

Vyper_contract.tokenToTokenSwapOutput( tokens_bought=42000000000000000000, max_tokens_sold=163646385642, max_eth_sold=115792089237316195423570985008687907853269984665640564039457584007913129639935, deadline=1584789659, token_addr=0x6B175474E89094C44Da98b954EedeAC495271d0F ) => ( out=162876766400 )
  • Vyper_contract.tokenToTokenSwapOutput( tokens_bought=42000000000000000000, max_tokens_sold=163646385642, max_eth_sold=115792089237316195423570985008687907853269984665640564039457584007913129639935, deadline=1584789659, token_addr=0x6B175474E89094C44Da98b954EedeAC495271d0F ) => ( out=162876766400 )
    • Vyper_contract.getExchange( token=0x6B175474E89094C44Da98b954EedeAC495271d0F ) => ( out=0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667 )
    • Vyper_contract.getEthToTokenOutputPrice( tokens_bought=42000000000000000000 ) => ( out=334554398216574880 )
      • Vyper_contract.getEthToTokenOutputPrice( tokens_bought=42000000000000000000 ) => ( out=334554398216574880 )
        • Dai.balanceOf( 0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667 ) => ( 1658282605319627785572071 )
        • RLC.balanceOf( _owner=0xA825CAE02B310E9901b4776806CE25db520c8642 ) => ( balance=141946499626698 )
        • RLC.transferFrom( _from=0xEFEA7656B79d8f5cdd4eFE28ddF71855d9C7F447, _to=0xA825CAE02B310E9901b4776806CE25db520c8642, _value=162876766400 ) => ( True )
        • ETH 0.33455439821657488 Vyper_contract.ethToTokenTransferOutput( tokens_bought=42000000000000000000, deadline=1584789659, recipient=0xEFEA7656B79d8f5cdd4eFE28ddF71855d9C7F447 ) => ( out=334554398216574880 )
          • ETH 0.33455439821657488 Vyper_contract.ethToTokenTransferOutput( tokens_bought=42000000000000000000, deadline=1584789659, recipient=0xEFEA7656B79d8f5cdd4eFE28ddF71855d9C7F447 ) => ( out=334554398216574880 )
            • Dai.balanceOf( 0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667 ) => ( 1658282605319627785572071 )
            • Dai.transfer( dst=0xEFEA7656B79d8f5cdd4eFE28ddF71855d9C7F447, wad=42000000000000000000 ) => ( True )
              File 1 of 6: Vyper_contract
              # @title Uniswap Exchange Interface V1
              # @notice Source code found at https://github.com/uniswap
              # @notice Use at your own risk
              
              contract Factory():
                  def getExchange(token_addr: address) -> address: constant
              
              contract Exchange():
                  def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei): constant
                  def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256: modifying
                  def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei): modifying
              
              TokenPurchase: event({buyer: indexed(address), eth_sold: indexed(uint256(wei)), tokens_bought: indexed(uint256)})
              EthPurchase: event({buyer: indexed(address), tokens_sold: indexed(uint256), eth_bought: indexed(uint256(wei))})
              AddLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              RemoveLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
              Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
              
              name: public(bytes32)                             # Uniswap V1
              symbol: public(bytes32)                           # UNI-V1
              decimals: public(uint256)                         # 18
              totalSupply: public(uint256)                      # total number of UNI in existence
              balances: uint256[address]                        # UNI balance of an address
              allowances: (uint256[address])[address]           # UNI allowance of one address on another
              token: address(ERC20)                             # address of the ERC20 token traded on this contract
              factory: Factory                                  # interface for the factory that created this contract
              
              # @dev This function acts as a contract constructor which is not currently supported in contracts deployed
              #      using create_with_code_of(). It is called once by the factory during contract creation.
              @public
              def setup(token_addr: address):
                  assert (self.factory == ZERO_ADDRESS and self.token == ZERO_ADDRESS) and token_addr != ZERO_ADDRESS
                  self.factory = msg.sender
                  self.token = token_addr
                  self.name = 0x556e697377617020563100000000000000000000000000000000000000000000
                  self.symbol = 0x554e492d56310000000000000000000000000000000000000000000000000000
                  self.decimals = 18
              
              # @notice Deposit ETH and Tokens (self.token) at current ratio to mint UNI tokens.
              # @dev min_liquidity does nothing when total UNI supply is 0.
              # @param min_liquidity Minimum number of UNI sender will mint if total UNI supply is greater than 0.
              # @param max_tokens Maximum number of tokens deposited. Deposits max amount if total UNI supply is 0.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of UNI minted.
              @public
              @payable
              def addLiquidity(min_liquidity: uint256, max_tokens: uint256, deadline: timestamp) -> uint256:
                  assert deadline > block.timestamp and (max_tokens > 0 and msg.value > 0)
                  total_liquidity: uint256 = self.totalSupply
                  if total_liquidity > 0:
                      assert min_liquidity > 0
                      eth_reserve: uint256(wei) = self.balance - msg.value
                      token_reserve: uint256 = self.token.balanceOf(self)
                      token_amount: uint256 = msg.value * token_reserve / eth_reserve + 1
                      liquidity_minted: uint256 = msg.value * total_liquidity / eth_reserve
                      assert max_tokens >= token_amount and liquidity_minted >= min_liquidity
                      self.balances[msg.sender] += liquidity_minted
                      self.totalSupply = total_liquidity + liquidity_minted
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, liquidity_minted)
                      return liquidity_minted
                  else:
                      assert (self.factory != ZERO_ADDRESS and self.token != ZERO_ADDRESS) and msg.value >= 1000000000
                      assert self.factory.getExchange(self.token) == self
                      token_amount: uint256 = max_tokens
                      initial_liquidity: uint256 = as_unitless_number(self.balance)
                      self.totalSupply = initial_liquidity
                      self.balances[msg.sender] = initial_liquidity
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, initial_liquidity)
                      return initial_liquidity
              
              # @dev Burn UNI tokens to withdraw ETH and Tokens at current ratio.
              # @param amount Amount of UNI burned.
              # @param min_eth Minimum ETH withdrawn.
              # @param min_tokens Minimum Tokens withdrawn.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of ETH and Tokens withdrawn.
              @public
              def removeLiquidity(amount: uint256, min_eth: uint256(wei), min_tokens: uint256, deadline: timestamp) -> (uint256(wei), uint256):
                  assert (amount > 0 and deadline > block.timestamp) and (min_eth > 0 and min_tokens > 0)
                  total_liquidity: uint256 = self.totalSupply
                  assert total_liquidity > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_amount: uint256(wei) = amount * self.balance / total_liquidity
                  token_amount: uint256 = amount * token_reserve / total_liquidity
                  assert eth_amount >= min_eth and token_amount >= min_tokens
                  self.balances[msg.sender] -= amount
                  self.totalSupply = total_liquidity - amount
                  send(msg.sender, eth_amount)
                  assert self.token.transfer(msg.sender, token_amount)
                  log.RemoveLiquidity(msg.sender, eth_amount, token_amount)
                  log.Transfer(msg.sender, ZERO_ADDRESS, amount)
                  return eth_amount, token_amount
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param input_amount Amount of ETH or Tokens being sold.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens bought.
              @private
              @constant
              def getInputPrice(input_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  input_amount_with_fee: uint256 = input_amount * 997
                  numerator: uint256 = input_amount_with_fee * output_reserve
                  denominator: uint256 = (input_reserve * 1000) + input_amount_with_fee
                  return numerator / denominator
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param output_amount Amount of ETH or Tokens being bought.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens sold.
              @private
              @constant
              def getOutputPrice(output_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  numerator: uint256 = input_reserve * output_amount * 1000
                  denominator: uint256 = (output_reserve - output_amount) * 997
                  return numerator / denominator + 1
              
              @private
              def ethToTokenInput(eth_sold: uint256(wei), min_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and (eth_sold > 0 and min_tokens > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_bought: uint256 = self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance - eth_sold), token_reserve)
                  assert tokens_bought >= min_tokens
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, eth_sold, tokens_bought)
                  return tokens_bought
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value).
              # @dev User cannot specify minimum output or deadline.
              @public
              @payable
              def __default__():
                  self.ethToTokenInput(msg.value, 1, block.timestamp, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value) and minimum output.
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenSwapInput(min_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies exact input (msg.value) and minimum output
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, recipient)
              
              @private
              def ethToTokenOutput(tokens_bought: uint256, max_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance - max_eth), token_reserve)
                  # Throws if eth_sold > max_eth
                  eth_refund: uint256(wei) = max_eth - as_wei_value(eth_sold, 'wei')
                  if eth_refund > 0:
                      send(buyer, eth_refund)
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, as_wei_value(eth_sold, 'wei'), tokens_bought)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenSwapOutput(tokens_bought: uint256, deadline: timestamp) -> uint256(wei):
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_sold > 0 and min_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth
                  send(recipient, wei_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return wei_bought
              
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH bought.
              @public
              def tokenToEthSwapInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp) -> uint256(wei):
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of ETH bought.
              @public
              def tokenToEthTransferInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens >= tokens_sold
                  send(recipient, eth_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthSwapOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthTransferOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, recipient)
              
              @private
              def tokenToTokenInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert (deadline >= block.timestamp and tokens_sold > 0) and (min_tokens_bought > 0 and min_eth_bought > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  tokens_bought: uint256 = Exchange(exchange_addr).ethToTokenTransferInput(min_tokens_bought, deadline, recipient, value=wei_bought)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return tokens_bought
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              @private
              def tokenToTokenOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth_sold > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  eth_bought: uint256(wei) = Exchange(exchange_addr).getEthToTokenOutputPrice(tokens_bought)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens_sold >= tokens_sold and max_eth_sold >= eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  eth_sold: uint256(wei) = Exchange(exchange_addr).ethToTokenTransferOutput(tokens_bought, deadline, recipient, value=eth_bought)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Public price function for ETH to Token trades with an exact input.
              # @param eth_sold Amount of ETH sold.
              # @return Amount of Tokens that can be bought with input ETH.
              @public
              @constant
              def getEthToTokenInputPrice(eth_sold: uint256(wei)) -> uint256:
                  assert eth_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance), token_reserve)
              
              # @notice Public price function for ETH to Token trades with an exact output.
              # @param tokens_bought Amount of Tokens bought.
              # @return Amount of ETH needed to buy output Tokens.
              @public
              @constant
              def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei):
                  assert tokens_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance), token_reserve)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact input.
              # @param tokens_sold Amount of Tokens sold.
              # @return Amount of ETH that can be bought with input Tokens.
              @public
              @constant
              def getTokenToEthInputPrice(tokens_sold: uint256) -> uint256(wei):
                  assert tokens_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  return as_wei_value(eth_bought, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact output.
              # @param eth_bought Amount of output ETH.
              # @return Amount of Tokens needed to buy output ETH.
              @public
              @constant
              def getTokenToEthOutputPrice(eth_bought: uint256(wei)) -> uint256:
                  assert eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
              
              # @return Address of Token that is sold on this exchange.
              @public
              @constant
              def tokenAddress() -> address:
                  return self.token
              
              # @return Address of factory that created this exchange.
              @public
              @constant
              def factoryAddress() -> address(Factory):
                  return self.factory
              
              # ERC20 compatibility for exchange liquidity modified from
              # https://github.com/ethereum/vyper/blob/master/examples/tokens/ERC20.vy
              @public
              @constant
              def balanceOf(_owner : address) -> uint256:
                  return self.balances[_owner]
              
              @public
              def transfer(_to : address, _value : uint256) -> bool:
                  self.balances[msg.sender] -= _value
                  self.balances[_to] += _value
                  log.Transfer(msg.sender, _to, _value)
                  return True
              
              @public
              def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
                  self.balances[_from] -= _value
                  self.balances[_to] += _value
                  self.allowances[_from][msg.sender] -= _value
                  log.Transfer(_from, _to, _value)
                  return True
              
              @public
              def approve(_spender : address, _value : uint256) -> bool:
                  self.allowances[msg.sender][_spender] = _value
                  log.Approval(msg.sender, _spender, _value)
                  return True
              
              @public
              @constant
              def allowance(_owner : address, _spender : address) -> uint256:
                  return self.allowances[_owner][_spender]

              File 2 of 6: RLC
              pragma solidity ^0.4.8;
              
              contract ERC20 {
                uint public totalSupply;
                function balanceOf(address who) constant returns (uint);
                function allowance(address owner, address spender) constant returns (uint);
              
                function transfer(address to, uint value) returns (bool ok);
                function transferFrom(address from, address to, uint value) returns (bool ok);
                function approve(address spender, uint value) returns (bool ok);
                event Transfer(address indexed from, address indexed to, uint value);
                event Approval(address indexed owner, address indexed spender, uint value);
              }
              
              
              contract Ownable {
                address public owner;
              
                function Ownable() {
                  owner = msg.sender;
                }
              
                modifier onlyOwner() {
                  if (msg.sender == owner)
                    _;
                }
              
                function transferOwnership(address newOwner) onlyOwner {
                  if (newOwner != address(0)) owner = newOwner;
                }
              
              }
              
              
              contract TokenSpender {
                  function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData);
              }
              
              contract SafeMath {
                function safeMul(uint a, uint b) internal returns (uint) {
                  uint c = a * b;
                  assert(a == 0 || c / a == b);
                  return c;
                }
              
                function safeDiv(uint a, uint b) internal returns (uint) {
                  assert(b > 0);
                  uint c = a / b;
                  assert(a == b * c + a % b);
                  return c;
                }
              
                function safeSub(uint a, uint b) internal returns (uint) {
                  assert(b <= a);
                  return a - b;
                }
              
                function safeAdd(uint a, uint b) internal returns (uint) {
                  uint c = a + b;
                  assert(c>=a && c>=b);
                  return c;
                }
              
                function max64(uint64 a, uint64 b) internal constant returns (uint64) {
                  return a >= b ? a : b;
                }
              
                function min64(uint64 a, uint64 b) internal constant returns (uint64) {
                  return a < b ? a : b;
                }
              
                function max256(uint256 a, uint256 b) internal constant returns (uint256) {
                  return a >= b ? a : b;
                }
              
                function min256(uint256 a, uint256 b) internal constant returns (uint256) {
                  return a < b ? a : b;
                }
              
                function assert(bool assertion) internal {
                  if (!assertion) {
                    throw;
                  }
                }
              }
              
              
              contract RLC is ERC20, SafeMath, Ownable {
              
                  /* Public variables of the token */
                string public name;       //fancy name
                string public symbol;
                uint8 public decimals;    //How many decimals to show.
                string public version = 'v0.1'; 
                uint public initialSupply;
                uint public totalSupply;
                bool public locked;
                //uint public unlockBlock;
              
                mapping(address => uint) balances;
                mapping (address => mapping (address => uint)) allowed;
              
                // lock transfer during the ICO
                modifier onlyUnlocked() {
                  if (msg.sender != owner && locked) throw;
                  _;
                }
              
                /*
                 *  The RLC Token created with the time at which the crowdsale end
                 */
              
                function RLC() {
                  // lock the transfer function during the crowdsale
                  locked = true;
                  //unlockBlock=  now + 45 days; // (testnet) - for mainnet put the block number
              
                  initialSupply = 87000000000000000;
                  totalSupply = initialSupply;
                  balances[msg.sender] = initialSupply;// Give the creator all initial tokens                    
                  name = 'iEx.ec Network Token';        // Set the name for display purposes     
                  symbol = 'RLC';                       // Set the symbol for display purposes  
                  decimals = 9;                        // Amount of decimals for display purposes
                }
              
                function unlock() onlyOwner {
                  locked = false;
                }
              
                function burn(uint256 _value) returns (bool){
                  balances[msg.sender] = safeSub(balances[msg.sender], _value) ;
                  totalSupply = safeSub(totalSupply, _value);
                  Transfer(msg.sender, 0x0, _value);
                  return true;
                }
              
                function transfer(address _to, uint _value) onlyUnlocked returns (bool) {
                  balances[msg.sender] = safeSub(balances[msg.sender], _value);
                  balances[_to] = safeAdd(balances[_to], _value);
                  Transfer(msg.sender, _to, _value);
                  return true;
                }
              
                function transferFrom(address _from, address _to, uint _value) onlyUnlocked returns (bool) {
                  var _allowance = allowed[_from][msg.sender];
                  
                  balances[_to] = safeAdd(balances[_to], _value);
                  balances[_from] = safeSub(balances[_from], _value);
                  allowed[_from][msg.sender] = safeSub(_allowance, _value);
                  Transfer(_from, _to, _value);
                  return true;
                }
              
                function balanceOf(address _owner) constant returns (uint balance) {
                  return balances[_owner];
                }
              
                function approve(address _spender, uint _value) returns (bool) {
                  allowed[msg.sender][_spender] = _value;
                  Approval(msg.sender, _spender, _value);
                  return true;
                }
              
                  /* Approve and then comunicate the approved contract in a single tx */
                function approveAndCall(address _spender, uint256 _value, bytes _extraData){    
                    TokenSpender spender = TokenSpender(_spender);
                    if (approve(_spender, _value)) {
                        spender.receiveApproval(msg.sender, _value, this, _extraData);
                    }
                }
              
                function allowance(address _owner, address _spender) constant returns (uint remaining) {
                  return allowed[_owner][_spender];
                }
                
              }

              File 3 of 6: Vyper_contract
              # @title Uniswap Exchange Interface V1
              # @notice Source code found at https://github.com/uniswap
              # @notice Use at your own risk
              
              contract Factory():
                  def getExchange(token_addr: address) -> address: constant
              
              contract Exchange():
                  def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei): constant
                  def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256: modifying
                  def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei): modifying
              
              TokenPurchase: event({buyer: indexed(address), eth_sold: indexed(uint256(wei)), tokens_bought: indexed(uint256)})
              EthPurchase: event({buyer: indexed(address), tokens_sold: indexed(uint256), eth_bought: indexed(uint256(wei))})
              AddLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              RemoveLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
              Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
              
              name: public(bytes32)                             # Uniswap V1
              symbol: public(bytes32)                           # UNI-V1
              decimals: public(uint256)                         # 18
              totalSupply: public(uint256)                      # total number of UNI in existence
              balances: uint256[address]                        # UNI balance of an address
              allowances: (uint256[address])[address]           # UNI allowance of one address on another
              token: address(ERC20)                             # address of the ERC20 token traded on this contract
              factory: Factory                                  # interface for the factory that created this contract
              
              # @dev This function acts as a contract constructor which is not currently supported in contracts deployed
              #      using create_with_code_of(). It is called once by the factory during contract creation.
              @public
              def setup(token_addr: address):
                  assert (self.factory == ZERO_ADDRESS and self.token == ZERO_ADDRESS) and token_addr != ZERO_ADDRESS
                  self.factory = msg.sender
                  self.token = token_addr
                  self.name = 0x556e697377617020563100000000000000000000000000000000000000000000
                  self.symbol = 0x554e492d56310000000000000000000000000000000000000000000000000000
                  self.decimals = 18
              
              # @notice Deposit ETH and Tokens (self.token) at current ratio to mint UNI tokens.
              # @dev min_liquidity does nothing when total UNI supply is 0.
              # @param min_liquidity Minimum number of UNI sender will mint if total UNI supply is greater than 0.
              # @param max_tokens Maximum number of tokens deposited. Deposits max amount if total UNI supply is 0.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of UNI minted.
              @public
              @payable
              def addLiquidity(min_liquidity: uint256, max_tokens: uint256, deadline: timestamp) -> uint256:
                  assert deadline > block.timestamp and (max_tokens > 0 and msg.value > 0)
                  total_liquidity: uint256 = self.totalSupply
                  if total_liquidity > 0:
                      assert min_liquidity > 0
                      eth_reserve: uint256(wei) = self.balance - msg.value
                      token_reserve: uint256 = self.token.balanceOf(self)
                      token_amount: uint256 = msg.value * token_reserve / eth_reserve + 1
                      liquidity_minted: uint256 = msg.value * total_liquidity / eth_reserve
                      assert max_tokens >= token_amount and liquidity_minted >= min_liquidity
                      self.balances[msg.sender] += liquidity_minted
                      self.totalSupply = total_liquidity + liquidity_minted
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, liquidity_minted)
                      return liquidity_minted
                  else:
                      assert (self.factory != ZERO_ADDRESS and self.token != ZERO_ADDRESS) and msg.value >= 1000000000
                      assert self.factory.getExchange(self.token) == self
                      token_amount: uint256 = max_tokens
                      initial_liquidity: uint256 = as_unitless_number(self.balance)
                      self.totalSupply = initial_liquidity
                      self.balances[msg.sender] = initial_liquidity
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, initial_liquidity)
                      return initial_liquidity
              
              # @dev Burn UNI tokens to withdraw ETH and Tokens at current ratio.
              # @param amount Amount of UNI burned.
              # @param min_eth Minimum ETH withdrawn.
              # @param min_tokens Minimum Tokens withdrawn.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of ETH and Tokens withdrawn.
              @public
              def removeLiquidity(amount: uint256, min_eth: uint256(wei), min_tokens: uint256, deadline: timestamp) -> (uint256(wei), uint256):
                  assert (amount > 0 and deadline > block.timestamp) and (min_eth > 0 and min_tokens > 0)
                  total_liquidity: uint256 = self.totalSupply
                  assert total_liquidity > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_amount: uint256(wei) = amount * self.balance / total_liquidity
                  token_amount: uint256 = amount * token_reserve / total_liquidity
                  assert eth_amount >= min_eth and token_amount >= min_tokens
                  self.balances[msg.sender] -= amount
                  self.totalSupply = total_liquidity - amount
                  send(msg.sender, eth_amount)
                  assert self.token.transfer(msg.sender, token_amount)
                  log.RemoveLiquidity(msg.sender, eth_amount, token_amount)
                  log.Transfer(msg.sender, ZERO_ADDRESS, amount)
                  return eth_amount, token_amount
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param input_amount Amount of ETH or Tokens being sold.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens bought.
              @private
              @constant
              def getInputPrice(input_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  input_amount_with_fee: uint256 = input_amount * 997
                  numerator: uint256 = input_amount_with_fee * output_reserve
                  denominator: uint256 = (input_reserve * 1000) + input_amount_with_fee
                  return numerator / denominator
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param output_amount Amount of ETH or Tokens being bought.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens sold.
              @private
              @constant
              def getOutputPrice(output_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  numerator: uint256 = input_reserve * output_amount * 1000
                  denominator: uint256 = (output_reserve - output_amount) * 997
                  return numerator / denominator + 1
              
              @private
              def ethToTokenInput(eth_sold: uint256(wei), min_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and (eth_sold > 0 and min_tokens > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_bought: uint256 = self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance - eth_sold), token_reserve)
                  assert tokens_bought >= min_tokens
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, eth_sold, tokens_bought)
                  return tokens_bought
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value).
              # @dev User cannot specify minimum output or deadline.
              @public
              @payable
              def __default__():
                  self.ethToTokenInput(msg.value, 1, block.timestamp, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value) and minimum output.
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenSwapInput(min_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies exact input (msg.value) and minimum output
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, recipient)
              
              @private
              def ethToTokenOutput(tokens_bought: uint256, max_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance - max_eth), token_reserve)
                  # Throws if eth_sold > max_eth
                  eth_refund: uint256(wei) = max_eth - as_wei_value(eth_sold, 'wei')
                  if eth_refund > 0:
                      send(buyer, eth_refund)
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, as_wei_value(eth_sold, 'wei'), tokens_bought)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenSwapOutput(tokens_bought: uint256, deadline: timestamp) -> uint256(wei):
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_sold > 0 and min_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth
                  send(recipient, wei_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return wei_bought
              
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH bought.
              @public
              def tokenToEthSwapInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp) -> uint256(wei):
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of ETH bought.
              @public
              def tokenToEthTransferInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens >= tokens_sold
                  send(recipient, eth_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthSwapOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthTransferOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, recipient)
              
              @private
              def tokenToTokenInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert (deadline >= block.timestamp and tokens_sold > 0) and (min_tokens_bought > 0 and min_eth_bought > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  tokens_bought: uint256 = Exchange(exchange_addr).ethToTokenTransferInput(min_tokens_bought, deadline, recipient, value=wei_bought)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return tokens_bought
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              @private
              def tokenToTokenOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth_sold > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  eth_bought: uint256(wei) = Exchange(exchange_addr).getEthToTokenOutputPrice(tokens_bought)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens_sold >= tokens_sold and max_eth_sold >= eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  eth_sold: uint256(wei) = Exchange(exchange_addr).ethToTokenTransferOutput(tokens_bought, deadline, recipient, value=eth_bought)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Public price function for ETH to Token trades with an exact input.
              # @param eth_sold Amount of ETH sold.
              # @return Amount of Tokens that can be bought with input ETH.
              @public
              @constant
              def getEthToTokenInputPrice(eth_sold: uint256(wei)) -> uint256:
                  assert eth_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance), token_reserve)
              
              # @notice Public price function for ETH to Token trades with an exact output.
              # @param tokens_bought Amount of Tokens bought.
              # @return Amount of ETH needed to buy output Tokens.
              @public
              @constant
              def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei):
                  assert tokens_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance), token_reserve)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact input.
              # @param tokens_sold Amount of Tokens sold.
              # @return Amount of ETH that can be bought with input Tokens.
              @public
              @constant
              def getTokenToEthInputPrice(tokens_sold: uint256) -> uint256(wei):
                  assert tokens_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  return as_wei_value(eth_bought, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact output.
              # @param eth_bought Amount of output ETH.
              # @return Amount of Tokens needed to buy output ETH.
              @public
              @constant
              def getTokenToEthOutputPrice(eth_bought: uint256(wei)) -> uint256:
                  assert eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
              
              # @return Address of Token that is sold on this exchange.
              @public
              @constant
              def tokenAddress() -> address:
                  return self.token
              
              # @return Address of factory that created this exchange.
              @public
              @constant
              def factoryAddress() -> address(Factory):
                  return self.factory
              
              # ERC20 compatibility for exchange liquidity modified from
              # https://github.com/ethereum/vyper/blob/master/examples/tokens/ERC20.vy
              @public
              @constant
              def balanceOf(_owner : address) -> uint256:
                  return self.balances[_owner]
              
              @public
              def transfer(_to : address, _value : uint256) -> bool:
                  self.balances[msg.sender] -= _value
                  self.balances[_to] += _value
                  log.Transfer(msg.sender, _to, _value)
                  return True
              
              @public
              def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
                  self.balances[_from] -= _value
                  self.balances[_to] += _value
                  self.allowances[_from][msg.sender] -= _value
                  log.Transfer(_from, _to, _value)
                  return True
              
              @public
              def approve(_spender : address, _value : uint256) -> bool:
                  self.allowances[msg.sender][_spender] = _value
                  log.Approval(msg.sender, _spender, _value)
                  return True
              
              @public
              @constant
              def allowance(_owner : address, _spender : address) -> uint256:
                  return self.allowances[_owner][_spender]

              File 4 of 6: Dai
              // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
              pragma solidity =0.5.12;
              
              ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
              // This program is free software: you can redistribute it and/or modify
              // it under the terms of the GNU General Public License as published by
              // the Free Software Foundation, either version 3 of the License, or
              // (at your option) any later version.
              
              // This program is distributed in the hope that it will be useful,
              // but WITHOUT ANY WARRANTY; without even the implied warranty of
              // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
              // GNU General Public License for more details.
              
              // You should have received a copy of the GNU General Public License
              // along with this program.  If not, see <http://www.gnu.org/licenses/>.
              
              /* pragma solidity 0.5.12; */
              
              contract LibNote {
                  event LogNote(
                      bytes4   indexed  sig,
                      address  indexed  usr,
                      bytes32  indexed  arg1,
                      bytes32  indexed  arg2,
                      bytes             data
                  ) anonymous;
              
                  modifier note {
                      _;
                      assembly {
                          // log an 'anonymous' event with a constant 6 words of calldata
                          // and four indexed topics: selector, caller, arg1 and arg2
                          let mark := msize                         // end of memory ensures zero
                          mstore(0x40, add(mark, 288))              // update free memory pointer
                          mstore(mark, 0x20)                        // bytes type data offset
                          mstore(add(mark, 0x20), 224)              // bytes size (padded)
                          calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                          log4(mark, 288,                           // calldata
                               shl(224, shr(224, calldataload(0))), // msg.sig
                               caller,                              // msg.sender
                               calldataload(4),                     // arg1
                               calldataload(36)                     // arg2
                              )
                      }
                  }
              }
              
              ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
              // Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico
              
              // This program is free software: you can redistribute it and/or modify
              // it under the terms of the GNU Affero General Public License as published by
              // the Free Software Foundation, either version 3 of the License, or
              // (at your option) any later version.
              //
              // This program is distributed in the hope that it will be useful,
              // but WITHOUT ANY WARRANTY; without even the implied warranty of
              // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
              // GNU Affero General Public License for more details.
              //
              // You should have received a copy of the GNU Affero General Public License
              // along with this program.  If not, see <https://www.gnu.org/licenses/>.
              
              /* pragma solidity 0.5.12; */
              
              /* import "./lib.sol"; */
              
              contract Dai is LibNote {
                  // --- Auth ---
                  mapping (address => uint) public wards;
                  function rely(address guy) external note auth { wards[guy] = 1; }
                  function deny(address guy) external note auth { wards[guy] = 0; }
                  modifier auth {
                      require(wards[msg.sender] == 1, "Dai/not-authorized");
                      _;
                  }
              
                  // --- ERC20 Data ---
                  string  public constant name     = "Dai Stablecoin";
                  string  public constant symbol   = "DAI";
                  string  public constant version  = "1";
                  uint8   public constant decimals = 18;
                  uint256 public totalSupply;
              
                  mapping (address => uint)                      public balanceOf;
                  mapping (address => mapping (address => uint)) public allowance;
                  mapping (address => uint)                      public nonces;
              
                  event Approval(address indexed src, address indexed guy, uint wad);
                  event Transfer(address indexed src, address indexed dst, uint wad);
              
                  // --- Math ---
                  function add(uint x, uint y) internal pure returns (uint z) {
                      require((z = x + y) >= x);
                  }
                  function sub(uint x, uint y) internal pure returns (uint z) {
                      require((z = x - y) <= x);
                  }
              
                  // --- EIP712 niceties ---
                  bytes32 public DOMAIN_SEPARATOR;
                  // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
                  bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
              
                  constructor(uint256 chainId_) public {
                      wards[msg.sender] = 1;
                      DOMAIN_SEPARATOR = keccak256(abi.encode(
                          keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                          keccak256(bytes(name)),
                          keccak256(bytes(version)),
                          chainId_,
                          address(this)
                      ));
                  }
              
                  // --- Token ---
                  function transfer(address dst, uint wad) external returns (bool) {
                      return transferFrom(msg.sender, dst, wad);
                  }
                  function transferFrom(address src, address dst, uint wad)
                      public returns (bool)
                  {
                      require(balanceOf[src] >= wad, "Dai/insufficient-balance");
                      if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
                          require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance");
                          allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
                      }
                      balanceOf[src] = sub(balanceOf[src], wad);
                      balanceOf[dst] = add(balanceOf[dst], wad);
                      emit Transfer(src, dst, wad);
                      return true;
                  }
                  function mint(address usr, uint wad) external auth {
                      balanceOf[usr] = add(balanceOf[usr], wad);
                      totalSupply    = add(totalSupply, wad);
                      emit Transfer(address(0), usr, wad);
                  }
                  function burn(address usr, uint wad) external {
                      require(balanceOf[usr] >= wad, "Dai/insufficient-balance");
                      if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {
                          require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance");
                          allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);
                      }
                      balanceOf[usr] = sub(balanceOf[usr], wad);
                      totalSupply    = sub(totalSupply, wad);
                      emit Transfer(usr, address(0), wad);
                  }
                  function approve(address usr, uint wad) external returns (bool) {
                      allowance[msg.sender][usr] = wad;
                      emit Approval(msg.sender, usr, wad);
                      return true;
                  }
              
                  // --- Alias ---
                  function push(address usr, uint wad) external {
                      transferFrom(msg.sender, usr, wad);
                  }
                  function pull(address usr, uint wad) external {
                      transferFrom(usr, msg.sender, wad);
                  }
                  function move(address src, address dst, uint wad) external {
                      transferFrom(src, dst, wad);
                  }
              
                  // --- Approve by signature ---
                  function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                                  bool allowed, uint8 v, bytes32 r, bytes32 s) external
                  {
                      bytes32 digest =
                          keccak256(abi.encodePacked(
                              "\x19\x01",
                              DOMAIN_SEPARATOR,
                              keccak256(abi.encode(PERMIT_TYPEHASH,
                                                   holder,
                                                   spender,
                                                   nonce,
                                                   expiry,
                                                   allowed))
                      ));
              
                      require(holder != address(0), "Dai/invalid-address-0");
                      require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
                      require(expiry == 0 || now <= expiry, "Dai/permit-expired");
                      require(nonce == nonces[holder]++, "Dai/invalid-nonce");
                      uint wad = allowed ? uint(-1) : 0;
                      allowance[holder][spender] = wad;
                      emit Approval(holder, spender, wad);
                  }
              }

              File 5 of 6: Vyper_contract
              # @title Uniswap Exchange Interface V1
              # @notice Source code found at https://github.com/uniswap
              # @notice Use at your own risk
              
              contract Factory():
                  def getExchange(token_addr: address) -> address: constant
              
              contract Exchange():
                  def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei): constant
                  def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256: modifying
                  def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei): modifying
              
              TokenPurchase: event({buyer: indexed(address), eth_sold: indexed(uint256(wei)), tokens_bought: indexed(uint256)})
              EthPurchase: event({buyer: indexed(address), tokens_sold: indexed(uint256), eth_bought: indexed(uint256(wei))})
              AddLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              RemoveLiquidity: event({provider: indexed(address), eth_amount: indexed(uint256(wei)), token_amount: indexed(uint256)})
              Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
              Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
              
              name: public(bytes32)                             # Uniswap V1
              symbol: public(bytes32)                           # UNI-V1
              decimals: public(uint256)                         # 18
              totalSupply: public(uint256)                      # total number of UNI in existence
              balances: uint256[address]                        # UNI balance of an address
              allowances: (uint256[address])[address]           # UNI allowance of one address on another
              token: address(ERC20)                             # address of the ERC20 token traded on this contract
              factory: Factory                                  # interface for the factory that created this contract
              
              # @dev This function acts as a contract constructor which is not currently supported in contracts deployed
              #      using create_with_code_of(). It is called once by the factory during contract creation.
              @public
              def setup(token_addr: address):
                  assert (self.factory == ZERO_ADDRESS and self.token == ZERO_ADDRESS) and token_addr != ZERO_ADDRESS
                  self.factory = msg.sender
                  self.token = token_addr
                  self.name = 0x556e697377617020563100000000000000000000000000000000000000000000
                  self.symbol = 0x554e492d56310000000000000000000000000000000000000000000000000000
                  self.decimals = 18
              
              # @notice Deposit ETH and Tokens (self.token) at current ratio to mint UNI tokens.
              # @dev min_liquidity does nothing when total UNI supply is 0.
              # @param min_liquidity Minimum number of UNI sender will mint if total UNI supply is greater than 0.
              # @param max_tokens Maximum number of tokens deposited. Deposits max amount if total UNI supply is 0.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of UNI minted.
              @public
              @payable
              def addLiquidity(min_liquidity: uint256, max_tokens: uint256, deadline: timestamp) -> uint256:
                  assert deadline > block.timestamp and (max_tokens > 0 and msg.value > 0)
                  total_liquidity: uint256 = self.totalSupply
                  if total_liquidity > 0:
                      assert min_liquidity > 0
                      eth_reserve: uint256(wei) = self.balance - msg.value
                      token_reserve: uint256 = self.token.balanceOf(self)
                      token_amount: uint256 = msg.value * token_reserve / eth_reserve + 1
                      liquidity_minted: uint256 = msg.value * total_liquidity / eth_reserve
                      assert max_tokens >= token_amount and liquidity_minted >= min_liquidity
                      self.balances[msg.sender] += liquidity_minted
                      self.totalSupply = total_liquidity + liquidity_minted
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, liquidity_minted)
                      return liquidity_minted
                  else:
                      assert (self.factory != ZERO_ADDRESS and self.token != ZERO_ADDRESS) and msg.value >= 1000000000
                      assert self.factory.getExchange(self.token) == self
                      token_amount: uint256 = max_tokens
                      initial_liquidity: uint256 = as_unitless_number(self.balance)
                      self.totalSupply = initial_liquidity
                      self.balances[msg.sender] = initial_liquidity
                      assert self.token.transferFrom(msg.sender, self, token_amount)
                      log.AddLiquidity(msg.sender, msg.value, token_amount)
                      log.Transfer(ZERO_ADDRESS, msg.sender, initial_liquidity)
                      return initial_liquidity
              
              # @dev Burn UNI tokens to withdraw ETH and Tokens at current ratio.
              # @param amount Amount of UNI burned.
              # @param min_eth Minimum ETH withdrawn.
              # @param min_tokens Minimum Tokens withdrawn.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return The amount of ETH and Tokens withdrawn.
              @public
              def removeLiquidity(amount: uint256, min_eth: uint256(wei), min_tokens: uint256, deadline: timestamp) -> (uint256(wei), uint256):
                  assert (amount > 0 and deadline > block.timestamp) and (min_eth > 0 and min_tokens > 0)
                  total_liquidity: uint256 = self.totalSupply
                  assert total_liquidity > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_amount: uint256(wei) = amount * self.balance / total_liquidity
                  token_amount: uint256 = amount * token_reserve / total_liquidity
                  assert eth_amount >= min_eth and token_amount >= min_tokens
                  self.balances[msg.sender] -= amount
                  self.totalSupply = total_liquidity - amount
                  send(msg.sender, eth_amount)
                  assert self.token.transfer(msg.sender, token_amount)
                  log.RemoveLiquidity(msg.sender, eth_amount, token_amount)
                  log.Transfer(msg.sender, ZERO_ADDRESS, amount)
                  return eth_amount, token_amount
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param input_amount Amount of ETH or Tokens being sold.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens bought.
              @private
              @constant
              def getInputPrice(input_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  input_amount_with_fee: uint256 = input_amount * 997
                  numerator: uint256 = input_amount_with_fee * output_reserve
                  denominator: uint256 = (input_reserve * 1000) + input_amount_with_fee
                  return numerator / denominator
              
              # @dev Pricing function for converting between ETH and Tokens.
              # @param output_amount Amount of ETH or Tokens being bought.
              # @param input_reserve Amount of ETH or Tokens (input type) in exchange reserves.
              # @param output_reserve Amount of ETH or Tokens (output type) in exchange reserves.
              # @return Amount of ETH or Tokens sold.
              @private
              @constant
              def getOutputPrice(output_amount: uint256, input_reserve: uint256, output_reserve: uint256) -> uint256:
                  assert input_reserve > 0 and output_reserve > 0
                  numerator: uint256 = input_reserve * output_amount * 1000
                  denominator: uint256 = (output_reserve - output_amount) * 997
                  return numerator / denominator + 1
              
              @private
              def ethToTokenInput(eth_sold: uint256(wei), min_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and (eth_sold > 0 and min_tokens > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_bought: uint256 = self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance - eth_sold), token_reserve)
                  assert tokens_bought >= min_tokens
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, eth_sold, tokens_bought)
                  return tokens_bought
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value).
              # @dev User cannot specify minimum output or deadline.
              @public
              @payable
              def __default__():
                  self.ethToTokenInput(msg.value, 1, block.timestamp, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies exact input (msg.value) and minimum output.
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenSwapInput(min_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies exact input (msg.value) and minimum output
              # @param min_tokens Minimum Tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of Tokens bought.
              @public
              @payable
              def ethToTokenTransferInput(min_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenInput(msg.value, min_tokens, deadline, msg.sender, recipient)
              
              @private
              def ethToTokenOutput(tokens_bought: uint256, max_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance - max_eth), token_reserve)
                  # Throws if eth_sold > max_eth
                  eth_refund: uint256(wei) = max_eth - as_wei_value(eth_sold, 'wei')
                  if eth_refund > 0:
                      send(buyer, eth_refund)
                  assert self.token.transfer(recipient, tokens_bought)
                  log.TokenPurchase(buyer, as_wei_value(eth_sold, 'wei'), tokens_bought)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Convert ETH to Tokens.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenSwapOutput(tokens_bought: uint256, deadline: timestamp) -> uint256(wei):
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, msg.sender)
              
              # @notice Convert ETH to Tokens and transfers Tokens to recipient.
              # @dev User specifies maximum input (msg.value) and exact output.
              # @param tokens_bought Amount of tokens bought.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output Tokens.
              # @return Amount of ETH sold.
              @public
              @payable
              def ethToTokenTransferOutput(tokens_bought: uint256, deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.ethToTokenOutput(tokens_bought, msg.value, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, buyer: address, recipient: address) -> uint256(wei):
                  assert deadline >= block.timestamp and (tokens_sold > 0 and min_eth > 0)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth
                  send(recipient, wei_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return wei_bought
              
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of ETH bought.
              @public
              def tokenToEthSwapInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp) -> uint256(wei):
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_eth Minimum ETH purchased.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of ETH bought.
              @public
              def tokenToEthTransferInput(tokens_sold: uint256, min_eth: uint256(wei), deadline: timestamp, recipient: address) -> uint256(wei):
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthInput(tokens_sold, min_eth, deadline, msg.sender, recipient)
              
              @private
              def tokenToEthOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, buyer: address, recipient: address) -> uint256:
                  assert deadline >= block.timestamp and eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens >= tokens_sold
                  send(recipient, eth_bought)
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens to ETH.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthSwapOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp) -> uint256:
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, msg.sender)
              
              # @notice Convert Tokens to ETH and transfers ETH to recipient.
              # @dev User specifies maximum input and exact output.
              # @param eth_bought Amount of ETH purchased.
              # @param max_tokens Maximum Tokens sold.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @return Amount of Tokens sold.
              @public
              def tokenToEthTransferOutput(eth_bought: uint256(wei), max_tokens: uint256, deadline: timestamp, recipient: address) -> uint256:
                  assert recipient != self and recipient != ZERO_ADDRESS
                  return self.tokenToEthOutput(eth_bought, max_tokens, deadline, msg.sender, recipient)
              
              @private
              def tokenToTokenInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert (deadline >= block.timestamp and tokens_sold > 0) and (min_tokens_bought > 0 and min_eth_bought > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  wei_bought: uint256(wei) = as_wei_value(eth_bought, 'wei')
                  assert wei_bought >= min_eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  tokens_bought: uint256 = Exchange(exchange_addr).ethToTokenTransferInput(min_tokens_bought, deadline, recipient, value=wei_bought)
                  log.EthPurchase(buyer, tokens_sold, wei_bought)
                  return tokens_bought
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (token_addr) bought.
              @public
              def tokenToTokenTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              @private
              def tokenToTokenOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, buyer: address, recipient: address, exchange_addr: address) -> uint256:
                  assert deadline >= block.timestamp and (tokens_bought > 0 and max_eth_sold > 0)
                  assert exchange_addr != self and exchange_addr != ZERO_ADDRESS
                  eth_bought: uint256(wei) = Exchange(exchange_addr).getEthToTokenOutputPrice(tokens_bought)
                  token_reserve: uint256 = self.token.balanceOf(self)
                  tokens_sold: uint256 = self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
                  # tokens sold is always > 0
                  assert max_tokens_sold >= tokens_sold and max_eth_sold >= eth_bought
                  assert self.token.transferFrom(buyer, self, tokens_sold)
                  eth_sold: uint256(wei) = Exchange(exchange_addr).ethToTokenTransferOutput(tokens_bought, deadline, recipient, value=eth_bought)
                  log.EthPurchase(buyer, tokens_sold, eth_bought)
                  return tokens_sold
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr).
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (token_addr) and transfers
              #         Tokens (token_addr) to recipient.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToTokenTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, token_addr: address) -> uint256:
                  exchange_addr: address = self.factory.getExchange(token_addr)
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeSwapInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies exact input and minimum output.
              # @param tokens_sold Amount of Tokens sold.
              # @param min_tokens_bought Minimum Tokens (token_addr) purchased.
              # @param min_eth_bought Minimum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (exchange_addr.token) bought.
              @public
              def tokenToExchangeTransferInput(tokens_sold: uint256, min_tokens_bought: uint256, min_eth_bought: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenInput(tokens_sold, min_tokens_bought, min_eth_bought, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token).
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param exchange_addr The address of the exchange for the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeSwapOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, exchange_addr: address) -> uint256:
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, msg.sender, exchange_addr)
              
              # @notice Convert Tokens (self.token) to Tokens (exchange_addr.token) and transfers
              #         Tokens (exchange_addr.token) to recipient.
              # @dev Allows trades through contracts that were not deployed from the same factory.
              # @dev User specifies maximum input and exact output.
              # @param tokens_bought Amount of Tokens (token_addr) bought.
              # @param max_tokens_sold Maximum Tokens (self.token) sold.
              # @param max_eth_sold Maximum ETH purchased as intermediary.
              # @param deadline Time after which this transaction can no longer be executed.
              # @param recipient The address that receives output ETH.
              # @param token_addr The address of the token being purchased.
              # @return Amount of Tokens (self.token) sold.
              @public
              def tokenToExchangeTransferOutput(tokens_bought: uint256, max_tokens_sold: uint256, max_eth_sold: uint256(wei), deadline: timestamp, recipient: address, exchange_addr: address) -> uint256:
                  assert recipient != self
                  return self.tokenToTokenOutput(tokens_bought, max_tokens_sold, max_eth_sold, deadline, msg.sender, recipient, exchange_addr)
              
              # @notice Public price function for ETH to Token trades with an exact input.
              # @param eth_sold Amount of ETH sold.
              # @return Amount of Tokens that can be bought with input ETH.
              @public
              @constant
              def getEthToTokenInputPrice(eth_sold: uint256(wei)) -> uint256:
                  assert eth_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getInputPrice(as_unitless_number(eth_sold), as_unitless_number(self.balance), token_reserve)
              
              # @notice Public price function for ETH to Token trades with an exact output.
              # @param tokens_bought Amount of Tokens bought.
              # @return Amount of ETH needed to buy output Tokens.
              @public
              @constant
              def getEthToTokenOutputPrice(tokens_bought: uint256) -> uint256(wei):
                  assert tokens_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_sold: uint256 = self.getOutputPrice(tokens_bought, as_unitless_number(self.balance), token_reserve)
                  return as_wei_value(eth_sold, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact input.
              # @param tokens_sold Amount of Tokens sold.
              # @return Amount of ETH that can be bought with input Tokens.
              @public
              @constant
              def getTokenToEthInputPrice(tokens_sold: uint256) -> uint256(wei):
                  assert tokens_sold > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  eth_bought: uint256 = self.getInputPrice(tokens_sold, token_reserve, as_unitless_number(self.balance))
                  return as_wei_value(eth_bought, 'wei')
              
              # @notice Public price function for Token to ETH trades with an exact output.
              # @param eth_bought Amount of output ETH.
              # @return Amount of Tokens needed to buy output ETH.
              @public
              @constant
              def getTokenToEthOutputPrice(eth_bought: uint256(wei)) -> uint256:
                  assert eth_bought > 0
                  token_reserve: uint256 = self.token.balanceOf(self)
                  return self.getOutputPrice(as_unitless_number(eth_bought), token_reserve, as_unitless_number(self.balance))
              
              # @return Address of Token that is sold on this exchange.
              @public
              @constant
              def tokenAddress() -> address:
                  return self.token
              
              # @return Address of factory that created this exchange.
              @public
              @constant
              def factoryAddress() -> address(Factory):
                  return self.factory
              
              # ERC20 compatibility for exchange liquidity modified from
              # https://github.com/ethereum/vyper/blob/master/examples/tokens/ERC20.vy
              @public
              @constant
              def balanceOf(_owner : address) -> uint256:
                  return self.balances[_owner]
              
              @public
              def transfer(_to : address, _value : uint256) -> bool:
                  self.balances[msg.sender] -= _value
                  self.balances[_to] += _value
                  log.Transfer(msg.sender, _to, _value)
                  return True
              
              @public
              def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
                  self.balances[_from] -= _value
                  self.balances[_to] += _value
                  self.allowances[_from][msg.sender] -= _value
                  log.Transfer(_from, _to, _value)
                  return True
              
              @public
              def approve(_spender : address, _value : uint256) -> bool:
                  self.allowances[msg.sender][_spender] = _value
                  log.Approval(msg.sender, _spender, _value)
                  return True
              
              @public
              @constant
              def allowance(_owner : address, _spender : address) -> uint256:
                  return self.allowances[_owner][_spender]

              File 6 of 6: Vyper_contract
              contract Exchange():
                  def setup(token_addr: address): modifying
              
              NewExchange: event({token: indexed(address), exchange: indexed(address)})
              
              exchangeTemplate: public(address)
              tokenCount: public(uint256)
              token_to_exchange: address[address]
              exchange_to_token: address[address]
              id_to_token: address[uint256]
              
              @public
              def initializeFactory(template: address):
                  assert self.exchangeTemplate == ZERO_ADDRESS
                  assert template != ZERO_ADDRESS
                  self.exchangeTemplate = template
              
              @public
              def createExchange(token: address) -> address:
                  assert token != ZERO_ADDRESS
                  assert self.exchangeTemplate != ZERO_ADDRESS
                  assert self.token_to_exchange[token] == ZERO_ADDRESS
                  exchange: address = create_with_code_of(self.exchangeTemplate)
                  Exchange(exchange).setup(token)
                  self.token_to_exchange[token] = exchange
                  self.exchange_to_token[exchange] = token
                  token_id: uint256 = self.tokenCount + 1
                  self.tokenCount = token_id
                  self.id_to_token[token_id] = token
                  log.NewExchange(token, exchange)
                  return exchange
              
              @public
              @constant
              def getExchange(token: address) -> address:
                  return self.token_to_exchange[token]
              
              @public
              @constant
              def getToken(exchange: address) -> address:
                  return self.exchange_to_token[exchange]
              
              @public
              @constant
              def getTokenWithId(token_id: uint256) -> address:
                  return self.id_to_token[token_id]