-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathTransparentProxyFactoryBase.sol
132 lines (115 loc) · 3.98 KB
/
TransparentProxyFactoryBase.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
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {TransparentUpgradeableProxy} from 'openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol';
import {ProxyAdmin} from 'openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol';
import {ITransparentProxyFactory} from './interfaces/ITransparentProxyFactory.sol';
/**
* @title TransparentProxyFactory
* @author BGD Labs
* @notice Factory contract to create transparent proxies, both with CREATE and CREATE2
* @dev `create()` and `createDeterministic()` are not unified for clearer interface, and at the same
* time allowing `createDeterministic()` with salt == 0
**/
abstract contract TransparentProxyFactoryBase is ITransparentProxyFactory {
mapping(address proxy => address admin) internal _proxyToAdmin;
/// @inheritdoc ITransparentProxyFactory
function getProxyAdmin(address proxy) external view returns (address) {
return _proxyToAdmin[proxy];
}
/// @inheritdoc ITransparentProxyFactory
function create(
address logic,
address initialOwner,
bytes calldata data
) external returns (address) {
address proxy = address(new TransparentUpgradeableProxy(logic, initialOwner, data));
_storeProxyInRegistry(proxy);
emit ProxyCreated(proxy, logic, initialOwner);
return proxy;
}
/// @inheritdoc ITransparentProxyFactory
function createProxyAdmin(address initialOwner) external returns (address) {
address proxyAdmin = address(new ProxyAdmin(initialOwner));
emit ProxyAdminCreated(proxyAdmin, initialOwner);
return proxyAdmin;
}
/// @inheritdoc ITransparentProxyFactory
function createDeterministic(
address logic,
address initialOwner,
bytes calldata data,
bytes32 salt
) external returns (address) {
address proxy = address(new TransparentUpgradeableProxy{salt: salt}(logic, initialOwner, data));
_storeProxyInRegistry(proxy);
emit ProxyDeterministicCreated(proxy, logic, initialOwner, salt);
return proxy;
}
/// @inheritdoc ITransparentProxyFactory
function createDeterministicProxyAdmin(
address initialOwner,
bytes32 salt
) external returns (address) {
address proxyAdmin = address(new ProxyAdmin{salt: salt}(initialOwner));
emit ProxyAdminDeterministicCreated(proxyAdmin, initialOwner, salt);
return proxyAdmin;
}
/// @inheritdoc ITransparentProxyFactory
function predictCreateDeterministic(
address logic,
address initialOwner,
bytes calldata data,
bytes32 salt
) public view returns (address) {
return
_predictCreate2Address(
address(this),
salt,
type(TransparentUpgradeableProxy).creationCode,
abi.encode(logic, initialOwner, data)
);
}
/// @inheritdoc ITransparentProxyFactory
function predictCreateDeterministicProxyAdmin(
bytes32 salt,
address initialOwner
) public view returns (address) {
return
_predictCreate2Address(
address(this),
salt,
type(ProxyAdmin).creationCode,
abi.encode(initialOwner)
);
}
function _predictCreate2Address(
address creator,
bytes32 salt,
bytes memory creationCode,
bytes memory constructorArgs
) internal pure virtual returns (address);
function _storeProxyInRegistry(address proxy) internal {
_proxyToAdmin[proxy] = _predictProxyAdminAddress(proxy);
}
/**
* @dev the prediction only depends on the address of the proxy.
* The admin is always the first and only contract deployed by the proxy.
*/
function _predictProxyAdminAddress(address proxy) internal pure virtual returns (address) {
return
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xd6), // RLP prefix for a list with total length 22
bytes1(0x94), // RLP prefix for an address (20 bytes)
proxy, // 20-byte address
uint8(1) // 1-byte nonce
)
)
)
)
);
}
}