This repository has been archived by the owner on Jan 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 201
/
ProxyFactory.sol
99 lines (80 loc) · 3.42 KB
/
ProxyFactory.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
pragma solidity ^0.5.3;
import "./InitializableAdminUpgradeabilityProxy.sol";
import "../cryptography/ECDSA.sol";
contract ProxyFactory {
event ProxyCreated(address proxy);
bytes32 private contractCodeHash;
constructor() public {
contractCodeHash = keccak256(
type(InitializableAdminUpgradeabilityProxy).creationCode
);
}
function deployMinimal(address _logic, bytes memory _data) public returns (address proxy) {
// Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
bytes20 targetBytes = bytes20(_logic);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
proxy := create(0, clone, 0x37)
}
emit ProxyCreated(address(proxy));
if(_data.length > 0) {
(bool success,) = proxy.call(_data);
require(success);
}
}
function deploy(uint256 _salt, address _logic, address _admin, bytes memory _data) public returns (address) {
return _deployProxy(_salt, _logic, _admin, _data, msg.sender);
}
function deploySigned(uint256 _salt, address _logic, address _admin, bytes memory _data, bytes memory _signature) public returns (address) {
address signer = getSigner(_salt, _logic, _admin, _data, _signature);
require(signer != address(0), "Invalid signature");
return _deployProxy(_salt, _logic, _admin, _data, signer);
}
function getDeploymentAddress(uint256 _salt, address _sender) public view returns (address) {
// Adapted from https://github.com/archanova/solidity/blob/08f8f6bedc6e71c24758d20219b7d0749d75919d/contracts/contractCreator/ContractCreator.sol
bytes32 salt = _getSalt(_salt, _sender);
bytes32 rawAddress = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
contractCodeHash
)
);
return address(bytes20(rawAddress << 96));
}
function getSigner(uint256 _salt, address _logic, address _admin, bytes memory _data, bytes memory _signature) public view returns (address) {
bytes32 msgHash = OpenZeppelinUpgradesECDSA.toEthSignedMessageHash(
keccak256(
abi.encodePacked(
_salt, _logic, _admin, _data, address(this)
)
)
);
return OpenZeppelinUpgradesECDSA.recover(msgHash, _signature);
}
function _deployProxy(uint256 _salt, address _logic, address _admin, bytes memory _data, address _sender) internal returns (address) {
InitializableAdminUpgradeabilityProxy proxy = _createProxy(_salt, _sender);
emit ProxyCreated(address(proxy));
proxy.initialize(_logic, _admin, _data);
return address(proxy);
}
function _createProxy(uint256 _salt, address _sender) internal returns (InitializableAdminUpgradeabilityProxy) {
address payable addr;
bytes memory code = type(InitializableAdminUpgradeabilityProxy).creationCode;
bytes32 salt = _getSalt(_salt, _sender);
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
return InitializableAdminUpgradeabilityProxy(addr);
}
function _getSalt(uint256 _salt, address _sender) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_salt, _sender));
}
}