This repository has been archived by the owner on Nov 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
VertexFactory.sol
199 lines (167 loc) · 7.57 KB
/
VertexFactory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Clones} from "@openzeppelin/proxy/Clones.sol";
import {VertexCore} from "src/VertexCore.sol";
import {VertexAccount} from "src/VertexAccount.sol";
import {VertexStrategy} from "src/VertexStrategy.sol";
import {VertexPolicy} from "src/VertexPolicy.sol";
import {VertexStrategy} from "src/VertexStrategy.sol";
import {VertexPolicyMetadata} from "src/VertexPolicyMetadata.sol";
import {Strategy, RoleHolderData, RolePermissionData} from "src/lib/Structs.sol";
import {RoleDescription} from "src/lib/UDVTs.sol";
/// @title Vertex Factory
/// @author Llama (vertex@llama.xyz)
/// @notice Factory for deploying new Vertex systems.
contract VertexFactory {
// ======================================
// ======== Errors and Modifiers ========
// ======================================
error OnlyVertex();
modifier onlyRootVertex() {
if (msg.sender != address(ROOT_VERTEX)) revert OnlyVertex();
_;
}
// ========================
// ======== Events ========
// ========================
event VertexCreated(uint256 indexed id, string indexed name, address vertexCore, address vertexPolicyNFT);
event StrategyLogicAuthorized(address indexed strategyLogic);
event AccountLogicAuthorized(address indexed accountLogic);
// =============================================================
// ======== Constants, Immutables and Storage Variables ========
// =============================================================
/// @notice The VertexCore implementation (logic) contract.
VertexCore public immutable VERTEX_CORE_LOGIC;
/// @notice The Vertex Policy implementation (logic) contract.
VertexPolicy public immutable VERTEX_POLICY_LOGIC;
/// @notice Mapping of all authorized Vertex Strategy implementation (logic) contracts.
mapping(address => bool) public authorizedStrategyLogics;
/// @notice Mapping of all authorized Vertex Account implementation (logic) contracts.
mapping(address => bool) public authorizedAccountLogics;
/// @notice The Vertex instance responsible for deploying new Vertex instances.
VertexCore public immutable ROOT_VERTEX;
/// @notice The Vertex Policy Metadata contract.
VertexPolicyMetadata public vertexPolicyMetadata;
/// @notice The current number of vertex systems created.
uint256 public vertexCount;
// ======================================================
// ======== Contract Creation and Initialization ========
// ======================================================
constructor(
VertexCore vertexCoreLogic,
address initialVertexStrategyLogic,
address initialVertexAccountLogic,
VertexPolicy vertexPolicyLogic,
VertexPolicyMetadata _vertexPolicyMetadata,
string memory name,
Strategy[] memory initialStrategies,
string[] memory initialAccounts,
RoleDescription[] memory initialRoleDescriptions,
RoleHolderData[] memory initialRoleHolders,
RolePermissionData[] memory initialRolePermissions
) {
VERTEX_CORE_LOGIC = vertexCoreLogic;
VERTEX_POLICY_LOGIC = vertexPolicyLogic;
vertexPolicyMetadata = _vertexPolicyMetadata;
_authorizeStrategyLogic(initialVertexStrategyLogic);
_authorizeAccountLogic(initialVertexAccountLogic);
ROOT_VERTEX = _deploy(
name,
initialVertexStrategyLogic,
initialVertexAccountLogic,
initialStrategies,
initialAccounts,
initialRoleDescriptions,
initialRoleHolders,
initialRolePermissions
);
}
// ===========================================
// ======== External and Public Logic ========
// ===========================================
/// @notice Deploys a new Vertex system. This function can only be called by the initial Vertex system.
/// @param name The name of this Vertex system.
/// @param strategyLogic The VertexStrategy implementation (logic) contract to use for this Vertex system.
/// @param accountLogic The VertexAccount implementation (logic) contract to use for this Vertex system.
/// @param initialStrategies The list of initial strategies.
/// @param initialAccounts The list of initial accounts.
/// @param initialRoleDescriptions The list of initial role descriptions.
/// @param initialRoleHolders The list of initial role holders and their role expirations.
/// @param initialRolePermissions The list initial permissions given to roles.
/// @return the address of the VertexCore contract of the newly created system.
function deploy(
string memory name,
address strategyLogic,
address accountLogic,
Strategy[] memory initialStrategies,
string[] memory initialAccounts,
RoleDescription[] memory initialRoleDescriptions,
RoleHolderData[] memory initialRoleHolders,
RolePermissionData[] memory initialRolePermissions
) external onlyRootVertex returns (VertexCore) {
return _deploy(
name,
strategyLogic,
accountLogic,
initialStrategies,
initialAccounts,
initialRoleDescriptions,
initialRoleHolders,
initialRolePermissions
);
}
/// @notice Authorizes a strategy logic contract.
/// @param strategyLogic The strategy logic contract to authorize.
function authorizeStrategyLogic(address strategyLogic) external onlyRootVertex {
_authorizeStrategyLogic(strategyLogic);
}
/// @notice Authorizes an account logic contract.
/// @param accountLogic The account logic contract to authorize.
function authorizeAccountLogic(address accountLogic) external onlyRootVertex {
_authorizeAccountLogic(accountLogic);
}
/// @notice Returns the token URI for a given Vertex Policy Holder.
/// @param name The name of the Vertex system.
/// @param symbol The symbol of the Vertex system.
/// @param tokenId The token ID of the Vertex Policy Holder.
function tokenURI(string memory name, string memory symbol, uint256 tokenId) external view returns (string memory) {
return vertexPolicyMetadata.tokenURI(name, symbol, tokenId);
}
/// @notice Sets the Vertex Policy Metadata contract.
/// @param _vertexPolicyMetadata The Vertex Policy Metadata contract.
function setPolicyMetadata(VertexPolicyMetadata _vertexPolicyMetadata) external onlyRootVertex {
vertexPolicyMetadata = _vertexPolicyMetadata;
}
// ================================
// ======== Internal Logic ========
// ================================
function _deploy(
string memory name,
address strategyLogic,
address accountLogic,
Strategy[] memory initialStrategies,
string[] memory initialAccounts,
RoleDescription[] memory initialRoleDescriptions,
RoleHolderData[] memory initialRoleHolders,
RolePermissionData[] memory initialRolePermissions
) internal returns (VertexCore vertex) {
// Deploy the system.
VertexPolicy policy =
VertexPolicy(Clones.cloneDeterministic(address(VERTEX_POLICY_LOGIC), keccak256(abi.encode(name))));
policy.initialize(name, initialRoleDescriptions, initialRoleHolders, initialRolePermissions);
vertex = VertexCore(Clones.cloneDeterministic(address(VERTEX_CORE_LOGIC), keccak256(abi.encode(name))));
vertex.initialize(name, policy, strategyLogic, accountLogic, initialStrategies, initialAccounts);
policy.setVertex(address(vertex));
unchecked {
emit VertexCreated(vertexCount++, name, address(vertex), address(policy));
}
}
function _authorizeStrategyLogic(address strategyLogic) internal {
authorizedStrategyLogics[strategyLogic] = true;
emit StrategyLogicAuthorized(strategyLogic);
}
function _authorizeAccountLogic(address accountLogic) internal {
authorizedAccountLogics[accountLogic] = true;
emit AccountLogicAuthorized(accountLogic);
}
}