aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contracts')
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol13
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol16
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol30
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol39
-rw-r--r--packages/contracts/test/exchange/match_orders.ts23
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts6
7 files changed, 88 insertions, 41 deletions
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 014210d33..1f5c15674 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -68,7 +68,7 @@
"solc": "^0.4.24",
"solhint": "^1.2.1",
"tslint": "5.11.0",
- "typescript": "2.7.1",
+ "typescript": "2.9.2",
"yargs": "^10.0.3"
},
"dependencies": {
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
index ac7382715..44de54817 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
@@ -96,14 +96,15 @@ contract MixinSignatureValidator is
"LENGTH_GREATER_THAN_0_REQUIRED"
);
- // Ensure signature is supported
+ // Pop last byte off of signature byte array.
uint8 signatureTypeRaw = uint8(signature.popLastByte());
+
+ // Ensure signature is supported
require(
signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
"SIGNATURE_UNSUPPORTED"
);
- // Pop last byte off of signature byte array.
SignatureType signatureType = SignatureType(signatureTypeRaw);
// Variables are not scoped in Solidity.
@@ -141,7 +142,12 @@ contract MixinSignatureValidator is
v = uint8(signature[0]);
r = signature.readBytes32(1);
s = signature.readBytes32(33);
- recovered = ecrecover(hash, v, r, s);
+ recovered = ecrecover(
+ hash,
+ v,
+ r,
+ s
+ );
isValid = signerAddress == recovered;
return isValid;
@@ -197,7 +203,6 @@ contract MixinSignatureValidator is
// | 0x14 + x | 1 | Signature type is always "\x06" |
} else if (signatureType == SignatureType.Validator) {
// Pop last 20 bytes off of signature byte array.
-
address validatorAddress = signature.popLast20Bytes();
// Ensure signer has approved validator.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
index 88d2da7d7..b5de1a5de 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
@@ -123,19 +123,23 @@ contract MixinTransactions is
bytes32 dataHash = keccak256(data);
// Assembly for more efficiently computing:
- // keccak256(abi.encode(
+ // keccak256(abi.encodePacked(
// EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,
// salt,
- // signerAddress,
+ // bytes32(signerAddress),
// keccak256(data)
// ));
assembly {
+ // Load free memory pointer
let memPtr := mload(64)
- mstore(memPtr, schemaHash)
- mstore(add(memPtr, 32), salt)
- mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff))
- mstore(add(memPtr, 96), dataHash)
+
+ mstore(memPtr, schemaHash) // hash of schema
+ mstore(add(memPtr, 32), salt) // salt
+ mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress
+ mstore(add(memPtr, 96), dataHash) // hash of data
+
+ // Compute hash
result := keccak256(memPtr, 128)
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
index 1fc41dafd..b02f7632e 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
@@ -30,7 +30,7 @@ contract LibEIP712 {
string constant internal EIP712_DOMAIN_VERSION = "2";
// Hash of the EIP712 Domain Separator Schema
- bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
+ bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(
"EIP712Domain(",
"string name,",
"string version,",
@@ -45,11 +45,11 @@ contract LibEIP712 {
constructor ()
public
{
- EIP712_DOMAIN_HASH = keccak256(abi.encode(
+ EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(
EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
keccak256(bytes(EIP712_DOMAIN_NAME)),
keccak256(bytes(EIP712_DOMAIN_VERSION)),
- address(this)
+ bytes32(address(this))
));
}
@@ -59,8 +59,28 @@ contract LibEIP712 {
function hashEIP712Message(bytes32 hashStruct)
internal
view
- returns (bytes32)
+ returns (bytes32 result)
{
- return keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, hashStruct));
+ bytes32 eip712DomainHash = EIP712_DOMAIN_HASH;
+
+ // Assembly for more efficient computing:
+ // keccak256(abi.encodePacked(
+ // EIP191_HEADER,
+ // EIP712_DOMAIN_HASH,
+ // hashStruct
+ // ));
+
+ assembly {
+ // Load free memory pointer
+ let memPtr := mload(64)
+
+ mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
+ mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
+ mstore(add(memPtr, 34), hashStruct) // Hash of struct
+
+ // Compute hash
+ result := keccak256(memPtr, 66)
+ }
+ return result;
}
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
index 4031ff26b..68f4f5f1b 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
@@ -103,11 +103,12 @@ contract LibOrder is
bytes32 takerAssetDataHash = keccak256(order.takerAssetData);
// Assembly for more efficiently computing:
- // keccak256(abi.encode(
- // order.makerAddress,
- // order.takerAddress,
- // order.feeRecipientAddress,
- // order.senderAddress,
+ // keccak256(abi.encodePacked(
+ // EIP712_ORDER_SCHEMA_HASH,
+ // bytes32(order.makerAddress),
+ // bytes32(order.takerAddress),
+ // bytes32(order.feeRecipientAddress),
+ // bytes32(order.senderAddress),
// order.makerAssetAmount,
// order.takerAssetAmount,
// order.makerFee,
@@ -119,24 +120,26 @@ contract LibOrder is
// ));
assembly {
+ // Calculate memory addresses that will be swapped out before hashing
+ let pos1 := sub(order, 32)
+ let pos2 := add(order, 320)
+ let pos3 := add(order, 352)
+
// Backup
- // solhint-disable-next-line space-after-comma
- let temp1 := mload(sub(order, 32))
- let temp2 := mload(add(order, 320))
- let temp3 := mload(add(order, 352))
+ let temp1 := mload(pos1)
+ let temp2 := mload(pos2)
+ let temp3 := mload(pos3)
// Hash in place
- // solhint-disable-next-line space-after-comma
- mstore(sub(order, 32), schemaHash)
- mstore(add(order, 320), makerAssetDataHash)
- mstore(add(order, 352), takerAssetDataHash)
- result := keccak256(sub(order, 32), 416)
+ mstore(pos1, schemaHash)
+ mstore(pos2, makerAssetDataHash)
+ mstore(pos3, takerAssetDataHash)
+ result := keccak256(pos1, 416)
// Restore
- // solhint-disable-next-line space-after-comma
- mstore(sub(order, 32), temp1)
- mstore(add(order, 320), temp2)
- mstore(add(order, 352), temp3)
+ mstore(pos1, temp1)
+ mstore(pos2, temp2)
+ mstore(pos3, temp3)
}
return result;
}
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts
index 440097562..46b3569bd 100644
--- a/packages/contracts/test/exchange/match_orders.ts
+++ b/packages/contracts/test/exchange/match_orders.ts
@@ -69,13 +69,22 @@ describe('matchOrders', () => {
before(async () => {
// Create accounts
const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ // Hack(albrow): Both Prettier and TSLint insert a trailing comma below
+ // but that is invalid syntax as of TypeScript version >= 2.8. We don't
+ // have the right fine-grained configuration options in TSLint,
+ // Prettier, or TypeScript, to reconcile this, so we will just have to
+ // wait for them to sort it out. We disable TSLint and Prettier for
+ // this part of the code for now. This occurs several times in this
+ // file. See https://github.com/prettier/prettier/issues/4624.
+ // prettier-ignore
const usedAddresses = ([
owner,
makerAddressLeft,
makerAddressRight,
takerAddress,
feeRecipientAddressLeft,
- feeRecipientAddressRight,
+ // tslint:disable-next-line:trailing-comma
+ feeRecipientAddressRight
] = _.slice(accounts, 0, 6));
// Create wrappers
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
@@ -201,9 +210,11 @@ describe('matchOrders', () => {
// Match signedOrderLeft with signedOrderRight
let newERC20BalancesByOwner: ERC20BalancesByOwner;
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
+ // prettier-ignore
[
newERC20BalancesByOwner,
- newERC721TokenIdsByOwner,
+ // tslint:disable-next-line:trailing-comma
+ newERC721TokenIdsByOwner
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
@@ -306,9 +317,11 @@ describe('matchOrders', () => {
// Match orders
let newERC20BalancesByOwner: ERC20BalancesByOwner;
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
+ // prettier-ignore
[
newERC20BalancesByOwner,
- newERC721TokenIdsByOwner,
+ // tslint:disable-next-line:trailing-comma
+ newERC721TokenIdsByOwner
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
@@ -374,9 +387,11 @@ describe('matchOrders', () => {
// Match orders
let newERC20BalancesByOwner: ERC20BalancesByOwner;
let newERC721TokenIdsByOwner: ERC721TokenIdsByOwner;
+ // prettier-ignore
[
newERC20BalancesByOwner,
- newERC721TokenIdsByOwner,
+ // tslint:disable-next-line:trailing-comma
+ newERC721TokenIdsByOwner
] = await matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft,
signedOrderRight,
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index f2bb42c75..bef0547bd 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -113,7 +113,7 @@ describe('MixinSignatureValidator', () => {
it('should revert when signature type is unsupported', async () => {
const unsupportedSignatureType = SignatureType.NSignatureTypes;
- const unsupportedSignatureHex = `0x${unsupportedSignatureType}`;
+ const unsupportedSignatureHex = '0x' + Buffer.from([unsupportedSignatureType]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
return expectContractCallFailed(
signatureValidator.publicIsValidSignature.callAsync(
@@ -126,7 +126,7 @@ describe('MixinSignatureValidator', () => {
});
it('should revert when SignatureType=Illegal', async () => {
- const unsupportedSignatureHex = `0x${SignatureType.Illegal}`;
+ const unsupportedSignatureHex = '0x' + Buffer.from([SignatureType.Illegal]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
return expectContractCallFailed(
signatureValidator.publicIsValidSignature.callAsync(
@@ -139,7 +139,7 @@ describe('MixinSignatureValidator', () => {
});
it('should return false when SignatureType=Invalid and signature has a length of zero', async () => {
- const signatureHex = `0x${SignatureType.Invalid}`;
+ const signatureHex = '0x' + Buffer.from([SignatureType.Invalid]).toString('hex');
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,