Skip to content
This repository was archived by the owner on Aug 12, 2023. It is now read-only.

Commit a7c6b5a

Browse files
authored
Add support for bridged ERC20 assets (#374)
* Add support for bridged ERC20 assets * Tweak bridged asset shape * Index asset bridge address * Store asset bridge address and data * Store bridge data for fee assets * Improve tests * Tweak test name
1 parent 20b0288 commit a7c6b5a

9 files changed

Lines changed: 858 additions & 179 deletions

File tree

package-lock.json

Lines changed: 721 additions & 162 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"prettier": "1.19.1"
3737
},
3838
"dependencies": {
39-
"@0x/order-utils": "8.1.1",
39+
"@0x/order-utils": "10.0.1",
4040
"@0x/subproviders": "4.1.0",
4141
"@0x/utils": "4.3.3",
4242
"@0x/web3-wrapper": "6.0.7",

src/index/fills/__snapshots__/create-document.test.js.snap

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`assets should include bridgeAddress property when asset is bridged 1`] = `
4+
Array [
5+
Object {
6+
"bridgeAddress": "0x58b7b96e170e46c07d02fac903cd1b3356b7549f",
7+
"tokenAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
8+
},
9+
Object {
10+
"bridgeAddress": "0x58b7b96e170e46c07d02fac903cd1b3356b7549f",
11+
"tokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
12+
},
13+
]
14+
`;
15+
316
exports[`should create Elasticsearch document for fill 1`] = `
417
Object {
518
"assets": Array [
619
Object {
20+
"bridgeAddress": undefined,
721
"tokenAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
822
},
923
Object {
24+
"bridgeAddress": undefined,
1025
"tokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
1126
},
1227
],

src/index/fills/create-document.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ const createDocument = fill => {
44
const value = _.get(fill, 'conversions.USD.amount');
55

66
return {
7-
assets: fill.assets.map(asset => ({ tokenAddress: asset.tokenAddress })),
7+
assets: fill.assets.map(asset => ({
8+
bridgeAddress: asset.bridgeAddress,
9+
tokenAddress: asset.tokenAddress,
10+
})),
811
date: fill.date,
912
fees: fill.fees.map(fee => ({ tokenAddress: fee.tokenAddress })),
1013
feeRecipient: fill.feeRecipient,

src/index/fills/create-document.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,16 @@ it('should exclude value property when fill is unmeasured', () => {
1818

1919
expect(doc.value).toBeUndefined();
2020
});
21+
22+
it('assets should include bridgeAddress property when asset is bridged', () => {
23+
const fill = {
24+
...V2_FILL,
25+
assets: V2_FILL.assets.map(asset => ({
26+
...asset,
27+
bridgeAddress: '0x58b7b96e170e46c07d02fac903cd1b3356b7549f',
28+
})),
29+
};
30+
const doc = createDocument(fill);
31+
32+
expect(doc.assets).toMatchSnapshot();
33+
});

src/jobs/create-fills/extract-fees-from-event-args.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,36 @@ describe('extractFeesFromEventArgs', () => {
4242
]);
4343
});
4444

45+
it('should extract bridged fees for v3.0 fill event', () => {
46+
const args = {
47+
...V3_EVENT.data.args,
48+
makerFeeAssetData:
49+
'0xdc1600f3000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000058b7b96e170e46c07d02fac903cd1b3356b7549f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000a5a2f',
50+
};
51+
const protocolVersion = 3;
52+
const fees = extractFeesFromEventArgs(args, protocolVersion);
53+
54+
expect(fees).toEqual([
55+
{
56+
amount: { token: 500000000000 },
57+
bridgeAddress: '0x58b7b96e170e46c07d02fac903cd1b3356b7549f',
58+
bridgeData:
59+
'0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000a5a2f',
60+
tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
61+
tokenType: 0,
62+
traderType: 0,
63+
},
64+
{
65+
amount: {
66+
token: 300000000,
67+
},
68+
tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
69+
tokenType: 0,
70+
traderType: 1,
71+
},
72+
]);
73+
});
74+
4575
it('should return undefined for v3 fill event when makerFeeAssetData is corrupt', () => {
4676
const protocolVersion = 3;
4777
const eventArgs = { ...V3_EVENT.data.args, makerFeeAssetData: 'fubar' };

src/jobs/create-fills/get-assets.test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,46 @@ it('should get assets for V2 event with multi-asset data', () => {
161161
]);
162162
});
163163

164+
it('should get assets for V2 event with bridged ERC20 asset data', () => {
165+
const eventArgs = {
166+
makerAddress: '0x9193ed9cbf94d109667c3d5659caffe21b4197bc',
167+
feeRecipientAddress: '0x0000000000000000000000000000000000000000',
168+
takerAddress: '0xdf1bc6498338135de5ffdbcb98817d81e2665912',
169+
senderAddress: '0xdf1bc6498338135de5ffdbcb98817d81e2665912',
170+
makerAssetFilledAmount: 7597171425070027,
171+
takerAssetFilledAmount: 46810278916603824.0,
172+
makerFeePaid: 0,
173+
takerFeePaid: 0,
174+
orderHash:
175+
'0xc9a69b17a479155016a724a250a6093903bcaafa318e757eab2c7fc6d5ca3edd',
176+
makerAssetData:
177+
'0xdc1600f3000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000058b7b96e170e46c07d02fac903cd1b3356b7549f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000400000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000a5a2f',
178+
takerAssetData:
179+
'0xf47261b000000000000000000000000053b04999c1ff2d77fcdde98935bb936a67209e4c',
180+
};
181+
const assets = getAssets(eventArgs, 2);
182+
183+
expect(assets).toEqual([
184+
{
185+
actor: 0,
186+
amount: 7597171425070027,
187+
bridgeAddress: '0x58b7b96e170e46c07d02fac903cd1b3356b7549f',
188+
bridgeData:
189+
'0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000a5a2f',
190+
tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
191+
tokenResolved: false,
192+
tokenType: 0,
193+
},
194+
{
195+
actor: 1,
196+
amount: 46810278916603820,
197+
tokenAddress: '0x53b04999c1ff2d77fcdde98935bb936a67209e4c',
198+
tokenResolved: false,
199+
tokenType: 0,
200+
},
201+
]);
202+
});
203+
164204
it('should return undefined when one of the assets data is corrupt', () => {
165205
const eventArgs = {
166206
makerAddress: '0x9193ed9cbf94d109667c3d5659caffe21b4197bc',

src/jobs/create-fills/parse-asset-data.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
const { assetDataUtils } = require('@0x/order-utils');
22
const { TOKEN_TYPE } = require('../../constants');
33

4-
const {
5-
decodeAssetDataOrThrow,
6-
isERC20AssetData,
7-
isERC721AssetData,
8-
isMultiAssetData,
9-
} = assetDataUtils;
4+
const { decodeAssetDataOrThrow } = assetDataUtils;
5+
6+
const isERC20AssetData = assetData => assetData.assetProxyId === '0xf47261b0';
7+
const isERC721AssetData = assetData => assetData.assetProxyId === '0x02571792';
8+
const isMultiAssetData = assetData => assetData.assetProxyId === '0x94cfcdd7';
9+
const isERC20BridgeAssetData = assetData =>
10+
assetData.assetProxyId === '0xdc1600f3';
1011

1112
const decodeAssetData = assetData => {
1213
try {
@@ -16,27 +17,37 @@ const decodeAssetData = assetData => {
1617
}
1718
};
1819

19-
const createAsset = (singleAssetData, amount) => {
20-
const simpleAsset = {
20+
const createAsset = (assetData, amount) => {
21+
const baseAsset = {
2122
amount,
22-
tokenAddress: singleAssetData.tokenAddress,
23+
tokenAddress: assetData.tokenAddress,
2324
};
2425

25-
if (isERC20AssetData(singleAssetData)) {
26+
if (isERC20AssetData(assetData)) {
2627
return {
27-
...simpleAsset,
28+
...baseAsset,
2829
tokenType: TOKEN_TYPE.ERC20,
2930
};
3031
}
3132

32-
if (isERC721AssetData(singleAssetData)) {
33+
if (isERC721AssetData(assetData)) {
3334
return {
34-
...simpleAsset,
35-
tokenId: singleAssetData.tokenId.toNumber(),
35+
...baseAsset,
36+
tokenId: assetData.tokenId.toNumber(),
3637
tokenType: TOKEN_TYPE.ERC721,
3738
};
3839
}
3940

41+
if (isERC20BridgeAssetData(assetData)) {
42+
return {
43+
...baseAsset,
44+
bridgeAddress: assetData.bridgeAddress,
45+
bridgeData: assetData.bridgeData,
46+
tokenAddress: assetData.tokenAddress,
47+
tokenType: TOKEN_TYPE.ERC20,
48+
};
49+
}
50+
4051
return undefined; // Unrecognised asset
4152
};
4253

@@ -68,7 +79,11 @@ const parseAssetData = (encodedData, amount) => {
6879
}
6980

7081
// When the asset data represents a single asset we can just return a single item array.
71-
if (isERC20AssetData(assetData) || isERC721AssetData(assetData)) {
82+
if (
83+
isERC20AssetData(assetData) ||
84+
isERC721AssetData(assetData) ||
85+
isERC20BridgeAssetData(assetData)
86+
) {
7287
return [createAsset(assetData, amount)];
7388
}
7489

src/model/fill.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const createModel = () => {
1010
{
1111
actor: Number,
1212
amount: Number,
13+
bridgeAddress: String,
14+
bridgeData: String,
1315
price: {
1416
USD: Number,
1517
},
@@ -36,6 +38,8 @@ const createModel = () => {
3638
fees: [
3739
{
3840
amount: { token: Number, USD: Number },
41+
bridgeAddress: String,
42+
bridgeData: String,
3943
tokenAddress: String,
4044
tokenId: Number,
4145
traderType: Number,

0 commit comments

Comments
 (0)