From 6001d75185f35a2938d35cef6409ee8cf9d727f9 Mon Sep 17 00:00:00 2001 From: TheJuze Date: Thu, 23 May 2024 19:11:24 +0300 Subject: [PATCH] update lockOrderTypes.ts --- package.json | 2 +- src/constants/lockOrderTypes.ts | 4 +- src/crypt/hashOrder.ts | 68 ++++++++++++----- src/crypt/signOrder.ts | 125 ++++++++------------------------ 4 files changed, 80 insertions(+), 119 deletions(-) diff --git a/package.json b/package.json index f0bc273..42b69a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.21.0-rc14", + "version": "0.21.0-rc15", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/constants/lockOrderTypes.ts b/src/constants/lockOrderTypes.ts index a8dffe2..411d04b 100644 --- a/src/constants/lockOrderTypes.ts +++ b/src/constants/lockOrderTypes.ts @@ -2,9 +2,9 @@ export const LOCK_ORDER_TYPES = { Order: [ { name: 'sender', type: 'address' }, { name: 'expiration', type: 'uint64' }, - { name: 'asset', type: 'string' }, + { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint64' }, - { name: 'targetChainId', type: 'uint64' }, + { name: 'targetChainId', type: 'uint24' }, { name: 'secretHash', type: 'bytes32' }, ], }; diff --git a/src/crypt/hashOrder.ts b/src/crypt/hashOrder.ts index 858b03d..5b3cd6e 100644 --- a/src/crypt/hashOrder.ts +++ b/src/crypt/hashOrder.ts @@ -1,28 +1,56 @@ import { ethers, keccak256 } from 'ethers'; import type { Order } from '../types.js'; +import generateSecret from '../utils/generateSecret'; +import getDomainData from './getDomainData'; +import type { SupportedChainId } from '../../lib'; -const ORDER_TYPEHASH = '0xb5132db62dfceb466f2f8aee7a039db36a99772e5a9771d28388a5f9baad7c54' +const CROSS_CHAIN_ORDER_TYPEHASH = '0xcb145a2347f48eab4e3341a245f53da2e686e47ef421c89a6b40dde27a063c3f' +const EIP712_DOMAIN_TYPEHASH = '0xa604fff5a27d5951f334ccda7abff3286a8af29caeeb196a6f2b40a1dce7612b'; -export default function getOrderHash(order: Order) { +export default function getOrderHash(order: Order, chainId: SupportedChainId) { const abiCoder = ethers.AbiCoder.defaultAbiCoder() + const secret = generateSecret(); + const secretHash = ethers.keccak256(secret); - const { - senderAddress, - matcherAddress, - baseAsset, - quoteAsset, - matcherFeeAsset, - amount, - price, - matcherFee, - nonce, - expiration, - buySide - } = order - const orderBytes = abiCoder.encode( - ['bytes32', 'address', 'address', 'address', 'address', 'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8'], - [ORDER_TYPEHASH, senderAddress, matcherAddress, baseAsset, quoteAsset, matcherFeeAsset, amount, price, matcherFee, nonce, expiration, buySide] - ) + // Generate the orderParamsHash + const orderParamsHash = keccak256((abiCoder.encode( + ['address', 'address', 'address', 'address', 'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8'], + [ + order.senderAddress, + order.matcherAddress, + order.baseAsset, + order.quoteAsset, + order.matcherFeeAsset, + order.amount, + order.price, + order.matcherFee, + order.nonce, + order.expiration, + order.buySide + ] + ))); - return keccak256(orderBytes) + // Generate the full crossChainOrder hash + const orderHash = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( + ['bytes32', 'bytes32', 'uint24', 'bytes32', 'uint64'], + [CROSS_CHAIN_ORDER_TYPEHASH, orderParamsHash, 97, '0x74a00e5cceb68d791486ddb9ea83bb8245eca22f67cb0ea81342f6eff8bf6e51', 1718955340461] + )); + + const domainData = getDomainData(chainId); + // Generate the full crossChainOrder hash + const domainSeparator = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( + ['bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32'], + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + [EIP712_DOMAIN_TYPEHASH, ethers.keccak256(ethers.toUtf8Bytes(domainData?.name as string)), ethers.keccak256(ethers.toUtf8Bytes(domainData?.version as string)), Number(domainData.chainId), domainData.salt] + )); + + const digest = ethers.solidityPackedKeccak256( + ['bytes', 'bytes32', 'bytes32'], ['0x1901', domainSeparator, orderHash] + ); + + console.log({ secretHash }, { orderParamsHash }, { orderHash }, { domainData }, { domainSeparator }, { digest }); + + return { secret, secretHash, orderHash }; } diff --git a/src/crypt/signOrder.ts b/src/crypt/signOrder.ts index 586403f..7ab50c9 100644 --- a/src/crypt/signOrder.ts +++ b/src/crypt/signOrder.ts @@ -1,12 +1,11 @@ import { BigNumber } from 'bignumber.js'; -import { ethers, keccak256 } from 'ethers'; +import { ethers } from 'ethers'; import { INTERNAL_PROTOCOL_PRECISION } from '../constants'; import ORDER_TYPES from '../constants/orderTypes.js'; import type { CrossOrder, Order, SignedOrder, SupportedChainId } from '../types.js'; import normalizeNumber from '../utils/normalizeNumber.js'; import getDomainData from './getDomainData.js'; import hashOrder from './hashOrder.js'; -import generateSecret from '../utils/generateSecret'; const DEFAULT_EXPIRATION = 29 * 24 * 60 * 60 * 1000; // 29 days @@ -79,75 +78,31 @@ export const signOrder = async ({ // lockOrderExpiration: expiration }; - // const limitOrder = { - // senderAddress, - // matcherAddress, - // baseAsset: baseAssetAddress, - // quoteAsset: quoteAssetAddress, - // matcherFeeAsset: serviceFeeAssetAddress, - // amount: normalizeNumber( - // amount, - // INTERNAL_PROTOCOL_PRECISION, - // BigNumber.ROUND_FLOOR, - // ), - // price: normalizeNumber( - // price, - // INTERNAL_PROTOCOL_PRECISION, - // BigNumber.ROUND_FLOOR, - // ), - // matcherFee: normalizeNumber( - // matcherFee, - // INTERNAL_PROTOCOL_PRECISION, - // BigNumber.ROUND_CEIL, // ROUND_CEIL because we don't want get "not enough fee" error - // ), - // nonce: BigInt(nonce), - // expiration: BigInt(expiration), - // buySide: side === 'BUY' ? 1 : 0, - // }; - const mockLimit = { - senderAddress: '0xb07f292216d845dce4887777ec44a18566ca0e95', - matcherAddress: '0xfbcad2c3a90fbd94c335fbdf8e22573456da7f68', - baseAsset: '0xcb2951e90d8dcf16e1fa84ac0c83f48906d6a744', - quoteAsset: '0xf223eca06261145b3287a0fefd8cfad371c7eb34', - matcherFeeAsset: '0xf223eca06261145b3287a0fefd8cfad371c7eb34', - amount: 2000000000, - price: 66490000, - matcherFee: 49730783, - nonce: 1716449740461, - expiration: 1718955340461, - buySide: 0, - } - - // const limitOrderHash = ethers.keccak256(ethers.toUtf8Bytes(JSON.stringify(limitOrder))); - // Generate the orderParamsHash - const orderParamsHash = keccak256((ethers.AbiCoder.defaultAbiCoder().encode( - ['address', 'address', 'address', 'address', 'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8'], - [ - mockLimit.senderAddress, - mockLimit.matcherAddress, - mockLimit.baseAsset, - mockLimit.quoteAsset, - mockLimit.matcherFeeAsset, - mockLimit.amount, - mockLimit.price, - mockLimit.matcherFee, - mockLimit.nonce, - mockLimit.expiration, - mockLimit.buySide - ] - ))); - - const secret = generateSecret(); - const secretHash = ethers.keccak256(secret); - - // Type hash from Solidity contract - const CROSS_CHAIN_ORDER_TYPEHASH = '0xcb145a2347f48eab4e3341a245f53da2e686e47ef421c89a6b40dde27a063c3f' - - // Generate the full crossChainOrder hash - const crossChainOrderHash = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - ['bytes32', 'bytes32', 'uint24', 'bytes32', 'uint64'], - [CROSS_CHAIN_ORDER_TYPEHASH, orderParamsHash, 97, '0x74a00e5cceb68d791486ddb9ea83bb8245eca22f67cb0ea81342f6eff8bf6e51', 1718955340461] - )); + const limitOrder: Order = { + senderAddress, + matcherAddress, + baseAsset: baseAssetAddress, + quoteAsset: quoteAssetAddress, + matcherFeeAsset: serviceFeeAssetAddress, + amount: Number(normalizeNumber( + amount, + INTERNAL_PROTOCOL_PRECISION, + BigNumber.ROUND_FLOOR, + )), + price: Number(normalizeNumber( + price, + INTERNAL_PROTOCOL_PRECISION, + BigNumber.ROUND_FLOOR, + )), + matcherFee: Number(normalizeNumber( + matcherFee, + INTERNAL_PROTOCOL_PRECISION, + BigNumber.ROUND_CEIL, // ROUND_CEIL because we don't want get "not enough fee" error + )), + nonce, + expiration, + buySide: side === 'BUY' ? 1 : 0, + }; const signature = await signer.signTypedData( getDomainData(chainId), @@ -155,40 +110,18 @@ export const signOrder = async ({ order, ); - const EIP712_DOMAIN_TYPEHASH = '0xa604fff5a27d5951f334ccda7abff3286a8af29caeeb196a6f2b40a1dce7612b'; - // const EIP712_DOMAIN_TYPEHASH1 = ethers.keccak256(ethers.toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,bytes32 salt)')); - - const domainData = getDomainData(chainId); - // Generate the full crossChainOrder hash - const DOMAIN_SEPARATOR = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - ['bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32'], - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - [EIP712_DOMAIN_TYPEHASH, ethers.keccak256(ethers.toUtf8Bytes(domainData?.name as string)), ethers.keccak256(ethers.toUtf8Bytes(domainData?.version as string)), Number(domainData.chainId), domainData.salt] - )); - - // const digest = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - // ['bytes', 'bytes32', 'bytes32'], ['\x19\x01', DOMAIN_SEPARATOR, crossChainOrderHash] - // )); - - const digest = ethers.solidityPackedKeccak256( - ['bytes', 'bytes32', 'bytes32'], ['0x1901', DOMAIN_SEPARATOR, crossChainOrderHash] - ); - - console.log('digest', digest) - // https://github.com/poap-xyz/poap-fun/pull/62#issue-928290265 // "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1" const fixedSignature = ethers.Signature.from(signature).serialized; // if (!fixedSignature) throw new Error("Can't sign order"); + const { orderHash, secret, secretHash } = hashOrder(limitOrder, chainId); const signedOrder: SignedOrder = { ...order, - id: hashOrder(order), + id: orderHash, signature: fixedSignature, - ...(isCrossChain ? { secret: crossChainOrderHash, secretHash, targetChainId } : {}) + ...(isCrossChain ? { secret, secretHash, targetChainId } : {}) }; return signedOrder; };