Skip to content

Commit

Permalink
isValidateSignauture refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
davidinsuomi committed Oct 19, 2023
1 parent d8062e4 commit bff16d0
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 5 deletions.
7 changes: 4 additions & 3 deletions contracts/handler/ERC1271Handler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ abstract contract ERC1271Handler is Authority, IERC1271Handler, SignatureValidat
return AccountStorage.layout().approvedHashes;
}

function isValidSignature(bytes32 hash, bytes calldata signature)
function isValidSignature(bytes32 rawHash, bytes calldata signature)
external
view
override
returns (bytes4 magicValue)
{
bytes32 datahash = _encodeRawHash(rawHash);
if (signature.length > 0) {
(uint256 _validationData, bool sigValid) = _isValidateSignature(hash, signature);
(uint256 _validationData, bool sigValid) = _isValidate1271Signature(datahash, signature);
if (!sigValid) {
return INVALID_ID;
}
Expand All @@ -40,7 +41,7 @@ abstract contract ERC1271Handler is Authority, IERC1271Handler, SignatureValidat
}

mapping(bytes32 => uint256) storage approvedHashes = _approvedHashes();
uint256 status = approvedHashes[hash];
uint256 status = approvedHashes[datahash];
if (status == 1) {
// approved
return MAGICVALUE;
Expand Down
8 changes: 6 additions & 2 deletions contracts/helper/SignatureValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ abstract contract SignatureValidator is OwnerAuth, Validator {
using ECDSA for bytes32;
using TypeConversion for address;

function _isValidateSignature(bytes32 rawHash, bytes calldata rawSignature)
function _encodeRawHash(bytes32 rawHash) internal view returns (bytes32 encodeRawHash) {
return validator().encodeRawHash(rawHash);
}

function _isValidate1271Signature(bytes32 rawHash, bytes calldata rawSignature)
internal
view
returns (uint256 validationData, bool sigValid)
Expand All @@ -24,7 +28,7 @@ abstract contract SignatureValidator is OwnerAuth, Validator {

(guardHookInputData, validatorSignature) = SignatureDecoder.decodeSignature(rawSignature);

(validationData, recovered, success) = validator().recoverSignature(rawHash, validatorSignature);
(validationData, recovered, success) = validator().recover1271Signature(rawHash, validatorSignature);

if (!success) {
sigValid = false;
Expand Down
6 changes: 6 additions & 0 deletions contracts/interfaces/IValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ interface IValidator {
external
view
returns (uint256 validationData, bytes32 recovered, bool success);
function recover1271Signature(bytes32 rawHash, bytes calldata rawSignature)
external
view
returns (uint256 validationData, bytes32 recovered, bool success);

function encodeRawHash(bytes32 rawHash) external view returns (bytes32);
}
39 changes: 39 additions & 0 deletions contracts/validator/BaseValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ import "../libraries/WebAuthn.sol";
abstract contract BaseValidator is IValidator {
using ECDSA for bytes32;
using TypeConversion for address;
//keccak256(
// "SoulWalletMessage(bytes32 message)"
//);

bytes32 private constant SOUL_WALLET_MSG_TYPEHASH =
0x04e6b5b1de6ba008d582849d4956d004d09a345fc11e7ba894975b5b56a4be66;
// keccak256(
// "EIP712Domain(uint256 chainId,address verifyingContract)"
// );
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH =
0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;

function _packSignatureHash(bytes32 hash, uint8 signatureType, uint256 validationData)
internal
Expand Down Expand Up @@ -60,4 +71,32 @@ abstract contract BaseValidator is IValidator {

(recovered, success) = recover(signatureType, hash, signature);
}
// 1271 signature verification doesn't needs to pack hash

function recover1271Signature(bytes32 rawHash, bytes calldata rawSignature)
external
view
override
returns (uint256 validationData, bytes32 recovered, bool success)
{
uint8 signatureType;
bytes calldata signature;
(signatureType, validationData, signature) = ValidatorSigDecoder.decodeValidatorSignature(rawSignature);
(recovered, success) = recover(signatureType, rawHash, signature);
}

function encodeRawHash(bytes32 rawHash) public view returns (bytes32) {
bytes32 encode1271MessageHash = keccak256(abi.encode(SOUL_WALLET_MSG_TYPEHASH, rawHash));
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), address(msg.sender)));
return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator, encode1271MessageHash));
}

function getChainId() public view returns (uint256) {
uint256 id;
// solhint-disable-next-line no-inline-assembly
assembly {
id := chainid()
}
return id;
}
}
75 changes: 75 additions & 0 deletions test/soulwallet/SoulWalletIsValidateSingature.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "./base/SoulWalletInstence.sol";
import "@source/handler/ERC1271Handler.sol";
import "@source/handler/DefaultCallbackHandler.sol";
import "@source/handler/ERC1271Handler.sol";
import "@source/dev/Tokens/TokenERC721.sol";

contract SoulWalletIsValidateSingatureTest is Test {
SoulWalletInstence public soulWalletInstence;
DefaultCallbackHandler public defaultCallbackHandler;
ISoulWallet public soulWallet;
TokenERC721 tokenERC721;
address ownwerAddress;
uint256 ownerPrivateKey;
bytes4 internal constant MAGICVALUE = 0x1626ba7e;
bytes4 internal constant INVALID_ID = 0xffffffff;
bytes4 internal constant INVALID_TIME_RANGE = 0xfffffffe;

//keccak256(
// "SoulWalletMessage(bytes32 message)"
//);

bytes32 private constant SOUL_WALLET_MSG_TYPEHASH =
0x04e6b5b1de6ba008d582849d4956d004d09a345fc11e7ba894975b5b56a4be66;
// keccak256(
// "EIP712Domain(uint256 chainId,address verifyingContract)"
// );
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH =
0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;

function setUp() public {
(ownwerAddress, ownerPrivateKey) = makeAddrAndKey("owner1");
bytes[] memory modules = new bytes[](0);
bytes[] memory plugins = new bytes[](0);
bytes32 salt = bytes32(0);
defaultCallbackHandler = new DefaultCallbackHandler();
soulWalletInstence =
new SoulWalletInstence(address(defaultCallbackHandler), ownwerAddress, modules, plugins, salt);
soulWallet = soulWalletInstence.soulWallet();
}

function encodeRawHash(bytes32 rawHash, address account) private view returns (bytes32) {
bytes32 encode1271MessageHash = keccak256(abi.encode(SOUL_WALLET_MSG_TYPEHASH, rawHash));
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), account));
return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator, encode1271MessageHash));
}

function getChainId() private view returns (uint256) {
uint256 id;
// solhint-disable-next-line no-inline-assembly
assembly {
id := chainid()
}
return id;
}

function test_isValidateSignauture() public {
bytes32 hash = keccak256(abi.encodePacked("hello world"));
bytes32 encodeHash = encodeRawHash(hash, address(soulWallet));
(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, encodeHash);
bytes memory sig = abi.encodePacked(r, s, v);
assertEq(sig.length, 65);
uint8 signType = 0;
bytes memory validatorSignature = abi.encodePacked(signType, sig);

uint8 dataType = 0;
bytes memory signSig = abi.encodePacked(dataType, validatorSignature);

bytes4 validResult = ERC1271Handler(address(soulWallet)).isValidSignature(hash, signSig);
assertEq(validResult, MAGICVALUE);
}
}

0 comments on commit bff16d0

Please sign in to comment.