contract MWTest is Test {
MondrianWallet mw;
MockERC20 erc20;
MockEntryPoint ep;
address user = makeAddr("user");
address secondUser = makeAddr("user2");
uint256 constant MINT_AMOUNT = 10 ether;
function setUp() public {
if (block.chainid == 1) {
ep = MockEntryPoint(
payable(address(0x0000000071727De22E5E9d8BAf0edAc6f37da032))
);
} else {
ep = new MockEntryPoint();
}
vm.prank(user);
mw = new MondrianWallet(address(ep));
erc20 = new MockERC20();
vm.deal(user, MINT_AMOUNT);
}
function testNFTImplementation() public {
vm.prank(secondUser);
MondrianWallet mw2 = new MondrianWallet(address(ep));
address ownerOf2 = mw2.ownerOf(1);
address ownerOf1 = mw.ownerOf(1);
assertEq(ownerOf2, secondUser);
assertEq(ownerOf1, user);
assert(ownerOf2 != ownerOf1);
}
}
pragma solidity ^0.8.23;
import "@openzeppelin/contracts/utils/Create2.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./SimpleAccount.sol";
* A sample factory contract for SimpleAccount
* A UserOperations "initCode" holds the address of the factory, and a method call (to createAccount, in this sample factory).
* The factory's createAccount returns the target account address even if it is already installed.
* This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.
*/
contract SimpleAccountFactory is ERC721 {
SimpleAccount public immutable accountImplementation;
constructor(IEntryPoint _entryPoint) {
accountImplementation = new SimpleAccount(_entryPoint);
}
* create an account, and return its address.
* returns the address even if the account is already deployed.
* Note that during UserOperation execution, this method is called only if the account is not deployed.
* This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation
*/
function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret) {
address addr = getAddress(owner, salt);
uint256 codeSize = addr.code.length;
if (codeSize > 0) {
return SimpleAccount(payable(addr));
}
ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(
address(accountImplementation),
abi.encodeCall(SimpleAccount.initialize, (owner))
)));
_mint(address(ret),1);
}
* calculate the counterfactual address of this account as it would be returned by createAccount()
*/
function getAddress(address owner,uint256 salt) public view returns (address) {
return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(
type(ERC1967Proxy).creationCode,
abi.encode(
address(accountImplementation),
abi.encodeCall(SimpleAccount.initialize, (owner))
)
)));
}
}