DyDx bridge implementation using contract as maker with signature validation.
This commit is contained in:
		
							
								
								
									
										293
									
								
								contracts/asset-proxy/contracts/src/bridges/DyDxBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								contracts/asset-proxy/contracts/src/bridges/DyDxBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,293 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright 2019 ZeroEx Intl.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					  you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					  distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					  See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					  limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pragma solidity ^0.5.9;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-utils/contracts/src/Authorizable.sol";
 | 
				
			||||||
 | 
					import "../interfaces/IERC20Bridge.sol";
 | 
				
			||||||
 | 
					import "../interfaces/IDydx.sol";
 | 
				
			||||||
 | 
					import "../interfaces/IAssetData.sol";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// solhint-disable space-after-comma
 | 
				
			||||||
 | 
					contract DydxBridge is
 | 
				
			||||||
 | 
					    IERC20Bridge,
 | 
				
			||||||
 | 
					    DeploymentConstants,
 | 
				
			||||||
 | 
					    Authorizable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using LibBytes for bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Return values for `isValidSignature`
 | 
				
			||||||
 | 
					    //  bytes4(keccak256('isValidSignature(bytes,bytes)'))
 | 
				
			||||||
 | 
					    bytes4 constant VALID_SIGNATURE_RETURN_VALUE = bytes4(0x20c13b0b);
 | 
				
			||||||
 | 
					    bytes4 constant INVALID_SIGNATURE_RETURN_VALUE = bytes4(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // OrderWithHash(LibOrder.Order order, bytes32 orderHash).selector
 | 
				
			||||||
 | 
					    // == bytes4(keccak256('OrderWithHash((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes32)'))
 | 
				
			||||||
 | 
					    bytes4 constant EIP1271_ORDER_WITH_HASH_SELECTOR = bytes4(0x3efe50c8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct BridgeData {
 | 
				
			||||||
 | 
					        // Fields used by dydx
 | 
				
			||||||
 | 
					        address dydxAccountOwner;           // The owner of the dydx account.
 | 
				
			||||||
 | 
					        uint256 dydxAccountNumber;          // Account number used to identify the owner's specific account.
 | 
				
			||||||
 | 
					        address dydxAccountOperator;        // Operator of dydx account who signed the order (if transferred by an operator).
 | 
				
			||||||
 | 
					        uint256 dydxFromMarketId;           // Market ID of `from` asset.
 | 
				
			||||||
 | 
					        uint256 dydxToMarketId;             // Market ID of `to` asset.
 | 
				
			||||||
 | 
					        // Fields used by bridge
 | 
				
			||||||
 | 
					        bool shouldDepositIntodydx;         // True iff contract balance should be deposited into dydx account.
 | 
				
			||||||
 | 
					        address fromTokenAddress;           // The token given to `from` or deposited into the dydx account.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Callback for `IERC20Bridge`.
 | 
				
			||||||
 | 
					    ///      Function Prerequisite:
 | 
				
			||||||
 | 
					    ///        1. Tokens are held in this contract that correspond to `dydxFromMarketId`, and
 | 
				
			||||||
 | 
					    ///        2. Tokens are held in a dydx account that correspond to `dydxToMarketId`
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    ///      When called, two actions take place:
 | 
				
			||||||
 | 
					    ///        1. The total balance held by this contract is either (i) deposited into the dydx account OR (ii) transferred to `from`.
 | 
				
			||||||
 | 
					    ///           This is dictated by `BridgeData.shouldDepositIntoDydx`.
 | 
				
			||||||
 | 
					    ///        2. Some `amount` of tokens are withdrawn from the dydx account into the address `to`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    ///      Notes:
 | 
				
			||||||
 | 
					    ///         1. This bridge must be set as an operator of the dydx account that is being operated on.
 | 
				
			||||||
 | 
					    ///         2. This function may only be called in the context of the 0x Exchange executing an order (ERC20Bridge is authorized).
 | 
				
			||||||
 | 
					    ///         3. The order must be signed by the owner or an operator of the dydx account. This is validated in `isValidSignature`.
 | 
				
			||||||
 | 
					    /// @param from The sender of the tokens.
 | 
				
			||||||
 | 
					    /// @param to The recipient of the tokens.
 | 
				
			||||||
 | 
					    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
				
			||||||
 | 
					    /// @param encodedBridgeData An abi-encoded `BridgeData` struct.
 | 
				
			||||||
 | 
					    /// @return success The magic bytes if successful.
 | 
				
			||||||
 | 
					    function bridgeTransferFrom(
 | 
				
			||||||
 | 
					        address,
 | 
				
			||||||
 | 
					        address from,
 | 
				
			||||||
 | 
					        address to,
 | 
				
			||||||
 | 
					        uint256 amount,
 | 
				
			||||||
 | 
					        bytes calldata encodedBridgeData
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        onlyAuthorized
 | 
				
			||||||
 | 
					        returns (bytes4 success)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Decode bridge data.
 | 
				
			||||||
 | 
					        (BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Cache dydx contract.
 | 
				
			||||||
 | 
					        IDydx dydx = IDydx(_getDydxAddress());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Cache the balance held by this contract.
 | 
				
			||||||
 | 
					        IERC20Token fromToken = IERC20Token(bridgeData.fromTokenAddress);
 | 
				
			||||||
 | 
					        uint256 fromTokenAmount = fromToken.balanceOf(address(this));
 | 
				
			||||||
 | 
					        uint256 toTokenAmount = amount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Construct dydx account info.
 | 
				
			||||||
 | 
					        IDydx.AccountInfo[] memory accounts = new IDydx.AccountInfo[](1);
 | 
				
			||||||
 | 
					        accounts[0] = IDydx.AccountInfo({
 | 
				
			||||||
 | 
					            owner: bridgeData.dydxAccountOwner,
 | 
				
			||||||
 | 
					            number: bridgeData.dydxAccountNumber
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Construct arguments to `dydx.operate`.
 | 
				
			||||||
 | 
					        IDydx.ActionArgs[] memory actions;
 | 
				
			||||||
 | 
					        if (bridgeData.shouldDepositIntodydx) {
 | 
				
			||||||
 | 
					            // Generate deposit/withdraw actions
 | 
				
			||||||
 | 
					            actions = new IDydx.ActionArgs[](2);
 | 
				
			||||||
 | 
					            actions[0] = _createDepositAction(
 | 
				
			||||||
 | 
					                address(this),                  // deposit `fromToken` into dydx from this contract.
 | 
				
			||||||
 | 
					                fromTokenAmount,                // amount to deposit.
 | 
				
			||||||
 | 
					                bridgeData                      // bridge data.
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            actions[1] = _createWithdrawAction(
 | 
				
			||||||
 | 
					                to,                             // withdraw `toToken` from dydx to `to`.
 | 
				
			||||||
 | 
					                toTokenAmount,                  // amount to withdraw.
 | 
				
			||||||
 | 
					                bridgeData                      // bridge data.
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Allow dydx to deposit `fromToken` from this contract.
 | 
				
			||||||
 | 
					            LibERC20Token.approve(
 | 
				
			||||||
 | 
					                bridgeData.fromTokenAddress,
 | 
				
			||||||
 | 
					                address(dydx),
 | 
				
			||||||
 | 
					                uint256(-1)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // Generate withdraw action
 | 
				
			||||||
 | 
					            actions = new IDydx.ActionArgs[](1);
 | 
				
			||||||
 | 
					            actions[0] = _createWithdrawAction(to, toTokenAmount, bridgeData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Transfer `fromToken` to `from`
 | 
				
			||||||
 | 
					            require(
 | 
				
			||||||
 | 
					                fromToken.transfer(from, fromTokenAmount),
 | 
				
			||||||
 | 
					                "TRANSFER_OF_FROM_TOKEN_FAILED"
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Run operations. This will revert on failure.
 | 
				
			||||||
 | 
					        dydx.operate(accounts, actions);
 | 
				
			||||||
 | 
					        return BRIDGE_SUCCESS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Returns a dydx `DepositAction`.
 | 
				
			||||||
 | 
					    function _createDepositAction(
 | 
				
			||||||
 | 
					        address depositFrom,
 | 
				
			||||||
 | 
					        uint256 amount,
 | 
				
			||||||
 | 
					        BridgeData memory bridgeData
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					        pure
 | 
				
			||||||
 | 
					        returns (IDydx.ActionArgs memory)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Construct action to deposit tokens held by this contract into dydx.
 | 
				
			||||||
 | 
					        IDydx.AssetAmount memory amountToDeposit = IDydx.AssetAmount({
 | 
				
			||||||
 | 
					            sign: true,                                 // true if positive.
 | 
				
			||||||
 | 
					            denomination: IDydx.AssetDenomination.Wei,  // Wei => actual token amount held in account.
 | 
				
			||||||
 | 
					            ref: IDydx.AssetReference.Target,           // Target => an absolute amount.
 | 
				
			||||||
 | 
					            value: amount                               // amount to deposit.
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IDydx.ActionArgs memory depositAction = IDydx.ActionArgs({
 | 
				
			||||||
 | 
					            actionType: IDydx.ActionType.Deposit,           // deposit tokens.
 | 
				
			||||||
 | 
					            amount: amountToDeposit,                        // amount to deposit.
 | 
				
			||||||
 | 
					            accountId: 0,                                   // index in the `accounts` when calling `operate` below.
 | 
				
			||||||
 | 
					            primaryMarketId: bridgeData.dydxFromMarketId,   // indicates which token to deposit.
 | 
				
			||||||
 | 
					            otherAddress: depositFrom,                      // deposit tokens from `this` address.
 | 
				
			||||||
 | 
					            // unused parameters
 | 
				
			||||||
 | 
					            secondaryMarketId: 0,
 | 
				
			||||||
 | 
					            otherAccountId: 0,
 | 
				
			||||||
 | 
					            data: hex''
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return depositAction;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Returns a dydx `WithdrawAction`.
 | 
				
			||||||
 | 
					    function _createWithdrawAction(
 | 
				
			||||||
 | 
					        address withdrawTo,
 | 
				
			||||||
 | 
					        uint256 amount,
 | 
				
			||||||
 | 
					        BridgeData memory bridgeData
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					        pure
 | 
				
			||||||
 | 
					        returns (IDydx.ActionArgs memory)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Construct action to withdraw tokens from dydx into `to`.
 | 
				
			||||||
 | 
					        IDydx.AssetAmount memory amountToWithdraw = IDydx.AssetAmount({
 | 
				
			||||||
 | 
					            sign: true,                                 // true if positive.
 | 
				
			||||||
 | 
					            denomination: IDydx.AssetDenomination.Wei,  // Wei => actual token amount held in account.
 | 
				
			||||||
 | 
					            ref: IDydx.AssetReference.Target,           // Target => an absolute amount.
 | 
				
			||||||
 | 
					            value: amount                               // amount to withdraw.
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IDydx.ActionArgs memory withdrawAction = IDydx.ActionArgs({
 | 
				
			||||||
 | 
					            actionType: IDydx.ActionType.Withdraw,          // withdraw tokens.
 | 
				
			||||||
 | 
					            amount: amountToWithdraw,                       // amount to withdraw.
 | 
				
			||||||
 | 
					            accountId: 0,                                   // index in the `accounts` when calling `operate` below.
 | 
				
			||||||
 | 
					            primaryMarketId: bridgeData.dydxToMarketId,     // indicates which token to withdraw.
 | 
				
			||||||
 | 
					            otherAddress: withdrawTo,                       // withdraw tokens to `to` address.
 | 
				
			||||||
 | 
					            // unused parameters
 | 
				
			||||||
 | 
					            secondaryMarketId: 0,
 | 
				
			||||||
 | 
					            otherAccountId: 0,
 | 
				
			||||||
 | 
					            data: hex''
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return withdrawAction;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Given a 0x order where the `makerAssetData` corresponds to a dydx transfer via this bridge,
 | 
				
			||||||
 | 
					    ///      `isValidSignature` verifies that the corresponding dydx account owner (or operator)
 | 
				
			||||||
 | 
					    ///      has authorized the trade by signing the input order.
 | 
				
			||||||
 | 
					    /// @param data Signed tuple (ZeroExOrder, hash(ZeroExOrder))
 | 
				
			||||||
 | 
					    /// @param signature Proof that `data` has been signed.
 | 
				
			||||||
 | 
					    /// @return bytes4(0x20c13b0b) if the signature check succeeds.
 | 
				
			||||||
 | 
					    function isValidSignature(
 | 
				
			||||||
 | 
					        bytes calldata data,
 | 
				
			||||||
 | 
					        bytes calldata signature
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (bytes4)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Assert that `data` is an encoded `OrderWithHash`.
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            data.readBytes4(0) == EIP1271_ORDER_WITH_HASH_SELECTOR,
 | 
				
			||||||
 | 
					            "INVALID_DATA_EXPECTED_EIP1271_ORDER_WITH_HASH"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Assert that signature is correct length.
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            signature.length == 65,
 | 
				
			||||||
 | 
					            "INVALID_SIGNATURE_LENGTH"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Decode the order and hash, plus extract the dydxBridge asset data.
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            LibOrder.Order memory order,
 | 
				
			||||||
 | 
					            bytes32 orderHash
 | 
				
			||||||
 | 
					        ) = abi.decode(
 | 
				
			||||||
 | 
					                data.slice(4, data.length),
 | 
				
			||||||
 | 
					                (LibOrder.Order, bytes32)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Decode and validate the asset proxy id.
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            order.makerAssetData.readBytes4(0) == IAssetData(address(0)).ERC20Bridge.selector,
 | 
				
			||||||
 | 
					            "MAKER_ASSET_DATA_NOT_ENCODED_FOR_ERC20_BRIDGE"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Decode the ERC20 Bridge asset data.
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					             /* address tokenAddress */,
 | 
				
			||||||
 | 
					            address bridgeAddress,
 | 
				
			||||||
 | 
					            bytes memory encodedBridgeData
 | 
				
			||||||
 | 
					        ) = abi.decode(
 | 
				
			||||||
 | 
					            order.makerAssetData.slice(4, order.makerAssetData.length),
 | 
				
			||||||
 | 
					            (address, address, bytes)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            bridgeAddress == address(this),
 | 
				
			||||||
 | 
					            "INVALID_BRIDGE_ADDRESS"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Decode and validate the `bridgeData` and extract the expected signer address.
 | 
				
			||||||
 | 
					        (BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
 | 
				
			||||||
 | 
					        address signerAddress = bridgeData.dydxAccountOperator != address(0)
 | 
				
			||||||
 | 
					            ? bridgeData.dydxAccountOperator
 | 
				
			||||||
 | 
					            : bridgeData.dydxAccountOwner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Validate signature.
 | 
				
			||||||
 | 
					        address recovered = ecrecover(
 | 
				
			||||||
 | 
					            keccak256(abi.encodePacked(
 | 
				
			||||||
 | 
					                    "\x19Ethereum Signed Message:\n32",
 | 
				
			||||||
 | 
					                    orderHash
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
 | 
					            uint8(signature[0]),        // v
 | 
				
			||||||
 | 
					            signature.readBytes32(1),   // r
 | 
				
			||||||
 | 
					            signature.readBytes32(33)   // s
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Return `VALID_SIGNATURE_RETURN_VALUE` iff signature is valid.
 | 
				
			||||||
 | 
					       return (signerAddress == recovered)
 | 
				
			||||||
 | 
					            ? VALID_SIGNATURE_RETURN_VALUE
 | 
				
			||||||
 | 
					            : INVALID_SIGNATURE_RETURN_VALUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										99
									
								
								contracts/asset-proxy/contracts/src/interfaces/IDyDx.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								contracts/asset-proxy/contracts/src/interfaces/IDyDx.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright 2019 ZeroEx Intl.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					  you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					  distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					  See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					  limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pragma solidity ^0.5.9;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IDydx {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Represents the unique key that specifies an account
 | 
				
			||||||
 | 
					    struct AccountInfo {
 | 
				
			||||||
 | 
					        address owner;  // The address that owns the account
 | 
				
			||||||
 | 
					        uint256 number; // A nonce that allows a single address to control many accounts
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum ActionType {
 | 
				
			||||||
 | 
					        Deposit,   // supply tokens
 | 
				
			||||||
 | 
					        Withdraw,  // borrow tokens
 | 
				
			||||||
 | 
					        Transfer,  // transfer balance between accounts
 | 
				
			||||||
 | 
					        Buy,       // buy an amount of some token (externally)
 | 
				
			||||||
 | 
					        Sell,      // sell an amount of some token (externally)
 | 
				
			||||||
 | 
					        Trade,     // trade tokens against another account
 | 
				
			||||||
 | 
					        Liquidate, // liquidate an undercollateralized or expiring account
 | 
				
			||||||
 | 
					        Vaporize,  // use excess tokens to zero-out a completely negative account
 | 
				
			||||||
 | 
					        Call       // send arbitrary data to an address
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Arguments that are passed to Solo in an ordered list as part of a single operation.
 | 
				
			||||||
 | 
					    /// Each ActionArgs has an actionType which specifies which action struct that this data will be
 | 
				
			||||||
 | 
					    /// parsed into before being processed.
 | 
				
			||||||
 | 
					    struct ActionArgs {
 | 
				
			||||||
 | 
					        ActionType actionType;
 | 
				
			||||||
 | 
					        uint256 accountId;
 | 
				
			||||||
 | 
					        AssetAmount amount;
 | 
				
			||||||
 | 
					        uint256 primaryMarketId;
 | 
				
			||||||
 | 
					        uint256 secondaryMarketId;
 | 
				
			||||||
 | 
					        address otherAddress;
 | 
				
			||||||
 | 
					        uint256 otherAccountId;
 | 
				
			||||||
 | 
					        bytes data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum AssetDenomination {
 | 
				
			||||||
 | 
					        Wei, // the amount is denominated in wei
 | 
				
			||||||
 | 
					        Par  // the amount is denominated in par
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum AssetReference {
 | 
				
			||||||
 | 
					        Delta, // the amount is given as a delta from the current value
 | 
				
			||||||
 | 
					        Target // the amount is given as an exact number to end up at
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AssetAmount {
 | 
				
			||||||
 | 
					        bool sign; // true if positive
 | 
				
			||||||
 | 
					        AssetDenomination denomination;
 | 
				
			||||||
 | 
					        AssetReference ref;
 | 
				
			||||||
 | 
					        uint256 value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev The main entry-point to Solo that allows users and contracts to manage accounts.
 | 
				
			||||||
 | 
					    ///      Take one or more actions on one or more accounts. The msg.sender must be the owner or
 | 
				
			||||||
 | 
					    ///      operator of all accounts except for those being liquidated, vaporized, or traded with.
 | 
				
			||||||
 | 
					    ///      One call to operate() is considered a singular "operation". Account collateralization is
 | 
				
			||||||
 | 
					    ///      ensured only after the completion of the entire operation.
 | 
				
			||||||
 | 
					    /// @param  accounts  A list of all accounts that will be used in this operation. Cannot contain
 | 
				
			||||||
 | 
					    ///                   duplicates. In each action, the relevant account will be referred-to by its
 | 
				
			||||||
 | 
					    ///                   index in the list.
 | 
				
			||||||
 | 
					    /// @param  actions   An ordered list of all actions that will be taken in this operation. The
 | 
				
			||||||
 | 
					    ///                   actions will be processed in order.
 | 
				
			||||||
 | 
					    function operate(
 | 
				
			||||||
 | 
					        AccountInfo[] calldata accounts,
 | 
				
			||||||
 | 
					        ActionArgs[] calldata actions
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Get the ERC20 token address for a market.
 | 
				
			||||||
 | 
					    /// @param  marketId  The market to query
 | 
				
			||||||
 | 
					    /// @return           The token address
 | 
				
			||||||
 | 
					    function getMarketTokenAddress(
 | 
				
			||||||
 | 
					        uint256 marketId
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (address);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								contracts/asset-proxy/contracts/test/TestDydxBridge.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								contracts/asset-proxy/contracts/test/TestDydxBridge.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright 2019 ZeroEx Intl.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					  you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					  You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					  distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					  See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					  limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pragma solidity ^0.5.9;
 | 
				
			||||||
 | 
					pragma experimental ABIEncoderV2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
 | 
				
			||||||
 | 
					import "../src/bridges/DydxBridge.sol";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contract TestDydxBridge {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     function OrderWithHash(
 | 
				
			||||||
 | 
					        LibOrder.Order calldata order,
 | 
				
			||||||
 | 
					        bytes32 orderHash
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					        external
 | 
				
			||||||
 | 
					        pure
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -38,8 +38,13 @@
 | 
				
			|||||||
        "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
 | 
					        "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "config": {
 | 
					    "config": {
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,ChaiBridge,TestStaticCallTarget",
 | 
					        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,ChaiBridge,TestStaticCallTarget",
 | 
				
			||||||
        "abis": "./test/generated-artifacts/@(ChaiBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
					        "abis": "./test/generated-artifacts/@(ChaiBridge|DyDxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDyDx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,TestStaticCallTarget",
 | 
				
			||||||
 | 
					        "abis": "./test/generated-artifacts/@(DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IDydx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
					        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "repository": {
 | 
					    "repository": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,12 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
import { ContractArtifact } from 'ethereum-types';
 | 
					import { ContractArtifact } from 'ethereum-types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
 | 
					import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
 | 
				
			||||||
 | 
					import * as DyDxBridge from '../test/generated-artifacts/DyDxBridge.json';
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
 | 
					import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
 | 
				
			||||||
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
 | 
					import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
 | 
				
			||||||
import * as ERC20Proxy from '../test/generated-artifacts/ERC20Proxy.json';
 | 
					import * as ERC20Proxy from '../test/generated-artifacts/ERC20Proxy.json';
 | 
				
			||||||
@@ -15,7 +20,12 @@ import * as IAssetData from '../test/generated-artifacts/IAssetData.json';
 | 
				
			|||||||
import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
 | 
					import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
 | 
				
			||||||
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
 | 
					import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
 | 
				
			||||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
 | 
					import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
import * as IChai from '../test/generated-artifacts/IChai.json';
 | 
					import * as IChai from '../test/generated-artifacts/IChai.json';
 | 
				
			||||||
 | 
					import * as IDyDx from '../test/generated-artifacts/IDyDx.json';
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					import * as IDydx from '../test/generated-artifacts/IDydx.json';
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
					import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
				
			||||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
					import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
				
			||||||
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
 | 
					import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
 | 
				
			||||||
@@ -44,7 +54,12 @@ export const artifacts = {
 | 
				
			|||||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
					    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
				
			||||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
					    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
				
			||||||
    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
					    StaticCallProxy: StaticCallProxy as ContractArtifact,
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
    ChaiBridge: ChaiBridge as ContractArtifact,
 | 
					    ChaiBridge: ChaiBridge as ContractArtifact,
 | 
				
			||||||
 | 
					    DyDxBridge: DyDxBridge as ContractArtifact,
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					    DydxBridge: DydxBridge as ContractArtifact,
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
					    Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
 | 
				
			||||||
    KyberBridge: KyberBridge as ContractArtifact,
 | 
					    KyberBridge: KyberBridge as ContractArtifact,
 | 
				
			||||||
    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
					    UniswapBridge: UniswapBridge as ContractArtifact,
 | 
				
			||||||
@@ -52,7 +67,12 @@ export const artifacts = {
 | 
				
			|||||||
    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
					    IAssetProxy: IAssetProxy as ContractArtifact,
 | 
				
			||||||
    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
					    IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
 | 
				
			||||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
					    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
    IChai: IChai as ContractArtifact,
 | 
					    IChai: IChai as ContractArtifact,
 | 
				
			||||||
 | 
					    IDyDx: IDyDx as ContractArtifact,
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					    IDydx: IDydx as ContractArtifact,
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
					    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
				
			||||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
					    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
				
			||||||
    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
					    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										120
									
								
								contracts/asset-proxy/test/dydx_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								contracts/asset-proxy/test/dydx_bridge.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					import {
 | 
				
			||||||
 | 
					    blockchainTests,
 | 
				
			||||||
 | 
					    constants,
 | 
				
			||||||
 | 
					    expect,
 | 
				
			||||||
 | 
					    getRandomInteger,
 | 
				
			||||||
 | 
					    hexLeftPad,
 | 
				
			||||||
 | 
					    hexRandom,
 | 
				
			||||||
 | 
					    OrderFactory,
 | 
				
			||||||
 | 
					    orderHashUtils,
 | 
				
			||||||
 | 
					    randomAddress,
 | 
				
			||||||
 | 
					    verifyEventsFromLogs,
 | 
				
			||||||
 | 
					} from '@0x/contracts-test-utils';
 | 
				
			||||||
 | 
					import { AssetProxyId } from '@0x/types';
 | 
				
			||||||
 | 
					import { AbiEncoder, BigNumber } from '@0x/utils';
 | 
				
			||||||
 | 
					import { DecodedLogs } from 'ethereum-types';
 | 
				
			||||||
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
 | 
					import * as ethUtil from 'ethereumjs-util';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { artifacts } from './artifacts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { DydxBridgeContract, IAssetDataContract, TestDydxBridgeContract } from './wrappers';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					blockchainTests.resets.only('Dydx unit tests', env => {
 | 
				
			||||||
 | 
					    const dydxAccountNumber = new BigNumber(1);
 | 
				
			||||||
 | 
					    const dydxFromMarketId = new BigNumber(2);
 | 
				
			||||||
 | 
					    const dydxToMarketId = new BigNumber(3);
 | 
				
			||||||
 | 
					    let testContract: DydxBridgeContract;
 | 
				
			||||||
 | 
					    let owner: string;
 | 
				
			||||||
 | 
					    let dydxAccountOwner: string;
 | 
				
			||||||
 | 
					    let bridgeDataEncoder: AbiEncoder.DataType;
 | 
				
			||||||
 | 
					    let eip1271Encoder: TestDydxBridgeContract;
 | 
				
			||||||
 | 
					    let assetDataEncoder: IAssetDataContract;
 | 
				
			||||||
 | 
					    let orderFactory: OrderFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    before(async () => {
 | 
				
			||||||
 | 
					        // Deploy dydx bridge
 | 
				
			||||||
 | 
					        testContract = await DydxBridgeContract.deployFrom0xArtifactAsync(
 | 
				
			||||||
 | 
					            artifacts.DydxBridge,
 | 
				
			||||||
 | 
					            env.provider,
 | 
				
			||||||
 | 
					            env.txDefaults,
 | 
				
			||||||
 | 
					            artifacts,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get accounts
 | 
				
			||||||
 | 
					        const accounts = await env.web3Wrapper.getAvailableAddressesAsync();
 | 
				
			||||||
 | 
					        [owner, dydxAccountOwner] = accounts;
 | 
				
			||||||
 | 
					        const dydxAccountOwnerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(dydxAccountOwner)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create order factory for dydx bridge
 | 
				
			||||||
 | 
					        const chainId = await env.getChainIdAsync();
 | 
				
			||||||
 | 
					        const defaultOrderParams = {
 | 
				
			||||||
 | 
					            ...constants.STATIC_ORDER_PARAMS,
 | 
				
			||||||
 | 
					            makerAddress: testContract.address,
 | 
				
			||||||
 | 
					            feeRecipientAddress: randomAddress(),
 | 
				
			||||||
 | 
					            makerAssetData: constants.NULL_BYTES,
 | 
				
			||||||
 | 
					            takerAssetData: constants.NULL_BYTES,
 | 
				
			||||||
 | 
					            makerFeeAssetData: constants.NULL_BYTES,
 | 
				
			||||||
 | 
					            takerFeeAssetData: constants.NULL_BYTES,
 | 
				
			||||||
 | 
					            makerFee: constants.ZERO_AMOUNT,
 | 
				
			||||||
 | 
					            takerFee: constants.ZERO_AMOUNT,
 | 
				
			||||||
 | 
					            exchangeAddress: constants.NULL_ADDRESS,
 | 
				
			||||||
 | 
					            chainId,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        orderFactory = new OrderFactory(dydxAccountOwnerPrivateKey, defaultOrderParams);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create encoder for Bridge Data
 | 
				
			||||||
 | 
					        bridgeDataEncoder = AbiEncoder.create([
 | 
				
			||||||
 | 
					            {name: 'dydxAccountOwner', type: 'address'},
 | 
				
			||||||
 | 
					            {name: 'dydxAccountNumber', type: 'uint256'},
 | 
				
			||||||
 | 
					            {name: 'dydxAccountOperator', type: 'address'},
 | 
				
			||||||
 | 
					            {name: 'dydxFromMarketId', type: 'uint256'},
 | 
				
			||||||
 | 
					            {name: 'dydxToMarketId', type: 'uint256'},
 | 
				
			||||||
 | 
					            {name: 'shouldDepositIntoDydx', type: 'bool'},
 | 
				
			||||||
 | 
					            {name: 'fromTokenAddress', type: 'address'},
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create encoders
 | 
				
			||||||
 | 
					        assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, env.provider);
 | 
				
			||||||
 | 
					        eip1271Encoder = new TestDydxBridgeContract(constants.NULL_ADDRESS, env.provider);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    describe('isValidSignature()', () => {
 | 
				
			||||||
 | 
					        const SUCCESS_BYTES = '0x20c13b0b';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it('returns success bytes if signature is valid', async () => {
 | 
				
			||||||
 | 
					            // Construct valid bridge data for dydx account owner
 | 
				
			||||||
 | 
					            const bridgeData = {
 | 
				
			||||||
 | 
					                dydxAccountOwner,
 | 
				
			||||||
 | 
					                dydxAccountNumber,
 | 
				
			||||||
 | 
					                dydxAccountOperator: constants.NULL_ADDRESS,
 | 
				
			||||||
 | 
					                dydxFromMarketId,
 | 
				
			||||||
 | 
					                dydxToMarketId,
 | 
				
			||||||
 | 
					                shouldDepositIntoDydx: false,
 | 
				
			||||||
 | 
					                fromTokenAddress: constants.NULL_ADDRESS,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            const encodedBridgeData = bridgeDataEncoder.encode(bridgeData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Construct valid order from dydx account owner
 | 
				
			||||||
 | 
					            const makerAssetData = assetDataEncoder
 | 
				
			||||||
 | 
					                .ERC20Bridge(
 | 
				
			||||||
 | 
					                    constants.NULL_ADDRESS,
 | 
				
			||||||
 | 
					                    testContract.address,
 | 
				
			||||||
 | 
					                    encodedBridgeData
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            .getABIEncodedTransactionData()
 | 
				
			||||||
 | 
					            const signedOrder = await orderFactory.newSignedOrderAsync({
 | 
				
			||||||
 | 
					                makerAssetData,
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            const signedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Encode `isValidSignature` parameters
 | 
				
			||||||
 | 
					            const eip1271Data = eip1271Encoder.OrderWithHash(signedOrder, signedOrderHash).getABIEncodedTransactionData();
 | 
				
			||||||
 | 
					            const eip1271Signature = ethUtil.bufferToHex(ethUtil.toBuffer(signedOrder.signature).slice(0, 65)); // pop signature type from end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Validate signature
 | 
				
			||||||
 | 
					            const result = await testContract.isValidSignature(eip1271Data, eip1271Signature).callAsync();
 | 
				
			||||||
 | 
					            expect(result).to.eq(SUCCESS_BYTES);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -3,7 +3,12 @@
 | 
				
			|||||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
					 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
				
			||||||
 * -----------------------------------------------------------------------------
 | 
					 * -----------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
export * from '../test/generated-wrappers/chai_bridge';
 | 
					export * from '../test/generated-wrappers/chai_bridge';
 | 
				
			||||||
 | 
					export * from '../test/generated-wrappers/dy_dx_bridge';
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					export * from '../test/generated-wrappers/dydx_bridge';
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
export * from '../test/generated-wrappers/erc1155_proxy';
 | 
					export * from '../test/generated-wrappers/erc1155_proxy';
 | 
				
			||||||
export * from '../test/generated-wrappers/erc20_bridge_proxy';
 | 
					export * from '../test/generated-wrappers/erc20_bridge_proxy';
 | 
				
			||||||
export * from '../test/generated-wrappers/erc20_proxy';
 | 
					export * from '../test/generated-wrappers/erc20_proxy';
 | 
				
			||||||
@@ -13,7 +18,12 @@ export * from '../test/generated-wrappers/i_asset_data';
 | 
				
			|||||||
export * from '../test/generated-wrappers/i_asset_proxy';
 | 
					export * from '../test/generated-wrappers/i_asset_proxy';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
 | 
					export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_authorizable';
 | 
					export * from '../test/generated-wrappers/i_authorizable';
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
export * from '../test/generated-wrappers/i_chai';
 | 
					export * from '../test/generated-wrappers/i_chai';
 | 
				
			||||||
 | 
					export * from '../test/generated-wrappers/i_dy_dx';
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					export * from '../test/generated-wrappers/i_dydx';
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
					export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_eth2_dai';
 | 
					export * from '../test/generated-wrappers/i_eth2_dai';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_kyber_network_proxy';
 | 
					export * from '../test/generated-wrappers/i_kyber_network_proxy';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,12 @@
 | 
				
			|||||||
        "generated-artifacts/StaticCallProxy.json",
 | 
					        "generated-artifacts/StaticCallProxy.json",
 | 
				
			||||||
        "generated-artifacts/TestStaticCallTarget.json",
 | 
					        "generated-artifacts/TestStaticCallTarget.json",
 | 
				
			||||||
        "generated-artifacts/UniswapBridge.json",
 | 
					        "generated-artifacts/UniswapBridge.json",
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
        "test/generated-artifacts/ChaiBridge.json",
 | 
					        "test/generated-artifacts/ChaiBridge.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/DyDxBridge.json",
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					        "test/generated-artifacts/DydxBridge.json",
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
        "test/generated-artifacts/ERC1155Proxy.json",
 | 
					        "test/generated-artifacts/ERC1155Proxy.json",
 | 
				
			||||||
        "test/generated-artifacts/ERC20BridgeProxy.json",
 | 
					        "test/generated-artifacts/ERC20BridgeProxy.json",
 | 
				
			||||||
        "test/generated-artifacts/ERC20Proxy.json",
 | 
					        "test/generated-artifacts/ERC20Proxy.json",
 | 
				
			||||||
@@ -26,7 +31,12 @@
 | 
				
			|||||||
        "test/generated-artifacts/IAssetProxy.json",
 | 
					        "test/generated-artifacts/IAssetProxy.json",
 | 
				
			||||||
        "test/generated-artifacts/IAssetProxyDispatcher.json",
 | 
					        "test/generated-artifacts/IAssetProxyDispatcher.json",
 | 
				
			||||||
        "test/generated-artifacts/IAuthorizable.json",
 | 
					        "test/generated-artifacts/IAuthorizable.json",
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
        "test/generated-artifacts/IChai.json",
 | 
					        "test/generated-artifacts/IChai.json",
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IDyDx.json",
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IDydx.json",
 | 
				
			||||||
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
        "test/generated-artifacts/IERC20Bridge.json",
 | 
					        "test/generated-artifacts/IERC20Bridge.json",
 | 
				
			||||||
        "test/generated-artifacts/IEth2Dai.json",
 | 
					        "test/generated-artifacts/IEth2Dai.json",
 | 
				
			||||||
        "test/generated-artifacts/IKyberNetworkProxy.json",
 | 
					        "test/generated-artifacts/IKyberNetworkProxy.json",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,8 @@ contract DeploymentConstants {
 | 
				
			|||||||
    address constant private DEV_UTILS_ADDRESS = 0xcCc2431a7335F21d9268bA62F0B32B0f2EFC463f;
 | 
					    address constant private DEV_UTILS_ADDRESS = 0xcCc2431a7335F21d9268bA62F0B32B0f2EFC463f;
 | 
				
			||||||
    /// @dev Kyber ETH pseudo-address.
 | 
					    /// @dev Kyber ETH pseudo-address.
 | 
				
			||||||
    address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
					    address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
				
			||||||
 | 
					    /// @dev Mainnet address of the DyDx contract.
 | 
				
			||||||
 | 
					    address constant private DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// @dev Overridable way to get the `KyberNetworkProxy` address.
 | 
					    /// @dev Overridable way to get the `KyberNetworkProxy` address.
 | 
				
			||||||
    /// @return kyberAddress The `IKyberNetworkProxy` address.
 | 
					    /// @return kyberAddress The `IKyberNetworkProxy` address.
 | 
				
			||||||
@@ -122,4 +124,14 @@ contract DeploymentConstants {
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return DEV_UTILS_ADDRESS;
 | 
					        return DEV_UTILS_ADDRESS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// @dev Overridable way to get the DyDx contract.
 | 
				
			||||||
 | 
					    /// @return exchange The DyDx exchange contract.
 | 
				
			||||||
 | 
					    function _getDyDxAddress()
 | 
				
			||||||
 | 
					        internal
 | 
				
			||||||
 | 
					        view
 | 
				
			||||||
 | 
					        returns (address dydxAddress)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return DYDX_ADDRESS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user