* add LibERC721Order.sol * Add ERC721 interface to vendor/ * Add ERC721OrdersFeature interface * Storage lib for ERC721 orders feature * Implement basic functionality for ERC721 orders (buy, sell, cancel, etc) * Add isValidERC721OrderSignature to interface * implement onERC721Received * Implement batchBuyERC721s * left/right orders -> sell/buy orders * Add missing @return comments * Implement matching functions * Use SafeMath where necessary * add rich errors for ERC721OrdersFeature * Add comments * Add presign support for ERC721 orders * Cancel using just the order nonce * Add IERC721OrdersFeature to IZeroEx * Add taker callback * Assembly optimizations in LibERC721Order * Add ERC721Orders TS class * create zero-ex/contracts/test/integration/ and tokens/ directories * TestMintableERC721Token * tmp * address feedback from original PR (#391) * address feedback from original PR * Update contracts/zero-ex/contracts/src/features/ERC721OrdersFeature.sol Co-authored-by: Kim Persson <kimpers@users.noreply.github.com> * address review feedback and improve order parameter naming * Add batchCancel function * Emit order fields in preSign * Fix tests Co-authored-by: Lawrence Forman <me@merklejerk.com> Co-authored-by: Kim Persson <kimpers@users.noreply.github.com> Co-authored-by: Michael Zhu <mchl.zhu.96@gmail.com> * Remove revertIfIncomplete from batchMatch * Sanity check maker address in preSign * ERC1155OrdersFeature contracts * Commence refactor, abstract base contract * ERC721OrdersFeature inherits from NFTOrders * Refactor ERC1155OrdersFeature to inherit from NFTOrders * Fix order hashing * Fix ERC721OrdersFeature tests * Typos * Remove maker address from preSigned mapping * disable dex sampler tests * Refactor TS tooling * Address PR feedback * Rearrange event fields to better align with struct fields * Update comments * update AbiEncoder.create params * Add ERC1155Order to protocol-utils * Add ERC1155OrdersFeeature tests * Bump package versions and regenerate contract wrappers * Add ERC165Feature * NFT orders: address audit findings (#417) * CVF-1: use pragma solidity ^0.6 instead of ^0.6.5 * CVF-11: fix inaccurate comment * CVF-16: Enable taker callbacks for batchBuyERC1155s * CVF-17: use internal call if revertIfIncomplete is true * CVF-21: avoid duplicate SLOAD * CVF-23: merge if statements * CVF-24: Reorder status checks to be consistent with ERC721OrdersFeature * CVF-25: Update unclear comment (canonical hash -> EIP-712 hash) * CVF-31: Document keys of orderState mapping * CVF-45: DRY up fees/properties hashing * CVF-47, CVF-50, CVF-57: calculate properties.length once; hash propertyStructHashArray in-place using assembly * CVF-56: More descriptive names for assembly variables * CVF-71: Update confusing comment about rounding in _payFees * CVF-72: Move ETH assertions outside of loop in _payFees * CVF-74: Move property validation loop to else branch * CVF-82: Update inaccurate comment * CVF-86: Enable taker callbacks for batchBuyERC721s * CVF-87: use internal call if revertIfIncomplete is true * CVF-89: Perform token mismatch checks before stateful operations * CVF-90, CVF-91: Defer ERC20 token mismatch check * CVF-93: Add inline comments for _payFees parameters in matchERC721Orders * CVF-94: Fix comment (Step 7 -> Step 5) * CVF-98: Use binary & operator instead of mod * CVF-99: Update unclear comment (canonical hash -> EIP-712 hash) * CVF-65, CVF-66, CVF-67: Copy params.ethAvailable into local variable; check that ethSpent does not exceed ethAvailable; remove ethAvailable < erc20FillAmount check * CVF-52, CVF-55, CVF-59: calculate fees.length once; hash feeStructHashArray in-place using assembly * CVF-14, CVF-32: OrderState struct; separate storage mapping for 1155 cancellations so orders can be cancelled by nonce * Update changelogs, IZeroEx artifact/wrapper Co-authored-by: Lawrence Forman <lawrence@0xproject.com> Co-authored-by: Lawrence Forman <me@merklejerk.com> Co-authored-by: Kim Persson <kimpers@users.noreply.github.com>
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { hexUtils, NULL_ADDRESS } from '@0x/utils';
|
|
|
|
export interface EIP712Domain {
|
|
name: string;
|
|
version: string;
|
|
chainId: number;
|
|
verifyingContract: string;
|
|
}
|
|
|
|
export type EIP712_STRUCT_ABI = Array<{ type: string; name: string }>;
|
|
|
|
export const EIP712_DOMAIN_PARAMETERS = [
|
|
{ name: 'name', type: 'string' },
|
|
{ name: 'version', type: 'string' },
|
|
{ name: 'chainId', type: 'uint256' },
|
|
{ name: 'verifyingContract', type: 'address' },
|
|
];
|
|
|
|
const EXCHANGE_PROXY_EIP712_DOMAIN_DEFAULT = {
|
|
chainId: 1,
|
|
verifyingContract: NULL_ADDRESS,
|
|
name: 'ZeroEx',
|
|
version: '1.0.0',
|
|
};
|
|
|
|
const EXCHANGE_PROXY_DOMAIN_TYPEHASH = hexUtils.hash(
|
|
hexUtils.toHex(
|
|
Buffer.from(
|
|
[
|
|
'EIP712Domain(',
|
|
['string name', 'string version', 'uint256 chainId', 'address verifyingContract'].join(','),
|
|
')',
|
|
].join(''),
|
|
),
|
|
),
|
|
);
|
|
|
|
/**
|
|
* Create an exchange proxy EIP712 domain.
|
|
*/
|
|
export function createExchangeProxyEIP712Domain(chainId?: number, verifyingContract?: string): EIP712Domain {
|
|
return {
|
|
...EXCHANGE_PROXY_EIP712_DOMAIN_DEFAULT,
|
|
...(chainId ? { chainId } : {}),
|
|
...(verifyingContract ? { verifyingContract } : {}),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get the hash of the exchange proxy EIP712 domain.
|
|
*/
|
|
export function getExchangeProxyEIP712DomainHash(chainId?: number, verifyingContract?: string): string {
|
|
const domain = createExchangeProxyEIP712Domain(chainId, verifyingContract);
|
|
return hexUtils.hash(
|
|
hexUtils.concat(
|
|
EXCHANGE_PROXY_DOMAIN_TYPEHASH,
|
|
hexUtils.hash(hexUtils.toHex(Buffer.from(domain.name))),
|
|
hexUtils.hash(hexUtils.toHex(Buffer.from(domain.version))),
|
|
hexUtils.leftPad(domain.chainId),
|
|
hexUtils.leftPad(domain.verifyingContract),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Compute a complete EIP712 hash given a struct hash.
|
|
*/
|
|
export function getExchangeProxyEIP712Hash(structHash: string, chainId?: number, verifyingContract?: string): string {
|
|
return hexUtils.hash(
|
|
hexUtils.concat('0x1901', getExchangeProxyEIP712DomainHash(chainId, verifyingContract), structHash),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Compute the type hash of an EIP712 struct given its ABI.
|
|
*/
|
|
export function getTypeHash(
|
|
primaryStructName: string,
|
|
primaryStructAbi: EIP712_STRUCT_ABI,
|
|
referencedStructs: { [structName: string]: EIP712_STRUCT_ABI } = {},
|
|
): string {
|
|
const primaryStructType = encodeType(primaryStructName, primaryStructAbi);
|
|
// Referenced structs are sorted lexicographically
|
|
const referencedStructTypes = Object.entries(referencedStructs)
|
|
.sort(([nameA], [nameB]) => nameA.localeCompare(nameB))
|
|
.map(([name, abi]) => encodeType(name, abi));
|
|
return hexUtils.hash(hexUtils.toHex(Buffer.from(primaryStructType + referencedStructTypes.join(''))));
|
|
}
|
|
|
|
function encodeType(structName: string, abi: EIP712_STRUCT_ABI): string {
|
|
return [`${structName}(`, abi.map(a => `${a.type} ${a.name}`).join(','), ')'].join('');
|
|
}
|