Skip to content

Commit

Permalink
mock accept everything module
Browse files Browse the repository at this point in the history
  • Loading branch information
livingrockrises committed Dec 7, 2023
1 parent cdaa8ea commit 9c46126
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 21 deletions.
79 changes: 79 additions & 0 deletions contracts/smart-account/modules/MockValidationModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/* solhint-disable no-unused-import */

import {BaseAuthorizationModule} from "./BaseAuthorizationModule.sol";
import {EIP1271_MAGIC_VALUE} from "contracts/smart-account/interfaces/ISignatureValidator.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {IAuthorizationModule} from "../interfaces/IAuthorizationModule.sol";
import {ISignatureValidator} from "../interfaces/ISignatureValidator.sol";

/**
* @title Mock validation module which allows any user operation.
* @notice DO NOT USE THIS MODULE IN PRODUCTION
*/

contract MockValidationModule is BaseAuthorizationModule {
string public constant NAME = "Mock Validation Module";
string public constant VERSION = "0.1.0";

function initForSmartAccount() external returns (address) {
return address(this);
}

/// @inheritdoc IAuthorizationModule
function validateUserOp(
UserOperation calldata userOp,
bytes32 userOpHash
) external view virtual override returns (uint256) {
(userOp, userOpHash);
return VALIDATION_SUCCESS;
}

/**
* @inheritdoc ISignatureValidator
* @dev Validates a signature for a message.
* @dev Appends smart account address to the hash to avoid replay attacks
* To be called from a Smart Account.
* @param dataHash Hash of the message that was signed.
* @param moduleSignature Signature to be validated.
* @return EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
*/
function isValidSignature(
bytes32 dataHash,
bytes memory moduleSignature
) public view virtual override returns (bytes4) {
return
isValidSignatureForAddress(dataHash, moduleSignature, msg.sender);
}

function isValidSignatureForAddress(
bytes32 dataHash,

Check failure on line 52 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "dataHash" is unused
bytes memory moduleSignature,

Check failure on line 53 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "moduleSignature" is unused
address smartAccount

Check failure on line 54 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "smartAccount" is unused
) public view virtual returns (bytes4) {
return EIP1271_MAGIC_VALUE;
}

/// @inheritdoc ISignatureValidator
function isValidSignatureUnsafe(
bytes32 dataHash,
bytes memory moduleSignature
) public view virtual returns (bytes4) {
return
isValidSignatureForAddressUnsafe(
dataHash,
moduleSignature,
msg.sender
);
}

function isValidSignatureForAddressUnsafe(
bytes32 dataHash,

Check failure on line 73 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "dataHash" is unused
bytes memory moduleSignature,

Check failure on line 74 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "moduleSignature" is unused
address smartAccount

Check failure on line 75 in contracts/smart-account/modules/MockValidationModule.sol

View workflow job for this annotation

GitHub Actions / Lint sources (18.x)

Variable "smartAccount" is unused
) public view virtual returns (bytes4) {
return EIP1271_MAGIC_VALUE;
}
}
55 changes: 34 additions & 21 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Deployer__factory,
ERC20SessionValidationModule__factory,
EcdsaOwnershipRegistryModule__factory,
MockValidationModule__factory,
MultichainECDSAValidator__factory,
PasskeyRegistryModule__factory,
SessionKeyManager__factory,
Expand Down Expand Up @@ -283,6 +284,16 @@ async function deploySmartContractOwnershipRegistryModule(
);
}

async function deployMockValidationModule(deployerInstance: Deployer) {
await deployGeneric(
deployerInstance,
DEPLOYMENT_SALTS.MOCK_VALIDATION_MODULE,
`${MockValidationModule__factory.bytecode}`,
"MockValidationModule",
[]
);
}

async function deployAddressResolver(deployerInstance: Deployer) {
if (
!smartAccountFactoryV1Address ||
Expand Down Expand Up @@ -387,27 +398,29 @@ export async function mainDeploy(): Promise<Record<string, string>> {
console.log("=========================================");

const deployerInstance = await getPredeployedDeployerContractInstance();
await deployEntryPointContract(deployerInstance);
console.log("=========================================");
await deployBaseWalletImpContract(deployerInstance);
console.log("=========================================");
await deployWalletFactoryContract(deployerInstance);
console.log("=========================================");
await deployEcdsaOwnershipRegistryModule(deployerInstance);
console.log("=========================================");
await deployMultichainValidatorModule(deployerInstance);
console.log("=========================================");
await deployPasskeyModule(deployerInstance);
console.log("=========================================");
await deploySessionKeyManagerModule(deployerInstance);
console.log("=========================================");
await deployBatchedSessionRouterModule(deployerInstance);
console.log("=========================================");
await deployErc20SessionValidationModule(deployerInstance);
console.log("=========================================");
await deploySmartContractOwnershipRegistryModule(deployerInstance);
console.log("=========================================");
await deployAddressResolver(deployerInstance);
// await deployEntryPointContract(deployerInstance);
// console.log("=========================================");
// await deployBaseWalletImpContract(deployerInstance);
// console.log("=========================================");
// await deployWalletFactoryContract(deployerInstance);
// console.log("=========================================");
// await deployEcdsaOwnershipRegistryModule(deployerInstance);
// console.log("=========================================");
// await deployMultichainValidatorModule(deployerInstance);
// console.log("=========================================");
// await deployPasskeyModule(deployerInstance);
// console.log("=========================================");
// await deploySessionKeyManagerModule(deployerInstance);
// console.log("=========================================");
// await deployBatchedSessionRouterModule(deployerInstance);
// console.log("=========================================");
// await deployErc20SessionValidationModule(deployerInstance);
// console.log("=========================================");
// await deploySmartContractOwnershipRegistryModule(deployerInstance);
// console.log("=========================================");
// await deployAddressResolver(deployerInstance);
// console.log("=========================================");
await deployMockValidationModule(deployerInstance);
console.log("=========================================");

console.log(
Expand Down
3 changes: 3 additions & 0 deletions scripts/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type DeploymentSaltsType = {
ERC20_SESSION_VALIDATION_MODULE: string;
SMART_CONTRACT_OWNERSHIP_REGISTRY_MODULE: string;
ADDRESS_RESOLVER: string;
MOCK_VALIDATION_MODULE: string;
};

// Dev Salts
Expand All @@ -62,6 +63,7 @@ export const DEPLOYMENT_SALTS_DEV: DeploymentSaltsType = {
SMART_CONTRACT_OWNERSHIP_REGISTRY_MODULE:
"DEVX_SMART_CONTRACT_OWNERSHIP_REGISTRY_MODULE_V0_21082023",
ADDRESS_RESOLVER: "DEVX_ADDRESS_RESOLVER_V0_07112023",
MOCK_VALIDATION_MODULE: "DEVX_MOCK_VALIDATION_MODULE_V1_07122023_6X7yarN",
};

// Prod Salts
Expand All @@ -86,6 +88,7 @@ export const DEPLOYMENT_SALTS_PROD: DeploymentSaltsType = {
SMART_CONTRACT_OWNERSHIP_REGISTRY_MODULE:
"PROD_SMART_CONTRACT_OWNERSHIP_REGISTRY_MODULE_V1_22082023_6X7yarN",
ADDRESS_RESOLVER: "PROD_ADDRESS_RESOLVER_V1_08112023_DZKffkv", // 0x00000e81673606e07fc79ce5f1b3b26957844468
MOCK_VALIDATION_MODULE: "PROD_MOCK_VALIDATION_MODULE_V1_07122023_6X7yarN",
};

export const DEPLOYMENT_CHAIN_GAS_PRICES: Record<
Expand Down
150 changes: 150 additions & 0 deletions test/module/MockValidationModule.specs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { expect } from "chai";
import hre, { ethers, deployments, waffle } from "hardhat";
import { hashMessage, solidityKeccak256 } from "ethers/lib/utils";
import {
makeEcdsaModuleUserOp,
getUserOpHash,
fillAndSign,
} from "../utils/userOp";
import {
getEntryPoint,
getSmartAccountFactory,
getEcdsaOwnershipRegistryModule,
deployContract,
getMockToken,
getSmartAccountWithModule,
} from "../utils/setupHelper";
import { encodeTransfer } from "../utils/testUtils";
import { AddressZero } from "@ethersproject/constants";
import { mock } from "node:test";

describe("ECDSA Registry Module: ", async () => {
const [deployer, smartAccountOwner, alice, bob, charlie] =
waffle.provider.getWallets();
const smartAccountDeploymentIndex = 0;
const SIG_VALIDATION_FAILED = 1;
const EIP1271_INVALID_SIGNATURE = "0xffffffff";
const EIP1271_MAGIC_VALUE = "0x1626ba7e";
const SIG_VALIDATION_SUCCESS = 0;

const setupTests = deployments.createFixture(async ({ deployments }) => {
await deployments.fixture();

const entryPoint = await getEntryPoint();
const saFactory = await getSmartAccountFactory();
const mockToken = await getMockToken();

const MockValidationModule = await hre.ethers.getContractFactory(
"MockValidationModule"
);

const mockModule = await MockValidationModule.deploy();
console.log(mockModule.address);

const setupData = mockModule.interface.encodeFunctionData(
"initForSmartAccount",
[]
);

const userSA = await getSmartAccountWithModule(
mockModule.address,
setupData, // can not be 0x!
smartAccountDeploymentIndex
);

const tokensToMint = ethers.utils.parseEther("100");
await mockToken.mint(userSA.address, tokensToMint.toString());
await mockToken.mint(bob.address, tokensToMint.toString());

await deployer.sendTransaction({
to: userSA.address,
value: ethers.utils.parseEther("60"),
});

await deployer.sendTransaction({
to: smartAccountOwner.address,
value: ethers.utils.parseEther("60"),
});

const randomContractCode = `
contract random {
function returnAddress() public view returns(address){
return address(this);
}
}
`;
const randomContract = await deployContract(deployer, randomContractCode);

return {
entryPoint: entryPoint,
saFactory: saFactory,
mockModule: mockModule,
randomContract: randomContract,
userSA: userSA,
mockToken: mockToken,
};
});

// validateUserOp(UserOperation calldata userOp,bytes32 userOpHash)
describe("validateUserOp(): ", async () => {
it("Returns SIG_VALIDATION_SUCCESS for a valid UserOp and valid userOpHash ", async () => {
const { mockModule, entryPoint, userSA, mockToken } = await setupTests();
const userSABalanceBefore = await mockToken.balanceOf(userSA.address);
const bobBalanceBefore = await mockToken.balanceOf(bob.address);
const tokenAmountToTransfer = ethers.utils.parseEther("3.5672");

const txnData = mockToken.interface.encodeFunctionData("transfer", [
bob.address,
tokenAmountToTransfer.toString(),
]);
const userOp = await makeEcdsaModuleUserOp(
"execute_ncC",
[mockToken.address, 0, txnData],
userSA.address,
charlie, // random dude
entryPoint,
mockModule.address,
{
preVerificationGas: 50000,
}
);
// Construct userOpHash
const provider = entryPoint?.provider;
const chainId = await provider!.getNetwork().then((net) => net.chainId);
const userOpHash = getUserOpHash(userOp, entryPoint.address, chainId);

const res = await mockModule.validateUserOp(userOp, userOpHash);
expect(res).to.be.equal(SIG_VALIDATION_SUCCESS);
await entryPoint.handleOps([userOp], bob.address);
expect(await mockToken.balanceOf(bob.address)).to.equal(
bobBalanceBefore.add(tokenAmountToTransfer)
);
expect(await mockToken.balanceOf(userSA.address)).to.equal(
userSABalanceBefore.sub(tokenAmountToTransfer)
);
});
});

describe("isValidSignatureForAddress(): ", async () => {
it("Returns EIP1271_MAGIC_VALUE always", async () => {
const { mockModule, userSA } = await setupTests();

const stringMessage = "random dude signed this message";
const messageHash = solidityKeccak256(["string"], [stringMessage]);
const messageHashAndAddress = ethers.utils.arrayify(
ethers.utils.hexConcat([messageHash, userSA.address])
);

// signMessage prepends the message with the prefix and length and then hashes it
const signature = await bob.signMessage(messageHashAndAddress);

expect(
await mockModule.isValidSignatureForAddress(
messageHash,
signature,
userSA.address
)
).to.equal(EIP1271_MAGIC_VALUE);
});
});
});
1 change: 1 addition & 0 deletions test/utils/setupHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const getSmartAccountWithModule = async (
moduleSetupData,
index
);
console.log("expectedSmartAccountAddress", expectedSmartAccountAddress);
await factory.deployCounterFactualAccount(
moduleSetupContract,
moduleSetupData,
Expand Down

0 comments on commit 9c46126

Please sign in to comment.