Skip to content

Commit 42840c4

Browse files
authored
ovault cleanup #1 (#1594)
Signed-off-by: shankar <shankar@layerzerolabs.org>
1 parent 5167acf commit 42840c4

6 files changed

Lines changed: 39 additions & 26 deletions

File tree

examples/ovault-evm/test/OVault.t.sol renamed to examples/ovault-evm/test/OVault_ERC4626_Equivalence.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contract
1515
import { console } from "forge-std/console.sol";
1616

1717
/// @dev Equivalent to Solmate's ERC4626 tests - https://github.com/transmissions11/solmate/blob/main/src/test/ERC4626.t.sol
18-
contract OVaultTest is TestHelperOz5 {
18+
contract OVaultERC4626EquivalenceTest is TestHelperOz5 {
1919
using Math for uint256;
2020

2121
MockOFT assetOFT;

examples/ovault-evm/test/composer/OVaultComposer_Unit.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ contract OVaultComposerUnitTest is OVaultComposerBaseTest {
231231
TOKENS_TO_SEND,
232232
TOKENS_TO_SEND + 1
233233
);
234-
emit IOVaultComposer.GenericError(guid, address(shareOFT_arb), errMsg);
234+
emit IOVaultComposer.OVaultError(guid, address(shareOFT_arb), errMsg);
235235

236236
assertEq(assetOFT_arb.totalSupply(), assetOFT_arb.balanceOf(address(OVaultComposerArb)), TOKENS_TO_SEND);
237237
assertEq(oVault_arb.totalSupply(), 0);
@@ -351,7 +351,7 @@ contract OVaultComposerUnitTest is OVaultComposerBaseTest {
351351
TOKENS_TO_SEND,
352352
targetAmount
353353
);
354-
emit IOVaultComposer.GenericError(guid, address(shareOFT_arb), errMsg);
354+
emit IOVaultComposer.OVaultError(guid, address(shareOFT_arb), errMsg);
355355

356356
vm.prank(arbEndpoint);
357357
OVaultComposerArb.lzCompose{ value: 1 ether }(address(assetOFT_arb), guid, composeMsg, arbExecutor, "");

packages/ovault-evm/contracts/OVaultComposer.sol

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

packages/ovault-evm/contracts/interfaces/IOVaultComposer.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ interface IOVaultComposer is IOAppComposer {
2626
event SendFailed(bytes32 indexed guid, address indexed oft);
2727
event Refunded(bytes32 indexed guid, address indexed oft);
2828
event Retried(bytes32 indexed guid, address indexed oft);
29-
event GenericError(bytes32 indexed guid, address indexed oft, bytes errMsg);
29+
event OVaultError(bytes32 indexed guid, address indexed oft, bytes errMsg);
3030
event NoPeer(bytes32 indexed guid, address indexed oft, uint32 dstEid);
3131

3232
/// ========================== Error Messages =====================================
@@ -48,10 +48,10 @@ interface IOVaultComposer is IOAppComposer {
4848
function ENDPOINT() external view returns (address);
4949

5050
/// ========================== FUNCTIONS =====================================
51-
function executeOVaultAction(
51+
function executeOVaultActionWithSlippageCheck(
5252
address _oft,
5353
uint256 _amount,
54-
SendParam calldata _sendParam
54+
uint256 _minAmountLD
5555
) external returns (uint256 vaultAmount);
5656

5757
function refund(bytes32 guid, bytes memory extraOptions) external payable;

packages/ovault-evm/test/OVault.t.sol renamed to packages/ovault-evm/test/OVault_ERC4626_Equivalence.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contract
1515
import { console } from "forge-std/console.sol";
1616

1717
/// @dev Equivalent to Solmate's ERC4626 tests - https://github.com/transmissions11/solmate/blob/main/src/test/ERC4626.t.sol
18-
contract OVaultTest is TestHelperOz5 {
18+
contract OVaultERC4626EquivalenceTest is TestHelperOz5 {
1919
using Math for uint256;
2020

2121
MockOFT assetOFT;

packages/ovault-evm/test/composer/OVaultComposer_Unit.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ contract OVaultComposerUnitTest is OVaultComposerBaseTest {
231231
TOKENS_TO_SEND,
232232
TOKENS_TO_SEND + 1
233233
);
234-
emit IOVaultComposer.GenericError(guid, address(shareOFT_arb), errMsg);
234+
emit IOVaultComposer.OVaultError(guid, address(shareOFT_arb), errMsg);
235235

236236
assertEq(assetOFT_arb.totalSupply(), assetOFT_arb.balanceOf(address(OVaultComposerArb)), TOKENS_TO_SEND);
237237
assertEq(oVault_arb.totalSupply(), 0);
@@ -351,7 +351,7 @@ contract OVaultComposerUnitTest is OVaultComposerBaseTest {
351351
TOKENS_TO_SEND,
352352
targetAmount
353353
);
354-
emit IOVaultComposer.GenericError(guid, address(shareOFT_arb), errMsg);
354+
emit IOVaultComposer.OVaultError(guid, address(shareOFT_arb), errMsg);
355355

356356
vm.prank(arbEndpoint);
357357
OVaultComposerArb.lzCompose{ value: 1 ether }(address(assetOFT_arb), guid, composeMsg, arbExecutor, "");

0 commit comments

Comments
 (0)