mirror of
https://github.com/getwax/zk-account-abstraction.git
synced 2026-01-08 20:18:05 -05:00
Make Gnosis account compatible with ERC-1271 (#191)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user