@@ -24,22 +24,24 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
2424
2525 mapping (bytes32 guid = > FailedMessage) public failedMessages;
2626
27- constructor (address _ovault , address _asset , address _share ) {
27+ constructor (address _ovault , address _assetOFT , address _shareOFT ) {
2828 OVAULT = IERC4626 (_ovault);
29- ASSET_OFT = _asset ;
30- SHARE_OFT = _share ;
29+ ASSET_OFT = _assetOFT ;
30+ SHARE_OFT = _shareOFT ;
3131
32- if (! IOFT (_share ).approvalRequired ()) {
33- revert ShareOFTShouldBeLockboxAdapter (address (_share ));
32+ if (! IOFT (_shareOFT ).approvalRequired ()) {
33+ revert ShareOFTShouldBeLockboxAdapter (address (_shareOFT ));
3434 }
3535
3636 ENDPOINT = address (IOAppCore (ASSET_OFT).endpoint ());
3737 HUB_EID = ILayerZeroEndpointV2 (ENDPOINT).eid ();
3838
39- // Approve the adapter to spend the share tokens held by this contract
40- IERC20 (IOFT (_share).token ()).approve (address (_ovault), type (uint256 ).max);
41- IERC20 (IOFT (_share).token ()).approve (_share, type (uint256 ).max);
42- IERC20 (IOFT (_asset).token ()).approve (address (_ovault), type (uint256 ).max);
39+ // Approve the ovault to spend the share and asset tokens held by this contract
40+ IERC20 (IOFT (_shareOFT).token ()).approve (address (_ovault), type (uint256 ).max);
41+ IERC20 (IOFT (_assetOFT).token ()).approve (address (_ovault), type (uint256 ).max);
42+
43+ // Approve the shareOFTAdapter with the share tokens held by this contract
44+ IERC20 (IOFT (_shareOFT).token ()).approve (_shareOFT, type (uint256 ).max);
4345 }
4446
4547 function lzCompose (
@@ -70,6 +72,7 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
7072 try this .decodeSendParam (sendParamEncoded) returns (SendParam memory sendParamDecoded ) {
7173 /// @dev In the case of a valid decode we have the raw SendParam to be forwarded to the target OFT (oft)
7274 sendParam = sendParamDecoded;
75+ /// @dev Setting target amount to 0 since the actual value will be determined by executeOVaultAction() (i.e. deposit or redeem)
7376 sendParam.amountLD = 0 ;
7477 } catch {
7578 /// @dev In the case of a failed decode we store the failed message and emit an event.
@@ -87,11 +90,14 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
8790 }
8891
8992 /// @dev Try to execute the action on the target OFT. If we hit an issue then it rolls back the storage changes.
90- try this .executeOVaultAction (_refundOFT, amount, sendParam) returns (uint256 vaultAmount ) {
93+ try this .executeOVaultActionWithSlippageCheck (_refundOFT, amount, sendParam.minAmountLD) returns (
94+ uint256 vaultAmount
95+ ) {
96+ /// @dev Setting the target amount to the actual value of the action (i.e. deposit or redeem)
9197 sendParam.amountLD = vaultAmount;
9298 } catch (bytes memory errMsg ) {
9399 failedMessages[_guid] = FailedMessage (oft, sendParam, _refundOFT, refundSendParam);
94- emit GenericError (_guid, oft, errMsg);
100+ emit OVaultError (_guid, oft, errMsg); /// @dev Since the ovault can revert with custom errors, the error message is valuable
95101 return ;
96102 }
97103
@@ -102,7 +108,7 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
102108 /// @dev A failed send can happen due to not enough msg.value
103109 /// @dev Since we have the target tokens in the composer, we can retry with more gas.
104110 failedMessages[_guid] = FailedMessage (oft, sendParam, address (0 ), refundSendParam);
105- emit SendFailed (_guid, oft);
111+ emit SendFailed (_guid, oft); /// @dev This can be due to msg.value or layerzero config (dvn config, etc)
106112 return ;
107113 }
108114 }
@@ -113,22 +119,26 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
113119 }
114120
115121 /// @dev External call for try...catch logic in lzCompose()
116- function executeOVaultAction (
122+ function executeOVaultActionWithSlippageCheck (
117123 address _oft ,
118124 uint256 _amount ,
119- SendParam calldata _sendParam
125+ uint256 _minAmountLD
120126 ) external nonReentrant returns (uint256 vaultAmount ) {
121127 if (msg .sender != address (this )) revert OnlySelf (msg .sender );
128+
122129 vaultAmount = _executeOVaultAction (_oft, _amount);
123- if (vaultAmount < _sendParam.minAmountLD) {
130+
131+ if (vaultAmount < _minAmountLD) {
124132 /// @dev Will rollback on this function's storage changes (trade does not happen)
125- revert NotEnoughTargetTokens (vaultAmount, _sendParam.minAmountLD );
133+ revert NotEnoughTargetTokens (vaultAmount, _minAmountLD );
126134 }
127135 }
128136
129137 /// @dev External call for try...catch logic in lzCompose()
130138 function send (address _oft , SendParam calldata _sendParam ) external payable nonReentrant {
131139 if (msg .sender != address (this )) revert OnlySelf (msg .sender );
140+
141+ /// @dev If the destination is the HUB chain, we just transfer the tokens to the receiver
132142 if (_sendParam.dstEid == HUB_EID) {
133143 address _receiver = _sendParam.to.bytes32ToAddress ();
134144 uint256 _amountLD = _sendParam.amountLD;
@@ -141,6 +151,8 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
141151 emit SentOnHub (_receiver, _oft, _amountLD);
142152 return ;
143153 }
154+
155+ /// @dev If the destination is not the HUB chain, we send the message to the target OFT
144156 _send (_oft, _sendParam);
145157 }
146158
@@ -159,7 +171,7 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
159171 }
160172
161173 /// @dev Permissionless function to retry the message with more gas
162- /// @dev Probabilistically possible if the OFT.send() fails - ex: invalid peer
174+ /// @dev Failure case when there is a LayerZero config issue - ex: dvn config
163175 function retry (bytes32 _guid , bytes calldata _extraOptions ) external payable nonReentrant {
164176 FailedMessage memory failedMessage = failedMessages[_guid];
165177 if (failedGuidState (_guid) != FailedState.CanOnlyRetry) revert CanNotRetry (_guid);
@@ -174,6 +186,7 @@ contract OVaultComposer is IOVaultComposer, ReentrancyGuard {
174186 }
175187
176188 /// @dev Retry mechanism for transactions that failed due to slippage. This can revert.
189+ /// @dev Failure case when there is a LayerZero config issue - ex: dvn config
177190 function retryWithSwap (bytes32 _guid , bytes calldata _extraOptions ) external payable {
178191 FailedMessage memory failedMessage = failedMessages[_guid];
179192 if (failedGuidState (_guid) != FailedState.CanRetryWithSwap) revert CanNotRetry (_guid);
0 commit comments