github.com/diadata-org/diadata@v1.4.593/config/nftContracts/opensea/contract.sol (about)

     1  /**
     2   *Submitted for verification at Etherscan.io on 2018-06-12
     3  */
     4  
     5  pragma solidity ^0.4.13;
     6  
     7  library SafeMath {
     8  
     9    /**
    10    * @dev Multiplies two numbers, throws on overflow.
    11    */
    12    function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    13      if (a == 0) {
    14        return 0;
    15      }
    16      c = a * b;
    17      assert(c / a == b);
    18      return c;
    19    }
    20  
    21    /**
    22    * @dev Integer division of two numbers, truncating the quotient.
    23    */
    24    function div(uint256 a, uint256 b) internal pure returns (uint256) {
    25      // assert(b > 0); // Solidity automatically throws when dividing by 0
    26      // uint256 c = a / b;
    27      // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    28      return a / b;
    29    }
    30  
    31    /**
    32    * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    33    */
    34    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    35      assert(b <= a);
    36      return a - b;
    37    }
    38  
    39    /**
    40    * @dev Adds two numbers, throws on overflow.
    41    */
    42    function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
    43      c = a + b;
    44      assert(c >= a);
    45      return c;
    46    }
    47  }
    48  
    49  contract Ownable {
    50    address public owner;
    51  
    52  
    53    event OwnershipRenounced(address indexed previousOwner);
    54    event OwnershipTransferred(
    55      address indexed previousOwner,
    56      address indexed newOwner
    57    );
    58  
    59  
    60    /**
    61     * @dev The Ownable constructor sets the original `owner` of the contract to the sender
    62     * account.
    63     */
    64    constructor() public {
    65      owner = msg.sender;
    66    }
    67  
    68    /**
    69     * @dev Throws if called by any account other than the owner.
    70     */
    71    modifier onlyOwner() {
    72      require(msg.sender == owner);
    73      _;
    74    }
    75  
    76    /**
    77     * @dev Allows the current owner to transfer control of the contract to a newOwner.
    78     * @param newOwner The address to transfer ownership to.
    79     */
    80    function transferOwnership(address newOwner) public onlyOwner {
    81      require(newOwner != address(0));
    82      emit OwnershipTransferred(owner, newOwner);
    83      owner = newOwner;
    84    }
    85  
    86    /**
    87     * @dev Allows the current owner to relinquish control of the contract.
    88     */
    89    function renounceOwnership() public onlyOwner {
    90      emit OwnershipRenounced(owner);
    91      owner = address(0);
    92    }
    93  }
    94  
    95  contract ERC20Basic {
    96    function totalSupply() public view returns (uint256);
    97    function balanceOf(address who) public view returns (uint256);
    98    function transfer(address to, uint256 value) public returns (bool);
    99    event Transfer(address indexed from, address indexed to, uint256 value);
   100  }
   101  
   102  contract ERC20 is ERC20Basic {
   103    function allowance(address owner, address spender)
   104      public view returns (uint256);
   105  
   106    function transferFrom(address from, address to, uint256 value)
   107      public returns (bool);
   108  
   109    function approve(address spender, uint256 value) public returns (bool);
   110    event Approval(
   111      address indexed owner,
   112      address indexed spender,
   113      uint256 value
   114    );
   115  }
   116  
   117  library ArrayUtils {
   118  
   119      /**
   120       * Replace bytes in an array with bytes in another array, guarded by a bitmask
   121       * Efficiency of this function is a bit unpredictable because of the EVM's word-specific model (arrays under 32 bytes will be slower)
   122       * 
   123       * @dev Mask must be the size of the byte array. A nonzero byte means the byte array can be changed.
   124       * @param array The original array
   125       * @param desired The target array
   126       * @param mask The mask specifying which bits can be changed
   127       * @return The updated byte array (the parameter will be modified inplace)
   128       */
   129      function guardedArrayReplace(bytes memory array, bytes memory desired, bytes memory mask)
   130          internal
   131          pure
   132      {
   133          require(array.length == desired.length);
   134          require(array.length == mask.length);
   135  
   136          uint words = array.length / 0x20;
   137          uint index = words * 0x20;
   138          assert(index / 0x20 == words);
   139          uint i;
   140  
   141          for (i = 0; i < words; i++) {
   142              /* Conceptually: array[i] = (!mask[i] && array[i]) || (mask[i] && desired[i]), bitwise in word chunks. */
   143              assembly {
   144                  let commonIndex := mul(0x20, add(1, i))
   145                  let maskValue := mload(add(mask, commonIndex))
   146                  mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
   147              }
   148          }
   149  
   150          /* Deal with the last section of the byte array. */
   151          if (words > 0) {
   152              /* This overlaps with bytes already set but is still more efficient than iterating through each of the remaining bytes individually. */
   153              i = words;
   154              assembly {
   155                  let commonIndex := mul(0x20, add(1, i))
   156                  let maskValue := mload(add(mask, commonIndex))
   157                  mstore(add(array, commonIndex), or(and(not(maskValue), mload(add(array, commonIndex))), and(maskValue, mload(add(desired, commonIndex)))))
   158              }
   159          } else {
   160              /* If the byte array is shorter than a word, we must unfortunately do the whole thing bytewise.
   161                 (bounds checks could still probably be optimized away in assembly, but this is a rare case) */
   162              for (i = index; i < array.length; i++) {
   163                  array[i] = ((mask[i] ^ 0xff) & array[i]) | (mask[i] & desired[i]);
   164              }
   165          }
   166      }
   167  
   168      /**
   169       * Test if two arrays are equal
   170       * Source: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol
   171       * 
   172       * @dev Arrays must be of equal length, otherwise will return false
   173       * @param a First array
   174       * @param b Second array
   175       * @return Whether or not all bytes in the arrays are equal
   176       */
   177      function arrayEq(bytes memory a, bytes memory b)
   178          internal
   179          pure
   180          returns (bool)
   181      {
   182          bool success = true;
   183  
   184          assembly {
   185              let length := mload(a)
   186  
   187              // if lengths don't match the arrays are not equal
   188              switch eq(length, mload(b))
   189              case 1 {
   190                  // cb is a circuit breaker in the for loop since there's
   191                  //  no said feature for inline assembly loops
   192                  // cb = 1 - don't breaker
   193                  // cb = 0 - break
   194                  let cb := 1
   195  
   196                  let mc := add(a, 0x20)
   197                  let end := add(mc, length)
   198  
   199                  for {
   200                      let cc := add(b, 0x20)
   201                  // the next line is the loop condition:
   202                  // while(uint(mc < end) + cb == 2)
   203                  } eq(add(lt(mc, end), cb), 2) {
   204                      mc := add(mc, 0x20)
   205                      cc := add(cc, 0x20)
   206                  } {
   207                      // if any of these checks fails then arrays are not equal
   208                      if iszero(eq(mload(mc), mload(cc))) {
   209                          // unsuccess:
   210                          success := 0
   211                          cb := 0
   212                      }
   213                  }
   214              }
   215              default {
   216                  // unsuccess:
   217                  success := 0
   218              }
   219          }
   220  
   221          return success;
   222      }
   223  
   224      /**
   225       * Unsafe write byte array into a memory location
   226       *
   227       * @param index Memory location
   228       * @param source Byte array to write
   229       * @return End memory index
   230       */
   231      function unsafeWriteBytes(uint index, bytes source)
   232          internal
   233          pure
   234          returns (uint)
   235      {
   236          if (source.length > 0) {
   237              assembly {
   238                  let length := mload(source)
   239                  let end := add(source, add(0x20, length))
   240                  let arrIndex := add(source, 0x20)
   241                  let tempIndex := index
   242                  for { } eq(lt(arrIndex, end), 1) {
   243                      arrIndex := add(arrIndex, 0x20)
   244                      tempIndex := add(tempIndex, 0x20)
   245                  } {
   246                      mstore(tempIndex, mload(arrIndex))
   247                  }
   248                  index := add(index, length)
   249              }
   250          }
   251          return index;
   252      }
   253  
   254      /**
   255       * Unsafe write address into a memory location
   256       *
   257       * @param index Memory location
   258       * @param source Address to write
   259       * @return End memory index
   260       */
   261      function unsafeWriteAddress(uint index, address source)
   262          internal
   263          pure
   264          returns (uint)
   265      {
   266          uint conv = uint(source) << 0x60;
   267          assembly {
   268              mstore(index, conv)
   269              index := add(index, 0x14)
   270          }
   271          return index;
   272      }
   273  
   274      /**
   275       * Unsafe write uint into a memory location
   276       *
   277       * @param index Memory location
   278       * @param source uint to write
   279       * @return End memory index
   280       */
   281      function unsafeWriteUint(uint index, uint source)
   282          internal
   283          pure
   284          returns (uint)
   285      {
   286          assembly {
   287              mstore(index, source)
   288              index := add(index, 0x20)
   289          }
   290          return index;
   291      }
   292  
   293      /**
   294       * Unsafe write uint8 into a memory location
   295       *
   296       * @param index Memory location
   297       * @param source uint8 to write
   298       * @return End memory index
   299       */
   300      function unsafeWriteUint8(uint index, uint8 source)
   301          internal
   302          pure
   303          returns (uint)
   304      {
   305          assembly {
   306              mstore8(index, source)
   307              index := add(index, 0x1)
   308          }
   309          return index;
   310      }
   311  
   312  }
   313  
   314  contract ReentrancyGuarded {
   315  
   316      bool reentrancyLock = false;
   317  
   318      /* Prevent a contract function from being reentrant-called. */
   319      modifier reentrancyGuard {
   320          if (reentrancyLock) {
   321              revert();
   322          }
   323          reentrancyLock = true;
   324          _;
   325          reentrancyLock = false;
   326      }
   327  
   328  }
   329  
   330  contract TokenRecipient {
   331      event ReceivedEther(address indexed sender, uint amount);
   332      event ReceivedTokens(address indexed from, uint256 value, address indexed token, bytes extraData);
   333  
   334      /**
   335       * @dev Receive tokens and generate a log event
   336       * @param from Address from which to transfer tokens
   337       * @param value Amount of tokens to transfer
   338       * @param token Address of token
   339       * @param extraData Additional data to log
   340       */
   341      function receiveApproval(address from, uint256 value, address token, bytes extraData) public {
   342          ERC20 t = ERC20(token);
   343          require(t.transferFrom(from, this, value));
   344          emit ReceivedTokens(from, value, token, extraData);
   345      }
   346  
   347      /**
   348       * @dev Receive Ether and generate a log event
   349       */
   350      function () payable public {
   351          emit ReceivedEther(msg.sender, msg.value);
   352      }
   353  }
   354  
   355  contract ExchangeCore is ReentrancyGuarded, Ownable {
   356  
   357      /* The token used to pay exchange fees. */
   358      ERC20 public exchangeToken;
   359  
   360      /* User registry. */
   361      ProxyRegistry public registry;
   362  
   363      /* Token transfer proxy. */
   364      TokenTransferProxy public tokenTransferProxy;
   365  
   366      /* Cancelled / finalized orders, by hash. */
   367      mapping(bytes32 => bool) public cancelledOrFinalized;
   368  
   369      /* Orders verified by on-chain approval (alternative to ECDSA signatures so that smart contracts can place orders directly). */
   370      mapping(bytes32 => bool) public approvedOrders;
   371  
   372      /* For split fee orders, minimum required protocol maker fee, in basis points. Paid to owner (who can change it). */
   373      uint public minimumMakerProtocolFee = 0;
   374  
   375      /* For split fee orders, minimum required protocol taker fee, in basis points. Paid to owner (who can change it). */
   376      uint public minimumTakerProtocolFee = 0;
   377  
   378      /* Recipient of protocol fees. */
   379      address public protocolFeeRecipient;
   380  
   381      /* Fee method: protocol fee or split fee. */
   382      enum FeeMethod { ProtocolFee, SplitFee }
   383  
   384      /* Inverse basis point. */
   385      uint public constant INVERSE_BASIS_POINT = 10000;
   386  
   387      /* An ECDSA signature. */ 
   388      struct Sig {
   389          /* v parameter */
   390          uint8 v;
   391          /* r parameter */
   392          bytes32 r;
   393          /* s parameter */
   394          bytes32 s;
   395      }
   396  
   397      /* An order on the exchange. */
   398      struct Order {
   399          /* Exchange address, intended as a versioning mechanism. */
   400          address exchange;
   401          /* Order maker address. */
   402          address maker;
   403          /* Order taker address, if specified. */
   404          address taker;
   405          /* Maker relayer fee of the order, unused for taker order. */
   406          uint makerRelayerFee;
   407          /* Taker relayer fee of the order, or maximum taker fee for a taker order. */
   408          uint takerRelayerFee;
   409          /* Maker protocol fee of the order, unused for taker order. */
   410          uint makerProtocolFee;
   411          /* Taker protocol fee of the order, or maximum taker fee for a taker order. */
   412          uint takerProtocolFee;
   413          /* Order fee recipient or zero address for taker order. */
   414          address feeRecipient;
   415          /* Fee method (protocol token or split fee). */
   416          FeeMethod feeMethod;
   417          /* Side (buy/sell). */
   418          SaleKindInterface.Side side;
   419          /* Kind of sale. */
   420          SaleKindInterface.SaleKind saleKind;
   421          /* Target. */
   422          address target;
   423          /* HowToCall. */
   424          AuthenticatedProxy.HowToCall howToCall;
   425          /* Calldata. */
   426          bytes calldata;
   427          /* Calldata replacement pattern, or an empty byte array for no replacement. */
   428          bytes replacementPattern;
   429          /* Static call target, zero-address for no static call. */
   430          address staticTarget;
   431          /* Static call extra data. */
   432          bytes staticExtradata;
   433          /* Token used to pay for the order, or the zero-address as a sentinel value for Ether. */
   434          address paymentToken;
   435          /* Base price of the order (in paymentTokens). */
   436          uint basePrice;
   437          /* Auction extra parameter - minimum bid increment for English auctions, starting/ending price difference. */
   438          uint extra;
   439          /* Listing timestamp. */
   440          uint listingTime;
   441          /* Expiration timestamp - 0 for no expiry. */
   442          uint expirationTime;
   443          /* Order salt, used to prevent duplicate hashes. */
   444          uint salt;
   445      }
   446      
   447      event OrderApprovedPartOne    (bytes32 indexed hash, address exchange, address indexed maker, address taker, uint makerRelayerFee, uint takerRelayerFee, uint makerProtocolFee, uint takerProtocolFee, address indexed feeRecipient, FeeMethod feeMethod, SaleKindInterface.Side side, SaleKindInterface.SaleKind saleKind, address target);
   448      event OrderApprovedPartTwo    (bytes32 indexed hash, AuthenticatedProxy.HowToCall howToCall, bytes calldata, bytes replacementPattern, address staticTarget, bytes staticExtradata, address paymentToken, uint basePrice, uint extra, uint listingTime, uint expirationTime, uint salt, bool orderbookInclusionDesired);
   449      event OrderCancelled          (bytes32 indexed hash);
   450      event OrdersMatched           (bytes32 buyHash, bytes32 sellHash, address indexed maker, address indexed taker, uint price, bytes32 indexed metadata);
   451  
   452      /**
   453       * @dev Change the minimum maker fee paid to the protocol (owner only)
   454       * @param newMinimumMakerProtocolFee New fee to set in basis points
   455       */
   456      function changeMinimumMakerProtocolFee(uint newMinimumMakerProtocolFee)
   457          public
   458          onlyOwner
   459      {
   460          minimumMakerProtocolFee = newMinimumMakerProtocolFee;
   461      }
   462  
   463      /**
   464       * @dev Change the minimum taker fee paid to the protocol (owner only)
   465       * @param newMinimumTakerProtocolFee New fee to set in basis points
   466       */
   467      function changeMinimumTakerProtocolFee(uint newMinimumTakerProtocolFee)
   468          public
   469          onlyOwner
   470      {
   471          minimumTakerProtocolFee = newMinimumTakerProtocolFee;
   472      }
   473  
   474      /**
   475       * @dev Change the protocol fee recipient (owner only)
   476       * @param newProtocolFeeRecipient New protocol fee recipient address
   477       */
   478      function changeProtocolFeeRecipient(address newProtocolFeeRecipient)
   479          public
   480          onlyOwner
   481      {
   482          protocolFeeRecipient = newProtocolFeeRecipient;
   483      }
   484  
   485      /**
   486       * @dev Transfer tokens
   487       * @param token Token to transfer
   488       * @param from Address to charge fees
   489       * @param to Address to receive fees
   490       * @param amount Amount of protocol tokens to charge
   491       */
   492      function transferTokens(address token, address from, address to, uint amount)
   493          internal
   494      {
   495          if (amount > 0) {
   496              require(tokenTransferProxy.transferFrom(token, from, to, amount));
   497          }
   498      }
   499  
   500      /**
   501       * @dev Charge a fee in protocol tokens
   502       * @param from Address to charge fees
   503       * @param to Address to receive fees
   504       * @param amount Amount of protocol tokens to charge
   505       */
   506      function chargeProtocolFee(address from, address to, uint amount)
   507          internal
   508      {
   509          transferTokens(exchangeToken, from, to, amount);
   510      }
   511  
   512      /**
   513       * @dev Execute a STATICCALL (introduced with Ethereum Metropolis, non-state-modifying external call)
   514       * @param target Contract to call
   515       * @param calldata Calldata (appended to extradata)
   516       * @param extradata Base data for STATICCALL (probably function selector and argument encoding)
   517       * @return The result of the call (success or failure)
   518       */
   519      function staticCall(address target, bytes memory calldata, bytes memory extradata)
   520          public
   521          view
   522          returns (bool result)
   523      {
   524          bytes memory combined = new bytes(calldata.length + extradata.length);
   525          uint index;
   526          assembly {
   527              index := add(combined, 0x20)
   528          }
   529          index = ArrayUtils.unsafeWriteBytes(index, extradata);
   530          ArrayUtils.unsafeWriteBytes(index, calldata);
   531          assembly {
   532              result := staticcall(gas, target, add(combined, 0x20), mload(combined), mload(0x40), 0)
   533          }
   534          return result;
   535      }
   536  
   537      /**
   538       * Calculate size of an order struct when tightly packed
   539       *
   540       * @param order Order to calculate size of
   541       * @return Size in bytes
   542       */
   543      function sizeOf(Order memory order)
   544          internal
   545          pure
   546          returns (uint)
   547      {
   548          return ((0x14 * 7) + (0x20 * 9) + 4 + order.calldata.length + order.replacementPattern.length + order.staticExtradata.length);
   549      }
   550  
   551      /**
   552       * @dev Hash an order, returning the canonical order hash, without the message prefix
   553       * @param order Order to hash
   554       * @return Hash of order
   555       */
   556      function hashOrder(Order memory order)
   557          internal
   558          pure
   559          returns (bytes32 hash)
   560      {
   561          /* Unfortunately abi.encodePacked doesn't work here, stack size constraints. */
   562          uint size = sizeOf(order);
   563          bytes memory array = new bytes(size);
   564          uint index;
   565          assembly {
   566              index := add(array, 0x20)
   567          }
   568          index = ArrayUtils.unsafeWriteAddress(index, order.exchange);
   569          index = ArrayUtils.unsafeWriteAddress(index, order.maker);
   570          index = ArrayUtils.unsafeWriteAddress(index, order.taker);
   571          index = ArrayUtils.unsafeWriteUint(index, order.makerRelayerFee);
   572          index = ArrayUtils.unsafeWriteUint(index, order.takerRelayerFee);
   573          index = ArrayUtils.unsafeWriteUint(index, order.makerProtocolFee);
   574          index = ArrayUtils.unsafeWriteUint(index, order.takerProtocolFee);
   575          index = ArrayUtils.unsafeWriteAddress(index, order.feeRecipient);
   576          index = ArrayUtils.unsafeWriteUint8(index, uint8(order.feeMethod));
   577          index = ArrayUtils.unsafeWriteUint8(index, uint8(order.side));
   578          index = ArrayUtils.unsafeWriteUint8(index, uint8(order.saleKind));
   579          index = ArrayUtils.unsafeWriteAddress(index, order.target);
   580          index = ArrayUtils.unsafeWriteUint8(index, uint8(order.howToCall));
   581          index = ArrayUtils.unsafeWriteBytes(index, order.calldata);
   582          index = ArrayUtils.unsafeWriteBytes(index, order.replacementPattern);
   583          index = ArrayUtils.unsafeWriteAddress(index, order.staticTarget);
   584          index = ArrayUtils.unsafeWriteBytes(index, order.staticExtradata);
   585          index = ArrayUtils.unsafeWriteAddress(index, order.paymentToken);
   586          index = ArrayUtils.unsafeWriteUint(index, order.basePrice);
   587          index = ArrayUtils.unsafeWriteUint(index, order.extra);
   588          index = ArrayUtils.unsafeWriteUint(index, order.listingTime);
   589          index = ArrayUtils.unsafeWriteUint(index, order.expirationTime);
   590          index = ArrayUtils.unsafeWriteUint(index, order.salt);
   591          assembly {
   592              hash := keccak256(add(array, 0x20), size)
   593          }
   594          return hash;
   595      }
   596  
   597      /**
   598       * @dev Hash an order, returning the hash that a client must sign, including the standard message prefix
   599       * @param order Order to hash
   600       * @return Hash of message prefix and order hash per Ethereum format
   601       */
   602      function hashToSign(Order memory order)
   603          internal
   604          pure
   605          returns (bytes32)
   606      {
   607          return keccak256("\x19Ethereum Signed Message:\n32", hashOrder(order));
   608      }
   609  
   610      /**
   611       * @dev Assert an order is valid and return its hash
   612       * @param order Order to validate
   613       * @param sig ECDSA signature
   614       */
   615      function requireValidOrder(Order memory order, Sig memory sig)
   616          internal
   617          view
   618          returns (bytes32)
   619      {
   620          bytes32 hash = hashToSign(order);
   621          require(validateOrder(hash, order, sig));
   622          return hash;
   623      }
   624  
   625      /**
   626       * @dev Validate order parameters (does *not* check signature validity)
   627       * @param order Order to validate
   628       */
   629      function validateOrderParameters(Order memory order)
   630          internal
   631          view
   632          returns (bool)
   633      {
   634          /* Order must be targeted at this protocol version (this Exchange contract). */
   635          if (order.exchange != address(this)) {
   636              return false;
   637          }
   638  
   639          /* Order must possess valid sale kind parameter combination. */
   640          if (!SaleKindInterface.validateParameters(order.saleKind, order.expirationTime)) {
   641              return false;
   642          }
   643  
   644          /* If using the split fee method, order must have sufficient protocol fees. */
   645          if (order.feeMethod == FeeMethod.SplitFee && (order.makerProtocolFee < minimumMakerProtocolFee || order.takerProtocolFee < minimumTakerProtocolFee)) {
   646              return false;
   647          }
   648  
   649          return true;
   650      }
   651  
   652      /**
   653       * @dev Validate a provided previously approved / signed order, hash, and signature.
   654       * @param hash Order hash (already calculated, passed to avoid recalculation)
   655       * @param order Order to validate
   656       * @param sig ECDSA signature
   657       */
   658      function validateOrder(bytes32 hash, Order memory order, Sig memory sig) 
   659          internal
   660          view
   661          returns (bool)
   662      {
   663          /* Not done in an if-conditional to prevent unnecessary ecrecover evaluation, which seems to happen even though it should short-circuit. */
   664  
   665          /* Order must have valid parameters. */
   666          if (!validateOrderParameters(order)) {
   667              return false;
   668          }
   669  
   670          /* Order must have not been canceled or already filled. */
   671          if (cancelledOrFinalized[hash]) {
   672              return false;
   673          }
   674          
   675          /* Order authentication. Order must be either:
   676          /* (a) previously approved */
   677          if (approvedOrders[hash]) {
   678              return true;
   679          }
   680  
   681          /* or (b) ECDSA-signed by maker. */
   682          if (ecrecover(hash, sig.v, sig.r, sig.s) == order.maker) {
   683              return true;
   684          }
   685  
   686          return false;
   687      }
   688  
   689      /**
   690       * @dev Approve an order and optionally mark it for orderbook inclusion. Must be called by the maker of the order
   691       * @param order Order to approve
   692       * @param orderbookInclusionDesired Whether orderbook providers should include the order in their orderbooks
   693       */
   694      function approveOrder(Order memory order, bool orderbookInclusionDesired)
   695          internal
   696      {
   697          /* CHECKS */
   698  
   699          /* Assert sender is authorized to approve order. */
   700          require(msg.sender == order.maker);
   701  
   702          /* Calculate order hash. */
   703          bytes32 hash = hashToSign(order);
   704  
   705          /* Assert order has not already been approved. */
   706          require(!approvedOrders[hash]);
   707  
   708          /* EFFECTS */
   709      
   710          /* Mark order as approved. */
   711          approvedOrders[hash] = true;
   712    
   713          /* Log approval event. Must be split in two due to Solidity stack size limitations. */
   714          {
   715              emit OrderApprovedPartOne(hash, order.exchange, order.maker, order.taker, order.makerRelayerFee, order.takerRelayerFee, order.makerProtocolFee, order.takerProtocolFee, order.feeRecipient, order.feeMethod, order.side, order.saleKind, order.target);
   716          }
   717          {   
   718              emit OrderApprovedPartTwo(hash, order.howToCall, order.calldata, order.replacementPattern, order.staticTarget, order.staticExtradata, order.paymentToken, order.basePrice, order.extra, order.listingTime, order.expirationTime, order.salt, orderbookInclusionDesired);
   719          }
   720      }
   721  
   722      /**
   723       * @dev Cancel an order, preventing it from being matched. Must be called by the maker of the order
   724       * @param order Order to cancel
   725       * @param sig ECDSA signature
   726       */
   727      function cancelOrder(Order memory order, Sig memory sig) 
   728          internal
   729      {
   730          /* CHECKS */
   731  
   732          /* Calculate order hash. */
   733          bytes32 hash = requireValidOrder(order, sig);
   734  
   735          /* Assert sender is authorized to cancel order. */
   736          require(msg.sender == order.maker);
   737    
   738          /* EFFECTS */
   739        
   740          /* Mark order as cancelled, preventing it from being matched. */
   741          cancelledOrFinalized[hash] = true;
   742  
   743          /* Log cancel event. */
   744          emit OrderCancelled(hash);
   745      }
   746  
   747      /**
   748       * @dev Calculate the current price of an order (convenience function)
   749       * @param order Order to calculate the price of
   750       * @return The current price of the order
   751       */
   752      function calculateCurrentPrice (Order memory order)
   753          internal  
   754          view
   755          returns (uint)
   756      {
   757          return SaleKindInterface.calculateFinalPrice(order.side, order.saleKind, order.basePrice, order.extra, order.listingTime, order.expirationTime);
   758      }
   759  
   760      /**
   761       * @dev Calculate the price two orders would match at, if in fact they would match (otherwise fail)
   762       * @param buy Buy-side order
   763       * @param sell Sell-side order
   764       * @return Match price
   765       */
   766      function calculateMatchPrice(Order memory buy, Order memory sell)
   767          view
   768          internal
   769          returns (uint)
   770      {
   771          /* Calculate sell price. */
   772          uint sellPrice = SaleKindInterface.calculateFinalPrice(sell.side, sell.saleKind, sell.basePrice, sell.extra, sell.listingTime, sell.expirationTime);
   773  
   774          /* Calculate buy price. */
   775          uint buyPrice = SaleKindInterface.calculateFinalPrice(buy.side, buy.saleKind, buy.basePrice, buy.extra, buy.listingTime, buy.expirationTime);
   776  
   777          /* Require price cross. */
   778          require(buyPrice >= sellPrice);
   779          
   780          /* Maker/taker priority. */
   781          return sell.feeRecipient != address(0) ? sellPrice : buyPrice;
   782      }
   783  
   784      /**
   785       * @dev Execute all ERC20 token / Ether transfers associated with an order match (fees and buyer => seller transfer)
   786       * @param buy Buy-side order
   787       * @param sell Sell-side order
   788       */
   789      function executeFundsTransfer(Order memory buy, Order memory sell)
   790          internal
   791          returns (uint)
   792      {
   793          /* Only payable in the special case of unwrapped Ether. */
   794          if (sell.paymentToken != address(0)) {
   795              require(msg.value == 0);
   796          }
   797  
   798          /* Calculate match price. */
   799          uint price = calculateMatchPrice(buy, sell);
   800  
   801          /* If paying using a token (not Ether), transfer tokens. This is done prior to fee payments to that a seller will have tokens before being charged fees. */
   802          if (price > 0 && sell.paymentToken != address(0)) {
   803              transferTokens(sell.paymentToken, buy.maker, sell.maker, price);
   804          }
   805  
   806          /* Amount that will be received by seller (for Ether). */
   807          uint receiveAmount = price;
   808  
   809          /* Amount that must be sent by buyer (for Ether). */
   810          uint requiredAmount = price;
   811  
   812          /* Determine maker/taker and charge fees accordingly. */
   813          if (sell.feeRecipient != address(0)) {
   814              /* Sell-side order is maker. */
   815        
   816              /* Assert taker fee is less than or equal to maximum fee specified by buyer. */
   817              require(sell.takerRelayerFee <= buy.takerRelayerFee);
   818  
   819              if (sell.feeMethod == FeeMethod.SplitFee) {
   820                  /* Assert taker fee is less than or equal to maximum fee specified by buyer. */
   821                  require(sell.takerProtocolFee <= buy.takerProtocolFee);
   822  
   823                  /* Maker fees are deducted from the token amount that the maker receives. Taker fees are extra tokens that must be paid by the taker. */
   824  
   825                  if (sell.makerRelayerFee > 0) {
   826                      uint makerRelayerFee = SafeMath.div(SafeMath.mul(sell.makerRelayerFee, price), INVERSE_BASIS_POINT);
   827                      if (sell.paymentToken == address(0)) {
   828                          receiveAmount = SafeMath.sub(receiveAmount, makerRelayerFee);
   829                          sell.feeRecipient.transfer(makerRelayerFee);
   830                      } else {
   831                          transferTokens(sell.paymentToken, sell.maker, sell.feeRecipient, makerRelayerFee);
   832                      }
   833                  }
   834  
   835                  if (sell.takerRelayerFee > 0) {
   836                      uint takerRelayerFee = SafeMath.div(SafeMath.mul(sell.takerRelayerFee, price), INVERSE_BASIS_POINT);
   837                      if (sell.paymentToken == address(0)) {
   838                          requiredAmount = SafeMath.add(requiredAmount, takerRelayerFee);
   839                          sell.feeRecipient.transfer(takerRelayerFee);
   840                      } else {
   841                          transferTokens(sell.paymentToken, buy.maker, sell.feeRecipient, takerRelayerFee);
   842                      }
   843                  }
   844  
   845                  if (sell.makerProtocolFee > 0) {
   846                      uint makerProtocolFee = SafeMath.div(SafeMath.mul(sell.makerProtocolFee, price), INVERSE_BASIS_POINT);
   847                      if (sell.paymentToken == address(0)) {
   848                          receiveAmount = SafeMath.sub(receiveAmount, makerProtocolFee);
   849                          protocolFeeRecipient.transfer(makerProtocolFee);
   850                      } else {
   851                          transferTokens(sell.paymentToken, sell.maker, protocolFeeRecipient, makerProtocolFee);
   852                      }
   853                  }
   854  
   855                  if (sell.takerProtocolFee > 0) {
   856                      uint takerProtocolFee = SafeMath.div(SafeMath.mul(sell.takerProtocolFee, price), INVERSE_BASIS_POINT);
   857                      if (sell.paymentToken == address(0)) {
   858                          requiredAmount = SafeMath.add(requiredAmount, takerProtocolFee);
   859                          protocolFeeRecipient.transfer(takerProtocolFee);
   860                      } else {
   861                          transferTokens(sell.paymentToken, buy.maker, protocolFeeRecipient, takerProtocolFee);
   862                      }
   863                  }
   864  
   865              } else {
   866                  /* Charge maker fee to seller. */
   867                  chargeProtocolFee(sell.maker, sell.feeRecipient, sell.makerRelayerFee);
   868  
   869                  /* Charge taker fee to buyer. */
   870                  chargeProtocolFee(buy.maker, sell.feeRecipient, sell.takerRelayerFee);
   871              }
   872          } else {
   873              /* Buy-side order is maker. */
   874  
   875              /* Assert taker fee is less than or equal to maximum fee specified by seller. */
   876              require(buy.takerRelayerFee <= sell.takerRelayerFee);
   877  
   878              if (sell.feeMethod == FeeMethod.SplitFee) {
   879                  /* The Exchange does not escrow Ether, so direct Ether can only be used to with sell-side maker / buy-side taker orders. */
   880                  require(sell.paymentToken != address(0));
   881  
   882                  /* Assert taker fee is less than or equal to maximum fee specified by seller. */
   883                  require(buy.takerProtocolFee <= sell.takerProtocolFee);
   884  
   885                  if (buy.makerRelayerFee > 0) {
   886                      makerRelayerFee = SafeMath.div(SafeMath.mul(buy.makerRelayerFee, price), INVERSE_BASIS_POINT);
   887                      transferTokens(sell.paymentToken, buy.maker, buy.feeRecipient, makerRelayerFee);
   888                  }
   889  
   890                  if (buy.takerRelayerFee > 0) {
   891                      takerRelayerFee = SafeMath.div(SafeMath.mul(buy.takerRelayerFee, price), INVERSE_BASIS_POINT);
   892                      transferTokens(sell.paymentToken, sell.maker, buy.feeRecipient, takerRelayerFee);
   893                  }
   894  
   895                  if (buy.makerProtocolFee > 0) {
   896                      makerProtocolFee = SafeMath.div(SafeMath.mul(buy.makerProtocolFee, price), INVERSE_BASIS_POINT);
   897                      transferTokens(sell.paymentToken, buy.maker, protocolFeeRecipient, makerProtocolFee);
   898                  }
   899  
   900                  if (buy.takerProtocolFee > 0) {
   901                      takerProtocolFee = SafeMath.div(SafeMath.mul(buy.takerProtocolFee, price), INVERSE_BASIS_POINT);
   902                      transferTokens(sell.paymentToken, sell.maker, protocolFeeRecipient, takerProtocolFee);
   903                  }
   904  
   905              } else {
   906                  /* Charge maker fee to buyer. */
   907                  chargeProtocolFee(buy.maker, buy.feeRecipient, buy.makerRelayerFee);
   908        
   909                  /* Charge taker fee to seller. */
   910                  chargeProtocolFee(sell.maker, buy.feeRecipient, buy.takerRelayerFee);
   911              }
   912          }
   913  
   914          if (sell.paymentToken == address(0)) {
   915              /* Special-case Ether, order must be matched by buyer. */
   916              require(msg.value >= requiredAmount);
   917              sell.maker.transfer(receiveAmount);
   918              /* Allow overshoot for variable-price auctions, refund difference. */
   919              uint diff = SafeMath.sub(msg.value, requiredAmount);
   920              if (diff > 0) {
   921                  buy.maker.transfer(diff);
   922              }
   923          }
   924  
   925          /* This contract should never hold Ether, however, we cannot assert this, since it is impossible to prevent anyone from sending Ether e.g. with selfdestruct. */
   926  
   927          return price;
   928      }
   929  
   930      /**
   931       * @dev Return whether or not two orders can be matched with each other by basic parameters (does not check order signatures / calldata or perform static calls)
   932       * @param buy Buy-side order
   933       * @param sell Sell-side order
   934       * @return Whether or not the two orders can be matched
   935       */
   936      function ordersCanMatch(Order memory buy, Order memory sell)
   937          internal
   938          view
   939          returns (bool)
   940      {
   941          return (
   942              /* Must be opposite-side. */
   943              (buy.side == SaleKindInterface.Side.Buy && sell.side == SaleKindInterface.Side.Sell) &&     
   944              /* Must use same fee method. */
   945              (buy.feeMethod == sell.feeMethod) &&
   946              /* Must use same payment token. */
   947              (buy.paymentToken == sell.paymentToken) &&
   948              /* Must match maker/taker addresses. */
   949              (sell.taker == address(0) || sell.taker == buy.maker) &&
   950              (buy.taker == address(0) || buy.taker == sell.maker) &&
   951              /* One must be maker and the other must be taker (no bool XOR in Solidity). */
   952              ((sell.feeRecipient == address(0) && buy.feeRecipient != address(0)) || (sell.feeRecipient != address(0) && buy.feeRecipient == address(0))) &&
   953              /* Must match target. */
   954              (buy.target == sell.target) &&
   955              /* Must match howToCall. */
   956              (buy.howToCall == sell.howToCall) &&
   957              /* Buy-side order must be settleable. */
   958              SaleKindInterface.canSettleOrder(buy.listingTime, buy.expirationTime) &&
   959              /* Sell-side order must be settleable. */
   960              SaleKindInterface.canSettleOrder(sell.listingTime, sell.expirationTime)
   961          );
   962      }
   963  
   964      /**
   965       * @dev Atomically match two orders, ensuring validity of the match, and execute all associated state transitions. Protected against reentrancy by a contract-global lock.
   966       * @param buy Buy-side order
   967       * @param buySig Buy-side order signature
   968       * @param sell Sell-side order
   969       * @param sellSig Sell-side order signature
   970       */
   971      function atomicMatch(Order memory buy, Sig memory buySig, Order memory sell, Sig memory sellSig, bytes32 metadata)
   972          internal
   973          reentrancyGuard
   974      {
   975          /* CHECKS */
   976        
   977          /* Ensure buy order validity and calculate hash if necessary. */
   978          bytes32 buyHash;
   979          if (buy.maker == msg.sender) {
   980              require(validateOrderParameters(buy));
   981          } else {
   982              buyHash = requireValidOrder(buy, buySig);
   983          }
   984  
   985          /* Ensure sell order validity and calculate hash if necessary. */
   986          bytes32 sellHash;
   987          if (sell.maker == msg.sender) {
   988              require(validateOrderParameters(sell));
   989          } else {
   990              sellHash = requireValidOrder(sell, sellSig);
   991          }
   992          
   993          /* Must be matchable. */
   994          require(ordersCanMatch(buy, sell));
   995  
   996          /* Target must exist (prevent malicious selfdestructs just prior to order settlement). */
   997          uint size;
   998          address target = sell.target;
   999          assembly {
  1000              size := extcodesize(target)
  1001          }
  1002          require(size > 0);
  1003        
  1004          /* Must match calldata after replacement, if specified. */ 
  1005          if (buy.replacementPattern.length > 0) {
  1006            ArrayUtils.guardedArrayReplace(buy.calldata, sell.calldata, buy.replacementPattern);
  1007          }
  1008          if (sell.replacementPattern.length > 0) {
  1009            ArrayUtils.guardedArrayReplace(sell.calldata, buy.calldata, sell.replacementPattern);
  1010          }
  1011          require(ArrayUtils.arrayEq(buy.calldata, sell.calldata));
  1012  
  1013          /* Retrieve delegateProxy contract. */
  1014          OwnableDelegateProxy delegateProxy = registry.proxies(sell.maker);
  1015  
  1016          /* Proxy must exist. */
  1017          require(delegateProxy != address(0));
  1018  
  1019          /* Assert implementation. */
  1020          require(delegateProxy.implementation() == registry.delegateProxyImplementation());
  1021  
  1022          /* Access the passthrough AuthenticatedProxy. */
  1023          AuthenticatedProxy proxy = AuthenticatedProxy(delegateProxy);
  1024  
  1025          /* EFFECTS */
  1026  
  1027          /* Mark previously signed or approved orders as finalized. */
  1028          if (msg.sender != buy.maker) {
  1029              cancelledOrFinalized[buyHash] = true;
  1030          }
  1031          if (msg.sender != sell.maker) {
  1032              cancelledOrFinalized[sellHash] = true;
  1033          }
  1034  
  1035          /* INTERACTIONS */
  1036  
  1037          /* Execute funds transfer and pay fees. */
  1038          uint price = executeFundsTransfer(buy, sell);
  1039  
  1040          /* Execute specified call through proxy. */
  1041          require(proxy.proxy(sell.target, sell.howToCall, sell.calldata));
  1042  
  1043          /* Static calls are intentionally done after the effectful call so they can check resulting state. */
  1044  
  1045          /* Handle buy-side static call if specified. */
  1046          if (buy.staticTarget != address(0)) {
  1047              require(staticCall(buy.staticTarget, sell.calldata, buy.staticExtradata));
  1048          }
  1049  
  1050          /* Handle sell-side static call if specified. */
  1051          if (sell.staticTarget != address(0)) {
  1052              require(staticCall(sell.staticTarget, sell.calldata, sell.staticExtradata));
  1053          }
  1054  
  1055          /* Log match event. */
  1056          emit OrdersMatched(buyHash, sellHash, sell.feeRecipient != address(0) ? sell.maker : buy.maker, sell.feeRecipient != address(0) ? buy.maker : sell.maker, price, metadata);
  1057      }
  1058  
  1059  }
  1060  
  1061  contract Exchange is ExchangeCore {
  1062  
  1063      /**
  1064       * @dev Call guardedArrayReplace - library function exposed for testing.
  1065       */
  1066      function guardedArrayReplace(bytes array, bytes desired, bytes mask)
  1067          public
  1068          pure
  1069          returns (bytes)
  1070      {
  1071          ArrayUtils.guardedArrayReplace(array, desired, mask);
  1072          return array;
  1073      }
  1074  
  1075      /**
  1076       * Test copy byte array
  1077       *
  1078       * @param arrToCopy Array to copy
  1079       * @return byte array
  1080       */
  1081      function testCopy(bytes arrToCopy)
  1082          public
  1083          pure
  1084          returns (bytes)
  1085      {
  1086          bytes memory arr = new bytes(arrToCopy.length);
  1087          uint index;
  1088          assembly {
  1089              index := add(arr, 0x20)
  1090          }
  1091          ArrayUtils.unsafeWriteBytes(index, arrToCopy);
  1092          return arr;
  1093      }
  1094  
  1095      /**
  1096       * Test write address to bytes
  1097       *
  1098       * @param addr Address to write
  1099       * @return byte array
  1100       */
  1101      function testCopyAddress(address addr)
  1102          public
  1103          pure
  1104          returns (bytes)
  1105      {
  1106          bytes memory arr = new bytes(0x14);
  1107          uint index;
  1108          assembly {
  1109              index := add(arr, 0x20)
  1110          }
  1111          ArrayUtils.unsafeWriteAddress(index, addr);
  1112          return arr;
  1113      }
  1114  
  1115      /**
  1116       * @dev Call calculateFinalPrice - library function exposed for testing.
  1117       */
  1118      function calculateFinalPrice(SaleKindInterface.Side side, SaleKindInterface.SaleKind saleKind, uint basePrice, uint extra, uint listingTime, uint expirationTime)
  1119          public
  1120          view
  1121          returns (uint)
  1122      {
  1123          return SaleKindInterface.calculateFinalPrice(side, saleKind, basePrice, extra, listingTime, expirationTime);
  1124      }
  1125  
  1126      /**
  1127       * @dev Call hashOrder - Solidity ABI encoding limitation workaround, hopefully temporary.
  1128       */
  1129      function hashOrder_(
  1130          address[7] addrs,
  1131          uint[9] uints,
  1132          FeeMethod feeMethod,
  1133          SaleKindInterface.Side side,
  1134          SaleKindInterface.SaleKind saleKind,
  1135          AuthenticatedProxy.HowToCall howToCall,
  1136          bytes calldata,
  1137          bytes replacementPattern,
  1138          bytes staticExtradata)
  1139          public
  1140          pure
  1141          returns (bytes32)
  1142      {
  1143          return hashOrder(
  1144            Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8])
  1145          );
  1146      }
  1147  
  1148      /**
  1149       * @dev Call hashToSign - Solidity ABI encoding limitation workaround, hopefully temporary.
  1150       */
  1151      function hashToSign_(
  1152          address[7] addrs,
  1153          uint[9] uints,
  1154          FeeMethod feeMethod,
  1155          SaleKindInterface.Side side,
  1156          SaleKindInterface.SaleKind saleKind,
  1157          AuthenticatedProxy.HowToCall howToCall,
  1158          bytes calldata,
  1159          bytes replacementPattern,
  1160          bytes staticExtradata)
  1161          public
  1162          pure
  1163          returns (bytes32)
  1164      { 
  1165          return hashToSign(
  1166            Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8])
  1167          );
  1168      }
  1169  
  1170      /**
  1171       * @dev Call validateOrderParameters - Solidity ABI encoding limitation workaround, hopefully temporary.
  1172       */
  1173      function validateOrderParameters_ (
  1174          address[7] addrs,
  1175          uint[9] uints,
  1176          FeeMethod feeMethod,
  1177          SaleKindInterface.Side side,
  1178          SaleKindInterface.SaleKind saleKind,
  1179          AuthenticatedProxy.HowToCall howToCall,
  1180          bytes calldata,
  1181          bytes replacementPattern,
  1182          bytes staticExtradata)
  1183          view
  1184          public
  1185          returns (bool)
  1186      {
  1187          Order memory order = Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]);
  1188          return validateOrderParameters(
  1189            order
  1190          );
  1191      }
  1192  
  1193      /**
  1194       * @dev Call validateOrder - Solidity ABI encoding limitation workaround, hopefully temporary.
  1195       */
  1196      function validateOrder_ (
  1197          address[7] addrs,
  1198          uint[9] uints,
  1199          FeeMethod feeMethod,
  1200          SaleKindInterface.Side side,
  1201          SaleKindInterface.SaleKind saleKind,
  1202          AuthenticatedProxy.HowToCall howToCall,
  1203          bytes calldata,
  1204          bytes replacementPattern,
  1205          bytes staticExtradata,
  1206          uint8 v,
  1207          bytes32 r,
  1208          bytes32 s)
  1209          view
  1210          public
  1211          returns (bool)
  1212      {
  1213          Order memory order = Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]);
  1214          return validateOrder(
  1215            hashToSign(order),
  1216            order,
  1217            Sig(v, r, s)
  1218          );
  1219      }
  1220  
  1221      /**
  1222       * @dev Call approveOrder - Solidity ABI encoding limitation workaround, hopefully temporary.
  1223       */
  1224      function approveOrder_ (
  1225          address[7] addrs,
  1226          uint[9] uints,
  1227          FeeMethod feeMethod,
  1228          SaleKindInterface.Side side,
  1229          SaleKindInterface.SaleKind saleKind,
  1230          AuthenticatedProxy.HowToCall howToCall,
  1231          bytes calldata,
  1232          bytes replacementPattern,
  1233          bytes staticExtradata,
  1234          bool orderbookInclusionDesired) 
  1235          public
  1236      {
  1237          Order memory order = Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]);
  1238          return approveOrder(order, orderbookInclusionDesired);
  1239      }
  1240  
  1241      /**
  1242       * @dev Call cancelOrder - Solidity ABI encoding limitation workaround, hopefully temporary.
  1243       */
  1244      function cancelOrder_(
  1245          address[7] addrs,
  1246          uint[9] uints,
  1247          FeeMethod feeMethod,
  1248          SaleKindInterface.Side side,
  1249          SaleKindInterface.SaleKind saleKind,
  1250          AuthenticatedProxy.HowToCall howToCall,
  1251          bytes calldata,
  1252          bytes replacementPattern,
  1253          bytes staticExtradata,
  1254          uint8 v,
  1255          bytes32 r,
  1256          bytes32 s)
  1257          public
  1258      {
  1259  
  1260          return cancelOrder(
  1261            Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]),
  1262            Sig(v, r, s)
  1263          );
  1264      }
  1265  
  1266      /**
  1267       * @dev Call calculateCurrentPrice - Solidity ABI encoding limitation workaround, hopefully temporary.
  1268       */
  1269      function calculateCurrentPrice_(
  1270          address[7] addrs,
  1271          uint[9] uints,
  1272          FeeMethod feeMethod,
  1273          SaleKindInterface.Side side,
  1274          SaleKindInterface.SaleKind saleKind,
  1275          AuthenticatedProxy.HowToCall howToCall,
  1276          bytes calldata,
  1277          bytes replacementPattern,
  1278          bytes staticExtradata)
  1279          public
  1280          view
  1281          returns (uint)
  1282      {
  1283          return calculateCurrentPrice(
  1284            Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], feeMethod, side, saleKind, addrs[4], howToCall, calldata, replacementPattern, addrs[5], staticExtradata, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8])
  1285          );
  1286      }
  1287  
  1288      /**
  1289       * @dev Call ordersCanMatch - Solidity ABI encoding limitation workaround, hopefully temporary.
  1290       */
  1291      function ordersCanMatch_(
  1292          address[14] addrs,
  1293          uint[18] uints,
  1294          uint8[8] feeMethodsSidesKindsHowToCalls,
  1295          bytes calldataBuy,
  1296          bytes calldataSell,
  1297          bytes replacementPatternBuy,
  1298          bytes replacementPatternSell,
  1299          bytes staticExtradataBuy,
  1300          bytes staticExtradataSell)
  1301          public
  1302          view
  1303          returns (bool)
  1304      {
  1305          Order memory buy = Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], FeeMethod(feeMethodsSidesKindsHowToCalls[0]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[1]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[2]), addrs[4], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[3]), calldataBuy, replacementPatternBuy, addrs[5], staticExtradataBuy, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]);
  1306          Order memory sell = Order(addrs[7], addrs[8], addrs[9], uints[9], uints[10], uints[11], uints[12], addrs[10], FeeMethod(feeMethodsSidesKindsHowToCalls[4]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[5]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[6]), addrs[11], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[7]), calldataSell, replacementPatternSell, addrs[12], staticExtradataSell, ERC20(addrs[13]), uints[13], uints[14], uints[15], uints[16], uints[17]);
  1307          return ordersCanMatch(
  1308            buy,
  1309            sell
  1310          );
  1311      }
  1312  
  1313      /**
  1314       * @dev Return whether or not two orders' calldata specifications can match
  1315       * @param buyCalldata Buy-side order calldata
  1316       * @param buyReplacementPattern Buy-side order calldata replacement mask
  1317       * @param sellCalldata Sell-side order calldata
  1318       * @param sellReplacementPattern Sell-side order calldata replacement mask
  1319       * @return Whether the orders' calldata can be matched
  1320       */
  1321      function orderCalldataCanMatch(bytes buyCalldata, bytes buyReplacementPattern, bytes sellCalldata, bytes sellReplacementPattern)
  1322          public
  1323          pure
  1324          returns (bool)
  1325      {
  1326          if (buyReplacementPattern.length > 0) {
  1327            ArrayUtils.guardedArrayReplace(buyCalldata, sellCalldata, buyReplacementPattern);
  1328          }
  1329          if (sellReplacementPattern.length > 0) {
  1330            ArrayUtils.guardedArrayReplace(sellCalldata, buyCalldata, sellReplacementPattern);
  1331          }
  1332          return ArrayUtils.arrayEq(buyCalldata, sellCalldata);
  1333      }
  1334  
  1335      /**
  1336       * @dev Call calculateMatchPrice - Solidity ABI encoding limitation workaround, hopefully temporary.
  1337       */
  1338      function calculateMatchPrice_(
  1339          address[14] addrs,
  1340          uint[18] uints,
  1341          uint8[8] feeMethodsSidesKindsHowToCalls,
  1342          bytes calldataBuy,
  1343          bytes calldataSell,
  1344          bytes replacementPatternBuy,
  1345          bytes replacementPatternSell,
  1346          bytes staticExtradataBuy,
  1347          bytes staticExtradataSell)
  1348          public
  1349          view
  1350          returns (uint)
  1351      {
  1352          Order memory buy = Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], FeeMethod(feeMethodsSidesKindsHowToCalls[0]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[1]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[2]), addrs[4], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[3]), calldataBuy, replacementPatternBuy, addrs[5], staticExtradataBuy, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]);
  1353          Order memory sell = Order(addrs[7], addrs[8], addrs[9], uints[9], uints[10], uints[11], uints[12], addrs[10], FeeMethod(feeMethodsSidesKindsHowToCalls[4]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[5]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[6]), addrs[11], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[7]), calldataSell, replacementPatternSell, addrs[12], staticExtradataSell, ERC20(addrs[13]), uints[13], uints[14], uints[15], uints[16], uints[17]);
  1354          return calculateMatchPrice(
  1355            buy,
  1356            sell
  1357          );
  1358      }
  1359  
  1360      /**
  1361       * @dev Call atomicMatch - Solidity ABI encoding limitation workaround, hopefully temporary.
  1362       */
  1363      function atomicMatch_(
  1364          address[14] addrs,
  1365          uint[18] uints,
  1366          uint8[8] feeMethodsSidesKindsHowToCalls,
  1367          bytes calldataBuy,
  1368          bytes calldataSell,
  1369          bytes replacementPatternBuy,
  1370          bytes replacementPatternSell,
  1371          bytes staticExtradataBuy,
  1372          bytes staticExtradataSell,
  1373          uint8[2] vs,
  1374          bytes32[5] rssMetadata)
  1375          public
  1376          payable
  1377      {
  1378  
  1379          return atomicMatch(
  1380            Order(addrs[0], addrs[1], addrs[2], uints[0], uints[1], uints[2], uints[3], addrs[3], FeeMethod(feeMethodsSidesKindsHowToCalls[0]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[1]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[2]), addrs[4], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[3]), calldataBuy, replacementPatternBuy, addrs[5], staticExtradataBuy, ERC20(addrs[6]), uints[4], uints[5], uints[6], uints[7], uints[8]),
  1381            Sig(vs[0], rssMetadata[0], rssMetadata[1]),
  1382            Order(addrs[7], addrs[8], addrs[9], uints[9], uints[10], uints[11], uints[12], addrs[10], FeeMethod(feeMethodsSidesKindsHowToCalls[4]), SaleKindInterface.Side(feeMethodsSidesKindsHowToCalls[5]), SaleKindInterface.SaleKind(feeMethodsSidesKindsHowToCalls[6]), addrs[11], AuthenticatedProxy.HowToCall(feeMethodsSidesKindsHowToCalls[7]), calldataSell, replacementPatternSell, addrs[12], staticExtradataSell, ERC20(addrs[13]), uints[13], uints[14], uints[15], uints[16], uints[17]),
  1383            Sig(vs[1], rssMetadata[2], rssMetadata[3]),
  1384            rssMetadata[4]
  1385          );
  1386      }
  1387  
  1388  }
  1389  
  1390  contract WyvernExchange is Exchange {
  1391  
  1392      string public constant name = "Project Wyvern Exchange";
  1393  
  1394      string public constant version = "2.2";
  1395  
  1396      string public constant codename = "Lambton Worm";
  1397  
  1398      /**
  1399       * @dev Initialize a WyvernExchange instance
  1400       * @param registryAddress Address of the registry instance which this Exchange instance will use
  1401       * @param tokenAddress Address of the token used for protocol fees
  1402       */
  1403      constructor (ProxyRegistry registryAddress, TokenTransferProxy tokenTransferProxyAddress, ERC20 tokenAddress, address protocolFeeAddress) public {
  1404          registry = registryAddress;
  1405          tokenTransferProxy = tokenTransferProxyAddress;
  1406          exchangeToken = tokenAddress;
  1407          protocolFeeRecipient = protocolFeeAddress;
  1408          owner = msg.sender;
  1409      }
  1410  
  1411  }
  1412  
  1413  library SaleKindInterface {
  1414  
  1415      /**
  1416       * Side: buy or sell.
  1417       */
  1418      enum Side { Buy, Sell }
  1419  
  1420      /**
  1421       * Currently supported kinds of sale: fixed price, Dutch auction. 
  1422       * English auctions cannot be supported without stronger escrow guarantees.
  1423       * Future interesting options: Vickrey auction, nonlinear Dutch auctions.
  1424       */
  1425      enum SaleKind { FixedPrice, DutchAuction }
  1426  
  1427      /**
  1428       * @dev Check whether the parameters of a sale are valid
  1429       * @param saleKind Kind of sale
  1430       * @param expirationTime Order expiration time
  1431       * @return Whether the parameters were valid
  1432       */
  1433      function validateParameters(SaleKind saleKind, uint expirationTime)
  1434          pure
  1435          internal
  1436          returns (bool)
  1437      {
  1438          /* Auctions must have a set expiration date. */
  1439          return (saleKind == SaleKind.FixedPrice || expirationTime > 0);
  1440      }
  1441  
  1442      /**
  1443       * @dev Return whether or not an order can be settled
  1444       * @dev Precondition: parameters have passed validateParameters
  1445       * @param listingTime Order listing time
  1446       * @param expirationTime Order expiration time
  1447       */
  1448      function canSettleOrder(uint listingTime, uint expirationTime)
  1449          view
  1450          internal
  1451          returns (bool)
  1452      {
  1453          return (listingTime < now) && (expirationTime == 0 || now < expirationTime);
  1454      }
  1455  
  1456      /**
  1457       * @dev Calculate the settlement price of an order
  1458       * @dev Precondition: parameters have passed validateParameters.
  1459       * @param side Order side
  1460       * @param saleKind Method of sale
  1461       * @param basePrice Order base price
  1462       * @param extra Order extra price data
  1463       * @param listingTime Order listing time
  1464       * @param expirationTime Order expiration time
  1465       */
  1466      function calculateFinalPrice(Side side, SaleKind saleKind, uint basePrice, uint extra, uint listingTime, uint expirationTime)
  1467          view
  1468          internal
  1469          returns (uint finalPrice)
  1470      {
  1471          if (saleKind == SaleKind.FixedPrice) {
  1472              return basePrice;
  1473          } else if (saleKind == SaleKind.DutchAuction) {
  1474              uint diff = SafeMath.div(SafeMath.mul(extra, SafeMath.sub(now, listingTime)), SafeMath.sub(expirationTime, listingTime));
  1475              if (side == Side.Sell) {
  1476                  /* Sell-side - start price: basePrice. End price: basePrice - extra. */
  1477                  return SafeMath.sub(basePrice, diff);
  1478              } else {
  1479                  /* Buy-side - start price: basePrice. End price: basePrice + extra. */
  1480                  return SafeMath.add(basePrice, diff);
  1481              }
  1482          }
  1483      }
  1484  
  1485  }
  1486  
  1487  contract ProxyRegistry is Ownable {
  1488  
  1489      /* DelegateProxy implementation contract. Must be initialized. */
  1490      address public delegateProxyImplementation;
  1491  
  1492      /* Authenticated proxies by user. */
  1493      mapping(address => OwnableDelegateProxy) public proxies;
  1494  
  1495      /* Contracts pending access. */
  1496      mapping(address => uint) public pending;
  1497  
  1498      /* Contracts allowed to call those proxies. */
  1499      mapping(address => bool) public contracts;
  1500  
  1501      /* Delay period for adding an authenticated contract.
  1502         This mitigates a particular class of potential attack on the Wyvern DAO (which owns this registry) - if at any point the value of assets held by proxy contracts exceeded the value of half the WYV supply (votes in the DAO),
  1503         a malicious but rational attacker could buy half the Wyvern and grant themselves access to all the proxy contracts. A delay period renders this attack nonthreatening - given two weeks, if that happened, users would have
  1504         plenty of time to notice and transfer their assets.
  1505      */
  1506      uint public DELAY_PERIOD = 2 weeks;
  1507  
  1508      /**
  1509       * Start the process to enable access for specified contract. Subject to delay period.
  1510       *
  1511       * @dev ProxyRegistry owner only
  1512       * @param addr Address to which to grant permissions
  1513       */
  1514      function startGrantAuthentication (address addr)
  1515          public
  1516          onlyOwner
  1517      {
  1518          require(!contracts[addr] && pending[addr] == 0);
  1519          pending[addr] = now;
  1520      }
  1521  
  1522      /**
  1523       * End the process to nable access for specified contract after delay period has passed.
  1524       *
  1525       * @dev ProxyRegistry owner only
  1526       * @param addr Address to which to grant permissions
  1527       */
  1528      function endGrantAuthentication (address addr)
  1529          public
  1530          onlyOwner
  1531      {
  1532          require(!contracts[addr] && pending[addr] != 0 && ((pending[addr] + DELAY_PERIOD) < now));
  1533          pending[addr] = 0;
  1534          contracts[addr] = true;
  1535      }
  1536  
  1537      /**
  1538       * Revoke access for specified contract. Can be done instantly.
  1539       *
  1540       * @dev ProxyRegistry owner only
  1541       * @param addr Address of which to revoke permissions
  1542       */    
  1543      function revokeAuthentication (address addr)
  1544          public
  1545          onlyOwner
  1546      {
  1547          contracts[addr] = false;
  1548      }
  1549  
  1550      /**
  1551       * Register a proxy contract with this registry
  1552       *
  1553       * @dev Must be called by the user which the proxy is for, creates a new AuthenticatedProxy
  1554       * @return New AuthenticatedProxy contract
  1555       */
  1556      function registerProxy()
  1557          public
  1558          returns (OwnableDelegateProxy proxy)
  1559      {
  1560          require(proxies[msg.sender] == address(0));
  1561          proxy = new OwnableDelegateProxy(msg.sender, delegateProxyImplementation, abi.encodeWithSignature("initialize(address,address)", msg.sender, address(this)));
  1562          proxies[msg.sender] = proxy;
  1563          return proxy;
  1564      }
  1565  
  1566  }
  1567  
  1568  contract TokenTransferProxy {
  1569  
  1570      /* Authentication registry. */
  1571      ProxyRegistry public registry;
  1572  
  1573      /**
  1574       * Call ERC20 `transferFrom`
  1575       *
  1576       * @dev Authenticated contract only
  1577       * @param token ERC20 token address
  1578       * @param from From address
  1579       * @param to To address
  1580       * @param amount Transfer amount
  1581       */
  1582      function transferFrom(address token, address from, address to, uint amount)
  1583          public
  1584          returns (bool)
  1585      {
  1586          require(registry.contracts(msg.sender));
  1587          return ERC20(token).transferFrom(from, to, amount);
  1588      }
  1589  
  1590  }
  1591  
  1592  contract OwnedUpgradeabilityStorage {
  1593  
  1594    // Current implementation
  1595    address internal _implementation;
  1596  
  1597    // Owner of the contract
  1598    address private _upgradeabilityOwner;
  1599  
  1600    /**
  1601     * @dev Tells the address of the owner
  1602     * @return the address of the owner
  1603     */
  1604    function upgradeabilityOwner() public view returns (address) {
  1605      return _upgradeabilityOwner;
  1606    }
  1607  
  1608    /**
  1609     * @dev Sets the address of the owner
  1610     */
  1611    function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal {
  1612      _upgradeabilityOwner = newUpgradeabilityOwner;
  1613    }
  1614  
  1615    /**
  1616    * @dev Tells the address of the current implementation
  1617    * @return address of the current implementation
  1618    */
  1619    function implementation() public view returns (address) {
  1620      return _implementation;
  1621    }
  1622  
  1623    /**
  1624    * @dev Tells the proxy type (EIP 897)
  1625    * @return Proxy type, 2 for forwarding proxy
  1626    */
  1627    function proxyType() public pure returns (uint256 proxyTypeId) {
  1628      return 2;
  1629    }
  1630  }
  1631  
  1632  contract AuthenticatedProxy is TokenRecipient, OwnedUpgradeabilityStorage {
  1633  
  1634      /* Whether initialized. */
  1635      bool initialized = false;
  1636  
  1637      /* Address which owns this proxy. */
  1638      address public user;
  1639  
  1640      /* Associated registry with contract authentication information. */
  1641      ProxyRegistry public registry;
  1642  
  1643      /* Whether access has been revoked. */
  1644      bool public revoked;
  1645  
  1646      /* Delegate call could be used to atomically transfer multiple assets owned by the proxy contract with one order. */
  1647      enum HowToCall { Call, DelegateCall }
  1648  
  1649      /* Event fired when the proxy access is revoked or unrevoked. */
  1650      event Revoked(bool revoked);
  1651  
  1652      /**
  1653       * Initialize an AuthenticatedProxy
  1654       *
  1655       * @param addrUser Address of user on whose behalf this proxy will act
  1656       * @param addrRegistry Address of ProxyRegistry contract which will manage this proxy
  1657       */
  1658      function initialize (address addrUser, ProxyRegistry addrRegistry)
  1659          public
  1660      {
  1661          require(!initialized);
  1662          initialized = true;
  1663          user = addrUser;
  1664          registry = addrRegistry;
  1665      }
  1666  
  1667      /**
  1668       * Set the revoked flag (allows a user to revoke ProxyRegistry access)
  1669       *
  1670       * @dev Can be called by the user only
  1671       * @param revoke Whether or not to revoke access
  1672       */
  1673      function setRevoke(bool revoke)
  1674          public
  1675      {
  1676          require(msg.sender == user);
  1677          revoked = revoke;
  1678          emit Revoked(revoke);
  1679      }
  1680  
  1681      /**
  1682       * Execute a message call from the proxy contract
  1683       *
  1684       * @dev Can be called by the user, or by a contract authorized by the registry as long as the user has not revoked access
  1685       * @param dest Address to which the call will be sent
  1686       * @param howToCall Which kind of call to make
  1687       * @param calldata Calldata to send
  1688       * @return Result of the call (success or failure)
  1689       */
  1690      function proxy(address dest, HowToCall howToCall, bytes calldata)
  1691          public
  1692          returns (bool result)
  1693      {
  1694          require(msg.sender == user || (!revoked && registry.contracts(msg.sender)));
  1695          if (howToCall == HowToCall.Call) {
  1696              result = dest.call(calldata);
  1697          } else if (howToCall == HowToCall.DelegateCall) {
  1698              result = dest.delegatecall(calldata);
  1699          }
  1700          return result;
  1701      }
  1702  
  1703      /**
  1704       * Execute a message call and assert success
  1705       * 
  1706       * @dev Same functionality as `proxy`, just asserts the return value
  1707       * @param dest Address to which the call will be sent
  1708       * @param howToCall What kind of call to make
  1709       * @param calldata Calldata to send
  1710       */
  1711      function proxyAssert(address dest, HowToCall howToCall, bytes calldata)
  1712          public
  1713      {
  1714          require(proxy(dest, howToCall, calldata));
  1715      }
  1716  
  1717  }
  1718  
  1719  contract Proxy {
  1720  
  1721    /**
  1722    * @dev Tells the address of the implementation where every call will be delegated.
  1723    * @return address of the implementation to which it will be delegated
  1724    */
  1725    function implementation() public view returns (address);
  1726  
  1727    /**
  1728    * @dev Tells the type of proxy (EIP 897)
  1729    * @return Type of proxy, 2 for upgradeable proxy
  1730    */
  1731    function proxyType() public pure returns (uint256 proxyTypeId);
  1732  
  1733    /**
  1734    * @dev Fallback function allowing to perform a delegatecall to the given implementation.
  1735    * This function will return whatever the implementation call returns
  1736    */
  1737    function () payable public {
  1738      address _impl = implementation();
  1739      require(_impl != address(0));
  1740  
  1741      assembly {
  1742        let ptr := mload(0x40)
  1743        calldatacopy(ptr, 0, calldatasize)
  1744        let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
  1745        let size := returndatasize
  1746        returndatacopy(ptr, 0, size)
  1747  
  1748        switch result
  1749        case 0 { revert(ptr, size) }
  1750        default { return(ptr, size) }
  1751      }
  1752    }
  1753  }
  1754  
  1755  contract OwnedUpgradeabilityProxy is Proxy, OwnedUpgradeabilityStorage {
  1756    /**
  1757    * @dev Event to show ownership has been transferred
  1758    * @param previousOwner representing the address of the previous owner
  1759    * @param newOwner representing the address of the new owner
  1760    */
  1761    event ProxyOwnershipTransferred(address previousOwner, address newOwner);
  1762  
  1763    /**
  1764    * @dev This event will be emitted every time the implementation gets upgraded
  1765    * @param implementation representing the address of the upgraded implementation
  1766    */
  1767    event Upgraded(address indexed implementation);
  1768  
  1769    /**
  1770    * @dev Upgrades the implementation address
  1771    * @param implementation representing the address of the new implementation to be set
  1772    */
  1773    function _upgradeTo(address implementation) internal {
  1774      require(_implementation != implementation);
  1775      _implementation = implementation;
  1776      emit Upgraded(implementation);
  1777    }
  1778  
  1779    /**
  1780    * @dev Throws if called by any account other than the owner.
  1781    */
  1782    modifier onlyProxyOwner() {
  1783      require(msg.sender == proxyOwner());
  1784      _;
  1785    }
  1786  
  1787    /**
  1788     * @dev Tells the address of the proxy owner
  1789     * @return the address of the proxy owner
  1790     */
  1791    function proxyOwner() public view returns (address) {
  1792      return upgradeabilityOwner();
  1793    }
  1794  
  1795    /**
  1796     * @dev Allows the current owner to transfer control of the contract to a newOwner.
  1797     * @param newOwner The address to transfer ownership to.
  1798     */
  1799    function transferProxyOwnership(address newOwner) public onlyProxyOwner {
  1800      require(newOwner != address(0));
  1801      emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
  1802      setUpgradeabilityOwner(newOwner);
  1803    }
  1804  
  1805    /**
  1806     * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy.
  1807     * @param implementation representing the address of the new implementation to be set.
  1808     */
  1809    function upgradeTo(address implementation) public onlyProxyOwner {
  1810      _upgradeTo(implementation);
  1811    }
  1812  
  1813    /**
  1814     * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy
  1815     * and delegatecall the new implementation for initialization.
  1816     * @param implementation representing the address of the new implementation to be set.
  1817     * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
  1818     * signature of the implementation to be called with the needed payload
  1819     */
  1820    function upgradeToAndCall(address implementation, bytes data) payable public onlyProxyOwner {
  1821      upgradeTo(implementation);
  1822      require(address(this).delegatecall(data));
  1823    }
  1824  }
  1825  
  1826  contract OwnableDelegateProxy is OwnedUpgradeabilityProxy {
  1827  
  1828      constructor(address owner, address initialImplementation, bytes calldata)
  1829          public
  1830      {
  1831          setUpgradeabilityOwner(owner);
  1832          _upgradeTo(initialImplementation);
  1833          require(initialImplementation.delegatecall(calldata));
  1834      }
  1835  
  1836  }