@@ -5,30 +5,26 @@ pragma solidity ^0.8.10;
55
66import {IERC20 } from "@openzeppelin/interfaces/IERC20.sol " ;
77import {IPoolAddressesProvider} from "@aave-v3-core/interfaces/IPoolAddressesProvider.sol " ;
8- import {TransparentUpgradeableProxy} from "@openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol " ;
9- import {ATokenVault} from "./ATokenVault.sol " ;
108import {SafeERC20} from "@openzeppelin/token/ERC20/utils/SafeERC20.sol " ;
11- import {ProxyAdmin} from "@openzeppelin/proxy/transparent/ProxyAdmin.sol " ;
9+ import {ATokenVaultRevenueSplitterOwner} from "./ATokenVaultRevenueSplitterOwner.sol " ;
10+ import {ImmutableATokenVault} from "./ImmutableATokenVault.sol " ;
11+ import {SSTORE2} from "@solmate/utils/SSTORE2.sol " ;
12+ import {Create2} from "@openzeppelin/utils/Create2.sol " ;
13+ import {LibZip} from "@solady/utils/LibZip.sol " ;
1214
1315/**
14- * @title ATokenVaultImplDeploymentLib
15- * @author Aave Labs
16- * @notice Library that handles the deployment of the ATokenVault implementation contract
17- * @dev This library is a helper to avoid holding the ATokenVault bytecode in the factory contract avoiding exceeding
18- * the contract size limit.
16+ * @dev Struct containing constructor parameters for vault deployment
1917 */
20- library ATokenVaultImplDeploymentLib {
21- function deployVaultImpl (
22- address underlying ,
23- uint16 referralCode ,
24- IPoolAddressesProvider poolAddressesProvider
25- ) external returns (address vault ) {
26- return address (new ATokenVault (
27- underlying,
28- referralCode,
29- poolAddressesProvider
30- ));
31- }
18+ struct VaultParams {
19+ address underlying;
20+ uint16 referralCode;
21+ IPoolAddressesProvider poolAddressesProvider;
22+ address owner;
23+ uint256 initialFee;
24+ string shareName;
25+ string shareSymbol;
26+ uint256 initialLockDeposit;
27+ ATokenVaultRevenueSplitterOwner.Recipient[] revenueRecipients;
3228}
3329
3430/**
@@ -39,75 +35,48 @@ library ATokenVaultImplDeploymentLib {
3935contract ATokenVaultFactory {
4036 using SafeERC20 for IERC20 ;
4137
42- /*//////////////////////////////////////////////////////////////
43- EVENTS
44- //////////////////////////////////////////////////////////////*/
45-
4638 /**
4739 * @dev Emitted when a new vault is deployed
48- * @param vault The address of the deployed vault proxy
49- * @param implementation The address of the vault implementation
40+ * @param vault The address of the deployed vault
5041 * @param underlying The underlying asset address
5142 * @param deployer The address that deployed the vault
5243 * @param params The parameters used to deploy the vault
5344 */
5445 event VaultDeployed (
5546 address indexed vault ,
56- address indexed implementation ,
5747 address indexed underlying ,
5848 address deployer ,
5949 VaultParams params
6050 );
6151
62- /*//////////////////////////////////////////////////////////////
63- CONSTANTS
64- //////////////////////////////////////////////////////////////*/
65-
66- /// @notice Proxy admin address for all deployed vaults, with renounced ownership.
67- /// @dev Future version will deploy a plain immutable vault without proxy.
68- address internal immutable RENOUNCED_PROXY_ADMIN;
69-
70- /*//////////////////////////////////////////////////////////////
71- STRUCTS
72- //////////////////////////////////////////////////////////////*/
73-
7452 /**
75- * @dev Struct containing constructor parameters for vault deployment
53+ * @dev Emitted when a new revenue splitter owner is deployed
54+ * @param revenueSplitterOwner The address of the deployed revenue splitter owner
55+ * @param vault The address of the vault to split the revenue from
56+ * @param owner The address of the owner of the revenue splitter, effective owner of the vault
57+ * @param revenueRecipients The recipients of the revenue
7658 */
77- struct VaultParams {
78- address underlying;
79- uint16 referralCode;
80- IPoolAddressesProvider poolAddressesProvider;
81- address owner;
82- uint256 initialFee;
83- string shareName;
84- string shareSymbol;
85- uint256 initialLockDeposit;
86- }
59+ event RevenueSplitterOwnerDeployed (
60+ address indexed revenueSplitterOwner ,
61+ address indexed vault ,
62+ address indexed owner ,
63+ ATokenVaultRevenueSplitterOwner.Recipient[] revenueRecipients
64+ );
8765
88- /*//////////////////////////////////////////////////////////////
89- CONSTRUCTOR
90- //////////////////////////////////////////////////////////////*/
66+ address immutable public VAULT_CREATION_CODE_SSTORE2_POINTER;
9167
92- /**
93- * @dev Constructor
94- * @param proxyAdmin The address that will be the admin of all deployed proxies. Must have renounced ownership.
95- */
96- constructor (address proxyAdmin ) {
97- RENOUNCED_PROXY_ADMIN = proxyAdmin;
98- require (ProxyAdmin (proxyAdmin).owner () == address (0 ), "PROXY_ADMIN_OWNERSHIP_NOT_RENOUNCED " );
99- }
68+ uint256 internal _nextSaltNonce;
10069
101- /*//////////////////////////////////////////////////////////////
102- EXTERNAL FUNCTIONS
103- //////////////////////////////////////////////////////////////*/
70+ constructor () {
71+ VAULT_CREATION_CODE_SSTORE2_POINTER = SSTORE2. write (LibZip. flzCompress ( type (ImmutableATokenVault).creationCode));
72+ }
10473
10574 /**
106- * @notice Deploy a new ATokenVault with the given parameters
75+ * @notice Deploys a new ATokenVault with the given parameters
10776 * @param params All parameters needed for vault deployment and initialization
10877 * @return vault The address of the deployed vault proxy
10978 */
110- function deployVault (VaultParams memory params ) public returns (address vault ) {
79+ function deployVault (VaultParams memory params ) public returns (address ) {
11180 require (params.underlying != address (0 ), "ZERO_ADDRESS_NOT_VALID " );
11281 require (address (params.poolAddressesProvider) != address (0 ), "ZERO_ADDRESS_NOT_VALID " );
11382 require (params.owner != address (0 ), "ZERO_ADDRESS_NOT_VALID " );
@@ -121,34 +90,84 @@ contract ATokenVaultFactory {
12190 params.initialLockDeposit
12291 );
12392
124- address implementation = ATokenVaultImplDeploymentLib.deployVaultImpl (
125- params.underlying,
126- params.referralCode,
127- params.poolAddressesProvider
93+ bytes32 salt = bytes32 (_nextSaltNonce++ );
94+
95+ bytes memory vaultInitCode = abi.encodePacked (
96+ LibZip.flzDecompress (SSTORE2.read (VAULT_CREATION_CODE_SSTORE2_POINTER)),
97+ abi.encode (
98+ params.underlying,
99+ params.referralCode,
100+ params.poolAddressesProvider,
101+ address (this ),
102+ params.initialFee,
103+ params.shareName,
104+ params.shareSymbol,
105+ params.initialLockDeposit
106+ )
128107 );
129108
130- vault = address (new TransparentUpgradeableProxy (
131- implementation,
132- RENOUNCED_PROXY_ADMIN,
133- ""
134- ));
109+ address vaultAddress = _computeVaultAddress (vaultInitCode, salt);
135110
136- IERC20 (params.underlying).safeApprove (vault , params.initialLockDeposit);
111+ IERC20 (params.underlying).safeApprove (vaultAddress , params.initialLockDeposit);
137112
138- ATokenVault (vault). initialize (
139- params.owner,
140- params.initialFee,
141- params.shareName,
142- params.shareSymbol,
143- params.initialLockDeposit
144- );
113+ _deployVault (vaultInitCode, salt);
114+
115+ address owner = params.owner;
116+ if (params.revenueRecipients. length > 0 ) {
117+ owner = _deployRevenueSplitterOwner (vaultAddress, params.owner, params.revenueRecipients);
118+ }
119+ ImmutableATokenVault (vaultAddress). transferOwnership (owner );
145120
146121 emit VaultDeployed (
147- vault,
148- implementation,
122+ vaultAddress,
149123 params.underlying,
150124 msg .sender ,
151125 params
152126 );
127+
128+ return vaultAddress;
129+ }
130+
131+ /**
132+ * @notice Deploys a new ATokenVaultRevenueSplitterOwner with the given parameters
133+ * @param vaultAddress The address of the vault to split the revenue from
134+ * @param owner The address of the owner of the revenue splitter, effective owner of the vault
135+ * @param revenueRecipients The recipients of the revenue
136+ * @return revenueSplitter The address of the deployed revenue splitter
137+ */
138+ function deployRevenueSplitterOwner (
139+ address vaultAddress ,
140+ address owner ,
141+ ATokenVaultRevenueSplitterOwner.Recipient[] memory revenueRecipients
142+ ) external returns (address ) {
143+ return _deployRevenueSplitterOwner (vaultAddress, owner, revenueRecipients);
144+ }
145+
146+ function _deployRevenueSplitterOwner (
147+ address vaultAddress ,
148+ address owner ,
149+ ATokenVaultRevenueSplitterOwner.Recipient[] memory revenueRecipients
150+ ) internal returns (address ) {
151+ address revenueSplitter = address (new ATokenVaultRevenueSplitterOwner (vaultAddress, owner, revenueRecipients));
152+ emit RevenueSplitterOwnerDeployed (revenueSplitter, vaultAddress, owner, revenueRecipients);
153+ return revenueSplitter;
154+ }
155+
156+ function _computeVaultAddress (bytes memory vaultInitCode , bytes32 salt ) internal view returns (address ) {
157+ return Create2.computeAddress (salt, keccak256 (vaultInitCode));
158+ }
159+
160+ function _deployVault (bytes memory vaultInitCode , bytes32 salt ) internal returns (address ) {
161+ address vaultAddress;
162+ assembly {
163+ vaultAddress := create2 (0 , add (vaultInitCode, 32 ), mload (vaultInitCode), salt)
164+ // If the deployment fails, revert bubbling up the error
165+ if iszero (vaultAddress) {
166+ let returnDataSize := returndatasize ()
167+ returndatacopy (0 , 0 , returnDataSize)
168+ revert (0 , returnDataSize)
169+ }
170+ }
171+ return vaultAddress;
153172 }
154173}
0 commit comments