Skip to content

Commit

Permalink
draft: Zora Account Manager (#378)
Browse files Browse the repository at this point in the history
* draft: Zora Account Manager

* cleanup pr

---------

Co-authored-by: Dan Oved <stangogh@gmail.com>
  • Loading branch information
kulkarohan and oveddan authored Jul 10, 2024
1 parent da3a13f commit 55c2312
Show file tree
Hide file tree
Showing 11 changed files with 321 additions and 31 deletions.
16 changes: 16 additions & 0 deletions packages/smart-wallet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env

lib/
3 changes: 3 additions & 0 deletions packages/smart-wallet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Smart Wallet Deployer

Contracts and deployment scripts for the Zora Smart Wallet Factory.
20 changes: 20 additions & 0 deletions packages/smart-wallet/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[profile.default]
evm_version = 'paris'
optimizer = true
optimizer_runs = 1_000_000
out = 'out'
solc = '0.8.23'
via_ir = true
libs = ["node_modules"]

[fuzz]
runs = 500

[fmt]
bracket_spacing = true
int_types = "long"
line_length = 150
quote_style = "double"
tab_width = 4

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
20 changes: 20 additions & 0 deletions packages/smart-wallet/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "smart-wallet",
"version": "0.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"scripts": {
"prettier:check": "prettier --check 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'",
"prettier": "prettier --write 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'"
},
"dependencies": {
"@openzeppelin/contracts": "5.0.2",
"@openzeppelin/contracts-upgradeable": "5.0.2",
"ds-test": "https://github.com/dapphub/ds-test#cd98eff28324bfac652e63a239a60632a761790b",
"forge-std": "https://github.com/foundry-rs/forge-std#v1.8.2"
},
"devDependencies": {
"permissionless": "^0.0.35"
}
}
4 changes: 4 additions & 0 deletions packages/smart-wallet/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ds-test/=node_modules/ds-test/src/
forge-std/=node_modules/forge-std/src/
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/
8 changes: 8 additions & 0 deletions packages/smart-wallet/src/ZoraAccountManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract ZoraAccountManager is ERC1967Proxy {
constructor(address _logic, bytes memory _data) ERC1967Proxy(_logic, _data) { }
}
55 changes: 55 additions & 0 deletions packages/smart-wallet/src/ZoraAccountManagerImpl.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { UUPSUpgradeable, ERC1967Utils } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import { IEntryPoint } from "./interfaces/IEntryPoint.sol";
import { ISmartWalletFactory } from "./interfaces/ISmartWalletFactory.sol";

contract ZoraAccountManagerImpl is UUPSUpgradeable, OwnableUpgradeable {
IEntryPoint public constant entryPoint = IEntryPoint(0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789);
ISmartWalletFactory public constant smartWalletFactory = ISmartWalletFactory(0x0BA5ED0c6AA8c49038F819E587E2633c4A9F428a);

constructor() initializer { }

function initialize(address initialOwner) public initializer {
__Ownable_init(initialOwner);
}

event ZoraSmartWalletCreated(address indexed smartWallet, address indexed baseOwner, address[] owners, uint256 nonce);

function createSmartWallet(bytes[] calldata encodedOwners, uint256 nonce) external returns (address) {
smartWalletFactory.createAccount(encodedOwners, nonce);

address[] memory owners = new address[](encodedOwners.length);

for (uint256 i; i < encodedOwners.length; ++i) {
owners[i] = abi.decode(encodedOwners[i], (address));
}

address smartWallet = smartWalletFactory.getAddress(encodedOwners, nonce);

emit ZoraSmartWalletCreated(smartWallet, owners[0], owners, nonce);

return smartWallet;
}

function getAddress(bytes[] calldata encodedOwners, uint256 nonce) external view returns (address) {
return smartWalletFactory.getAddress(encodedOwners, nonce);
}

function getNonce(address smartWallet) external view returns (uint256) {
return entryPoint.getNonce(smartWallet, 0);
}

function getKeyNonce(address smartWallet, uint192 key) external view returns (uint256) {
return entryPoint.getNonce(smartWallet, key);
}

function implementation() external view returns (address) {
return ERC1967Utils.getImplementation();
}

function _authorizeUpgrade(address) internal override onlyOwner { }
}
6 changes: 6 additions & 0 deletions packages/smart-wallet/src/interfaces/IEntryPoint.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface IEntryPoint {
function getNonce(address sender, uint192 key) external view returns (uint256);
}
10 changes: 10 additions & 0 deletions packages/smart-wallet/src/interfaces/ISmartWalletFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

interface ISmartWalletFactory {
function createAccount(bytes[] calldata owners, uint256 nonce) external;
function getAddress(bytes[] calldata owners, uint256 nonce) external view returns (address);

function initCodeHash() external view returns (bytes32);
function implementation() external view returns (address);
}
63 changes: 63 additions & 0 deletions packages/smart-wallet/test/ZoraAccountManager.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";

import { ZoraAccountManagerImpl } from "../src/ZoraAccountManagerImpl.sol";
import { ZoraAccountManager } from "../src/ZoraAccountManager.sol";
import { ISmartWalletFactory } from "../src/interfaces/ISmartWalletFactory.sol";

contract ZoraAccountManagerTest is Test {
struct Users {
address alice;
address bob;
address charlie;
address owner;
}

Users internal users;
address[] internal mockOwners;

ZoraAccountManagerImpl internal managerImpl;
ZoraAccountManagerImpl internal manager;

ISmartWalletFactory internal constant smartWalletFactory = ISmartWalletFactory(0x0BA5ED0c6AA8c49038F819E587E2633c4A9F428a);

function setUp() public {
vm.createSelectFork(vm.envString("ZORA_SEPOLIA_RPC_URL"));

users = Users({ alice: makeAddr("alice"), bob: makeAddr("bob"), charlie: makeAddr("charlie"), owner: makeAddr("owner") });
mockOwners = new address[](3);
mockOwners[0] = users.alice;
mockOwners[1] = users.bob;
mockOwners[2] = users.charlie;

managerImpl = new ZoraAccountManagerImpl();
manager = ZoraAccountManagerImpl(address(new ZoraAccountManager(address(managerImpl), "")));
manager.initialize(users.owner);
}

function testDeploy() public view {
assertEq(manager.implementation(), address(managerImpl));
assertEq(manager.owner(), users.owner);
}

function testCreateSmartWallet() public {
bytes[] memory encodedOwners = encodeOwners(mockOwners);
uint256 nonce = 0;

address smartWallet = manager.createSmartWallet(encodedOwners, nonce);

assertEq(manager.getAddress(encodedOwners, nonce), smartWallet);
}

function encodeOwners(address[] memory owners) public pure returns (bytes[] memory) {
bytes[] memory encodedOwners = new bytes[](owners.length);

for (uint256 i; i < owners.length; ++i) {
encodedOwners[i] = abi.encode(owners[i]);
}

return encodedOwners;
}
}
Loading

0 comments on commit 55c2312

Please sign in to comment.