Skip to content

Commit

Permalink
Merge pull request #57 from consenlabs/feature/support_rfq_v2
Browse files Browse the repository at this point in the history
Feat: supporting RFQv2 protocol
  • Loading branch information
BenjaminLu authored Aug 30, 2023
2 parents 3aa9cbb + 4aef6d6 commit da81523
Show file tree
Hide file tree
Showing 12 changed files with 680 additions and 59 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Program setup,
- Modify the options in `app/mmConfig.js`, including,
- EXCHANGE_URL, point to tokenlon exchange server
- PROVIDER_URL, point to ethereum node, like your infura endpoint
- PERMIT_TYPE, approve tokens to `RFQv2` contract directly or approve tokens to `AllowanceTarget` contract.
- WALLET_ADDRESS, as your signer wallet address
- WALLET_PRIVATE_KEY, private key of above wallet, or use WALLET_KEYSTORE
- WALLET_TYPE, a market maker's wallet smart contract.
Expand All @@ -26,10 +27,10 @@ Program setup,
- types.WalletType.ERC1271
- types.WalletType.EOA
- SIGNING_URL, If you wanna sign orders in your own service instead of the mmsk,
please set the SIGNING_URL to your service endpoint. the mmsk would post every unsigned RFQ orders to your service. Remember to set the WALLET_ADDRESS as well. An example request is shown below:
please set the SIGNING_URL to your service endpoint. the mmsk would post every unsigned PMM/RFQV1/RFQV2 orders to your service. Remember to set the WALLET_ADDRESS as well. An example RFQV1 request is shown below:
```
{
rfqOrer: {
rfqOrder: {
takerAddr: '0x87fca7135c1c54876a62dc4922da3ce45f38debf',
makerAddr: '0x86B9F429C3Ef44c599EB560Eb531A0E3f2E36f64',
takerAssetAddr: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
Expand All @@ -55,7 +56,7 @@ Program setup,
- HTTP_SERVER_ENDPOINT, your backend http quoting server
- CHAIN_ID, 1 for mainnet, 5 for testnet(Goerli)
- Testing with `node app/check.js`
- Register contract address & signer address & MMSK server url to Tokenlon team
- Register contract address, signer address and MMSK server url to Tokenlon team
## Version Release
Expand Down
1 change: 1 addition & 0 deletions app/mmConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
// Tokenlon server address
EXCHANGE_URL: process.env.EXCHANGE_URL,
PROVIDER_URL: process.env.PROVIDER_URL,
PERMIT_TYPE: types.PermitType.APPROVE_RFQV2,

// Signing
/**
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@consenlabs/tokenlon-mmsk",
"version": "5.2.10",
"version": "5.3.0",
"description": "Tokenlon market maker server kit",
"author": "imToken PTE. LTD.",
"license": "MIT",
Expand All @@ -26,7 +26,7 @@
"check": "node ./app/check.js",
"clean": "rm -rf ./lib",
"start": "node ./app/start.js",
"test": "chainId=1 npx hardhat --network hardhat test",
"test": "chainId=5 npx hardhat --network hardhat test",
"watch": "tsc -w"
},
"devDependencies": {
Expand Down
27 changes: 21 additions & 6 deletions src/handler/newOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { addQuoteIdPrefix, constructQuoteResponse, preprocessQuote } from '../qu

import { assetDataUtils } from '0x-v2-order-utils'
import { buildSignedOrder as buildRFQV1SignedOrder } from '../signer/rfqv1'
import { buildSignedOrder as buildRFQV2SignedOrder } from '../signer/rfqv2'
import { buildSignedOrder } from '../signer/pmmv5'
import { buildSignedOrder as buildAMMV1Order } from '../signer/ammv1'
import { buildSignedOrder as buildAMMV2Order } from '../signer/ammv2'
Expand Down Expand Up @@ -158,11 +159,10 @@ function getOrderAndFeeFactor(query: QueryInterface, rate, tokenList, tokenConfi
config.wethContractAddress
)
// ETH -> WETH
const takerAssetAddress = getWethAddrIfIsEth(
takerToken.contractAddress,
config.wethContractAddress
)

let takerAssetAddress = getWethAddrIfIsEth(takerToken.contractAddress, config.wethContractAddress)
if (Protocol.RFQV2 === query.protocol) {
takerAssetAddress = takerToken.contractAddress
}
return {
makerAddress: config.mmProxyContractAddress.toLowerCase(),
makerAssetAmount,
Expand Down Expand Up @@ -192,7 +192,7 @@ const _getBaseTokenByAddress = (baseTokenAddr, tokenList) => {
const getBaseTokenByAddress = memoize(_getBaseTokenByAddress)

export const newOrder = async (ctx) => {
const { quoter, signer, chainID, walletType, signingUrl } = ctx
const { quoter, signer, chainID, walletType, signingUrl, permitType } = ctx
const req: QueryInterface = {
protocol: Protocol.PMMV5, // by default is v2 protocol
...ctx.query, // overwrite from request
Expand Down Expand Up @@ -270,6 +270,21 @@ export const newOrder = async (ctx) => {
}
)
break
case Protocol.RFQV2:
resp.order = await buildRFQV2SignedOrder(
signer,
order,
userAddr.toLowerCase(),
chainID,
config.addressBookV5.RFQV2,
walletType,
permitType,
{
signingUrl,
salt,
}
)
break
default:
console.log(`unknown protocol ${protocol}`)
throw new Error('Unrecognized protocol: ' + protocol)
Expand Down
2 changes: 1 addition & 1 deletion src/handler/version.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const VERSION = '5.2.10'
export const VERSION = '5.3.0'

export const version = (ctx) => {
ctx.body = {
Expand Down
31 changes: 30 additions & 1 deletion src/signer/orderHash.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { utils } from 'ethers'
import { RFQOrder } from './types'
import { Offer, RFQOrder } from './types'

const EIP712_DOMAIN_NAME = 'Tokenlon'
const EIP712_DOMAIN_VERSION = 'v5'
Expand All @@ -18,6 +18,20 @@ const RFQ_ORDER_SCHEMA = {
],
}

const RFQ_V2_ORDER_SCHEMA = {
Offer: [
{ name: 'taker', type: 'address' },
{ name: 'maker', type: 'address' },
{ name: 'takerToken', type: 'address' },
{ name: 'takerTokenAmount', type: 'uint256' },
{ name: 'makerToken', type: 'address' },
{ name: 'makerTokenAmount', type: 'uint256' },
{ name: 'feeFactor', type: 'uint256' },
{ name: 'expiry', type: 'uint256' },
{ name: 'salt', type: 'uint256' },
],
}

export function getOrderSignDigest(order: RFQOrder, chainId: number, address: string): string {
const domain = {
name: EIP712_DOMAIN_NAME,
Expand All @@ -36,6 +50,17 @@ export function getOrderSignDigest(order: RFQOrder, chainId: number, address: st
return utils._TypedDataEncoder.hash(domain, RFQ_ORDER_SCHEMA, value)
}

export function getOfferSignDigest(order: Offer, chainId: number, address: string): string {
const domain = {
name: EIP712_DOMAIN_NAME,
version: EIP712_DOMAIN_VERSION,
chainId: chainId,
verifyingContract: address,
}

return utils._TypedDataEncoder.hash(domain, RFQ_V2_ORDER_SCHEMA, order)
}

export function getOrderHash(order: RFQOrder): string {
// The data to sign
const value = {
Expand All @@ -47,3 +72,7 @@ export function getOrderHash(order: RFQOrder): string {

return utils._TypedDataEncoder.hashStruct('Order', RFQ_ORDER_SCHEMA, value)
}

export function getOfferHash(order: Offer): string {
return utils._TypedDataEncoder.hashStruct('Offer', RFQ_V2_ORDER_SCHEMA, order)
}
16 changes: 8 additions & 8 deletions src/signer/rfqv1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,31 +149,31 @@ export const buildSignedOrder = async (
const signingUrl = options ? options.signingUrl : undefined
order.salt = generateSaltWithFeeFactor(feeFactor, salt)

const rfqOrer = toRFQOrder(order)
const rfqOrder = toRFQOrder(order)

const orderHash = getOrderHash(rfqOrer)
const orderHash = getOrderHash(rfqOrder)
console.log(`orderHash: ${orderHash}`)
const orderSignDigest = getOrderSignDigest(rfqOrer, chainId, rfqAddr)
const orderSignDigest = getOrderSignDigest(rfqOrder, chainId, rfqAddr)
console.log(`orderSignDigest: ${orderSignDigest}`)
let makerWalletSignature
if (!signingUrl) {
if (signer.address.toLowerCase() == order.makerAddress.toLowerCase()) {
makerWalletSignature = await signRFQOrder(
chainId,
rfqAddr,
rfqOrer,
rfqOrder,
signer,
rfqOrer.feeFactor,
rfqOrder.feeFactor,
SignatureType.EIP712
)
} else if (walletType === WalletType.ERC1271_EIP712) {
// standard ERC1271 + ERC712 signature
makerWalletSignature = await signRFQOrder(
chainId,
rfqAddr,
rfqOrer,
rfqOrder,
signer,
rfqOrer.feeFactor,
rfqOrder.feeFactor,
SignatureType.WalletBytes32
)
} else {
Expand All @@ -188,7 +188,7 @@ export const buildSignedOrder = async (
}
} else {
makerWalletSignature = await forwardUnsignedOrder(signingUrl, {
rfqOrer: rfqOrer,
rfqOrder: rfqOrder,
userAddr: userAddr,
signer: signer.address,
chainId: chainId,
Expand Down
Loading

0 comments on commit da81523

Please sign in to comment.