From d46e3f677805c8e3e4b4873fb9b0cec2988a4d63 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 19 Jun 2018 17:20:53 -0700 Subject: Twenty new tests for MixinSignatureValidator. Fixed handling of unsupported types. Fixed trezor prefix. --- .../protocol/Exchange/MixinSignatureValidator.sol | 11 +++- .../Exchange/mixins/MSignatureValidator.sol | 19 ++++--- .../current/test/TestValidator/TestValidator.sol | 52 +++++++++++++++++ .../current/test/TestWallet/TestWallet.sol | 65 ++++++++++++++++++++++ packages/contracts/src/utils/artifacts.ts | 4 ++ packages/contracts/src/utils/types.ts | 1 + 6 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol create mode 100644 packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 8ad15aaff..4a2beff57 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -33,7 +33,7 @@ contract MixinSignatureValidator is { // Personal message headers string constant ETH_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n32"; - string constant TREZOR_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n\x41"; + string constant TREZOR_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n\x20"; // Mapping of hash => signer => signed mapping (bytes32 => mapping (address => bool)) public preSigned; @@ -92,8 +92,15 @@ contract MixinSignatureValidator is LENGTH_GREATER_THAN_0_REQUIRED ); + // Ensure signature is supported + uint8 signatureTypeRaw = uint8(popLastByte(signature)); + require( + signatureTypeRaw < uint8(SignatureType.NSignatureTypes), + SIGNATURE_UNSUPPORTED + ); + // Pop last byte off of signature byte array. - SignatureType signatureType = SignatureType(uint8(popLastByte(signature))); + SignatureType signatureType = SignatureType(signatureTypeRaw); // Variables are not scoped in Solidity. uint8 v; diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol index 5e286e43a..0cab95193 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -25,14 +25,15 @@ contract MSignatureValidator is { // Allowed signature types. enum SignatureType { - Illegal, // 0x00, default value - Invalid, // 0x01 - EIP712, // 0x02 - EthSign, // 0x03 - Caller, // 0x04 - Wallet, // 0x05 - Validator, // 0x06 - PreSigned, // 0x07 - Trezor // 0x08 + Illegal, // 0x00, default value + Invalid, // 0x01 + EIP712, // 0x02 + EthSign, // 0x03 + Caller, // 0x04 + Wallet, // 0x05 + Validator, // 0x06 + PreSigned, // 0x07 + Trezor, // 0x08 + NSignatureTypes // 0x09, always leave at end. } } diff --git a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol new file mode 100644 index 000000000..ba661f89d --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol @@ -0,0 +1,52 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +import "../../protocol/Exchange/interfaces/IValidator.sol"; + +contract TestValidator is + IValidator +{ + + // The single valid signer for this wallet. + address validSigner; + + /// @dev constructs a new `TestValidator` with a single valid signer. + /// @param _validSigner The sole signer for this wallet. + constructor (address _validSigner) public { + validSigner = _validSigner; + } + + /// @dev Verifies that a signature is valid. + /// @param hash Message hash that is signed. + /// @param signer Address that should have signed the given hash. + /// @param signature Proof of signing. + /// @return Validity of order signature. + function isValidSignature( + bytes32 hash, + address signer, + bytes signature + ) + external + view + returns (bool isValid) + { + return (signer == validSigner); + } +} diff --git a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol new file mode 100644 index 000000000..5baba1d98 --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol @@ -0,0 +1,65 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +import "../../protocol/Exchange/interfaces/IWallet.sol"; +import "../../utils/LibBytes/LibBytes.sol"; + +contract TestWallet is + IWallet, + LibBytes +{ + + string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; + + // The owner of this wallet. + address walletOwner; + + /// @dev constructs a new `TestWallet` with a single owner. + /// @param _walletOwner The owner of this wallet. + constructor (address _walletOwner) public { + walletOwner = _walletOwner; + } + + /// @dev Validates an EIP712 signature. + /// The signer must match the signer of this wallet. + /// @param hash Message hash that is signed. + /// @param eip721Signature Proof of signing. + /// @return Validity of order signature. + function isValidSignature( + bytes32 hash, + bytes eip721Signature + ) + external + view + returns (bool isValid) + { + require( + eip721Signature.length == 65, + LENGTH_65_REQUIRED + ); + + uint8 v = uint8(eip721Signature[0]); + bytes32 r = readBytes32(eip721Signature, 1); + bytes32 s = readBytes32(eip721Signature, 33); + address recoveredAddress = ecrecover(hash, v, r, s); + isValid = walletOwner == recoveredAddress; + return isValid; + } +} diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 7ba467708..4375d87c6 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -17,6 +17,8 @@ import * as TestLibBytes from '../artifacts/TestLibBytes.json'; import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json'; +import * as TestValidator from '../artifacts/TestValidator.json'; +import * as TestWallet from '../artifacts/TestWallet.json'; import * as TokenRegistry from '../artifacts/TokenRegistry.json'; import * as EtherToken from '../artifacts/WETH9.json'; import * as Whitelist from '../artifacts/Whitelist.json'; @@ -41,6 +43,8 @@ export const artifacts = { TestLibMem: (TestLibMem as any) as ContractArtifact, TestLibs: (TestLibs as any) as ContractArtifact, TestSignatureValidator: (TestSignatureValidator as any) as ContractArtifact, + TestValidator: (TestValidator as any) as ContractArtifact, + TestWallet: (TestWallet as any) as ContractArtifact, TokenRegistry: (TokenRegistry as any) as ContractArtifact, Whitelist: (Whitelist as any) as ContractArtifact, ZRX: (ZRX as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index bb8c12088..a6d0c2a88 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -100,6 +100,7 @@ export enum ContractName { DummyERC721Receiver = 'DummyERC721Receiver', DummyERC721Token = 'DummyERC721Token', TestLibBytes = 'TestLibBytes', + TestWallet = 'TestWallet', Authorizable = 'Authorizable', Whitelist = 'Whitelist', } -- cgit From 2c7358d64ffb0e9fcbc462bbe3cd89edd67cec81 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 19 Jun 2018 17:27:09 -0700 Subject: Minor style tweaks --- .../current/protocol/Exchange/mixins/MSignatureValidator.sol | 2 +- .../contracts/current/test/TestValidator/TestValidator.sol | 2 +- .../src/contracts/current/test/TestWallet/TestWallet.sol | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol index 0cab95193..9c6fbe22b 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -34,6 +34,6 @@ contract MSignatureValidator is Validator, // 0x06 PreSigned, // 0x07 Trezor, // 0x08 - NSignatureTypes // 0x09, always leave at end. + NSignatureTypes // 0x09, number of signature types. Always leave at end. } } diff --git a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol index ba661f89d..c0daf8f38 100644 --- a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol +++ b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol @@ -33,7 +33,7 @@ contract TestValidator is validSigner = _validSigner; } - /// @dev Verifies that a signature is valid. + /// @dev Verifies that a signature is valid. /// @param hash Message hash that is signed. /// @param signer Address that should have signed the given hash. /// @param signature Proof of signing. diff --git a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol index 5baba1d98..51556971d 100644 --- a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol +++ b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol @@ -40,24 +40,24 @@ contract TestWallet is /// @dev Validates an EIP712 signature. /// The signer must match the signer of this wallet. /// @param hash Message hash that is signed. - /// @param eip721Signature Proof of signing. + /// @param eip712Signature Proof of signing. /// @return Validity of order signature. function isValidSignature( bytes32 hash, - bytes eip721Signature + bytes eip712Signature ) external view returns (bool isValid) { require( - eip721Signature.length == 65, + eip712Signature.length == 65, LENGTH_65_REQUIRED ); - uint8 v = uint8(eip721Signature[0]); - bytes32 r = readBytes32(eip721Signature, 1); - bytes32 s = readBytes32(eip721Signature, 33); + uint8 v = uint8(eip712Signature[0]); + bytes32 r = readBytes32(eip712Signature, 1); + bytes32 s = readBytes32(eip712Signature, 33); address recoveredAddress = ecrecover(hash, v, r, s); isValid = walletOwner == recoveredAddress; return isValid; -- cgit From 8d003dbc30735d72b860e739fd7dc47fad557df9 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 19 Jun 2018 18:26:42 -0700 Subject: Fixed two mislabelled revert reasons + Signature Validator revert tests working on Geth --- .../contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol | 4 ++-- packages/contracts/src/utils/constants.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol index adf27bec3..aab428e74 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol @@ -56,6 +56,6 @@ contract LibExchangeErrors { /// Length validation errors /// string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. - string constant LENGTH_0_REQUIRED = "LENGTH_1_REQUIRED"; // Byte array must have a length of 1. - string constant LENGTH_65_REQUIRED = "LENGTH_66_REQUIRED"; // Byte array must have a length of 66. + string constant LENGTH_0_REQUIRED = "LENGTH_0_REQUIRED"; // Byte array must have a length of 0. + string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; // Byte array must have a length of 65. } diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts index ec3c8fd36..f21b8c7a0 100644 --- a/packages/contracts/src/utils/constants.ts +++ b/packages/contracts/src/utils/constants.ts @@ -27,6 +27,11 @@ export const constants = { LIB_BYTES_GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED', ERC20_INSUFFICIENT_BALANCE: 'Insufficient balance to complete transfer.', ERC20_INSUFFICIENT_ALLOWANCE: 'Insufficient allowance to complete transfer.', + EXCHANGE_LENGTH_GREATER_THAN_0_REQUIRED: 'LENGTH_GREATER_THAN_0_REQUIRED', + EXCHANGE_SIGNATURE_UNSUPPORTED: 'SIGNATURE_UNSUPPORTED', + EXCHANGE_SIGNATURE_ILLEGAL: 'SIGNATURE_ILLEGAL', + EXCHANGE_LENGTH_0_REQUIRED: 'LENGTH_0_REQUIRED', + EXCHANGE_LENGTH_65_REQUIRED: 'LENGTH_65_REQUIRED', TESTRPC_NETWORK_ID: 50, // Note(albrow): In practice V8 and most other engines limit the minimum // interval for setInterval to 10ms. We still set it to 0 here in order to -- cgit From 7814a391d8698f0b865d5f2675b9cc068eeab986 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 19 Jun 2018 18:55:19 -0700 Subject: Few more minor #nit wording changes --- .../src/contracts/current/test/TestValidator/TestValidator.sol | 6 +++--- .../contracts/src/contracts/current/test/TestWallet/TestWallet.sol | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol index c0daf8f38..7eba61073 100644 --- a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol +++ b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol @@ -28,16 +28,16 @@ contract TestValidator is address validSigner; /// @dev constructs a new `TestValidator` with a single valid signer. - /// @param _validSigner The sole signer for this wallet. + /// @param _validSigner The sole, valid signer. constructor (address _validSigner) public { validSigner = _validSigner; } - /// @dev Verifies that a signature is valid. + /// @dev Verifies that a signature is valid. `signer` must match `validSigner`. /// @param hash Message hash that is signed. /// @param signer Address that should have signed the given hash. /// @param signature Proof of signing. - /// @return Validity of order signature. + /// @return Validity of signature. function isValidSignature( bytes32 hash, address signer, diff --git a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol index 51556971d..e7ddf1d9f 100644 --- a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol +++ b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol @@ -38,10 +38,10 @@ contract TestWallet is } /// @dev Validates an EIP712 signature. - /// The signer must match the signer of this wallet. + /// The signer must match the owner of this wallet. /// @param hash Message hash that is signed. /// @param eip712Signature Proof of signing. - /// @return Validity of order signature. + /// @return Validity of signature. function isValidSignature( bytes32 hash, bytes eip712Signature -- cgit From 12e16d532bd1844b561a5c1d32fc1c9b1fae2efc Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 20 Jun 2018 13:50:11 -0700 Subject: Renamed constants in test wallet/validator --- .../contracts/current/test/TestValidator/TestValidator.sol | 12 ++++++------ .../src/contracts/current/test/TestWallet/TestWallet.sol | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol index 7eba61073..13953b482 100644 --- a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol +++ b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol @@ -25,15 +25,15 @@ contract TestValidator is { // The single valid signer for this wallet. - address validSigner; + address VALID_SIGNER; /// @dev constructs a new `TestValidator` with a single valid signer. - /// @param _validSigner The sole, valid signer. - constructor (address _validSigner) public { - validSigner = _validSigner; + /// @param validSigner The sole, valid signer. + constructor (address validSigner) public { + VALID_SIGNER = validSigner; } - /// @dev Verifies that a signature is valid. `signer` must match `validSigner`. + /// @dev Verifies that a signature is valid. `signer` must match `VALID_SIGNER`. /// @param hash Message hash that is signed. /// @param signer Address that should have signed the given hash. /// @param signature Proof of signing. @@ -47,6 +47,6 @@ contract TestValidator is view returns (bool isValid) { - return (signer == validSigner); + return (signer == VALID_SIGNER); } } diff --git a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol index e7ddf1d9f..aca74b409 100644 --- a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol +++ b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol @@ -29,12 +29,12 @@ contract TestWallet is string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; // The owner of this wallet. - address walletOwner; + address WALLET_OWNER; /// @dev constructs a new `TestWallet` with a single owner. - /// @param _walletOwner The owner of this wallet. - constructor (address _walletOwner) public { - walletOwner = _walletOwner; + /// @param walletOwner The owner of this wallet. + constructor (address walletOwner) public { + WALLET_OWNER = walletOwner; } /// @dev Validates an EIP712 signature. @@ -59,7 +59,7 @@ contract TestWallet is bytes32 r = readBytes32(eip712Signature, 1); bytes32 s = readBytes32(eip712Signature, 33); address recoveredAddress = ecrecover(hash, v, r, s); - isValid = walletOwner == recoveredAddress; + isValid = WALLET_OWNER == recoveredAddress; return isValid; } } -- cgit From 8ee6e26608a832e48f235fbcb948721afcee648f Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 12 Jun 2018 13:33:06 -0700 Subject: Removed MixinSettlement. Moved `settleOrder` into `MixinExchangeCore` and `settleMatchedOrders` into `MixinMatchOrders` --- .../current/protocol/Exchange/Exchange.sol | 5 +- .../protocol/Exchange/MixinExchangeCore.sol | 52 +++++- .../current/protocol/Exchange/MixinMatchOrders.sol | 93 ++++++++++- .../current/protocol/Exchange/MixinSettlement.sol | 182 --------------------- .../protocol/Exchange/libs/LibConstants.sol | 37 +++++ .../protocol/Exchange/mixins/MExchangeCore.sol | 12 ++ .../protocol/Exchange/mixins/MMatchOrders.sol | 13 ++ .../protocol/Exchange/mixins/MSettlement.sol | 49 ------ 8 files changed, 205 insertions(+), 238 deletions(-) delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibConstants.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol index 51f99bafa..d36e9633e 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol @@ -19,9 +19,9 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; +import "./libs/LibConstants.sol"; import "./MixinExchangeCore.sol"; import "./MixinSignatureValidator.sol"; -import "./MixinSettlement.sol"; import "./MixinWrapperFunctions.sol"; import "./MixinAssetProxyDispatcher.sol"; import "./MixinTransactions.sol"; @@ -30,7 +30,6 @@ import "./MixinMatchOrders.sol"; contract Exchange is MixinExchangeCore, MixinMatchOrders, - MixinSettlement, MixinSignatureValidator, MixinTransactions, MixinAssetProxyDispatcher, @@ -42,9 +41,9 @@ contract Exchange is // Mixins are instantiated in the order they are inherited constructor (bytes memory _zrxAssetData) public + LibConstants(_zrxAssetData) // @TODO: Remove when we deploy. MixinExchangeCore() MixinMatchOrders() - MixinSettlement(_zrxAssetData) MixinSignatureValidator() MixinTransactions() MixinAssetProxyDispatcher() diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index c406354a7..2e6c86d48 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -19,22 +19,26 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; +import "./libs/LibConstants.sol"; +import "../../utils/LibBytes/LibBytes.sol"; import "./libs/LibFillResults.sol"; import "./libs/LibOrder.sol"; import "./libs/LibMath.sol"; import "./libs/LibExchangeErrors.sol"; import "./mixins/MExchangeCore.sol"; -import "./mixins/MSettlement.sol"; import "./mixins/MSignatureValidator.sol"; import "./mixins/MTransactions.sol"; +import "./mixins/MAssetProxyDispatcher.sol"; contract MixinExchangeCore is + LibConstants, + LibBytes, LibMath, LibOrder, LibFillResults, LibExchangeErrors, + MAssetProxyDispatcher, MExchangeCore, - MSettlement, MSignatureValidator, MTransactions { @@ -389,4 +393,48 @@ contract MixinExchangeCore is return fillResults; } + + /// @dev Settles an order by transferring assets between counterparties. + /// @param order Order struct containing order specifications. + /// @param takerAddress Address selling takerAsset and buying makerAsset. + /// @param fillResults Amounts to be filled and fees paid by maker and taker. + function settleOrder( + LibOrder.Order memory order, + address takerAddress, + LibFillResults.FillResults memory fillResults + ) + internal + { + uint8 makerAssetProxyId = uint8(popLastByte(order.makerAssetData)); + uint8 takerAssetProxyId = uint8(popLastByte(order.takerAssetData)); + bytes memory zrxAssetData = ZRX_ASSET_DATA; + dispatchTransferFrom( + order.makerAssetData, + makerAssetProxyId, + order.makerAddress, + takerAddress, + fillResults.makerAssetFilledAmount + ); + dispatchTransferFrom( + order.takerAssetData, + takerAssetProxyId, + takerAddress, + order.makerAddress, + fillResults.takerAssetFilledAmount + ); + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + order.makerAddress, + order.feeRecipientAddress, + fillResults.makerFeePaid + ); + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + takerAddress, + order.feeRecipientAddress, + fillResults.takerFeePaid + ); + } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol index 517b743fe..945153731 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol @@ -14,21 +14,25 @@ pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; +import "./libs/LibConstants.sol"; +import "../../utils/LibBytes/LibBytes.sol"; import "./libs/LibMath.sol"; import "./libs/LibOrder.sol"; import "./libs/LibFillResults.sol"; import "./libs/LibExchangeErrors.sol"; import "./mixins/MExchangeCore.sol"; import "./mixins/MMatchOrders.sol"; -import "./mixins/MSettlement.sol"; import "./mixins/MTransactions.sol"; +import "./mixins/MAssetProxyDispatcher.sol"; contract MixinMatchOrders is + LibConstants, + LibBytes, LibMath, LibExchangeErrors, + MAssetProxyDispatcher, MExchangeCore, MMatchOrders, - MSettlement, MTransactions { @@ -224,4 +228,89 @@ contract MixinMatchOrders is // Return fill results return matchedFillResults; } + + /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient. + /// @param leftOrder First matched order. + /// @param rightOrder Second matched order. + /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit. + /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients. + function settleMatchedOrders( + LibOrder.Order memory leftOrder, + LibOrder.Order memory rightOrder, + address takerAddress, + LibFillResults.MatchedFillResults memory matchedFillResults + ) + internal + { + uint8 leftMakerAssetProxyId = uint8(popLastByte(leftOrder.makerAssetData)); + uint8 rightMakerAssetProxyId = uint8(popLastByte(rightOrder.makerAssetData)); + bytes memory zrxAssetData = ZRX_ASSET_DATA; + // Order makers and taker + dispatchTransferFrom( + leftOrder.makerAssetData, + leftMakerAssetProxyId, + leftOrder.makerAddress, + rightOrder.makerAddress, + matchedFillResults.right.takerAssetFilledAmount + ); + dispatchTransferFrom( + rightOrder.makerAssetData, + rightMakerAssetProxyId, + rightOrder.makerAddress, + leftOrder.makerAddress, + matchedFillResults.left.takerAssetFilledAmount + ); + dispatchTransferFrom( + leftOrder.makerAssetData, + leftMakerAssetProxyId, + leftOrder.makerAddress, + takerAddress, + matchedFillResults.leftMakerAssetSpreadAmount + ); + + // Maker fees + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + leftOrder.makerAddress, + leftOrder.feeRecipientAddress, + matchedFillResults.left.makerFeePaid + ); + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + rightOrder.makerAddress, + rightOrder.feeRecipientAddress, + matchedFillResults.right.makerFeePaid + ); + + // Taker fees + if (leftOrder.feeRecipientAddress == rightOrder.feeRecipientAddress) { + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + takerAddress, + leftOrder.feeRecipientAddress, + safeAdd( + matchedFillResults.left.takerFeePaid, + matchedFillResults.right.takerFeePaid + ) + ); + } else { + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + takerAddress, + leftOrder.feeRecipientAddress, + matchedFillResults.left.takerFeePaid + ); + dispatchTransferFrom( + zrxAssetData, + ZRX_PROXY_ID, + takerAddress, + rightOrder.feeRecipientAddress, + matchedFillResults.right.takerFeePaid + ); + } + } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol deleted file mode 100644 index 29a9c87bd..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol +++ /dev/null @@ -1,182 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; -pragma experimental ABIEncoderV2; - -import "../../utils/LibBytes/LibBytes.sol"; -import "./libs/LibMath.sol"; -import "./libs/LibFillResults.sol"; -import "./libs/LibOrder.sol"; -import "./libs/LibExchangeErrors.sol"; -import "./mixins/MMatchOrders.sol"; -import "./mixins/MSettlement.sol"; -import "./mixins/MAssetProxyDispatcher.sol"; - -contract MixinSettlement is - LibBytes, - LibMath, - LibExchangeErrors, - MMatchOrders, - MSettlement, - MAssetProxyDispatcher -{ - // ZRX address encoded as a byte array. - // This will be constant throughout the life of the Exchange contract, - // since ZRX will always be transferred via the ERC20 AssetProxy. - bytes internal ZRX_ASSET_DATA; - uint8 constant ZRX_PROXY_ID = 1; - - /// TODO: _zrxAssetData should be a constant in production. - /// @dev Constructor sets the metadata that will be used for paying ZRX fees. - /// @param _zrxAssetData Byte array containing ERC20 proxy id concatenated with address of ZRX. - constructor (bytes memory _zrxAssetData) - public - { - ZRX_ASSET_DATA = _zrxAssetData; - } - - /// @dev Settles an order by transferring assets between counterparties. - /// @param order Order struct containing order specifications. - /// @param takerAddress Address selling takerAsset and buying makerAsset. - /// @param fillResults Amounts to be filled and fees paid by maker and taker. - function settleOrder( - LibOrder.Order memory order, - address takerAddress, - LibFillResults.FillResults memory fillResults - ) - internal - { - uint8 makerAssetProxyId = uint8(popLastByte(order.makerAssetData)); - uint8 takerAssetProxyId = uint8(popLastByte(order.takerAssetData)); - bytes memory zrxAssetData = ZRX_ASSET_DATA; - dispatchTransferFrom( - order.makerAssetData, - makerAssetProxyId, - order.makerAddress, - takerAddress, - fillResults.makerAssetFilledAmount - ); - dispatchTransferFrom( - order.takerAssetData, - takerAssetProxyId, - takerAddress, - order.makerAddress, - fillResults.takerAssetFilledAmount - ); - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - order.makerAddress, - order.feeRecipientAddress, - fillResults.makerFeePaid - ); - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - takerAddress, - order.feeRecipientAddress, - fillResults.takerFeePaid - ); - } - - /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient. - /// @param leftOrder First matched order. - /// @param rightOrder Second matched order. - /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit. - /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients. - function settleMatchedOrders( - LibOrder.Order memory leftOrder, - LibOrder.Order memory rightOrder, - address takerAddress, - LibFillResults.MatchedFillResults memory matchedFillResults - ) - internal - { - uint8 leftMakerAssetProxyId = uint8(popLastByte(leftOrder.makerAssetData)); - uint8 rightMakerAssetProxyId = uint8(popLastByte(rightOrder.makerAssetData)); - bytes memory zrxAssetData = ZRX_ASSET_DATA; - // Order makers and taker - dispatchTransferFrom( - leftOrder.makerAssetData, - leftMakerAssetProxyId, - leftOrder.makerAddress, - rightOrder.makerAddress, - matchedFillResults.right.takerAssetFilledAmount - ); - dispatchTransferFrom( - rightOrder.makerAssetData, - rightMakerAssetProxyId, - rightOrder.makerAddress, - leftOrder.makerAddress, - matchedFillResults.left.takerAssetFilledAmount - ); - dispatchTransferFrom( - leftOrder.makerAssetData, - leftMakerAssetProxyId, - leftOrder.makerAddress, - takerAddress, - matchedFillResults.leftMakerAssetSpreadAmount - ); - - // Maker fees - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - leftOrder.makerAddress, - leftOrder.feeRecipientAddress, - matchedFillResults.left.makerFeePaid - ); - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - rightOrder.makerAddress, - rightOrder.feeRecipientAddress, - matchedFillResults.right.makerFeePaid - ); - - // Taker fees - if (leftOrder.feeRecipientAddress == rightOrder.feeRecipientAddress) { - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - takerAddress, - leftOrder.feeRecipientAddress, - safeAdd( - matchedFillResults.left.takerFeePaid, - matchedFillResults.right.takerFeePaid - ) - ); - } else { - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - takerAddress, - leftOrder.feeRecipientAddress, - matchedFillResults.left.takerFeePaid - ); - dispatchTransferFrom( - zrxAssetData, - ZRX_PROXY_ID, - takerAddress, - rightOrder.feeRecipientAddress, - matchedFillResults.right.takerFeePaid - ); - } - } -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibConstants.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibConstants.sol new file mode 100644 index 000000000..4a9452448 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibConstants.sol @@ -0,0 +1,37 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +contract LibConstants { + + // Asset data for ZRX token. Used for fee transfers. + // @TODO: Hardcode constant when we deploy. Currently + // not constant to make testing easier. + bytes public ZRX_ASSET_DATA; + + // Proxy Id for ZRX token. + uint8 constant ZRX_PROXY_ID = 1; + + // @TODO: Remove when we deploy. + constructor (bytes memory zrxAssetData) + public + { + ZRX_ASSET_DATA = zrxAssetData; + } +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index fb345294c..c752d928c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -121,4 +121,16 @@ contract MExchangeCore is internal pure returns (LibFillResults.FillResults memory fillResults); + + /// @dev Settles an order by transferring assets between counterparties. + /// @param order Order struct containing order specifications. + /// @param takerAddress Address selling takerAsset and buying makerAsset. + /// @param fillResults Amounts to be filled and fees paid by maker and taker. + function settleOrder( + LibOrder.Order memory order, + address takerAddress, + LibFillResults.FillResults memory fillResults + ) + internal; + } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol index e52963a26..6b4cff972 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol @@ -54,4 +54,17 @@ contract MMatchOrders is internal pure returns (LibFillResults.MatchedFillResults memory matchedFillResults); + + /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient. + /// @param leftOrder First matched order. + /// @param rightOrder Second matched order. + /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit. + /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients. + function settleMatchedOrders( + LibOrder.Order memory leftOrder, + LibOrder.Order memory rightOrder, + address takerAddress, + LibFillResults.MatchedFillResults memory matchedFillResults + ) + internal; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol deleted file mode 100644 index 2c403162f..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol +++ /dev/null @@ -1,49 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; - -import "../libs/LibOrder.sol"; -import "../libs/LibFillResults.sol"; - -contract MSettlement { - - /// @dev Settles an order by transferring assets between counterparties. - /// @param order Order struct containing order specifications. - /// @param takerAddress Address selling takerAsset and buying makerAsset. - /// @param fillResults Amounts to be filled and fees paid by maker and taker. - function settleOrder( - LibOrder.Order memory order, - address takerAddress, - LibFillResults.FillResults memory fillResults - ) - internal; - - /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient. - /// @param leftOrder First matched order. - /// @param rightOrder Second matched order. - /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit. - /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients. - function settleMatchedOrders( - LibOrder.Order memory leftOrder, - LibOrder.Order memory rightOrder, - address takerAddress, - LibFillResults.MatchedFillResults memory matchedFillResults - ) - internal; -} -- cgit From 6d5b16725d364a632f6838129086e915fcc0b338 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 20 Jun 2018 17:27:45 -0700 Subject: Set settleOrder and settleMatchedOrders to private --- .../current/protocol/Exchange/MixinExchangeCore.sol | 2 +- .../contracts/current/protocol/Exchange/MixinMatchOrders.sol | 2 +- .../current/protocol/Exchange/mixins/MExchangeCore.sol | 11 ----------- .../current/protocol/Exchange/mixins/MMatchOrders.sol | 12 ------------ 4 files changed, 2 insertions(+), 25 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 2e6c86d48..8539342b7 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -403,7 +403,7 @@ contract MixinExchangeCore is address takerAddress, LibFillResults.FillResults memory fillResults ) - internal + private { uint8 makerAssetProxyId = uint8(popLastByte(order.makerAssetData)); uint8 takerAssetProxyId = uint8(popLastByte(order.takerAssetData)); diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol index 945153731..82325a29f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol @@ -240,7 +240,7 @@ contract MixinMatchOrders is address takerAddress, LibFillResults.MatchedFillResults memory matchedFillResults ) - internal + private { uint8 leftMakerAssetProxyId = uint8(popLastByte(leftOrder.makerAssetData)); uint8 rightMakerAssetProxyId = uint8(popLastByte(rightOrder.makerAssetData)); diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index c752d928c..1737f5baf 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -122,15 +122,4 @@ contract MExchangeCore is pure returns (LibFillResults.FillResults memory fillResults); - /// @dev Settles an order by transferring assets between counterparties. - /// @param order Order struct containing order specifications. - /// @param takerAddress Address selling takerAsset and buying makerAsset. - /// @param fillResults Amounts to be filled and fees paid by maker and taker. - function settleOrder( - LibOrder.Order memory order, - address takerAddress, - LibFillResults.FillResults memory fillResults - ) - internal; - } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol index 6b4cff972..abe7c3596 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MMatchOrders.sol @@ -55,16 +55,4 @@ contract MMatchOrders is pure returns (LibFillResults.MatchedFillResults memory matchedFillResults); - /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient. - /// @param leftOrder First matched order. - /// @param rightOrder Second matched order. - /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit. - /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients. - function settleMatchedOrders( - LibOrder.Order memory leftOrder, - LibOrder.Order memory rightOrder, - address takerAddress, - LibFillResults.MatchedFillResults memory matchedFillResults - ) - internal; } -- cgit From a3ba7683f4734d82cf8e2508cc00709a775bbc58 Mon Sep 17 00:00:00 2001 From: Austin Roberts Date: Thu, 21 Jun 2018 14:15:20 -0500 Subject: Remove unreachable PreSigned check This code was unreachable, as it had the exact same condition as line 206. --- .../contracts/current/protocol/Exchange/MixinSignatureValidator.sol | 4 ---- 1 file changed, 4 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 4a2beff57..5897e6416 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -232,10 +232,6 @@ contract MixinSignatureValidator is isValid = signer == recovered; return isValid; - // Signer signed hash previously using the preSign function - } else if (signatureType == SignatureType.PreSigned) { - isValid = preSigned[hash][signer]; - return isValid; } // Anything else is illegal (We do not return false because -- cgit From 6a073d5f866665c43ab57d7246c7ea693264ed88 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Wed, 20 Jun 2018 14:29:30 -0700 Subject: Add senderAddress to Fill and Cancel logs, add comments to events and types --- .../protocol/Exchange/MixinExchangeCore.sol | 4 ++- .../protocol/Exchange/libs/LibFillResults.sol | 14 ++++---- .../current/protocol/Exchange/libs/LibOrder.sol | 33 +++++++++---------- .../protocol/Exchange/mixins/MExchangeCore.sol | 38 ++++++++++++---------- 4 files changed, 45 insertions(+), 44 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 8539342b7..901e71936 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -225,8 +225,9 @@ contract MixinExchangeCore is // Log order emit Fill( order.makerAddress, - takerAddress, order.feeRecipientAddress, + takerAddress, + msg.sender, fillResults.makerAssetFilledAmount, fillResults.takerAssetFilledAmount, fillResults.makerFeePaid, @@ -255,6 +256,7 @@ contract MixinExchangeCore is emit Cancel( order.makerAddress, order.feeRecipientAddress, + msg.sender, orderHash, order.makerAssetData, order.takerAssetData diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol index b7550d6d2..63f1b8c87 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol @@ -25,16 +25,16 @@ contract LibFillResults is { struct FillResults { - uint256 makerAssetFilledAmount; - uint256 takerAssetFilledAmount; - uint256 makerFeePaid; - uint256 takerFeePaid; + uint256 makerAssetFilledAmount; // Total amount of makerAsset(s) filled. + uint256 takerAssetFilledAmount; // Total amount of takerAsset(s) filled. + uint256 makerFeePaid; // Total amount of ZRX paid by maker(s) to feeRecipient(s). + uint256 takerFeePaid; // Total amount of ZRX paid by taker to feeRecipients(s). } struct MatchedFillResults { - FillResults left; - FillResults right; - uint256 leftMakerAssetSpreadAmount; + FillResults left; // Amounts filled and fees paid of left order. + FillResults right; // Amounts filled and fees paid of right order. + uint256 leftMakerAssetSpreadAmount; // Spread between price of left and right order, denominated in the left order's makerAsset, paid to taker. } /// @dev Adds properties of both FillResults instances. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index bfc7aaae0..f3f1e9277 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -55,27 +55,24 @@ contract LibOrder is } struct Order { - address makerAddress; - address takerAddress; - address feeRecipientAddress; - address senderAddress; - uint256 makerAssetAmount; - uint256 takerAssetAmount; - uint256 makerFee; - uint256 takerFee; - uint256 expirationTimeSeconds; - uint256 salt; - bytes makerAssetData; - bytes takerAssetData; + address makerAddress; // Address that created the order. + address takerAddress; // Address that is allowed to fill the order. If set to 0, any address is allowed to fill the order. + address feeRecipientAddress; // Address that will recieve fees when order is filled. + address senderAddress; // Address that is allowed to call Exchange contract methods that affect this order. If set to 0, any address is allowed to call these methods. + uint256 makerAssetAmount; // Amount of makerAsset being offered by maker. Must be greater than 0. + uint256 takerAssetAmount; // Amount of takerAsset being bid on by maker. Must be greater than 0. + uint256 makerFee; // Amount of ZRX paid to feeRecipient by maker when order is filled. If set to 0, no transfer of ZRX from maker to feeRecipient will be attempted. + uint256 takerFee; // Amount of ZRX paid to feeRecipient by taker when order is filled. If set to 0, no transfer of ZRX from taker to feeRecipient will be attempted. + uint256 expirationTimeSeconds; // Timestamp in seconds at which order expires. + uint256 salt; // Arbitrary number to facilitate uniqueness of the order's hash. + bytes makerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring makerAsset. The last byte references the id of this proxy. + bytes takerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring takerAsset. The last byte references the id of this proxy. } struct OrderInfo { - // See LibStatus for a complete description of order statuses - uint8 orderStatus; - // Keccak-256 EIP712 hash of the order - bytes32 orderHash; - // Amount of order that has been filled - uint256 orderTakerAssetFilledAmount; + uint8 orderStatus; // Status that describes order's validity and fillability. + bytes32 orderHash; // EIP712 hash of the order (see LibOrder.getOrderHash). + uint256 orderTakerAssetFilledAmount; // Amount of order that has already been filled. } /// @dev Calculates Keccak-256 hash of the order. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index 1737f5baf..b0dbceff6 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -28,32 +28,34 @@ contract MExchangeCore is { // Fill event is emitted whenever an order is filled. event Fill( - address indexed makerAddress, - address takerAddress, - address indexed feeRecipientAddress, - uint256 makerAssetFilledAmount, - uint256 takerAssetFilledAmount, - uint256 makerFeePaid, - uint256 takerFeePaid, - bytes32 indexed orderHash, - bytes makerAssetData, - bytes takerAssetData + address indexed makerAddress, // Address that created the order. + address indexed feeRecipientAddress, // Address that received fees. + address takerAddress, // Address that filled the order. + address senderAddress, // Address that called the Exchange contract (msg.sender). + uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker. + uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker. + uint256 makerFeePaid, // Amount of ZRX paid to feeRecipient by maker. + uint256 takerFeePaid, // Amount of ZRX paid to feeRecipient by taker. + bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash) + bytes makerAssetData, // Encoded data specific to makerAsset. + bytes takerAssetData // Encoded data specific to takerAsset. ); // Cancel event is emitted whenever an individual order is cancelled. event Cancel( - address indexed makerAddress, - address indexed feeRecipientAddress, - bytes32 indexed orderHash, - bytes makerAssetData, - bytes takerAssetData + address indexed makerAddress, // Address that created the order. + address indexed feeRecipientAddress, // Address that would have recieved fees if order was filled. + address senderAddress, // Address that called the Exchange contract (msg.sender). + bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash) + bytes makerAssetData, // Encoded data specific to makerAsset. + bytes takerAssetData // Encoded data specific to takerAsset. ); // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully. event CancelUpTo( - address indexed makerAddress, - address indexed senderAddress, - uint256 orderEpoch + address indexed makerAddress, // Orders cancelled must have been created by this address. + address indexed senderAddress, // Orders cancelled must have a `senderAddress` equal to this address. + uint256 orderEpoch // Orders specified makerAddress and senderAddress with a salt <= this value are considered cancelled. ); /// @dev Updates state with results of a fill order. -- cgit From b333ed91de8d4f08cd614a52e2b0d602995c2b27 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 21 Jun 2018 16:08:45 -0700 Subject: Add event to setSignatureValidatorApproval, rename signer => signerAddress accross all contracts --- .../protocol/Exchange/MixinExchangeCore.sol | 6 ++- .../protocol/Exchange/MixinSignatureValidator.sol | 50 +++++++++++++--------- .../protocol/Exchange/MixinTransactions.sol | 28 +++++++----- .../Exchange/interfaces/ISignatureValidator.sol | 12 +++--- .../protocol/Exchange/interfaces/ITransactions.sol | 4 +- .../protocol/Exchange/interfaces/IValidator.sol | 4 +- .../Exchange/mixins/MAssetProxyDispatcher.sol | 6 +-- .../protocol/Exchange/mixins/MExchangeCore.sol | 4 +- .../Exchange/mixins/MSignatureValidator.sol | 26 ++++++----- .../current/test/TestValidator/TestValidator.sol | 6 +-- .../contracts/current/test/Whitelist/Whitelist.sol | 6 +-- packages/contracts/src/utils/exchange_wrapper.ts | 2 +- .../contracts/src/utils/transaction_factory.ts | 6 +-- packages/contracts/src/utils/types.ts | 2 +- 14 files changed, 94 insertions(+), 68 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 901e71936..c227d210f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -312,7 +312,11 @@ contract MixinExchangeCore is // Validate Maker signature (check only if first time seen) if (orderInfo.orderTakerAssetFilledAmount == 0) { require( - isValidSignature(orderInfo.orderHash, order.makerAddress, signature), + isValidSignature( + orderInfo.orderHash, + order.makerAddress, + signature + ), INVALID_ORDER_SIGNATURE ); } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 5897e6416..881d6e7b3 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -43,43 +43,52 @@ contract MixinSignatureValidator is /// @dev Approves a hash on-chain using any valid signature type. /// After presigning a hash, the preSign signature type will become valid for that hash and signer. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof that the hash has been signed by signer. function preSign( bytes32 hash, - address signer, + address signerAddress, bytes signature ) external { require( - isValidSignature(hash, signer, signature), + isValidSignature( + hash, + signerAddress, + signature + ), INVALID_SIGNATURE ); - preSigned[hash][signer] = true; + preSigned[hash][signerAddress] = true; } /// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf. - /// @param validator Address of Validator contract. + /// @param validatorAddress Address of Validator contract. /// @param approval Approval or disapproval of Validator contract. function setSignatureValidatorApproval( - address validator, + address validatorAddress, bool approval ) external { - address signer = getCurrentContextAddress(); - allowedValidators[signer][validator] = approval; + address signerAddress = getCurrentContextAddress(); + allowedValidators[signerAddress][validatorAddress] = approval; + emit SignatureValidatorApproval( + signerAddress, + validatorAddress, + approval + ); } /// @dev Verifies that a hash has been signed by the given signer. /// @param hash Any 32 byte hash. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof that the hash has been signed by signer. /// @return True if the address recovered from the provided signature matches the input signer address. function isValidSignature( bytes32 hash, - address signer, + address signerAddress, bytes memory signature ) public @@ -138,7 +147,7 @@ contract MixinSignatureValidator is r = readBytes32(signature, 1); s = readBytes32(signature, 33); recovered = ecrecover(hash, v, r, s); - isValid = signer == recovered; + isValid = signerAddress == recovered; return isValid; // Signed using web3.eth_sign @@ -156,7 +165,7 @@ contract MixinSignatureValidator is r, s ); - isValid = signer == recovered; + isValid = signerAddress == recovered; return isValid; // Implicitly signed by caller. @@ -172,13 +181,13 @@ contract MixinSignatureValidator is signature.length == 0, LENGTH_0_REQUIRED ); - isValid = signer == msg.sender; + isValid = signerAddress == msg.sender; return isValid; // Signature verified by wallet contract. // If used with an order, the maker of the order is the wallet contract. } else if (signatureType == SignatureType.Wallet) { - isValid = IWallet(signer).isValidSignature(hash, signature); + isValid = IWallet(signerAddress).isValidSignature(hash, signature); return isValid; // Signature verified by validator contract. @@ -190,21 +199,21 @@ 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 validator = popLast20Bytes(signature); + address validatorAddress = popLast20Bytes(signature); // Ensure signer has approved validator. - if (!allowedValidators[signer][validator]) { + if (!allowedValidators[signerAddress][validatorAddress]) { return false; } - isValid = IValidator(validator).isValidSignature( + isValid = IValidator(validatorAddress).isValidSignature( hash, - signer, + signerAddress, signature ); return isValid; // Signer signed hash previously using the preSign function. } else if (signatureType == SignatureType.PreSigned) { - isValid = preSigned[hash][signer]; + isValid = preSigned[hash][signerAddress]; return isValid; // Signature from Trezor hardware wallet. @@ -229,9 +238,8 @@ contract MixinSignatureValidator is r, s ); - isValid = signer == recovered; + isValid = signerAddress == recovered; return isValid; - } // Anything else is illegal (We do not return false because diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index f1332363c..d3d22d48f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -41,17 +41,17 @@ contract MixinTransactions is bytes32 constant EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked( "ZeroExTransaction(", "uint256 salt,", - "address signer,", + "address signerAddress,", "bytes data", ")" )); /// @dev Calculates EIP712 hash of the Transaction. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. - /// @param signer Address of transaction signer. + /// @param signerAddress Address of transaction signer. /// @param data AbiV2 encoded calldata. /// @return EIP712 hash of the Transaction. - function hashZeroExTransaction(uint256 salt, address signer, bytes data) + function hashZeroExTransaction(uint256 salt, address signerAddress, bytes data) internal pure returns (bytes32) @@ -59,19 +59,19 @@ contract MixinTransactions is return keccak256(abi.encode( EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, salt, - signer, + signerAddress, keccak256(data) )); } /// @dev Executes an exchange method call in the context of signer. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. - /// @param signer Address of transaction signer. + /// @param signerAddress Address of transaction signer. /// @param data AbiV2 encoded calldata. /// @param signature Proof of signer transaction by signer. function executeTransaction( uint256 salt, - address signer, + address signerAddress, bytes data, bytes signature ) @@ -83,7 +83,11 @@ contract MixinTransactions is REENTRANCY_ILLEGAL ); - bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction(salt, signer, data)); + bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction( + salt, + signerAddress, + data + )); // Validate transaction has not been executed require( @@ -92,15 +96,19 @@ contract MixinTransactions is ); // Transaction always valid if signer is sender of transaction - if (signer != msg.sender) { + if (signerAddress != msg.sender) { // Validate signature require( - isValidSignature(transactionHash, signer, signature), + isValidSignature( + transactionHash, + signerAddress, + signature + ), INVALID_TX_SIGNATURE ); // Set the current transaction signer - currentContextAddress = signer; + currentContextAddress = signerAddress; } // Execute transaction diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol index 02aa9776e..511463309 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol @@ -22,32 +22,32 @@ contract ISignatureValidator { /// @dev Approves a hash on-chain using any valid signature type. /// After presigning a hash, the preSign signature type will become valid for that hash and signer. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof that the hash has been signed by signer. function preSign( bytes32 hash, - address signer, + address signerAddress, bytes signature ) external; /// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf. - /// @param validator Address of Validator contract. + /// @param validatorAddress Address of Validator contract. /// @param approval Approval or disapproval of Validator contract. function setSignatureValidatorApproval( - address validator, + address validatorAddress, bool approval ) external; /// @dev Verifies that a signature is valid. /// @param hash Message hash that is signed. - /// @param signer Address of signer. + /// @param signerAddress Address of signer. /// @param signature Proof of signing. /// @return Validity of order signature. function isValidSignature( bytes32 hash, - address signer, + address signerAddress, bytes memory signature ) public diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol index 2f9a5bc7c..a7cab8f55 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol @@ -21,12 +21,12 @@ contract ITransactions { /// @dev Executes an exchange method call in the context of signer. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. - /// @param signer Address of transaction signer. + /// @param signerAddress Address of transaction signer. /// @param data AbiV2 encoded calldata. /// @param signature Proof of signer transaction by signer. function executeTransaction( uint256 salt, - address signer, + address signerAddress, bytes data, bytes signature ) diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IValidator.sol index 3e5ccc190..0b1796a66 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IValidator.sol @@ -22,12 +22,12 @@ contract IValidator { /// @dev Verifies that a signature is valid. /// @param hash Message hash that is signed. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof of signing. /// @return Validity of order signature. function isValidSignature( bytes32 hash, - address signer, + address signerAddress, bytes signature ) external diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol index d16a830f4..788f42c60 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol @@ -27,9 +27,9 @@ contract MAssetProxyDispatcher is // Logs registration of new asset proxy event AssetProxySet( - uint8 id, - address newAssetProxy, - address oldAssetProxy + uint8 id, // Id of new registered AssetProxy. + address newAssetProxy, // Address of new registered AssetProxy. + address oldAssetProxy // Address of AssetProxy that was overwritten at given id (or null address). ); /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index b0dbceff6..6e406e1c4 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -36,7 +36,7 @@ contract MExchangeCore is uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker. uint256 makerFeePaid, // Amount of ZRX paid to feeRecipient by maker. uint256 takerFeePaid, // Amount of ZRX paid to feeRecipient by taker. - bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash) + bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash). bytes makerAssetData, // Encoded data specific to makerAsset. bytes takerAssetData // Encoded data specific to takerAsset. ); @@ -46,7 +46,7 @@ contract MExchangeCore is address indexed makerAddress, // Address that created the order. address indexed feeRecipientAddress, // Address that would have recieved fees if order was filled. address senderAddress, // Address that called the Exchange contract (msg.sender). - bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash) + bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash). bytes makerAssetData, // Encoded data specific to makerAsset. bytes takerAssetData // Encoded data specific to takerAsset. ); diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol index 9c6fbe22b..6cc1d7a10 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -23,17 +23,23 @@ import "../interfaces/ISignatureValidator.sol"; contract MSignatureValidator is ISignatureValidator { + event SignatureValidatorApproval( + address indexed signerAddress, // Address that approves or disapproves a contract to verify signatures. + address indexed validatorAddress, // Address of signature validator contract. + bool approved // Approval or disapproval of validator contract. + ); + // Allowed signature types. enum SignatureType { - Illegal, // 0x00, default value - Invalid, // 0x01 - EIP712, // 0x02 - EthSign, // 0x03 - Caller, // 0x04 - Wallet, // 0x05 - Validator, // 0x06 - PreSigned, // 0x07 - Trezor, // 0x08 - NSignatureTypes // 0x09, number of signature types. Always leave at end. + Illegal, // 0x00, default value + Invalid, // 0x01 + EIP712, // 0x02 + EthSign, // 0x03 + Caller, // 0x04 + Wallet, // 0x05 + Validator, // 0x06 + PreSigned, // 0x07 + Trezor, // 0x08 + NSignatureTypes // 0x09, number of signature types. Always leave at end. } } diff --git a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol index 13953b482..f9271bf7a 100644 --- a/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol +++ b/packages/contracts/src/contracts/current/test/TestValidator/TestValidator.sol @@ -35,18 +35,18 @@ contract TestValidator is /// @dev Verifies that a signature is valid. `signer` must match `VALID_SIGNER`. /// @param hash Message hash that is signed. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof of signing. /// @return Validity of signature. function isValidSignature( bytes32 hash, - address signer, + address signerAddress, bytes signature ) external view returns (bool isValid) { - return (signer == VALID_SIGNER); + return (signerAddress == VALID_SIGNER); } } diff --git a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol index 460c9ea42..d35815474 100644 --- a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol +++ b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol @@ -116,18 +116,18 @@ contract Whitelist is /// @dev Verifies signer is same as signer of current Ethereum transaction. /// NOTE: This function can currently be used to validate signatures coming from outside of this contract. /// Extra safety checks can be added for a production contract. - /// @param signer Address that should have signed the given hash. + /// @param signerAddress Address that should have signed the given hash. /// @param signature Proof of signing. /// @return Validity of order signature. function isValidSignature( bytes32 hash, - address signer, + address signerAddress, bytes signature ) external view returns (bool isValid) { - return signer == tx.origin; + return signerAddress == tx.origin; } } diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts index 4cc8f0b89..06eb70644 100644 --- a/packages/contracts/src/utils/exchange_wrapper.ts +++ b/packages/contracts/src/utils/exchange_wrapper.ts @@ -215,7 +215,7 @@ export class ExchangeWrapper { ): Promise { const txHash = await this._exchange.executeTransaction.sendTransactionAsync( signedTx.salt, - signedTx.signer, + signedTx.signerAddress, signedTx.data, signedTx.signature, { from }, diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index 19ef4e1bf..348c0715d 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -9,7 +9,7 @@ const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = { name: 'ZeroExTransaction', parameters: [ { name: 'salt', type: EIP712Types.Uint256 }, - { name: 'signer', type: EIP712Types.Address }, + { name: 'signerAddress', type: EIP712Types.Address }, { name: 'data', type: EIP712Types.Bytes }, ], }; @@ -25,10 +25,10 @@ export class TransactionFactory { } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { const salt = generatePseudoRandomSalt(); - const signer = `0x${this._signerBuff.toString('hex')}`; + const signerAddress = `0x${this._signerBuff.toString('hex')}`; const executeTransactionData = { salt, - signer, + signerAddress, data, }; const executeTransactionHashBuff = EIP712Utils.structHash( diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index a6d0c2a88..7a1f92afd 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -108,7 +108,7 @@ export enum ContractName { export interface SignedTransaction { exchangeAddress: string; salt: BigNumber; - signer: string; + signerAddress: string; data: string; signature: string; } -- cgit From 2d8e9eda56f1455d5d5de61924c9c061e64756f5 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 21 Jun 2018 15:16:26 -0700 Subject: Converted `hashZeroExTransaction` to assembly. Saves 1k gas --- .../protocol/Exchange/MixinTransactions.sol | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index d3d22d48f..86f7c7b72 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -51,17 +51,27 @@ contract MixinTransactions is /// @param signerAddress Address of transaction signer. /// @param data AbiV2 encoded calldata. /// @return EIP712 hash of the Transaction. - function hashZeroExTransaction(uint256 salt, address signerAddress, bytes data) + function hashZeroExTransaction( + uint256 salt, + address signerAddress, + bytes memory data + ) internal pure - returns (bytes32) + returns (bytes32 result) { - return keccak256(abi.encode( - EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, - salt, - signerAddress, - keccak256(data) - )); + bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH; + bytes32 dataHash = keccak256(data); + assembly { + let memPtr := mload(64) + mstore(memPtr, schemaHash) + mstore(add(memPtr, 32), salt) + mstore(add(memPtr, 64), signerAddress) + mstore(add(memPtr, 96), dataHash) + result := keccak256(memPtr, 128) + } + + return result; } /// @dev Executes an exchange method call in the context of signer. -- cgit From 607b44e01d16e38dd293c95f1f3d1fabfd7f6e2b Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 21 Jun 2018 14:26:34 -0700 Subject: Check that assetProxy exists before attempting transfer --- .../protocol/AssetProxy/MixinERC721Transfer.sol | 7 +++- .../Exchange/MixinAssetProxyDispatcher.sol | 23 ++++++++--- .../protocol/Exchange/libs/LibExchangeErrors.sol | 45 ++++++++++++---------- 3 files changed, 48 insertions(+), 27 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index 9dc9e6525..6e3156e8a 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -53,7 +53,12 @@ contract MixinERC721Transfer is bytes memory receiverData ) = decodeERC721AssetData(assetData); - ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); + ERC721Token(token).safeTransferFrom( + from, + to, + tokenId, + receiverData + ); } /// @dev Decodes ERC721 Asset data. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index 9e0246303..f85019012 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -47,7 +47,7 @@ contract MixinAssetProxyDispatcher is onlyOwner { // Ensure the existing asset proxy is not unintentionally overwritten - address currentAssetProxy = address(assetProxies[assetProxyId]); + address currentAssetProxy = assetProxies[assetProxyId]; require( oldAssetProxy == currentAssetProxy, ASSET_PROXY_MISMATCH @@ -66,7 +66,11 @@ contract MixinAssetProxyDispatcher is // Add asset proxy and log registration. assetProxies[assetProxyId] = assetProxy; - emit AssetProxySet(assetProxyId, newAssetProxy, oldAssetProxy); + emit AssetProxySet( + assetProxyId, + newAssetProxy, + oldAssetProxy + ); } /// @dev Gets an asset proxy. @@ -77,8 +81,7 @@ contract MixinAssetProxyDispatcher is view returns (address) { - address assetProxy = address(assetProxies[assetProxyId]); - return assetProxy; + return assetProxies[assetProxyId]; } /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws. @@ -100,8 +103,18 @@ contract MixinAssetProxyDispatcher is if (amount > 0) { // Lookup assetProxy IAssetProxy assetProxy = assetProxies[assetProxyId]; + // Ensure that assetProxy exists + require( + assetProxy != address(0), + ASSET_PROXY_DOES_NOT_EXIST + ); // transferFrom will either succeed or throw. - assetProxy.transferFrom(assetData, from, to, amount); + assetProxy.transferFrom( + assetData, + from, + to, + amount + ); } } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol index aab428e74..a43f0f927 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol @@ -20,42 +20,45 @@ pragma solidity ^0.4.24; contract LibExchangeErrors { /// Order validation errors /// - string constant ORDER_UNFILLABLE = "ORDER_UNFILLABLE"; // Order cannot be filled. - string constant INVALID_MAKER = "INVALID_MAKER"; // Invalid makerAddress. - string constant INVALID_TAKER = "INVALID_TAKER"; // Invalid takerAddress. - string constant INVALID_SENDER = "INVALID_SENDER"; // Invalid `msg.sender`. - string constant INVALID_ORDER_SIGNATURE = "INVALID_ORDER_SIGNATURE"; // Signature validation failed. + string constant ORDER_UNFILLABLE = "ORDER_UNFILLABLE"; // Order cannot be filled. + string constant INVALID_MAKER = "INVALID_MAKER"; // Invalid makerAddress. + string constant INVALID_TAKER = "INVALID_TAKER"; // Invalid takerAddress. + string constant INVALID_SENDER = "INVALID_SENDER"; // Invalid `msg.sender`. + string constant INVALID_ORDER_SIGNATURE = "INVALID_ORDER_SIGNATURE"; // Signature validation failed. /// fillOrder validation errors /// - string constant INVALID_TAKER_AMOUNT = "INVALID_TAKER_AMOUNT"; // takerAssetFillAmount cannot equal 0. - string constant ROUNDING_ERROR = "ROUNDING_ERROR"; // Rounding error greater than 0.1% of takerAssetFillAmount. + string constant INVALID_TAKER_AMOUNT = "INVALID_TAKER_AMOUNT"; // takerAssetFillAmount cannot equal 0. + string constant ROUNDING_ERROR = "ROUNDING_ERROR"; // Rounding error greater than 0.1% of takerAssetFillAmount. /// Signature validation errors /// - string constant INVALID_SIGNATURE = "INVALID_SIGNATURE"; // Signature validation failed. - string constant SIGNATURE_ILLEGAL = "SIGNATURE_ILLEGAL"; // Signature type is illegal. - string constant SIGNATURE_UNSUPPORTED = "SIGNATURE_UNSUPPORTED"; // Signature type unsupported. + string constant INVALID_SIGNATURE = "INVALID_SIGNATURE"; // Signature validation failed. + string constant SIGNATURE_ILLEGAL = "SIGNATURE_ILLEGAL"; // Signature type is illegal. + string constant SIGNATURE_UNSUPPORTED = "SIGNATURE_UNSUPPORTED"; // Signature type unsupported. /// cancelOrdersUptTo errors /// - string constant INVALID_NEW_ORDER_EPOCH = "INVALID_NEW_ORDER_EPOCH"; // Specified salt must be greater than or equal to existing orderEpoch. + string constant INVALID_NEW_ORDER_EPOCH = "INVALID_NEW_ORDER_EPOCH"; // Specified salt must be greater than or equal to existing orderEpoch. /// fillOrKillOrder errors /// - string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired takerAssetFillAmount could not be completely filled. + string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired takerAssetFillAmount could not be completely filled. /// matchOrders errors /// - string constant NEGATIVE_SPREAD_REQUIRED = "NEGATIVE_SPREAD_REQUIRED"; // Matched orders must have a negative spread. + string constant NEGATIVE_SPREAD_REQUIRED = "NEGATIVE_SPREAD_REQUIRED"; // Matched orders must have a negative spread. /// Transaction errors /// - string constant REENTRANCY_ILLEGAL = "REENTRANCY_ILLEGAL"; // Recursive reentrancy is not allowed. - string constant INVALID_TX_HASH = "INVALID_TX_HASH"; // Transaction has already been executed. - string constant INVALID_TX_SIGNATURE = "INVALID_TX_SIGNATURE"; // Signature validation failed. - string constant FAILED_EXECUTION = "FAILED_EXECUTION"; // Transaction execution failed. + string constant REENTRANCY_ILLEGAL = "REENTRANCY_ILLEGAL"; // Recursive reentrancy is not allowed. + string constant INVALID_TX_HASH = "INVALID_TX_HASH"; // Transaction has already been executed. + string constant INVALID_TX_SIGNATURE = "INVALID_TX_SIGNATURE"; // Signature validation failed. + string constant FAILED_EXECUTION = "FAILED_EXECUTION"; // Transaction execution failed. /// registerAssetProxy errors /// - string constant ASSET_PROXY_MISMATCH = "ASSET_PROXY_MISMATCH"; // oldAssetProxy proxy does not match currentAssetProxy. - string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // newAssetProxyId does not match given assetProxyId. + string constant ASSET_PROXY_MISMATCH = "ASSET_PROXY_MISMATCH"; // oldAssetProxy proxy does not match currentAssetProxy. + string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // newAssetProxyId does not match given assetProxyId. + + /// dispatchTransferFrom errors /// + string constant ASSET_PROXY_DOES_NOT_EXIST = "ASSET_PROXY_DOES_NOT_EXIST"; // No assetProxy registered at given id. /// Length validation errors /// string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. - string constant LENGTH_0_REQUIRED = "LENGTH_0_REQUIRED"; // Byte array must have a length of 0. - string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; // Byte array must have a length of 65. + string constant LENGTH_0_REQUIRED = "LENGTH_0_REQUIRED"; // Byte array must have a length of 0. + string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; // Byte array must have a length of 65. } -- cgit From 7fcd34eb3656a49eaac684ee3cb1b7d55d9e15e6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 22 Jun 2018 16:35:50 -0700 Subject: Apply mask to address to zero-out unused bytes. --- .../src/contracts/current/protocol/Exchange/MixinTransactions.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 86f7c7b72..20a4a12df 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -66,7 +66,7 @@ contract MixinTransactions is let memPtr := mload(64) mstore(memPtr, schemaHash) mstore(add(memPtr, 32), salt) - mstore(add(memPtr, 64), signerAddress) + mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(memPtr, 96), dataHash) result := keccak256(memPtr, 128) } -- cgit From 7f84049538af09e7596623158e1364a68bb17a35 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:36:35 +0200 Subject: Merge LibMem and LibBytes --- .../current/test/TestLibBytes/TestLibBytes.sol | 30 +++++ .../current/test/TestLibMem/TestLibMem.sol | 56 -------- .../contracts/current/utils/LibBytes/LibBytes.sol | 125 +++++++++++++++++- .../src/contracts/current/utils/LibMem/LibMem.sol | 142 --------------------- packages/contracts/src/utils/artifacts.ts | 2 - packages/contracts/src/utils/types.ts | 1 - 6 files changed, 150 insertions(+), 206 deletions(-) delete mode 100644 packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol delete mode 100644 packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 6f1898acd..d9b246b29 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -221,4 +221,34 @@ contract TestLibBytes is writeBytes(b, index, input); return b; } + + /// @dev Copies a block of memory from one location to another. + /// @param mem Memory contents we want to apply memCopy to + /// @param dest Destination offset into . + /// @param source Source offset into . + /// @param length Length of bytes to copy from to + /// @return mem Memory contents after calling memCopy. + function testMemcpy( + bytes mem, + uint256 dest, + uint256 source, + uint256 length + ) + public // not external, we need input in memory + pure + returns (bytes) + { + // Sanity check. Overflows are not checked. + require(source + length <= mem.length); + require(dest + length <= mem.length); + + // Get pointer to memory contents + uint256 offset = getMemAddress(mem) + 32; + + // Execute memCopy adjusted for memory array location + memCopy(offset + dest, offset + source, length); + + // Return modified memory contents + return mem; + } } diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol deleted file mode 100644 index b7e2e06b8..000000000 --- a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol +++ /dev/null @@ -1,56 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; - -import "../../utils/LibMem/LibMem.sol"; - -contract TestLibMem is - LibMem -{ - - /// @dev Copies a block of memory from one location to another. - /// @param mem Memory contents we want to apply memCopy to - /// @param dest Destination offset into . - /// @param source Source offset into . - /// @param length Length of bytes to copy from to - /// @return mem Memory contents after calling memCopy. - function testMemcpy( - bytes mem, - uint256 dest, - uint256 source, - uint256 length - ) - public // not external, we need input in memory - pure - returns (bytes) - { - // Sanity check. Overflows are not checked. - require(source + length <= mem.length); - require(dest + length <= mem.length); - - // Get pointer to memory contents - uint256 offset = getMemAddress(mem) + 32; - - // Execute memCopy adjusted for memory array location - memCopy(offset + dest, offset + source, length); - - // Return modified memory contents - return mem; - } -} diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 10d7ce41a..cb63e38e6 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -18,11 +18,7 @@ pragma solidity ^0.4.24; -import "../LibMem/LibMem.sol"; - -contract LibBytes is - LibMem -{ +contract LibBytes { // Revert reasons string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED"; @@ -32,6 +28,125 @@ contract LibBytes is string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED"; + /// @dev Gets the memory address for a byte array. + /// @param input Byte array to lookup. + /// @return memoryAddress Memory address of byte array. + function getMemAddress(bytes memory input) + internal + pure + returns (uint256 memoryAddress) + { + assembly { + memoryAddress := input + } + return memoryAddress; + } + + /// @dev Copies `length` bytes from memory location `source` to `dest`. + /// @param dest memory address to copy bytes to. + /// @param source memory address to copy bytes from. + /// @param length number of bytes to copy. + function memCopy( + uint256 dest, + uint256 source, + uint256 length + ) + internal + pure + { + if (length < 32) { + // Handle a partial word by reading destination and masking + // off the bits we are interested in. + // This correctly handles overlap, zero lengths and source == dest + assembly { + let mask := sub(exp(256, sub(32, length)), 1) + let s := and(mload(source), not(mask)) + let d := and(mload(dest), mask) + mstore(dest, or(s, d)) + } + } else { + // Skip the O(length) loop when source == dest. + if (source == dest) { + return; + } + + // For large copies we copy whole words at a time. The final + // word is aligned to the end of the range (instead of after the + // previous) to handle partial words. So a copy will look like this: + // + // #### + // #### + // #### + // #### + // + // We handle overlap in the source and destination range by + // changing the copying direction. This prevents us from + // overwriting parts of source that we still need to copy. + // + // This correctly handles source == dest + // + if (source > dest) { + assembly { + // We subtract 32 from `sEnd` and `dEnd` because it + // is easier to compare with in the loop, and these + // are also the addresses we need for copying the + // last bytes. + length := sub(length, 32) + let sEnd := add(source, length) + let dEnd := add(dest, length) + + // Remember the last 32 bytes of source + // This needs to be done here and not after the loop + // because we may have overwritten the last bytes in + // source already due to overlap. + let last := mload(sEnd) + + // Copy whole words front to back + // Note: the first check is always true, + // this could have been a do-while loop. + for {} lt(source, sEnd) {} { + mstore(dest, mload(source)) + source := add(source, 32) + dest := add(dest, 32) + } + + // Write the last 32 bytes + mstore(dEnd, last) + } + } else { + assembly { + // We subtract 32 from `sEnd` and `dEnd` because those + // are the starting points when copying a word at the end. + length := sub(length, 32) + let sEnd := add(source, length) + let dEnd := add(dest, length) + + // Remember the first 32 bytes of source + // This needs to be done here and not after the loop + // because we may have overwritten the first bytes in + // source already due to overlap. + let first := mload(source) + + // Copy whole words back to front + // We use a signed comparisson here to allow dEnd to become + // negative (happens when source and dest < 32). Valid + // addresses in local memory will never be larger than + // 2**255, so they can be safely re-interpreted as signed. + // Note: the first check is always true, + // this could have been a do-while loop. + for {} slt(dest, dEnd) {} { + mstore(dEnd, mload(sEnd)) + sEnd := sub(sEnd, 32) + dEnd := sub(dEnd, 32) + } + + // Write the first 32 bytes + mstore(dest, first) + } + } + } + } + /// @dev Pops the last byte off of a byte array by modifying its length. /// @param b Byte array that will be modified. /// @return The byte that was popped off. diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol deleted file mode 100644 index 97fb5fb0f..000000000 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ /dev/null @@ -1,142 +0,0 @@ -/* - - Copyright 2018 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.4.24; - -contract LibMem -{ - - /// @dev Gets the memory address for a byte array. - /// @param input Byte array to lookup. - /// @return memoryAddress Memory address of byte array. - function getMemAddress(bytes memory input) - internal - pure - returns (uint256 memoryAddress) - { - assembly { - memoryAddress := input - } - return memoryAddress; - } - - /// @dev Copies `length` bytes from memory location `source` to `dest`. - /// @param dest memory address to copy bytes to. - /// @param source memory address to copy bytes from. - /// @param length number of bytes to copy. - function memCopy( - uint256 dest, - uint256 source, - uint256 length - ) - internal - pure - { - if (length < 32) { - // Handle a partial word by reading destination and masking - // off the bits we are interested in. - // This correctly handles overlap, zero lengths and source == dest - assembly { - let mask := sub(exp(256, sub(32, length)), 1) - let s := and(mload(source), not(mask)) - let d := and(mload(dest), mask) - mstore(dest, or(s, d)) - } - } else { - // Skip the O(length) loop when source == dest. - if (source == dest) { - return; - } - - // For large copies we copy whole words at a time. The final - // word is aligned to the end of the range (instead of after the - // previous) to handle partial words. So a copy will look like this: - // - // #### - // #### - // #### - // #### - // - // We handle overlap in the source and destination range by - // changing the copying direction. This prevents us from - // overwriting parts of source that we still need to copy. - // - // This correctly handles source == dest - // - if (source > dest) { - assembly { - // We subtract 32 from `sEnd` and `dEnd` because it - // is easier to compare with in the loop, and these - // are also the addresses we need for copying the - // last bytes. - length := sub(length, 32) - let sEnd := add(source, length) - let dEnd := add(dest, length) - - // Remember the last 32 bytes of source - // This needs to be done here and not after the loop - // because we may have overwritten the last bytes in - // source already due to overlap. - let last := mload(sEnd) - - // Copy whole words front to back - // Note: the first check is always true, - // this could have been a do-while loop. - for {} lt(source, sEnd) {} { - mstore(dest, mload(source)) - source := add(source, 32) - dest := add(dest, 32) - } - - // Write the last 32 bytes - mstore(dEnd, last) - } - } else { - assembly { - // We subtract 32 from `sEnd` and `dEnd` because those - // are the starting points when copying a word at the end. - length := sub(length, 32) - let sEnd := add(source, length) - let dEnd := add(dest, length) - - // Remember the first 32 bytes of source - // This needs to be done here and not after the loop - // because we may have overwritten the first bytes in - // source already due to overlap. - let first := mload(source) - - // Copy whole words back to front - // We use a signed comparisson here to allow dEnd to become - // negative (happens when source and dest < 32). Valid - // addresses in local memory will never be larger than - // 2**255, so they can be safely re-interpreted as signed. - // Note: the first check is always true, - // this could have been a do-while loop. - for {} slt(dest, dEnd) {} { - mstore(dEnd, mload(sEnd)) - sEnd := sub(sEnd, 32) - dEnd := sub(dEnd, 32) - } - - // Write the first 32 bytes - mstore(dest, first) - } - } - } - } -} diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index 4375d87c6..fa18cc9d2 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -14,7 +14,6 @@ import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTime import * as TestAssetDataDecoders from '../artifacts/TestAssetDataDecoders.json'; import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; -import * as TestLibMem from '../artifacts/TestLibMem.json'; import * as TestLibs from '../artifacts/TestLibs.json'; import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json'; import * as TestValidator from '../artifacts/TestValidator.json'; @@ -40,7 +39,6 @@ export const artifacts = { TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact, TestAssetDataDecoders: (TestAssetDataDecoders as any) as ContractArtifact, TestLibBytes: (TestLibBytes as any) as ContractArtifact, - TestLibMem: (TestLibMem as any) as ContractArtifact, TestLibs: (TestLibs as any) as ContractArtifact, TestSignatureValidator: (TestSignatureValidator as any) as ContractArtifact, TestValidator: (TestValidator as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts index 7a1f92afd..5dfac64fc 100644 --- a/packages/contracts/src/utils/types.ts +++ b/packages/contracts/src/utils/types.ts @@ -92,7 +92,6 @@ export enum ContractName { Arbitrage = 'Arbitrage', TestAssetDataDecoders = 'TestAssetDataDecoders', TestAssetProxyDispatcher = 'TestAssetProxyDispatcher', - TestLibMem = 'TestLibMem', TestLibs = 'TestLibs', TestSignatureValidator = 'TestSignatureValidator', ERC20Proxy = 'ERC20Proxy', -- cgit From afd83e59b8bf2b755e589562ab12b300aaf12601 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:53:22 +0200 Subject: Make LibBytes a library --- .../protocol/AssetProxy/MixinERC20Transfer.sol | 3 +- .../protocol/AssetProxy/MixinERC721Transfer.sol | 7 ++--- .../protocol/AssetProxyOwner/AssetProxyOwner.sol | 3 +- .../protocol/Exchange/MixinSignatureValidator.sol | 18 ++++++------ .../current/test/TestLibBytes/TestLibBytes.sol | 32 ++++++++++------------ .../contracts/current/utils/LibBytes/LibBytes.sol | 2 +- 6 files changed, 30 insertions(+), 35 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol index 4af39a00b..34da13fcc 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol @@ -24,7 +24,6 @@ import "../../tokens/ERC20Token/IERC20Token.sol"; import "./libs/LibTransferErrors.sol"; contract MixinERC20Transfer is - LibBytes, LibTransferErrors { /// @dev Internal version of `transferFrom`. @@ -41,7 +40,7 @@ contract MixinERC20Transfer is internal { // Decode asset data. - address token = readAddress(assetData, 0); + address token = LibBytes.readAddress(assetData, 0); // Transfer tokens. // We do a raw call so we can check the success separate diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index 6e3156e8a..028f4ed8a 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -24,7 +24,6 @@ import "../../tokens/ERC721Token/ERC721Token.sol"; import "./libs/LibTransferErrors.sol"; contract MixinERC721Transfer is - LibBytes, LibTransferErrors { /// @dev Internal version of `transferFrom`. @@ -78,10 +77,10 @@ contract MixinERC721Transfer is ) { // Decode asset data. - token = readAddress(assetData, 0); - tokenId = readUint256(assetData, 20); + token = LibBytes.readAddress(assetData, 0); + tokenId = LibBytes.readUint256(assetData, 20); if (assetData.length > 52) { - receiverData = readBytes(assetData, 52); + receiverData = LibBytes.readBytes(assetData, 52); } return ( diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol index 7f5f056b5..4d5e5f786 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -22,7 +22,6 @@ import "../../multisig/MultiSigWalletWithTimeLock.sol"; import "../../utils/LibBytes/LibBytes.sol"; contract AssetProxyOwner is - LibBytes, MultiSigWalletWithTimeLock { @@ -104,7 +103,7 @@ contract AssetProxyOwner is pure returns (bool) { - bytes4 first4Bytes = readFirst4(data); + bytes4 first4Bytes = LibBytes.readFirst4(data); require(REMOVE_AUTHORIZED_ADDRESS_SELECTOR == first4Bytes); return true; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 881d6e7b3..4a6bb5de5 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -26,7 +26,6 @@ import "./interfaces/IWallet.sol"; import "./interfaces/IValidator.sol"; contract MixinSignatureValidator is - LibBytes, LibExchangeErrors, MSignatureValidator, MTransactions @@ -102,7 +101,7 @@ contract MixinSignatureValidator is ); // Ensure signature is supported - uint8 signatureTypeRaw = uint8(popLastByte(signature)); + uint8 signatureTypeRaw = uint8(LibBytes.popLastByte(signature)); require( signatureTypeRaw < uint8(SignatureType.NSignatureTypes), SIGNATURE_UNSUPPORTED @@ -144,8 +143,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = readBytes32(signature, 1); - s = readBytes32(signature, 33); + r = LibBytes.readBytes32(signature, 1); + s = LibBytes.readBytes32(signature, 33); recovered = ecrecover(hash, v, r, s); isValid = signerAddress == recovered; return isValid; @@ -157,8 +156,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = readBytes32(signature, 1); - s = readBytes32(signature, 33); + r = LibBytes.readBytes32(signature, 1); + s = LibBytes.readBytes32(signature, 33); recovered = ecrecover( keccak256(abi.encodePacked(ETH_PERSONAL_MESSAGE, hash)), v, @@ -199,7 +198,8 @@ 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 = popLast20Bytes(signature); + address validatorAddress = LibBytes.popLast20Bytes(signature); + // Ensure signer has approved validator. if (!allowedValidators[signerAddress][validatorAddress]) { return false; @@ -230,8 +230,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = readBytes32(signature, 1); - s = readBytes32(signature, 33); + r = LibBytes.readBytes32(signature, 1); + s = LibBytes.readBytes32(signature, 33); recovered = ecrecover( keccak256(abi.encodePacked(TREZOR_PERSONAL_MESSAGE, hash)), v, diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index d9b246b29..fc9d1e5c4 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -21,9 +21,7 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; -contract TestLibBytes is - LibBytes -{ +contract TestLibBytes { /// @dev Pops the last byte off of a byte array by modifying its length. /// @param b Byte array that will be modified. @@ -33,7 +31,7 @@ contract TestLibBytes is pure returns (bytes memory, bytes1 result) { - result = popLastByte(b); + result = LibBytes.popLastByte(b); return (b, result); } @@ -45,7 +43,7 @@ contract TestLibBytes is pure returns (bytes memory, address result) { - result = popLast20Bytes(b); + result = LibBytes.popLast20Bytes(b); return (b, result); } @@ -58,7 +56,7 @@ contract TestLibBytes is pure returns (bool equal) { - equal = areBytesEqual(lhs, rhs); + equal = LibBytes.areBytesEqual(lhs, rhs); return equal; } @@ -89,7 +87,7 @@ contract TestLibBytes is pure returns (address result) { - result = readAddress(b, index); + result = LibBytes.readAddress(b, index); return result; } @@ -106,7 +104,7 @@ contract TestLibBytes is pure returns (bytes memory) { - writeAddress(b, index, input); + LibBytes.writeAddress(b, index, input); return b; } @@ -122,7 +120,7 @@ contract TestLibBytes is pure returns (bytes32 result) { - result = readBytes32(b, index); + result = LibBytes.readBytes32(b, index); return result; } @@ -139,7 +137,7 @@ contract TestLibBytes is pure returns (bytes memory) { - writeBytes32(b, index, input); + LibBytes.writeBytes32(b, index, input); return b; } @@ -155,7 +153,7 @@ contract TestLibBytes is pure returns (uint256 result) { - result = readUint256(b, index); + result = LibBytes.readUint256(b, index); return result; } @@ -172,7 +170,7 @@ contract TestLibBytes is pure returns (bytes memory) { - writeUint256(b, index, input); + LibBytes.writeUint256(b, index, input); return b; } @@ -184,7 +182,7 @@ contract TestLibBytes is pure returns (bytes4 result) { - result = readFirst4(b); + result = LibBytes.readFirst4(b); return result; } @@ -200,7 +198,7 @@ contract TestLibBytes is pure returns (bytes memory result) { - result = readBytes(b, index); + result = LibBytes.readBytes(b, index); return result; } @@ -218,7 +216,7 @@ contract TestLibBytes is pure returns (bytes memory) { - writeBytes(b, index, input); + LibBytes.writeBytes(b, index, input); return b; } @@ -243,10 +241,10 @@ contract TestLibBytes is require(dest + length <= mem.length); // Get pointer to memory contents - uint256 offset = getMemAddress(mem) + 32; + uint256 offset = LibBytes.getMemAddress(mem) + 32; // Execute memCopy adjusted for memory array location - memCopy(offset + dest, offset + source, length); + LibBytes.memCopy(offset + dest, offset + source, length); // Return modified memory contents return mem; diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index cb63e38e6..05cf53df5 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -18,7 +18,7 @@ pragma solidity ^0.4.24; -contract LibBytes { +library LibBytes { // Revert reasons string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED"; -- cgit From 2ea0b839d3f704ea85c992912b86db0cb49f80ea Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 12:02:32 +0200 Subject: Using LibBytes for bytes --- .../protocol/AssetProxy/MixinERC20Transfer.sol | 4 +++- .../protocol/AssetProxy/MixinERC721Transfer.sol | 8 ++++--- .../protocol/AssetProxyOwner/AssetProxyOwner.sol | 3 ++- .../protocol/Exchange/MixinSignatureValidator.sol | 19 ++++++++------- .../protocol/Exchange/MixinWrapperFunctions.sol | 2 ++ .../current/test/TestLibBytes/TestLibBytes.sol | 28 ++++++++++++---------- 6 files changed, 38 insertions(+), 26 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol index 34da13fcc..0e7f3fc89 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol @@ -26,6 +26,8 @@ import "./libs/LibTransferErrors.sol"; contract MixinERC20Transfer is LibTransferErrors { + using LibBytes for bytes; + /// @dev Internal version of `transferFrom`. /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. @@ -40,7 +42,7 @@ contract MixinERC20Transfer is internal { // Decode asset data. - address token = LibBytes.readAddress(assetData, 0); + address token = assetData.readAddress(0); // Transfer tokens. // We do a raw call so we can check the success separate diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index 028f4ed8a..2df9725b4 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -26,6 +26,8 @@ import "./libs/LibTransferErrors.sol"; contract MixinERC721Transfer is LibTransferErrors { + using LibBytes for bytes; + /// @dev Internal version of `transferFrom`. /// @param assetData Encoded byte array. /// @param from Address to transfer asset from. @@ -77,10 +79,10 @@ contract MixinERC721Transfer is ) { // Decode asset data. - token = LibBytes.readAddress(assetData, 0); - tokenId = LibBytes.readUint256(assetData, 20); + token = assetData.readAddress(0); + tokenId = assetData.readUint256(20); if (assetData.length > 52) { - receiverData = LibBytes.readBytes(assetData, 52); + receiverData = assetData.readBytes(52); } return ( diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol index 4d5e5f786..261ce8f34 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -24,6 +24,7 @@ import "../../utils/LibBytes/LibBytes.sol"; contract AssetProxyOwner is MultiSigWalletWithTimeLock { + using LibBytes for bytes; event AssetProxyRegistration(address assetProxyContract, bool isRegistered); @@ -103,7 +104,7 @@ contract AssetProxyOwner is pure returns (bool) { - bytes4 first4Bytes = LibBytes.readFirst4(data); + bytes4 first4Bytes = data.readFirst4(); require(REMOVE_AUTHORIZED_ADDRESS_SELECTOR == first4Bytes); return true; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 4a6bb5de5..cbb55bfce 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -30,6 +30,8 @@ contract MixinSignatureValidator is MSignatureValidator, MTransactions { + using LibBytes for bytes; + // Personal message headers string constant ETH_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n32"; string constant TREZOR_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n\x20"; @@ -101,7 +103,7 @@ contract MixinSignatureValidator is ); // Ensure signature is supported - uint8 signatureTypeRaw = uint8(LibBytes.popLastByte(signature)); + uint8 signatureTypeRaw = uint8(signature.popLastByte()); require( signatureTypeRaw < uint8(SignatureType.NSignatureTypes), SIGNATURE_UNSUPPORTED @@ -143,8 +145,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = LibBytes.readBytes32(signature, 1); - s = LibBytes.readBytes32(signature, 33); + r = signature.readBytes32(1); + s = signature.readBytes32(33); recovered = ecrecover(hash, v, r, s); isValid = signerAddress == recovered; return isValid; @@ -156,8 +158,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = LibBytes.readBytes32(signature, 1); - s = LibBytes.readBytes32(signature, 33); + r = signature.readBytes32(1); + s = signature.readBytes32(33); recovered = ecrecover( keccak256(abi.encodePacked(ETH_PERSONAL_MESSAGE, hash)), v, @@ -198,7 +200,8 @@ 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 = LibBytes.popLast20Bytes(signature); + + address validatorAddress = signature.popLast20Bytes(); // Ensure signer has approved validator. if (!allowedValidators[signerAddress][validatorAddress]) { @@ -230,8 +233,8 @@ contract MixinSignatureValidator is LENGTH_65_REQUIRED ); v = uint8(signature[0]); - r = LibBytes.readBytes32(signature, 1); - s = LibBytes.readBytes32(signature, 33); + r = signature.readBytes32(1); + s = signature.readBytes32(33); recovered = ecrecover( keccak256(abi.encodePacked(TREZOR_PERSONAL_MESSAGE, hash)), v, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 724f95518..87375d4bf 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -31,6 +31,8 @@ contract MixinWrapperFunctions is LibExchangeErrors, MExchangeCore { + using LibBytes for bytes; + /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. /// @param order Order struct containing order specifications. /// @param takerAssetFillAmount Desired amount of takerAsset to sell. diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index fc9d1e5c4..96020906c 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -22,6 +22,8 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; contract TestLibBytes { + + using LibBytes for bytes; /// @dev Pops the last byte off of a byte array by modifying its length. /// @param b Byte array that will be modified. @@ -31,7 +33,7 @@ contract TestLibBytes { pure returns (bytes memory, bytes1 result) { - result = LibBytes.popLastByte(b); + result = b.popLastByte(); return (b, result); } @@ -43,7 +45,7 @@ contract TestLibBytes { pure returns (bytes memory, address result) { - result = LibBytes.popLast20Bytes(b); + result = b.popLast20Bytes(); return (b, result); } @@ -56,7 +58,7 @@ contract TestLibBytes { pure returns (bool equal) { - equal = LibBytes.areBytesEqual(lhs, rhs); + equal = lhs.areBytesEqual(rhs); return equal; } @@ -87,7 +89,7 @@ contract TestLibBytes { pure returns (address result) { - result = LibBytes.readAddress(b, index); + result = b.readAddress(index); return result; } @@ -104,7 +106,7 @@ contract TestLibBytes { pure returns (bytes memory) { - LibBytes.writeAddress(b, index, input); + b.writeAddress(index, input); return b; } @@ -120,7 +122,7 @@ contract TestLibBytes { pure returns (bytes32 result) { - result = LibBytes.readBytes32(b, index); + result = b.readBytes32(index); return result; } @@ -137,7 +139,7 @@ contract TestLibBytes { pure returns (bytes memory) { - LibBytes.writeBytes32(b, index, input); + b.writeBytes32(index, input); return b; } @@ -153,7 +155,7 @@ contract TestLibBytes { pure returns (uint256 result) { - result = LibBytes.readUint256(b, index); + result = b.readUint256(index); return result; } @@ -170,7 +172,7 @@ contract TestLibBytes { pure returns (bytes memory) { - LibBytes.writeUint256(b, index, input); + b.writeUint256(index, input); return b; } @@ -182,7 +184,7 @@ contract TestLibBytes { pure returns (bytes4 result) { - result = LibBytes.readFirst4(b); + result = b.readFirst4(); return result; } @@ -198,7 +200,7 @@ contract TestLibBytes { pure returns (bytes memory result) { - result = LibBytes.readBytes(b, index); + result = b.readBytes(index); return result; } @@ -216,7 +218,7 @@ contract TestLibBytes { pure returns (bytes memory) { - LibBytes.writeBytes(b, index, input); + b.writeBytes(index, input); return b; } @@ -241,7 +243,7 @@ contract TestLibBytes { require(dest + length <= mem.length); // Get pointer to memory contents - uint256 offset = LibBytes.getMemAddress(mem) + 32; + uint256 offset = mem.getMemAddress() + 32; // Execute memCopy adjusted for memory array location LibBytes.memCopy(offset + dest, offset + source, length); -- cgit From 88982f98ff2ece93831b1442d2c4e1ef0878d919 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 17:13:59 +0200 Subject: Rename read/writeBytesWithLength --- .../contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol | 2 +- .../src/contracts/current/test/TestLibBytes/TestLibBytes.sol | 8 ++++---- .../contracts/src/contracts/current/utils/LibBytes/LibBytes.sol | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index 2df9725b4..944068bbb 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -82,7 +82,7 @@ contract MixinERC721Transfer is token = assetData.readAddress(0); tokenId = assetData.readUint256(20); if (assetData.length > 52) { - receiverData = assetData.readBytes(52); + receiverData = assetData.readBytesWithLength(52); } return ( diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 96020906c..84b9e4673 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -192,7 +192,7 @@ contract TestLibBytes { /// @param b Byte array containing nested bytes. /// @param index Index of nested bytes. /// @return result Nested bytes. - function publicReadBytes( + function publicReadBytesWithLength( bytes memory b, uint256 index ) @@ -200,7 +200,7 @@ contract TestLibBytes { pure returns (bytes memory result) { - result = b.readBytes(index); + result = b.readBytesWithLength(index); return result; } @@ -209,7 +209,7 @@ contract TestLibBytes { /// @param index Index in byte array of . /// @param input bytes to insert. /// @return b Updated input byte array - function publicWriteBytes( + function publicWriteBytesWithLength( bytes memory b, uint256 index, bytes memory input @@ -218,7 +218,7 @@ contract TestLibBytes { pure returns (bytes memory) { - b.writeBytes(index, input); + b.writeBytesWithLength(index, input); return b; } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 05cf53df5..ad3a35aef 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -371,7 +371,7 @@ library LibBytes { /// @param b Byte array containing nested bytes. /// @param index Index of nested bytes. /// @return result Nested bytes. - function readBytes( + function readBytesWithLength( bytes memory b, uint256 index ) @@ -405,7 +405,7 @@ library LibBytes { /// @param b Byte array to insert into. /// @param index Index in byte array of . /// @param input bytes to insert. - function writeBytes( + function writeBytesWithLength( bytes memory b, uint256 index, bytes memory input -- cgit From 2054cd78da9c39e5572cd76bb9fff7a4cd581903 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 17:20:18 +0200 Subject: Rename bytes.rawAddress and add bytes.contentAddress --- .../current/test/TestLibBytes/TestLibBytes.sol | 2 +- .../contracts/current/utils/LibBytes/LibBytes.sol | 31 +++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 84b9e4673..299452c96 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -243,7 +243,7 @@ contract TestLibBytes { require(dest + length <= mem.length); // Get pointer to memory contents - uint256 offset = mem.getMemAddress() + 32; + uint256 offset = mem.contentAddress(); // Execute memCopy adjusted for memory array location LibBytes.memCopy(offset + dest, offset + source, length); diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index ad3a35aef..d824449a2 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -19,6 +19,7 @@ pragma solidity ^0.4.24; library LibBytes { + using LibBytes for bytes; // Revert reasons string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED"; @@ -30,8 +31,10 @@ library LibBytes { /// @dev Gets the memory address for a byte array. /// @param input Byte array to lookup. - /// @return memoryAddress Memory address of byte array. - function getMemAddress(bytes memory input) + /// @return memoryAddress Memory address of byte array. This + /// points to the header of the byte array which contains + /// the length. + function rawAddress(bytes memory input) internal pure returns (uint256 memoryAddress) @@ -41,6 +44,20 @@ library LibBytes { } return memoryAddress; } + + /// @dev Gets the memory address for the contents of a byte array. + /// @param input Byte array to lookup. + /// @return memoryAddress Memory address of the contents of the byte array. + function contentAddress(bytes memory input) + internal + pure + returns (uint256 memoryAddress) + { + assembly { + memoryAddress := add(input, 32) + } + return memoryAddress; + } /// @dev Copies `length` bytes from memory location `source` to `dest`. /// @param dest memory address to copy bytes to. @@ -393,8 +410,8 @@ library LibBytes { // Allocate memory and copy value to result result = new bytes(nestedBytesLength); memCopy( - getMemAddress(result) + 32, // +32 skips array length - getMemAddress(b) + index + 32, + result.contentAddress(), + b.contentAddress() + index, nestedBytesLength ); @@ -422,9 +439,9 @@ library LibBytes { // Copy into memCopy( - getMemAddress(b) + 32 + index, // +32 to skip length of - getMemAddress(input), // includes length of - input.length + 32 // +32 bytes to store length + b.contentAddress() + index, + input.rawAddress(), // includes length of + input.length + 32 // +32 bytes to store length ); } -- cgit From c83ee04662177407f1d484175d8a76dddf3c4e85 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 17:34:35 +0200 Subject: Add slice and sliceDestructive --- .../contracts/current/utils/LibBytes/LibBytes.sol | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index d824449a2..58ce31c70 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -28,6 +28,8 @@ library LibBytes { string constant GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED"; string constant GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED"; + string constant FROM_LESS_THAN_TO_REQUIRED = "FROM_LESS_THAN_TO_REQUIRED"; + string constant TO_LESS_THAN_LENGTH_REQUIRED = "TO_LESS_THAN_LENGTH_REQUIRED"; /// @dev Gets the memory address for a byte array. /// @param input Byte array to lookup. @@ -163,6 +165,50 @@ library LibBytes { } } } + + /// @dev Returns a slices from a byte array. + /// @param b The byte array to take a slice from. + /// @param from The starting index for the slice (inclusive). + /// @param to The final index for the slice (exclusive). + /// @return result The slice containing bytes at indices [from, to) + function slice(bytes memory b, uint256 from, uint256 to) + internal + pure + returns (bytes memory result) + { + require(from <= to, FROM_LESS_THAN_TO_REQUIRED); + require(to < b.length, TO_LESS_THAN_LENGTH_REQUIRED); + + // Create a new bytes structure and copy contents + result = new bytes(to - from); + memCopy( + result.contentAddress(), + b.contentAddress() + from, + result.length); + return result; + } + + /// @dev Returns a slices from a byte array without preserving the input. + /// @param b The byte array to take a slice from. Will be destroyed in the process. + /// @param from The starting index for the slice (inclusive). + /// @param to The final index for the slice (exclusive). + /// @return result The slice containing bytes at indices [from, to) + /// @dev When `from == 0`, the original array will match the slice. In other cases it's state will be corrupted. + function sliceDestructive(bytes memory b, uint256 from, uint256 to) + internal + pure + returns (bytes memory result) + { + require(from <= to, FROM_LESS_THAN_TO_REQUIRED); + require(to < b.length, TO_LESS_THAN_LENGTH_REQUIRED); + + // Create a new bytes structure around [from, to) in-place. + assembly { + result := add(b, from) + mstore(result, sub(to, from)) + } + return result; + } /// @dev Pops the last byte off of a byte array by modifying its length. /// @param b Byte array that will be modified. -- cgit From 425af46f98c83e2796aaf0b946d250193393754c Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 17:46:46 +0200 Subject: Rename bytes.equals --- .../current/test/TestLibBytes/TestLibBytes.sol | 4 +-- .../contracts/current/utils/LibBytes/LibBytes.sol | 35 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 299452c96..60ee3db7f 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -53,12 +53,12 @@ contract TestLibBytes { /// @param lhs First byte array to compare. /// @param rhs Second byte array to compare. /// @return True if arrays are the same. False otherwise. - function publicAreBytesEqual(bytes memory lhs, bytes memory rhs) + function publicEquals(bytes memory lhs, bytes memory rhs) public pure returns (bool equal) { - equal = lhs.areBytesEqual(rhs); + equal = lhs.equals(rhs); return equal; } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 58ce31c70..2862ee3dd 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -258,6 +258,41 @@ library LibBytes { return result; } + /// @dev Tests equality of two byte arrays. + /// @param lhs First byte array to compare. + /// @param rhs Second byte array to compare. + /// @return True if arrays are the same. False otherwise. + function equals( + bytes memory lhs, + bytes memory rhs + ) + internal + pure + returns (bool equal) + { + assembly { + // Get the number of words occupied by + let lenFullWords := div(add(mload(lhs), 0x1F), 0x20) + + // Add 1 to the number of words, to account for the length field + lenFullWords := add(lenFullWords, 0x1) + + // Test equality word-by-word. + // Terminates early if there is a mismatch. + for {let i := 0} lt(i, lenFullWords) {i := add(i, 1)} { + let lhsWord := mload(add(lhs, mul(i, 0x20))) + let rhsWord := mload(add(rhs, mul(i, 0x20))) + equal := eq(lhsWord, rhsWord) + if eq(equal, 0) { + // Break + i := lenFullWords + } + } + } + + return equal; + } + /// @dev Reads an address from a position in a byte array. /// @param b Byte array containing an address. /// @param index Index in byte array of address. -- cgit From 384cd2f6059bba994a6af2992a7df4909e24897c Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 18:12:45 +0200 Subject: Add trailing garbage testcase for LibBytes.equals --- .../src/contracts/current/test/TestLibBytes/TestLibBytes.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 60ee3db7f..d14022a64 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -61,6 +61,17 @@ contract TestLibBytes { equal = lhs.equals(rhs); return equal; } + + function publicEqualsPop1(bytes memory lhs, bytes memory rhs) + public + pure + returns (bool equal) + { + lhs.popByte(); + rhs.popByte(); + equal = lhs.equals(rhs); + return equal; + } /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length. /// @param dest Byte array that will be overwritten with source bytes. -- cgit From 4bf4f96f478ba8e08bf2d44817294ddd5fe895c5 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 18:13:17 +0200 Subject: Fix LibBytes.equals --- .../contracts/current/utils/LibBytes/LibBytes.sol | 25 ++++------------------ 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 2862ee3dd..3149a47e5 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -270,27 +270,10 @@ library LibBytes { pure returns (bool equal) { - assembly { - // Get the number of words occupied by - let lenFullWords := div(add(mload(lhs), 0x1F), 0x20) - - // Add 1 to the number of words, to account for the length field - lenFullWords := add(lenFullWords, 0x1) - - // Test equality word-by-word. - // Terminates early if there is a mismatch. - for {let i := 0} lt(i, lenFullWords) {i := add(i, 1)} { - let lhsWord := mload(add(lhs, mul(i, 0x20))) - let rhsWord := mload(add(rhs, mul(i, 0x20))) - equal := eq(lhsWord, rhsWord) - if eq(equal, 0) { - // Break - i := lenFullWords - } - } - } - - return equal; + // Keccak gas cost is 30 + numWords * 6. This is a cheap way to compare. + // We early exit on unequal lengths, but keccak would also correctly + // handle this. + return lhs.length == rhs.length && keccak256(lhs) == keccak256(rhs); } /// @dev Reads an address from a position in a byte array. -- cgit From 943e556f43a328dbb606567b06392851ba4ec3de Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 18:28:11 +0200 Subject: Refactor LibBytes.readBytes4 for consistency --- .../current/protocol/AssetProxyOwner/AssetProxyOwner.sol | 2 +- .../contracts/current/test/TestLibBytes/TestLibBytes.sol | 14 +++++++++----- .../src/contracts/current/utils/LibBytes/LibBytes.sol | 13 ++++++++----- 3 files changed, 18 insertions(+), 11 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol index 261ce8f34..50c538cea 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -104,7 +104,7 @@ contract AssetProxyOwner is pure returns (bool) { - bytes4 first4Bytes = data.readFirst4(); + bytes4 first4Bytes = data.readBytes4(0); require(REMOVE_AUTHORIZED_ADDRESS_SELECTOR == first4Bytes); return true; } diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index d14022a64..5421045a0 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -187,15 +187,19 @@ contract TestLibBytes { return b; } - /// @dev Reads the first 4 bytes from a byte array of arbitrary length. - /// @param b Byte array to read first 4 bytes from. - /// @return First 4 bytes of data. - function publicReadFirst4(bytes memory b) + /// @dev Reads an unpadded bytes4 value from a position in a byte array. + /// @param b Byte array containing a bytes4 value. + /// @param index Index in byte array of bytes4 value. + /// @return bytes4 value from byte array. + function publicReadBytes4( + bytes memory b, + uint256 index + ) public pure returns (bytes4 result) { - result = b.readFirst4(); + result = b.readBytes4(index); return result; } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 3149a47e5..cbe4f3be1 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -430,16 +430,19 @@ library LibBytes { writeBytes32(b, index, bytes32(input)); } - /// @dev Reads the first 4 bytes from a byte array of arbitrary length. - /// @param b Byte array to read first 4 bytes from. - /// @return First 4 bytes of data. - function readFirst4(bytes memory b) + /// @dev Reads an unpadded bytes4 value from a position in a byte array. + /// @param b Byte array containing a bytes4 value. + /// @param index Index in byte array of bytes4 value. + /// @return bytes4 value from byte array. + function readBytes4( + bytes memory b, + uint256 index) internal pure returns (bytes4 result) { require( - b.length >= 4, + b.length >= index + 4, GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED ); assembly { -- cgit From 5c612a186f6b6282323bc7172de22f43c511b8e4 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 18:36:56 +0200 Subject: Clean high bits in address --- packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index cbe4f3be1..c443dda8f 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -341,6 +341,10 @@ library LibBytes { // 2. Load 32-byte word from memory // 3. Apply 12-byte mask to obtain extra bytes occupying word of memory where we'll store the address let neighbors := and(mload(add(b, index)), 0xffffffffffffffffffffffff0000000000000000000000000000000000000000) + + // Make sure input address is clean. + // (Solidity does not guarantee this) + input := and(input, 0xffffffffffffffffffffffffffffffffffffffff) // Store the neighbors and address into memory mstore(add(b, index), xor(input, neighbors)) -- cgit From c66477c69097b15b90d9474222e308baeaa929a6 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 18:37:12 +0200 Subject: Clean low bits in bytes4 --- packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index c443dda8f..4a1397470 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -451,6 +451,9 @@ library LibBytes { ); assembly { result := mload(add(b, 32)) + // Solidity does not require us to clean the trailing bytes. + // We do it anyway + result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000) } return result; } -- cgit From 20a07494f669e4d161db4906f1a104afb89fbbbf Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:36:35 +0200 Subject: Fix usage of `contentAddress()` --- packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 4a1397470..a5ef3b5aa 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -571,8 +571,8 @@ library LibBytes { GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED ); memCopy( - getMemAddress(dest) + 32, // +32 to skip length of - getMemAddress(source) + 32, // +32 to skip length of + dest.contentAddress(), + source.contentAddress(), sourceLen ); } -- cgit From ba1baafca591fca8c1f6d3677021cf452fc5efc7 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:36:35 +0200 Subject: Remove `areBytesEqual` --- .../contracts/current/utils/LibBytes/LibBytes.sol | 35 ---------------------- 1 file changed, 35 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index a5ef3b5aa..81cd99cff 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -519,41 +519,6 @@ library LibBytes { ); } - /// @dev Tests equality of two byte arrays. - /// @param lhs First byte array to compare. - /// @param rhs Second byte array to compare. - /// @return True if arrays are the same. False otherwise. - function areBytesEqual( - bytes memory lhs, - bytes memory rhs - ) - internal - pure - returns (bool equal) - { - assembly { - // Get the number of words occupied by - let lenFullWords := div(add(mload(lhs), 0x1F), 0x20) - - // Add 1 to the number of words, to account for the length field - lenFullWords := add(lenFullWords, 0x1) - - // Test equality word-by-word. - // Terminates early if there is a mismatch. - for {let i := 0} lt(i, lenFullWords) {i := add(i, 1)} { - let lhsWord := mload(add(lhs, mul(i, 0x20))) - let rhsWord := mload(add(rhs, mul(i, 0x20))) - equal := eq(lhsWord, rhsWord) - if eq(equal, 0) { - // Break - i := lenFullWords - } - } - } - - return equal; - } - /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length. /// @param dest Byte array that will be overwritten with source bytes. /// @param source Byte array to copy onto dest bytes. -- cgit From 2f8ceca2ef40a53579336850e728012d18f346a6 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:36:35 +0200 Subject: Fix LibBytes is a library --- .../current/protocol/Exchange/MixinAssetProxyDispatcher.sol | 2 -- .../src/contracts/current/protocol/Exchange/MixinExchangeCore.sol | 7 ++++--- .../src/contracts/current/protocol/Exchange/MixinMatchOrders.sol | 6 +++--- .../contracts/current/protocol/Exchange/MixinWrapperFunctions.sol | 2 -- .../src/contracts/current/test/TestLibBytes/TestLibBytes.sol | 2 +- .../src/contracts/current/test/TestWallet/TestWallet.sol | 8 ++++---- 6 files changed, 12 insertions(+), 15 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index f85019012..b8d6c0722 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -19,14 +19,12 @@ pragma solidity ^0.4.24; import "../../utils/Ownable/Ownable.sol"; -import "../../utils/LibBytes/LibBytes.sol"; import "./libs/LibExchangeErrors.sol"; import "./mixins/MAssetProxyDispatcher.sol"; import "../AssetProxy/interfaces/IAssetProxy.sol"; contract MixinAssetProxyDispatcher is Ownable, - LibBytes, LibExchangeErrors, MAssetProxyDispatcher { diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index c227d210f..b207b3e57 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -32,7 +32,6 @@ import "./mixins/MAssetProxyDispatcher.sol"; contract MixinExchangeCore is LibConstants, - LibBytes, LibMath, LibOrder, LibFillResults, @@ -42,6 +41,8 @@ contract MixinExchangeCore is MSignatureValidator, MTransactions { + using LibBytes for bytes; + // Mapping of orderHash => amount of takerAsset already bought by maker mapping (bytes32 => uint256) public filled; @@ -411,8 +412,8 @@ contract MixinExchangeCore is ) private { - uint8 makerAssetProxyId = uint8(popLastByte(order.makerAssetData)); - uint8 takerAssetProxyId = uint8(popLastByte(order.takerAssetData)); + uint8 makerAssetProxyId = uint8(order.makerAssetData.popLastByte()); + uint8 takerAssetProxyId = uint8(order.takerAssetData.popLastByte()); bytes memory zrxAssetData = ZRX_ASSET_DATA; dispatchTransferFrom( order.makerAssetData, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol index 82325a29f..e36fcc2c5 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol @@ -27,7 +27,6 @@ import "./mixins/MAssetProxyDispatcher.sol"; contract MixinMatchOrders is LibConstants, - LibBytes, LibMath, LibExchangeErrors, MAssetProxyDispatcher, @@ -35,6 +34,7 @@ contract MixinMatchOrders is MMatchOrders, MTransactions { + using LibBytes for bytes; /// @dev Match two complementary orders that have a profitable spread. /// Each order is filled at their respective price point. However, the calculations are @@ -242,8 +242,8 @@ contract MixinMatchOrders is ) private { - uint8 leftMakerAssetProxyId = uint8(popLastByte(leftOrder.makerAssetData)); - uint8 rightMakerAssetProxyId = uint8(popLastByte(rightOrder.makerAssetData)); + uint8 leftMakerAssetProxyId = uint8(leftOrder.makerAssetData.popLastByte()); + uint8 rightMakerAssetProxyId = uint8(rightOrder.makerAssetData.popLastByte()); bytes memory zrxAssetData = ZRX_ASSET_DATA; // Order makers and taker dispatchTransferFrom( diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 87375d4bf..724f95518 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -31,8 +31,6 @@ contract MixinWrapperFunctions is LibExchangeErrors, MExchangeCore { - using LibBytes for bytes; - /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. /// @param order Order struct containing order specifications. /// @param takerAssetFillAmount Desired amount of takerAsset to sell. diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index 5421045a0..b2823aa88 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -84,7 +84,7 @@ contract TestLibBytes { pure returns (bytes memory) { - deepCopyBytes(dest, source); + LibBytes.deepCopyBytes(dest, source); return dest; } diff --git a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol index aca74b409..17dee9e9c 100644 --- a/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol +++ b/packages/contracts/src/contracts/current/test/TestWallet/TestWallet.sol @@ -22,9 +22,9 @@ import "../../protocol/Exchange/interfaces/IWallet.sol"; import "../../utils/LibBytes/LibBytes.sol"; contract TestWallet is - IWallet, - LibBytes + IWallet { + using LibBytes for bytes; string constant LENGTH_65_REQUIRED = "LENGTH_65_REQUIRED"; @@ -56,8 +56,8 @@ contract TestWallet is ); uint8 v = uint8(eip712Signature[0]); - bytes32 r = readBytes32(eip712Signature, 1); - bytes32 s = readBytes32(eip712Signature, 33); + bytes32 r = eip712Signature.readBytes32(1); + bytes32 s = eip712Signature.readBytes32(33); address recoveredAddress = ecrecover(hash, v, r, s); isValid = WALLET_OWNER == recoveredAddress; return isValid; -- cgit From 19ba272d62a3d838bb024e5152a2eb88f33645cd Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 11:36:35 +0200 Subject: Fix usage of `popLastByte` --- .../src/contracts/current/test/TestLibBytes/TestLibBytes.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol index b2823aa88..f45faaf36 100644 --- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol +++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol @@ -67,8 +67,8 @@ contract TestLibBytes { pure returns (bool equal) { - lhs.popByte(); - rhs.popByte(); + lhs.popLastByte(); + rhs.popLastByte(); equal = lhs.equals(rhs); return equal; } -- cgit From 6a6f98299de5fd67f9162cc57c73583702924a2f Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Wed, 13 Jun 2018 20:21:01 +0200 Subject: Move isFunctionRemoveAuthorizedAddress to test --- .../protocol/AssetProxyOwner/AssetProxyOwner.sol | 15 +------ .../TestAssetProxyOwner/TestAssetProxyOwner.sol | 47 ++++++++++++++++++++++ packages/contracts/src/utils/artifacts.ts | 2 + 3 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol index 50c538cea..79f64312f 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -39,7 +39,7 @@ contract AssetProxyOwner is modifier validRemoveAuthorizedAddressTx(uint256 transactionId) { Transaction storage tx = transactions[transactionId]; require(isAssetProxyRegistered[tx.destination]); - require(isFunctionRemoveAuthorizedAddress(tx.data)); + require(tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_SELECTOR); _; } @@ -95,17 +95,4 @@ contract AssetProxyOwner is tx.executed = false; } } - - /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function selector. - /// @param data Transaction data. - /// @return Successful if data is a call to removeAuthorizedAddress. - function isFunctionRemoveAuthorizedAddress(bytes memory data) - public - pure - returns (bool) - { - bytes4 first4Bytes = data.readBytes4(0); - require(REMOVE_AUTHORIZED_ADDRESS_SELECTOR == first4Bytes); - return true; - } } diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol new file mode 100644 index 000000000..35746d2ad --- /dev/null +++ b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol @@ -0,0 +1,47 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.24; + +import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol"; + +contract TestAssetProxyOwner is + AssetProxyOwner +{ + constructor( + address[] memory _owners, + address[] memory _assetProxyContracts, + uint256 _required, + uint256 _secondsTimeLocked + ) + public + AssetProxyOwner(_owners, _assetProxyContracts, _required, _secondsTimeLocked) + { + } + + /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function selector. + /// @param data Transaction data. + /// @return Successful if data is a call to removeAuthorizedAddress. + function isFunctionRemoveAuthorizedAddress(bytes memory data) + public + pure + returns (bool) + { + return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_SELECTOR; + } +} diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index fa18cc9d2..a46bab9ae 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -13,6 +13,7 @@ import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; import * as TestAssetDataDecoders from '../artifacts/TestAssetDataDecoders.json'; import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json'; +import * as TestAssetProxyOwner from '../artifacts/TestAssetProxyOwner.json'; import * as TestLibBytes from '../artifacts/TestLibBytes.json'; import * as TestLibs from '../artifacts/TestLibs.json'; import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json'; @@ -36,6 +37,7 @@ export const artifacts = { MixinAuthorizable: (MixinAuthorizable as any) as ContractArtifact, MultiSigWallet: (MultiSigWallet as any) as ContractArtifact, MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, + TestAssetProxyOwner: (TestAssetProxyOwner as any) as ContractArtifact, TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact, TestAssetDataDecoders: (TestAssetDataDecoders as any) as ContractArtifact, TestLibBytes: (TestLibBytes as any) as ContractArtifact, -- cgit From 1681361aedb2c7c4d97f8b74890ee2f86d96df45 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 21 Jun 2018 14:49:16 -0700 Subject: Change removeAuthorizedAddress => removeAuthorizedAddressAtIndex --- .../protocol/AssetProxyOwner/AssetProxyOwner.sol | 18 +++++++++--------- .../test/TestAssetProxyOwner/TestAssetProxyOwner.sol | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol index 79f64312f..eb58b3374 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -29,17 +29,17 @@ contract AssetProxyOwner is event AssetProxyRegistration(address assetProxyContract, bool isRegistered); // Mapping of AssetProxy contract address => - // if this contract is allowed to call the AssetProxy's removeAuthorizedAddress method without a time lock. + // if this contract is allowed to call the AssetProxy's `removeAuthorizedAddressAtIndex` method without a time lock. mapping (address => bool) public isAssetProxyRegistered; - bytes4 constant REMOVE_AUTHORIZED_ADDRESS_SELECTOR = bytes4(keccak256("removeAuthorizedAddress(address)")); + bytes4 constant REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR = bytes4(keccak256("removeAuthorizedAddressAtIndex(address,uint256)")); - /// @dev Function will revert if the transaction does not call `removeAuthorizedAddress` + /// @dev Function will revert if the transaction does not call `removeAuthorizedAddressAtIndex` /// on an approved AssetProxy contract. - modifier validRemoveAuthorizedAddressTx(uint256 transactionId) { + modifier validRemoveAuthorizedAddressAtIndexTx(uint256 transactionId) { Transaction storage tx = transactions[transactionId]; require(isAssetProxyRegistered[tx.destination]); - require(tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_SELECTOR); + require(tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR); _; } @@ -66,7 +66,7 @@ contract AssetProxyOwner is } /// @dev Registers or deregisters an AssetProxy to be able to execute - /// removeAuthorizedAddress without a timelock. + /// `removeAuthorizedAddressAtIndex` without a timelock. /// @param assetProxyContract Address of AssetProxy contract. /// @param isRegistered Status of approval for AssetProxy contract. function registerAssetProxy(address assetProxyContract, bool isRegistered) @@ -78,13 +78,13 @@ contract AssetProxyOwner is AssetProxyRegistration(assetProxyContract, isRegistered); } - /// @dev Allows execution of removeAuthorizedAddress without time lock. + /// @dev Allows execution of `removeAuthorizedAddressAtIndex` without time lock. /// @param transactionId Transaction ID. - function executeRemoveAuthorizedAddress(uint256 transactionId) + function executeRemoveAuthorizedAddressAtIndex(uint256 transactionId) public notExecuted(transactionId) fullyConfirmed(transactionId) - validRemoveAuthorizedAddressTx(transactionId) + validRemoveAuthorizedAddressAtIndexTx(transactionId) { Transaction storage tx = transactions[transactionId]; tx.executed = true; diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol index 35746d2ad..40a6255cb 100644 --- a/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol @@ -34,14 +34,23 @@ contract TestAssetProxyOwner is { } - /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function selector. + function testValidRemoveAuthorizedAddressTx(uint256 id) + public + validRemoveAuthorizedAddressAtIndexTx(id) + returns (bool) + { + // Do nothing. We expect reverts through the modifier + return true; + } + + /// @dev Compares first 4 bytes of byte array to `removeAuthorizedAddressAtIndex` function selector. /// @param data Transaction data. - /// @return Successful if data is a call to removeAuthorizedAddress. - function isFunctionRemoveAuthorizedAddress(bytes memory data) + /// @return Successful if data is a call to `removeAuthorizedAddressAtIndex`. + function isFunctionRemoveAuthorizedAddressAtIndex(bytes memory data) public pure returns (bool) { - return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_SELECTOR; + return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR; } } -- cgit From 8ddcb6c841fd97bca2cddffd49a5b773cf53635f Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 21 Jun 2018 16:25:42 -0700 Subject: Update and add tests --- .../current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol | 2 +- packages/contracts/src/utils/multi_sig_wrapper.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol index 40a6255cb..2abcd17a0 100644 --- a/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol +++ b/packages/contracts/src/contracts/current/test/TestAssetProxyOwner/TestAssetProxyOwner.sol @@ -34,7 +34,7 @@ contract TestAssetProxyOwner is { } - function testValidRemoveAuthorizedAddressTx(uint256 id) + function testValidRemoveAuthorizedAddressAtIndexTx(uint256 id) public validRemoveAuthorizedAddressAtIndexTx(id) returns (bool) diff --git a/packages/contracts/src/utils/multi_sig_wrapper.ts b/packages/contracts/src/utils/multi_sig_wrapper.ts index f0098bd5e..b0d4fa8ab 100644 --- a/packages/contracts/src/utils/multi_sig_wrapper.ts +++ b/packages/contracts/src/utils/multi_sig_wrapper.ts @@ -40,13 +40,15 @@ export class MultiSigWrapper { const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); return tx; } - public async executeRemoveAuthorizedAddressAsync( + public async executeRemoveAuthorizedAddressAtIndexAsync( txId: BigNumber, from: string, ): Promise { // tslint:disable-next-line:no-unnecessary-type-assertion const txHash = await (this - ._multiSig as AssetProxyOwnerContract).executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from }); + ._multiSig as AssetProxyOwnerContract).executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, { + from, + }); const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); return tx; } -- cgit From ea8c2b8d6923f37412cefcb8dc8482e009dce104 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 22 Jun 2018 17:17:55 -0700 Subject: Add modifier and tests for removeAuthorizedAddressAtIndex --- .../contracts/current/protocol/AssetProxy/MixinAuthorizable.sol | 7 ++++++- packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol index 8cb4254c5..37c12f861 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol @@ -69,7 +69,7 @@ contract MixinAuthorizable is ); delete authorized[target]; - for (uint i = 0; i < authorities.length; i++) { + for (uint256 i = 0; i < authorities.length; i++) { if (authorities[i] == target) { authorities[i] = authorities[authorities.length - 1]; authorities.length -= 1; @@ -87,7 +87,12 @@ contract MixinAuthorizable is uint256 index ) external + onlyOwner { + require( + authorized[target], + TARGET_NOT_AUTHORIZED + ); require( index < authorities.length, INDEX_OUT_OF_BOUNDS diff --git a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol index 296c6c856..99b93d0d2 100644 --- a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol +++ b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol @@ -13,6 +13,9 @@ import "./IOwnable.sol"; contract Ownable is IOwnable { address public owner; + // Revert reasons + string constant ONLY_CONTRACT_OWNER = "ONLY_CONTRACT_OWNER"; + constructor () public { @@ -22,7 +25,7 @@ contract Ownable is IOwnable { modifier onlyOwner() { require( msg.sender == owner, - "Only contract owner is allowed to call this method." + ONLY_CONTRACT_OWNER ); _; } -- cgit From 82af1df3c3d62ab0a0dd4687bf9bb65d3b261054 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Sat, 23 Jun 2018 13:55:02 +0200 Subject: Fix typos in comments --- packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/contracts/src') diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 81cd99cff..e4cbf318b 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -188,12 +188,12 @@ library LibBytes { return result; } - /// @dev Returns a slices from a byte array without preserving the input. + /// @dev Returns a slice from a byte array without preserving the input. /// @param b The byte array to take a slice from. Will be destroyed in the process. /// @param from The starting index for the slice (inclusive). /// @param to The final index for the slice (exclusive). /// @return result The slice containing bytes at indices [from, to) - /// @dev When `from == 0`, the original array will match the slice. In other cases it's state will be corrupted. + /// @dev When `from == 0`, the original array will match the slice. In other cases its state will be corrupted. function sliceDestructive(bytes memory b, uint256 from, uint256 to) internal pure -- cgit