DyDx bridge implementation using contract as maker with signature validation.

This commit is contained in:
Greg Hysen
2019-11-20 16:42:13 -08:00
parent 70870ffcd2
commit 56cbb69401
9 changed files with 605 additions and 1 deletions

View File

@@ -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,

View 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);
});
});
});

View File

@@ -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';