Make Gnosis account compatible with ERC-1271 (#191)

This commit is contained in:
Derek Chiang
2023-02-13 05:50:30 -08:00
committed by GitHub
parent 1b78ed29c0
commit e8290a3629
2 changed files with 41 additions and 2 deletions

View File

@@ -5,16 +5,22 @@ pragma solidity ^0.8.7;
import "@gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol";
import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../../interfaces/IAccount.sol";
import "./EIP4337Manager.sol";
using ECDSA for bytes32;
/**
* The GnosisSafe enables adding custom functions implementation to the Safe by setting a 'fallbackHandler'.
* This 'fallbackHandler' adds an implementation of 'validateUserOp' to the GnosisSafe.
* Note that the implementation of the 'validateUserOp' method is located in the EIP4337Manager.
* Upon receiving the 'validateUserOp', a Safe with EIP4337Fallback enabled makes a 'delegatecall' to EIP4337Manager.
*/
contract EIP4337Fallback is DefaultCallbackHandler, IAccount {
contract EIP4337Fallback is DefaultCallbackHandler, IAccount, IERC1271 {
bytes4 internal constant ERC1271_MAGIC_VALUE = 0x1626ba7e;
address immutable public eip4337manager;
constructor(address _eip4337manager) {
eip4337manager = _eip4337manager;
@@ -55,4 +61,21 @@ contract EIP4337Fallback is DefaultCallbackHandler, IAccount {
) external {
delegateToManager();
}
}
function isValidSignature(
bytes32 _hash,
bytes memory _signature
) external override view returns (bytes4) {
bytes32 hash = _hash.toEthSignedMessageHash();
address recovered = hash.recover(_signature);
GnosisSafe safe = GnosisSafe(payable(address(msg.sender)));
// Validate signatures
if (safe.isOwner(recovered)) {
return ERC1271_MAGIC_VALUE;
} else {
return 0xffffffff;
}
}
}

View File

@@ -2,6 +2,7 @@ import './aa.init'
import { ethers } from 'hardhat'
import { Signer } from 'ethers'
import {
EIP4337Fallback__factory,
EIP4337Manager,
EIP4337Manager__factory,
EntryPoint,
@@ -205,6 +206,21 @@ describe('Gnosis Proxy', function () {
console.log('gasUsed=', rcpt.gasUsed, rcpt.transactionHash)
})
it('should validate ERC1271 signatures', async function () {
const safe = EIP4337Fallback__factory.connect(proxySafe.address, ethersSigner)
const message = ethers.utils.hexlify(ethers.utils.toUtf8Bytes('hello erc1271'))
const dataHash = ethers.utils.arrayify(ethers.utils.keccak256(message))
const sig = await owner.signMessage(dataHash)
expect(await safe.isValidSignature(dataHash, sig)).to.be.eq('0x1626ba7e')
// make an sig invalid
const badWallet = ethers.Wallet.createRandom()
const badSig = await badWallet.signMessage(dataHash)
expect(await safe.isValidSignature(dataHash, badSig)).to.be.not.eq('0x1626ba7e')
})
context('#replaceEIP4337', () => {
let signature: string
let newEntryPoint: EntryPoint