Skip to content

Commit 94361d9

Browse files
feat: setup
1 parent 0184799 commit 94361d9

File tree

6 files changed

+256
-0
lines changed

6 files changed

+256
-0
lines changed

test/foundry/mocks/Counter.sol

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.28;
3+
4+
contract Counter {
5+
error CounterRevertOperation();
6+
7+
uint256 private _number;
8+
9+
function incrementNumber() public {
10+
_number++;
11+
}
12+
13+
function decrementNumber() public {
14+
_number--;
15+
}
16+
17+
function getNumber() public view returns (uint256) {
18+
return _number;
19+
}
20+
21+
function revertOperation() public pure {
22+
revert CounterRevertOperation();
23+
}
24+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.27;
3+
4+
import {IModule} from '../../../src/interfaces/IERC7579Module.sol';
5+
import {IModuleManager} from '../../../src/interfaces/core/IModuleManager.sol';
6+
import {
7+
ERC1271_INVALID,
8+
ERC1271_MAGICVALUE,
9+
MODULE_TYPE_VALIDATOR,
10+
VALIDATION_FAILED,
11+
VALIDATION_SUCCESS
12+
} from '../../../src/types/Constants.sol';
13+
14+
import {MessageHashUtils} from '@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol';
15+
import {PackedUserOperation} from 'account-abstraction/interfaces/PackedUserOperation.sol';
16+
import {ERC7739Validator} from 'erc7739Validator/ERC7739Validator.sol';
17+
import {ECDSA} from 'solady/utils/ECDSA.sol';
18+
19+
contract MockValidator is ERC7739Validator {
20+
error ValidatorStillInstalled();
21+
22+
using ECDSA for bytes32;
23+
24+
mapping(address => address) public smartAccountOwners;
25+
26+
function validateUserOp(
27+
PackedUserOperation calldata userOp,
28+
bytes32 userOpHash
29+
) external view returns (uint256 validation) {
30+
address owner = getOwner(msg.sender);
31+
return _validateSignatureForOwner(owner, userOpHash, userOp.signature) ? VALIDATION_SUCCESS : VALIDATION_FAILED;
32+
}
33+
34+
function isValidSignatureWithSender(
35+
address sender,
36+
bytes32 hash,
37+
bytes calldata signature
38+
) external view virtual returns (bytes4 sigValidationResult) {
39+
// can put additional checks based on sender here
40+
return _erc1271IsValidSignatureWithSender(sender, hash, _erc1271UnwrapSignature(signature));
41+
}
42+
43+
// ISessionValidator interface for smart session
44+
function validateSignatureWithData(
45+
bytes32 hash,
46+
bytes calldata sig,
47+
bytes calldata data
48+
) external view returns (bool validSig) {
49+
address owner = address(bytes20(data[0:20]));
50+
return _validateSignatureForOwner(owner, hash, sig);
51+
}
52+
53+
function _validateSignatureForOwner(
54+
address owner,
55+
bytes32 hash,
56+
bytes calldata signature
57+
) internal view returns (bool) {
58+
if (_recoverSigner(hash, signature) == owner) return true;
59+
if (_recoverSigner(hash.toEthSignedMessageHash(), signature) == owner) return true;
60+
return false;
61+
}
62+
63+
function _recoverSigner(bytes32 hash, bytes calldata signature) internal view returns (address) {
64+
return hash.tryRecoverCalldata(signature);
65+
}
66+
67+
/// @dev Returns whether the `hash` and `signature` are valid.
68+
/// Obtains the authorized signer's credentials and calls some
69+
/// module's specific internal function to validate the signature
70+
/// against credentials.
71+
function _erc1271IsValidSignatureNowCalldata(
72+
bytes32 hash,
73+
bytes calldata signature
74+
) internal view override returns (bool) {
75+
// call custom internal function to validate the signature against credentials
76+
return _validateSignatureForOwner(getOwner(msg.sender), hash, signature);
77+
}
78+
79+
/// @dev Returns whether the `sender` is considered safe, such
80+
/// that we don't need to use the nested EIP-712 workflow.
81+
/// See: https://mirror.xyz/curiousapple.eth/pFqAdW2LiJ-6S4sg_u1z08k4vK6BCJ33LcyXpnNb8yU
82+
// The canonical `MulticallerWithSigner` at 0x000000000000D9ECebf3C23529de49815Dac1c4c
83+
// is known to include the account in the hash to be signed.
84+
// msg.sender = Smart Account
85+
// sender = 1271 og request sender
86+
function _erc1271CallerIsSafe(address sender) internal view virtual override returns (bool) {
87+
return (
88+
sender == 0x000000000000D9ECebf3C23529de49815Dac1c4c // MulticallerWithSigner
89+
|| sender == msg.sender
90+
);
91+
}
92+
93+
/**
94+
* Get the owner of the smart account
95+
* @param smartAccount The address of the smart account
96+
* @return The owner of the smart account
97+
*/
98+
function getOwner(address smartAccount) public view returns (address) {
99+
address owner = smartAccountOwners[smartAccount];
100+
return owner == address(0) ? smartAccount : owner;
101+
}
102+
103+
function onInstall(bytes calldata data) external {
104+
smartAccountOwners[msg.sender] = address(bytes20(data));
105+
}
106+
107+
function onUninstall(bytes calldata data) external {
108+
if (IModuleManager(msg.sender).isModuleInstalled(MODULE_TYPE_VALIDATOR, address(this), '')) {
109+
revert ValidatorStillInstalled();
110+
}
111+
data;
112+
delete smartAccountOwners[msg.sender];
113+
}
114+
115+
function isModuleType(uint256 moduleTypeId) external pure returns (bool) {
116+
return moduleTypeId == MODULE_TYPE_VALIDATOR;
117+
}
118+
119+
function isOwner(address account, address owner) external view returns (bool) {
120+
return smartAccountOwners[account] == owner;
121+
}
122+
123+
function isInitialized(address) external view returns (bool) {
124+
return smartAccountOwners[msg.sender] != address(0);
125+
}
126+
}

test/foundry/utils/CheatCodes.sol

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
import {Test, Vm, stdMath} from 'forge-std/Test.sol';
5+
6+
/// @title CheatCodes - A utility contract for testing with cheat codes
7+
/// @notice Provides various helper functions for testing
8+
contract CheatCodes is Test {
9+
/// @notice Creates a new wallet from a given name
10+
/// @param name The name to generate a wallet from
11+
/// @return wallet A struct containing the new wallet's address and private key
12+
function newWallet(string memory name) internal returns (Vm.Wallet memory) {
13+
Vm.Wallet memory wallet = vm.createWallet(name);
14+
vm.label(wallet.addr, name);
15+
return wallet;
16+
}
17+
18+
/// @notice Signs a message with the given address
19+
/// @param signer The address to sign the message with
20+
/// @param hash The hash of the message to sign
21+
/// @return v The recovery id (v)
22+
/// @return r Output of ECDSA signature (r)
23+
/// @return s Output of ECDSA signature (s)
24+
function signMessage(address signer, bytes32 hash) internal pure returns (uint8 v, bytes32 r, bytes32 s) {
25+
uint256 privateKey = uint256(keccak256(abi.encodePacked(signer)));
26+
(v, r, s) = vm.sign(privateKey, hash);
27+
}
28+
29+
/// @notice Mocks the next call to be made from a specific address
30+
/// @param addr The address to make the next call from
31+
function prank(address addr) internal {
32+
vm.prank(addr);
33+
}
34+
35+
/// @notice Starts mocking calls to be made from a specific address
36+
/// @param addr The address to make the calls from
37+
function startPrank(address addr) internal {
38+
vm.startPrank(addr);
39+
}
40+
41+
/// @notice Stops mocking calls to be made from a specific address
42+
function stopPrank() internal {
43+
vm.stopPrank();
44+
}
45+
46+
/// @notice Creates a snapshot of the current state
47+
/// @return The ID of the created snapshot
48+
function createSnapshot() internal returns (uint256) {
49+
return vm.snapshot();
50+
}
51+
52+
/// @notice Reverts the state to a specific snapshot
53+
/// @param snapshotId The ID of the snapshot to revert to
54+
function revertToSnapshot(uint256 snapshotId) internal {
55+
vm.revertTo(snapshotId);
56+
}
57+
58+
/// @notice Skips the test if a specific condition is met
59+
/// @param condition The condition to check
60+
function skipTest(bool condition) internal {
61+
if (condition) {
62+
vm.skip(true);
63+
}
64+
}
65+
66+
/// @notice Asserts that two uint256 values are approximately equal
67+
/// @param a The first value to compare
68+
/// @param b The second value to compare
69+
/// @param maxPercentDelta The maximum allowed percentage difference
70+
function almostEq(uint256 a, uint256 b, uint256 maxPercentDelta) internal {
71+
if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.
72+
73+
uint256 percentDelta = stdMath.percentDelta(a, b);
74+
75+
if (percentDelta > maxPercentDelta) {
76+
emit log('Error: a ~= b not satisfied [uint]');
77+
emit log_named_uint(' Left', a);
78+
emit log_named_uint(' Right', b);
79+
emit log_named_decimal_uint(' Max % Delta', maxPercentDelta * 100, 18);
80+
emit log_named_decimal_uint(' % Delta', percentDelta * 100, 18);
81+
fail();
82+
}
83+
}
84+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
contract EventsAndErrors {
5+
// placeholder
6+
event ModuleInstalled(uint256 hookType, address module);
7+
event ModuleUninstalled(uint256 hookType, address module);
8+
event ModuleUpdated(uint256 hookType, address module);
9+
event ModuleUpgraded(uint256 hookType, address module);
10+
event ModuleDowngraded(uint256 hookType, address module);
11+
event ModuleRemoved(uint256 hookType, address module);
12+
event ModuleAdded(uint256 hookType, address module);
13+
event ModuleReplaced(uint256 hookType, address module);
14+
}

test/foundry/utils/TestBase.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
// Startale Account Base

test/foundry/utils/TestHelper.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.28;
3+
4+
// Helper functions for testing

0 commit comments

Comments
 (0)