@@ -44,14 +44,19 @@ abstract contract LiquidityVault is
4444 * @notice The storage for the LiquidityVault contract
4545 * @param _decimals The decimals of the vault
4646 * @param _decimalsOffset The decimals offset for measuring internal precision of shares
47- * @param _depositableAsset The address of the depositable asset
48- * @param _redeemableAsset The address of the redeemable asset
47+ * @param _depositableAssets The addresses of the depositable assets
48+ * @param _depositableAssetIndex The index of the depositable assets (one-indexed)
49+ * @param _redeemableAssets The addresses of the redeemable assets
50+ * @param _redeemableAssetIndex The index of the redeemable assets (one-indexed)
4951 */
5052 struct LiquidityVaultStorage {
5153 uint8 _decimals;
5254 uint8 _decimalsOffset;
53- address _depositableAsset;
54- address _redeemableAsset;
55+ address [] _depositableAssets;
56+ mapping (address => uint256 ) _depositableAssetIndex;
57+ address [] _redeemableAssets;
58+ mapping (address => uint256 ) _redeemableAssetIndex;
59+
5560 bool _whitelistEnforced;
5661 }
5762
@@ -83,11 +88,11 @@ abstract contract LiquidityVault is
8388 string memory symbol ,
8489 uint8 _decimals ,
8590 uint8 _decimalsOffset ,
86- address _depositableAsset ,
87- address _redeemableAsset
91+ address [] memory _depositableAssets ,
92+ address [] memory _redeemableAssets
8893 ) internal onlyInitializing {
8994 __ERC20_init_unchained (name, symbol);
90- __LiquidityVault_init_unchained (_decimals, _decimalsOffset, _depositableAsset, _redeemableAsset );
95+ __LiquidityVault_init_unchained (_decimals, _decimalsOffset, _depositableAssets, _redeemableAssets );
9196 }
9297
9398 /**
@@ -97,14 +102,20 @@ abstract contract LiquidityVault is
97102 function __LiquidityVault_init_unchained (
98103 uint8 _decimals ,
99104 uint8 _decimalsOffset ,
100- address _depositableAsset ,
101- address _redeemableAsset
105+ address [] memory _depositableAssets ,
106+ address [] memory _redeemableAssets
102107 ) internal onlyInitializing {
103108 LiquidityVaultStorage storage $ = _getLiquidityVaultStorage ();
104109 $._decimals = _decimals;
105110 $._decimalsOffset = _decimalsOffset;
106- $._depositableAsset = _depositableAsset;
107- $._redeemableAsset = _redeemableAsset;
111+ $._depositableAssets = _depositableAssets;
112+ for (uint256 i = 0 ; i < _depositableAssets.length ; i++ ) {
113+ $._depositableAssetIndex[_depositableAssets[i]] = i + 1 ;
114+ }
115+ $._redeemableAssets = _redeemableAssets;
116+ for (uint256 i = 0 ; i < _redeemableAssets.length ; i++ ) {
117+ $._redeemableAssetIndex[_redeemableAssets[i]] = i + 1 ;
118+ }
108119 $._whitelistEnforced = false ;
109120 }
110121
@@ -114,18 +125,18 @@ abstract contract LiquidityVault is
114125 * @param symbol The symbol of the liquidity vault
115126 * @param _decimals The decimals of the liquidity vault
116127 * @param _decimalsOffset The decimals offset for measuring internal precision of shares
117- * @param _depositableAsset The address of the depositable asset
118- * @param _redeemableAsset The address of the redeemable asset
128+ * @param _depositableAssets The addresses of the depositable assets
129+ * @param _redeemableAssets The addresses of the redeemable assets
119130 */
120131 function initialize (
121132 string memory name ,
122133 string memory symbol ,
123134 uint8 _decimals ,
124135 uint8 _decimalsOffset ,
125- address _depositableAsset ,
126- address _redeemableAsset
136+ address [] memory _depositableAssets ,
137+ address [] memory _redeemableAssets
127138 ) external virtual initializer {
128- __LiquidityVault_init (name, symbol, _decimals, _decimalsOffset, _depositableAsset, _redeemableAsset );
139+ __LiquidityVault_init (name, symbol, _decimals, _decimalsOffset, _depositableAssets, _redeemableAssets );
129140 _grantRole (DEFAULT_ADMIN_ROLE, _msgSender ());
130141 }
131142
@@ -184,13 +195,13 @@ abstract contract LiquidityVault is
184195 }
185196
186197 /// @inheritdoc ILiquidityVault
187- function depositableAsset () public view virtual override returns (address ) {
188- return _getLiquidityVaultStorage ()._depositableAsset ;
198+ function depositableAssets () public view virtual override returns (address [] memory ) {
199+ return _getLiquidityVaultStorage ()._depositableAssets ;
189200 }
190201
191202 /// @inheritdoc ILiquidityVault
192- function redeemableAsset () public view virtual override returns (address ) {
193- return _getLiquidityVaultStorage ()._redeemableAsset ;
203+ function redeemableAssets () public view virtual override returns (address [] memory ) {
204+ return _getLiquidityVaultStorage ()._redeemableAssets ;
194205 }
195206
196207 function _totalAssets () internal view virtual returns (uint256 );
@@ -206,8 +217,12 @@ abstract contract LiquidityVault is
206217 }
207218
208219 /// @dev Internal conversion function (from shares to assets) with support for rounding direction.
209- function _convertToAssets (uint256 shares , Math.Rounding rounding ) internal view virtual returns (uint256 ) {
210- return shares.mulDiv (totalAssets () + 1 , totalSupply () + 10 ** decimalsOffset (), rounding);
220+ function _convertToAssets (uint256 shares , Math.Rounding rounding ) internal view virtual returns (uint256 [] memory ) {
221+ uint256 [] memory assets = new uint256 [](redeemableAssets ().length );
222+ for (uint256 i = 0 ; i < redeemableAssets ().length ; i++ ) {
223+ assets[i] = shares.mulDiv (IERC20 (redeemableAssets ()[i]).balanceOf (address (this )) + 1 , totalSupply () + 10 ** decimalsOffset (), rounding);
224+ }
225+ return assets;
211226 }
212227
213228 /// @inheritdoc ILiquidityVault
@@ -220,28 +235,39 @@ abstract contract LiquidityVault is
220235 }
221236
222237 /// @inheritdoc ILiquidityVault
223- function deposit (uint256 assets ) external virtual override whenNotPaused checkWhitelistEnforced {
238+ function deposit (address depositableAsset , uint256 assets ) external virtual override whenNotPaused checkWhitelistEnforced {
239+ // Validate the depositable asset is in the depositable assets list
240+ if (_getLiquidityVaultStorage ()._depositableAssetIndex[depositableAsset] == 0 ) {
241+ revert AssetNotDepositable (depositableAsset);
242+ }
224243 // Calculate the corresponding amount of shares for the deposited amount
225244 uint256 shares = _convertToShares (assets, Math.Rounding.Floor);
226245 // Mint the corresponding amount of shares to the sender
227246 _mint (msg .sender , shares);
228247 // Emit the deposited event
229- emit Deposited (msg .sender , depositableAsset () , assets, shares);
248+ emit Deposited (msg .sender , depositableAsset, assets, shares);
230249 // Transfer the depositable asset from the sender to the vault
231- IERC20 (depositableAsset () ).safeTransferFrom (msg .sender , address (this ), assets);
250+ IERC20 (depositableAsset).safeTransferFrom (msg .sender , address (this ), assets);
232251 }
233252
234253 /// @inheritdoc ILiquidityVault
235254 /// @dev No whitelist enforcement for redeeming. This prevents funds from being locked in the vault.
236255 function redeem (uint256 shares ) external virtual override whenNotPaused {
237256 // Calculate the corresponding amount of assets for the redeemed shares
238- uint256 assets = _convertToAssets (shares, Math.Rounding.Floor);
257+ uint256 [] memory assetAmounts = _convertToAssets (shares, Math.Rounding.Floor);
239258 // Burn the corresponding amount of shares
240259 _burn (msg .sender , shares);
260+
261+ // Cache the redeemable assets array
262+ address [] memory rAssets = redeemableAssets ();
263+
241264 // Emit the redeemed event
242- emit Redeemed (msg .sender , redeemableAsset (), assets, shares);
243- // Transfer the redeemable asset from the vault to the sender
244- IERC20 (redeemableAsset ()).safeTransfer (msg .sender , assets);
265+ emit Redeemed (msg .sender , rAssets, assetAmounts, shares);
266+
267+ // Transfer the corresponding amount of redeemable assets to the sender
268+ for (uint256 i = 0 ; i < rAssets.length ; i++ ) {
269+ IERC20 (rAssets[i]).safeTransfer (msg .sender , assetAmounts[i]);
270+ }
245271 }
246272}
247273
0 commit comments