From c54c89d722c732bee2da399ea7e15e8dd572ef14 Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 11 Jul 2024 12:57:07 +0200 Subject: [PATCH] [#754] Run tests --- .../test/erc4337/ReferenceEntryPoint.spec.ts | 61 +++++++++++++++++++ .../4337/test/erc4337/Safe4337Module.spec.ts | 32 ++++++++++ 2 files changed, 93 insertions(+) diff --git a/modules/4337/test/erc4337/ReferenceEntryPoint.spec.ts b/modules/4337/test/erc4337/ReferenceEntryPoint.spec.ts index 1bb41972..a30f9154 100644 --- a/modules/4337/test/erc4337/ReferenceEntryPoint.spec.ts +++ b/modules/4337/test/erc4337/ReferenceEntryPoint.spec.ts @@ -356,6 +356,67 @@ describe('Safe4337Module - Reference EntryPoint', () => { .withArgs(0, 'AA24 signature error') }) + it('should revert when expected offset and given dynamic pointer in signatures are not equal - Smart contract signature (NOTE: would require a staked paymaster for ERC-4337)', async () => { + const { user, relayer, safe: parentSafe, validator, entryPoint, safeGlobalConfig } = await setupTests() + + await parentSafe.deploy(user) + const daughterSafe = Safe4337.withSigner(parentSafe.address, safeGlobalConfig) + + const accountBalance = ethers.parseEther('1.0') + await user.sendTransaction({ to: daughterSafe.address, value: accountBalance }) + expect(await ethers.provider.getBalance(daughterSafe.address)).to.be.eq(accountBalance) + + const transfer = ethers.parseEther('0.1') + const safeOp = buildSafeUserOpTransaction( + daughterSafe.address, + user.address, + transfer, + '0x', + '0x0', + await entryPoint.getAddress(), + false, + false, + { + initCode: daughterSafe.getInitCode(), + }, + ) + + const opData = calculateSafeOperationData(await validator.getAddress(), safeOp, await chainId()) + const signature = buildSignatureBytes([ + { + signer: parentSafe.address, + data: await user.signTypedData( + { + verifyingContract: parentSafe.address, + chainId: await chainId(), + }, + { + SafeMessage: [{ type: 'bytes', name: 'message' }], + }, + { + message: opData, + }, + ), + dynamic: true, + }, + ]) + + const userOp = buildPackedUserOperationFromSafeUserOperation({ + safeOp, + // Replace the 2nd word of static part of signature containing the pointer to dynamic part with invalid pointer value + signature: + signature.slice(0, 66) + + ((signature.length - 2) / 2).toString(16).padStart(64, '0') + + '00' + + signature.slice(132) + + signature.slice(132), + }) + + await expect(entryPoint.handleOps([userOp], await relayer.getAddress())) + .to.be.revertedWithCustomError(entryPoint, 'FailedOp') + .withArgs(0, 'AA24 signature error') + }) + function isEventLog(log: Log): log is EventLog { return typeof (log as Partial).eventName === 'string' } diff --git a/modules/4337/test/erc4337/Safe4337Module.spec.ts b/modules/4337/test/erc4337/Safe4337Module.spec.ts index 744a4b63..e8782349 100644 --- a/modules/4337/test/erc4337/Safe4337Module.spec.ts +++ b/modules/4337/test/erc4337/Safe4337Module.spec.ts @@ -302,6 +302,38 @@ describe('Safe4337Module', () => { expect(await safeFromEntryPoint.validateUserOp.staticCall(userOp, ethers.ZeroHash, 0)).to.eq(packedValidationData) }) + + it('should indicate failed validation data when dynamic position pointer is invalid', async () => { + const { user, safeModule, entryPoint } = await setupTests() + + const validAfter = BigInt(ethers.hexlify(ethers.randomBytes(3))) + const validUntil = validAfter + BigInt(ethers.hexlify(ethers.randomBytes(3))) + + const safeOp = buildSafeUserOpTransaction( + await safeModule.getAddress(), + user.address, + 0, + '0x', + '0', + await entryPoint.getAddress(), + false, + false, + { + validAfter, + validUntil, + }, + ) + + const userOp = buildPackedUserOperationFromSafeUserOperation({ + safeOp, + signature: ethers.hexlify(ethers.randomBytes(32)) + '00'.padStart(64, '0') + '00' + ethers.hexlify(ethers.randomBytes(65)).slice(2), + }) + const packedValidationData = packValidationData(1, validUntil, validAfter) + const entryPointImpersonator = await ethers.getSigner(await entryPoint.getAddress()) + const safeFromEntryPoint = safeModule.connect(entryPointImpersonator) + + expect(await safeFromEntryPoint.validateUserOp.staticCall(userOp, ethers.ZeroHash, 0)).to.eq(packedValidationData) + }) }) describe('execUserOp', () => {