Convert MixinSignatureValidator to use rich reverts

This commit is contained in:
Lawrence Forman
2019-04-02 10:28:10 -04:00
committed by Amir Bandeali
parent d40f343d2a
commit 8a9b9c55ce

View File

@@ -25,15 +25,17 @@ import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
import "./interfaces/IWallet.sol";
import "./interfaces/IValidator.sol";
import "./mixins/MExchangeRichErrors.sol";
contract MixinSignatureValidator is
ReentrancyGuard,
MSignatureValidator,
MTransactions
MTransactions,
MExchangeRichErrors
{
using LibBytes for bytes;
// Mapping of hash => signer => signed
mapping (bytes32 => mapping (address => bool)) public preSigned;
@@ -52,14 +54,16 @@ contract MixinSignatureValidator is
external
{
if (signerAddress != msg.sender) {
require(
isValidSignature(
if (!isValidSignature(
hash,
signerAddress,
signature
),
"INVALID_SIGNATURE"
);
)) {
rrevert(SignatureError(
hash,
SignatureErrorCodes.BAD_SIGNATURE
));
}
}
preSigned[hash][signerAddress] = true;
}
@@ -97,19 +101,17 @@ contract MixinSignatureValidator is
view
returns (bool isValid)
{
require(
signature.length > 0,
"LENGTH_GREATER_THAN_0_REQUIRED"
);
if (signature.length == 0) {
rrevert(SignatureError(hash, SignatureErrorCodes.INVALID_LENGTH));
}
// Pop last byte off of signature byte array.
uint8 signatureTypeRaw = uint8(signature.popLastByte());
// Ensure signature is supported
require(
signatureTypeRaw < uint8(SignatureType.NSignatureTypes),
"SIGNATURE_UNSUPPORTED"
);
if (signatureTypeRaw >= uint8(SignatureType.NSignatureTypes)) {
rrevert(SignatureError(hash, SignatureErrorCodes.UNSUPPORTED));
}
SignatureType signatureType = SignatureType(signatureTypeRaw);
@@ -125,26 +127,33 @@ contract MixinSignatureValidator is
// it an explicit option. This aids testing and analysis. It is
// also the initialization value for the enum type.
if (signatureType == SignatureType.Illegal) {
revert("SIGNATURE_ILLEGAL");
rrevert(SignatureError(
hash,
SignatureErrorCodes.ILLEGAL
));
// Always invalid signature.
// Like Illegal, this is always implicitly available and therefore
// offered explicitly. It can be implicitly created by providing
// a correctly formatted but incorrect signature.
} else if (signatureType == SignatureType.Invalid) {
require(
signature.length == 0,
"LENGTH_0_REQUIRED"
);
if (signature.length != 0) {
rrevert(SignatureError(
hash,
SignatureErrorCodes.INVALID_LENGTH
));
}
isValid = false;
return isValid;
// Signature using EIP712
} else if (signatureType == SignatureType.EIP712) {
require(
signature.length == 65,
"LENGTH_65_REQUIRED"
);
if (signature.length != 65) {
rrevert(SignatureError(
hash,
SignatureErrorCodes.INVALID_LENGTH
));
}
v = uint8(signature[0]);
r = signature.readBytes32(1);
s = signature.readBytes32(33);
@@ -159,10 +168,12 @@ contract MixinSignatureValidator is
// Signed using web3.eth_sign
} else if (signatureType == SignatureType.EthSign) {
require(
signature.length == 65,
"LENGTH_65_REQUIRED"
);
if (signature.length != 65) {
rrevert(SignatureError(
hash,
SignatureErrorCodes.INVALID_LENGTH
));
}
v = uint8(signature[0]);
r = signature.readBytes32(1);
s = signature.readBytes32(33);
@@ -198,7 +209,7 @@ contract MixinSignatureValidator is
} else if (signatureType == SignatureType.Validator) {
// Pop last 20 bytes off of signature byte array.
address validatorAddress = signature.popLast20Bytes();
// Ensure signer has approved validator.
if (!allowedValidators[signerAddress][validatorAddress]) {
return false;
@@ -222,7 +233,7 @@ contract MixinSignatureValidator is
// that we currently support. In this case returning false
// may lead the caller to incorrectly believe that the
// signature was invalid.)
revert("SIGNATURE_UNSUPPORTED");
rrevert(SignatureError(hash, SignatureErrorCodes.UNSUPPORTED));
}
/// @dev Verifies signature using logic defined by Wallet contract.
@@ -245,9 +256,10 @@ contract MixinSignatureValidator is
hash,
signature
);
bool didSucceed;
assembly {
let cdStart := add(callData, 32)
let success := staticcall(
didSucceed := staticcall(
gas, // forward all gas
walletAddress, // address of Wallet contract
cdStart, // pointer to start of input
@@ -256,21 +268,14 @@ contract MixinSignatureValidator is
32 // output size is 32 bytes
)
switch success
case 0 {
// Revert with `Error("WALLET_ERROR")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000000c57414c4c45545f4552524f5200000000000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
case 1 {
if eq(didSucceed, 1) {
// Signature is valid if call did not revert and returned true
isValid := mload(cdStart)
}
}
return isValid;
if (didSucceed)
return isValid;
rrevert(SignatureError(hash, SignatureErrorCodes.WALLET_ERROR));
}
/// @dev Verifies signature using logic defined by Validator contract.
@@ -295,9 +300,10 @@ contract MixinSignatureValidator is
signerAddress,
signature
);
bool didSucceed;
assembly {
let cdStart := add(callData, 32)
let success := staticcall(
didSucceed := staticcall(
gas, // forward all gas
validatorAddress, // address of Validator contract
cdStart, // pointer to start of input
@@ -306,20 +312,14 @@ contract MixinSignatureValidator is
32 // output size is 32 bytes
)
switch success
case 0 {
// Revert with `Error("VALIDATOR_ERROR")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x0000000f56414c494441544f525f4552524f5200000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
case 1 {
if eq(didSucceed, 1) {
// Signature is valid if call did not revert and returned true
isValid := mload(cdStart)
}
}
return isValid;
if (didSucceed)
return isValid;
rrevert(
SignatureError(hash, SignatureErrorCodes.VALIDATOR_ERROR));
}
}