Skip to content

Commit

Permalink
Add tests for EIP1271 encumberBySig
Browse files Browse the repository at this point in the history
  • Loading branch information
kevincheng96 committed Jun 29, 2023
1 parent e96afa3 commit 199a00a
Show file tree
Hide file tree
Showing 3 changed files with 402 additions and 3 deletions.
6 changes: 5 additions & 1 deletion src/EncumberableToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ contract EncumberableToken is ERC20, IERC20Permit, IERC7246 {
if (isValidSignature(owner, digest, v, r, s)) {
nonces[owner]++;
_approve(owner, spender, amount);
} else {
revert("Bad signatory");
}
}

Expand Down Expand Up @@ -283,6 +285,8 @@ contract EncumberableToken is ERC20, IERC20Permit, IERC7246 {
if (isValidSignature(owner, digest, v, r, s)) {
nonces[owner]++;
_encumber(owner, taker, amount);
} else {
revert("Bad signatory");
}
}

Expand All @@ -308,7 +312,7 @@ contract EncumberableToken is ERC20, IERC20Permit, IERC7246 {
(bool success, bytes memory data) = signer.staticcall(
abi.encodeWithSelector(EIP1271_MAGIC_VALUE, digest, signature)
);
require(success == true, "Call to verify signature failed");
require(success == true, "Call to verify EIP1271 signature failed");
bytes4 returnValue = abi.decode(data, (bytes4));
return returnValue == EIP1271_MAGIC_VALUE;
} else {
Expand Down
66 changes: 66 additions & 0 deletions src/test/EIP1271Signer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.15;

contract EIP1271Signer {
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x1626ba7e;

address public owner;

constructor(address _owner) {
owner = _owner;
}

function isValidSignature(bytes32 messageHash, bytes memory signature) external view returns (bytes4) {
if (recoverSigner(messageHash, signature) == owner) {
return EIP1271_MAGIC_VALUE;
} else {
return 0xffffffff;
}
}

function recoverSigner(bytes32 messageHash, bytes memory signature) internal pure returns (address) {
require(signature.length == 65, "SignatureValidator#recoverSigner: invalid signature length");

// Variables are not scoped in Solidity.
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 32))
s := mload(add(signature, 64))
v := and(mload(add(signature, 65)), 255)
}

// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
//
// Source OpenZeppelin
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol

if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
revert("SignatureValidator#recoverSigner: invalid signature 's' value");
}

if (v != 27 && v != 28) {
revert("SignatureValidator#recoverSigner: invalid signature 'v' value");
}

// Recover ECDSA signer
address signer = ecrecover(messageHash, v, r, s);

// Prevent signer from being 0x0
require(
signer != address(0x0),
"SignatureValidator#recoverSigner: INVALID_SIGNER"
);

return signer;
}
}
Loading

0 comments on commit 199a00a

Please sign in to comment.