From 0a1ae2c31139e446b2fb3b7f03caf371c6668ae2 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 24 Aug 2018 00:19:06 -0700 Subject: Remove pragma experimental v0.5.0 and use staticcall is assembly --- .../protocol/Exchange/MixinSignatureValidator.sol | 84 +++++++++++++++++++++- .../Exchange/mixins/MSignatureValidator.sol | 31 ++++++++ .../TestSignatureValidator.sol | 1 - .../2.0.0/test/TestStaticCall/TestStaticCall.sol | 16 +++++ 4 files changed, 128 insertions(+), 4 deletions(-) (limited to 'packages/contracts/src/2.0.0') diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol index fd655e757..6bfbb5107 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol @@ -17,7 +17,6 @@ */ pragma solidity 0.4.24; -pragma experimental "v0.5.0"; import "../../utils/LibBytes/LibBytes.sol"; import "./mixins/MSignatureValidator.sol"; @@ -192,7 +191,11 @@ contract MixinSignatureValidator is // 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(signerAddress).isValidSignature(hash, signature); + isValid = isValidWalletSignature( + hash, + signerAddress, + signature + ); return isValid; // Signature verified by validator contract. @@ -210,7 +213,8 @@ contract MixinSignatureValidator is if (!allowedValidators[signerAddress][validatorAddress]) { return false; } - isValid = IValidator(validatorAddress).isValidSignature( + isValid = isValidValidatorSignature( + validatorAddress, hash, signerAddress, signature @@ -258,4 +262,78 @@ contract MixinSignatureValidator is // signature was invalid.) revert("SIGNATURE_UNSUPPORTED"); } + + /// @dev Verifies signature using logic defined by Wallet contract. + /// @param hash Any 32 byte hash. + /// @param walletAddress Address that should have signed the given hash + /// and defines its own signature verification method. + /// @param signature Proof that the hash has been signed by signer. + /// @return True if signature is valid for given wallet.. + function isValidWalletSignature( + bytes32 hash, + address walletAddress, + bytes signature + ) + internal + view + returns (bool isValid) + { + bytes memory calldata = abi.encodeWithSelector( + IWallet(walletAddress).isValidSignature.selector, + hash, + signature + ); + assembly { + let cdStart := add(calldata, 32) + let success := staticcall( + gas, // forward all gas + walletAddress, // address of Wallet contract + cdStart, // pointer to start of input + mload(calldata), // length of input + cdStart, // write input over output + 32 // output size is 32 bytes + ) + // Signature is valid if call did not revert and returned true + isValid := and(success, mload(cdStart)) + } + return isValid; + } + + /// @dev Verifies signature using logic defined by Validator contract. + /// @param validatorAddress Address of validator contract. + /// @param hash Any 32 byte 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 isValidValidatorSignature( + address validatorAddress, + bytes32 hash, + address signerAddress, + bytes signature + ) + internal + view + returns (bool isValid) + { + bytes memory calldata = abi.encodeWithSelector( + IValidator(signerAddress).isValidSignature.selector, + hash, + signerAddress, + signature + ); + assembly { + let cdStart := add(calldata, 32) + let success := staticcall( + gas, // forward all gas + validatorAddress, // address of Validator contract + cdStart, // pointer to start of input + mload(calldata), // length of input + cdStart, // write input over output + 32 // output size is 32 bytes + ) + // Signature is valid if call did not revert and returned true + isValid := and(success, mload(cdStart)) + } + return isValid; + } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol index f14f2ba00..75fe9ec46 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol @@ -43,4 +43,35 @@ contract MSignatureValidator is Trezor, // 0x08 NSignatureTypes // 0x09, number of signature types. Always leave at end. } + + /// @dev Verifies signature using logic defined by Wallet contract. + /// @param hash Any 32 byte hash. + /// @param walletAddress Address that should have signed the given hash + /// and defines its own signature verification method. + /// @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 isValidWalletSignature( + bytes32 hash, + address walletAddress, + bytes signature + ) + internal + view + returns (bool isValid); + + /// @dev Verifies signature using logic defined by Validator contract. + /// @param validatorAddress Address of validator contract. + /// @param hash Any 32 byte 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 isValidValidatorSignature( + address validatorAddress, + bytes32 hash, + address signerAddress, + bytes signature + ) + internal + view + returns (bool isValid); } diff --git a/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol b/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol index 3845b7b9e..e1a610469 100644 --- a/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol +++ b/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol @@ -17,7 +17,6 @@ */ pragma solidity 0.4.24; -pragma experimental "v0.5.0"; import "../../protocol/Exchange/MixinSignatureValidator.sol"; import "../../protocol/Exchange/MixinTransactions.sol"; diff --git a/packages/contracts/src/2.0.0/test/TestStaticCall/TestStaticCall.sol b/packages/contracts/src/2.0.0/test/TestStaticCall/TestStaticCall.sol index be24e2f37..5a9581f51 100644 --- a/packages/contracts/src/2.0.0/test/TestStaticCall/TestStaticCall.sol +++ b/packages/contracts/src/2.0.0/test/TestStaticCall/TestStaticCall.sol @@ -18,6 +18,8 @@ pragma solidity 0.4.24; +import "../../tokens/ERC20Token/IERC20Token.sol"; + contract TestStaticCall { @@ -55,6 +57,20 @@ contract TestStaticCall { return true; } + /// @dev Approves an ERC20 token to spend tokens from this address. + /// @param token Address of ERC20 token. + /// @param spender Address that will spend tokens. + /// @param value Amount of tokens spender is approved to spend. + function approveERC20( + address token, + address spender, + uint256 value + ) + external + { + IERC20Token(token).approve(spender, value); + } + /// @dev Increments state variable. function updateState() internal -- cgit