-
Notifications
You must be signed in to change notification settings - Fork 22
/
CMTAT_BEACON_FACTORY.sol
109 lines (99 loc) · 4.09 KB
/
CMTAT_BEACON_FACTORY.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
//SPDX-License-Identifier: MPL-2.0
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
import '@openzeppelin/contracts/utils/Create2.sol';
import '@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol';
import "../CMTAT_PROXY.sol";
import "./libraries/CMTATFactoryRoot.sol";
/**
* @notice Factory to deploy beacon proxy
*
*/
contract CMTAT_BEACON_FACTORY is AccessControl, CMTATFactoryRoot {
UpgradeableBeacon public immutable beacon;
/**
* @param implementation_ contract implementation
* @param factoryAdmin admin
* @param beaconOwner owner
*/
constructor(address implementation_, address factoryAdmin, address beaconOwner, bool useCustomSalt_)CMTATFactoryRoot(factoryAdmin, useCustomSalt_) {
if(beaconOwner == address(0)){
revert FactoryErrors.CMTAT_Factory_AddressZeroNotAllowedForBeaconOwner();
}
if(implementation_ == address(0)){
// Forwarder is the zero address if no implementation provided
implementation_ = address(new CMTAT_PROXY(address(0)));
}
beacon = new UpgradeableBeacon(implementation_, beaconOwner);
}
/*//////////////////////////////////////////////////////////////
PUBLIC/EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice deploy CMTAT with a beacon proxy
*
*/
function deployCMTAT(
bytes32 deploymentSaltInput,
// CMTAT function initialize
CMTAT_ARGUMENT calldata cmtatArgument
) public onlyRole(CMTAT_DEPLOYER_ROLE) returns(BeaconProxy cmtat) {
bytes32 deploymentSalt = _checkAndDetermineDeploymentSalt(deploymentSaltInput);
bytes memory bytecode = _getBytecode(
// CMTAT function initialize
cmtatArgument);
cmtat = _deployBytecode(bytecode, deploymentSalt);
return cmtat;
}
/**
* @param deploymentSalt salt for the deployment
* @param cmtatArgument argument for the function initialize
* @notice get the proxy address depending on a particular salt
*/
function computedProxyAddress(
bytes32 deploymentSalt,
// CMTAT function initialize
CMTAT_ARGUMENT calldata cmtatArgument) public view returns (address) {
bytes memory bytecode = _getBytecode(
// CMTAT function initialize
cmtatArgument);
return Create2.computeAddress(deploymentSalt, keccak256(bytecode), address(this) );
}
/**
* @notice get the implementation address from the beacon
* @return implementation address
*/
function implementation() public view returns (address) {
return beacon.implementation();
}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Deploy CMTAT and push the created CMTAT in the list
*/
function _deployBytecode(bytes memory bytecode, bytes32 deploymentSalt) internal returns (BeaconProxy cmtat) {
address cmtatAddress = Create2.deploy(0, deploymentSalt, bytecode);
cmtat = BeaconProxy(payable(cmtatAddress));
cmtats[cmtatCounterId] = address(cmtat);
emit CMTAT(address(cmtat), cmtatCounterId);
++cmtatCounterId;
cmtatsList.push(address(cmtat));
return cmtat;
}
/**
* @notice return the smart contract bytecode
*/
function _getBytecode(
// CMTAT function initialize
CMTAT_ARGUMENT calldata cmtatArgument) internal view returns(bytes memory bytecode) {
bytes memory _implementation = abi.encodeWithSelector(
CMTAT_PROXY(address(0)).initialize.selector,
cmtatArgument.CMTATAdmin,
cmtatArgument.ERC20Attributes,
cmtatArgument.baseModuleAttributes,
cmtatArgument.engines
);
bytecode = abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(address(beacon), _implementation));
}
}