DyDx bridge implementation using contract as maker with signature validation.
This commit is contained in:
@@ -5,7 +5,12 @@
|
||||
*/
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
<<<<<<< HEAD
|
||||
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 ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.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 IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
|
||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
|
||||
<<<<<<< HEAD
|
||||
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 IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
|
||||
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
|
||||
@@ -44,7 +54,12 @@ export const artifacts = {
|
||||
ERC721Proxy: ERC721Proxy as ContractArtifact,
|
||||
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
|
||||
StaticCallProxy: StaticCallProxy as ContractArtifact,
|
||||
<<<<<<< HEAD
|
||||
ChaiBridge: ChaiBridge as ContractArtifact,
|
||||
DyDxBridge: DyDxBridge as ContractArtifact,
|
||||
=======
|
||||
DydxBridge: DydxBridge as ContractArtifact,
|
||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
|
||||
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
|
||||
KyberBridge: KyberBridge as ContractArtifact,
|
||||
UniswapBridge: UniswapBridge as ContractArtifact,
|
||||
@@ -52,7 +67,12 @@ export const artifacts = {
|
||||
IAssetProxy: IAssetProxy as ContractArtifact,
|
||||
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
|
||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||
<<<<<<< HEAD
|
||||
IChai: IChai as ContractArtifact,
|
||||
IDyDx: IDyDx as ContractArtifact,
|
||||
=======
|
||||
IDydx: IDydx as ContractArtifact,
|
||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
|
||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||
IEth2Dai: IEth2Dai 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.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
<<<<<<< HEAD
|
||||
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/erc20_bridge_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_dispatcher';
|
||||
export * from '../test/generated-wrappers/i_authorizable';
|
||||
<<<<<<< HEAD
|
||||
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_eth2_dai';
|
||||
export * from '../test/generated-wrappers/i_kyber_network_proxy';
|
||||
|
||||
Reference in New Issue
Block a user