Skip to content

Commit 3d10d40

Browse files
authored
Merge pull request #76 from Loopring/v2
V2
2 parents 03a743a + b9c8cc0 commit 3d10d40

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

src/ethereum/contracts/Contracts.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import Contract from './Contract';
2+
import validator from '../validator'
3+
import {getRingHash} from '../../relay/rpc/ring'
4+
import { addHexPrefix, toBig, toBuffer, toFixed, toHex, toNumber} from '../../common/formatter'
5+
import {ecsign} from 'ethereumjs-util'
26

37
const erc20Abi = require('../../config/abis/erc20.json');
48
const wethAbi = require('../../config/abis/weth.json');
@@ -12,7 +16,7 @@ const LoopringProtocol = new Contract(loopringProtocolAbi);
1216

1317
const encodeCancelOrder = (signedOrder, amount) => {
1418
const {
15-
owner, tokenS, tokenB, walletAddress,authAddr,
19+
owner, tokenS, tokenB, walletAddress, authAddr,
1620
amountS, amountB, validSince, validUntil, lrcFee,
1721
buyNoMoreThanAmountB,
1822
marginSplitPercentage,
@@ -26,8 +30,41 @@ const encodeCancelOrder = (signedOrder, amount) => {
2630
return LoopringProtocol.encodeInputs('cancelOrder',{addresses, orderValues, buyNoMoreThanAmountB, marginSplitPercentage, v, r, s});
2731
};
2832

33+
const encodeSubmitRing = (orders, feeRecipient, feeSelections) => {
2934

30-
Object.assign(LoopringProtocol,{encodeCancelOrder});
35+
validator.validate({type: 'ETH_ADDRESS', value: feeRecipient})
36+
if(feeSelections === null || feeSelections === undefined){
37+
feeSelections = 0;
38+
}
39+
const rate = Math.pow(orders.reduce(order => (total,order) => {
40+
total.times(toBig(order.amountS).div(toBig(order.amountB)))
41+
}), orders.length);
42+
43+
const ringHash = getRingHash(orders, feeRecipient, feeSelections);
44+
const addressList = orders.map(order => [order.owner,order.tokenS,order.walletAddress,order.authAddr])
45+
const uintArgsList = orders.map(order => [order.amountS,order.amountB,order.validSince,order.validUntil,order.lrcFee, toHex(toBig(toFixed(toBig(order.amountS).times(toBig(rate)))))])
46+
const uint8ArgsList = orders.map(order => [order.marginSplitPercentage])
47+
const buyNoMoreThanAmountBList = orders.map(order => order.buyNoMoreThanAmountB)
48+
const sigs = orders.map(order => {
49+
const sig = ecsign(ringHash, toBuffer(addHexPrefix(order.authPrivateKey)))
50+
return {
51+
v: toNumber(sig.v),
52+
r: toHex(sig.r),
53+
s: toHex(sig.s)
54+
}
55+
})
56+
const vList = orders.map(order => order.v);
57+
vList.push(...sigs.map(sig => sig.v));
58+
const rList = orders.map(order => order.r);
59+
rList.push(...sigs.map(sig => sig.r));
60+
const sList = orders.map(order => order.s);
61+
sList.push(...sigs.map(sig => sig.s));
62+
63+
return LoopringProtocol.encodeInputs('submitRing',{addressList,uintArgsList,uint8ArgsList,buyNoMoreThanAmountBList,vList,rList,sList,feeRecipient,feeSelections})
64+
}
65+
66+
67+
Object.assign(LoopringProtocol,{encodeCancelOrder,encodeSubmitRing});
3168

3269
export default {
3370
ERC20Token,

src/relay/rpc/ring.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import validator from '../validator'
44
import Response from '../../common/response'
55
import code from "../../common/code"
66
import {toBig, toHex} from "../../common/formatter";
7+
import {getOrderHash} from './order'
8+
import {soliditySHA3} from 'ethereumjs-abi'
79

810
export default class Ring{
911

@@ -22,6 +24,10 @@ export default class Ring{
2224
getFills(filter){
2325
return getFills(this.host,filter)
2426
}
27+
28+
getRingHash(orders, feeRecipient, feeSelections){
29+
return getRingHash(orders, feeRecipient, feeSelections)
30+
}
2531
}
2632

2733
/**
@@ -119,3 +125,29 @@ export function getFills(host,filter) {
119125
}
120126

121127

128+
export function getRingHash (orders,feeRecipient, feeSelections) {
129+
const orderHashList = orders.map(order =>getOrderHash(order) )
130+
return soliditySHA3(["string", "address", "uint16"],[
131+
xorReduceStr(orderHashList),
132+
feeRecipient,
133+
feeSelections
134+
]);
135+
136+
}
137+
138+
139+
function xorReduceStr(strArr){
140+
const s0 = strArr[0];
141+
const tail = strArr.slice(1);
142+
const strXor = (s1, s2) => {
143+
const buf1 = Buffer.from(s1.slice(2), "hex");
144+
const buf2 = Buffer.from(s2.slice(2), "hex");
145+
const res = Buffer.alloc(32);
146+
for (let i = 0; i < 32; i++) {
147+
res[i] = buf1[i] ^ buf2[i];
148+
}
149+
return toHex(res);
150+
};
151+
const reduceRes = tail.reduce((a, b) => strXor(a, b), s0);
152+
return Buffer.from(reduceRes.slice(2), "hex");
153+
}

0 commit comments

Comments
 (0)