@pendle/core-v2 6.3.2-swaphubtest → 6.3.2-swaphubtest2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,6 @@ import {
8
8
  OFTReceipt,
9
9
  SendParam
10
10
  } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol";
11
- import {PMath} from "../../core/libraries/math/PMath.sol";
12
11
  import {ApprovedCall, IPDepositBox} from "../../interfaces/IPDepositBox.sol";
13
12
  import {SwapData} from "./swap/IPSwapExecutor.sol";
14
13
  import {SwapHubBase} from "./SwapHubBase.sol";
@@ -26,78 +25,134 @@ contract PendleCrossChainSwapHub is SwapHubBase {
26
25
  }
27
26
 
28
27
  function withdrawToken(WithdrawTokenMessage memory ms, bytes memory sig) external onlyExecutor {
29
- _verifyOwnerSigAndNonce(ms.owner, ms.expiry, ms.nonce, hashTypedData(ms), sig);
28
+ _handleWithdrawToken({ms: ms, sig: sig, claimFailed: false});
29
+ }
30
30
 
31
- IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
32
- box.withdrawTo(ms.receiver, ms.token, ms.withdrawAmount);
33
- box.payTreasury(ms.token, ms.feeAmount);
31
+ function bridgeToken(BridgeTokenMessage memory ms, bytes memory sig) external payable onlyExecutor {
32
+ _handleBridgeToken({ms: ms, sig: sig, claimFailed: false});
33
+ }
34
34
 
35
- emit WithdrawToken(ms.owner, ms.boxId, ms.receiver, ms.token, ms.withdrawAmount, ms.feeAmount);
35
+ function swapToken(SwapTokenMessage memory ms, bytes memory sig) external onlyExecutor {
36
+ _handleSwapToken({ms: ms, sig: sig, claimFailed: false});
36
37
  }
37
38
 
38
- function bridgeToken(BridgeTokenMessage memory ms, bytes memory sig) external payable onlyExecutor {
39
- _verifyOwnerSigAndNonce(ms.owner, ms.expiry, ms.nonce, hashTypedData(ms), sig);
39
+ function buyCrossChainPt(BuyCrossChainPtMessage memory ms, bytes memory sig) external payable onlyExecutor {
40
+ _handleBuyCrossChainPt({ms: ms, sig: sig, claimFailed: false});
41
+ }
40
42
 
41
- IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
42
- _bridgeToken(ms, box, msg.value);
43
- box.payTreasury(ms.token, ms.feeAmount);
43
+ function claimFee(WithdrawTokenMessage memory ms, bytes memory sig) external onlyExecutor {
44
+ _handleWithdrawToken({ms: ms, sig: sig, claimFailed: true});
45
+ }
44
46
 
45
- emit BridgeToken(ms.owner, ms.boxId, ms.bridgeExtRouter, ms.token, ms.bridgeAmount, ms.feeAmount);
47
+ function claimFee(BridgeTokenMessage memory ms, bytes memory sig) external onlyExecutor {
48
+ _handleBridgeToken({ms: ms, sig: sig, claimFailed: true});
46
49
  }
47
50
 
48
- function swapToken(SwapTokenMessage memory ms, bytes memory sig) external onlyExecutor {
49
- _verifyOwnerSigAndNonce(ms.owner, ms.expiry, ms.nonce, hashTypedData(ms), sig);
51
+ function claimFee(SwapTokenMessage memory ms, bytes memory sig) external onlyExecutor {
52
+ _handleSwapToken({ms: ms, sig: sig, claimFailed: true});
53
+ }
54
+
55
+ function claimFee(BuyCrossChainPtMessage memory ms, bytes memory sig) external onlyExecutor {
56
+ _handleBuyCrossChainPt({ms: ms, sig: sig, claimFailed: true});
57
+ }
58
+
59
+ function _handleWithdrawToken(WithdrawTokenMessage memory ms, bytes memory sig, bool claimFailed) internal {
60
+ bytes32 actionHash = hashTypedData(ms);
61
+ _verifyOwnerSig(ms.owner, ms.expiry, ms.nonce, actionHash, sig, !claimFailed);
50
62
 
51
63
  IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
52
- uint256 netTokenReceived = _swapToken(ms, box) - ms.feeAmount;
53
- box.payTreasury(ms.tokenReceived, ms.feeAmount);
54
64
 
55
- require(netTokenReceived >= ms.minReceived, InsufficientTokenReceived());
65
+ if (claimFailed) {
66
+ _markFailedAndTakeFee(actionHash, box, ms.token, ms.amountFee);
67
+ emit ClaimFeeForFailedAction(ms.owner, ms.boxId, actionHash, ms.token, ms.amountFee);
68
+ } else {
69
+ box.withdrawTo(ms.receiver, ms.token, ms.amountWithdraw);
56
70
 
57
- emit SwapToken(ms.owner, ms.boxId, ms.tokenSpent, ms.amountSpent, ms.tokenReceived, netTokenReceived);
71
+ _markSucceededAndTakeFee(actionHash, box, ms.token, ms.amountFee);
72
+ emit WithdrawToken(ms.owner, ms.boxId, actionHash, ms.receiver, ms.token, ms.amountWithdraw, ms.amountFee);
73
+ }
58
74
  }
59
75
 
60
- function buyCrossChainPt(
61
- BuyCrossChainPtIntent memory intent,
62
- bytes memory intentSig,
63
- ExecuteBuyCrossChainPtMessage memory execMsg,
64
- bytes memory execSig
65
- ) external payable onlyExecutor {
66
- _verifyOwnerSig(intent.owner, intent.expiry, hashTypedData(intent), intentSig);
67
- _verifyValidatorSig(execMsg.validator, execMsg.expiry, hashTypedData(execMsg), execSig);
76
+ function _handleBridgeToken(BridgeTokenMessage memory ms, bytes memory sig, bool claimFailed) internal {
77
+ bytes32 actionHash = hashTypedData(ms);
78
+ _verifyOwnerSig(ms.owner, ms.expiry, ms.nonce, actionHash, sig, !claimFailed);
79
+
80
+ IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
81
+
82
+ if (claimFailed) {
83
+ _markFailedAndTakeFee(actionHash, box, ms.token, ms.amountFee);
84
+ emit ClaimFeeForFailedAction(ms.owner, ms.boxId, actionHash, ms.token, ms.amountFee);
85
+ } else {
86
+ _bridgeToken(ms, box, msg.value);
87
+
88
+ _markSucceededAndTakeFee(actionHash, box, ms.token, ms.amountFee);
89
+ emit BridgeToken(
90
+ ms.owner, ms.boxId, actionHash, ms.bridgeExtRouter, ms.token, ms.amountBridge, ms.amountFee
91
+ );
92
+ }
93
+ }
68
94
 
69
- bytes32 intentHash = keccak256(abi.encode(intent));
70
- _verifyIntentHashAndMarkExecuted(execMsg.intentHash, intentHash);
95
+ function _handleSwapToken(SwapTokenMessage memory ms, bytes memory sig, bool claimFailed) internal {
96
+ bytes32 actionHash = hashTypedData(ms);
97
+ _verifyOwnerSig(ms.owner, ms.expiry, ms.nonce, actionHash, sig, !claimFailed);
71
98
 
72
- IPDepositBox box = _checkAndDeployBox(intent.owner, intent.boxId);
73
- uint256 netPtReceived = _buyPt(intent, execMsg, box) - execMsg.feeAmount;
74
- box.payTreasury(intent.pt, execMsg.feeAmount);
99
+ IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
75
100
 
76
- if (intent.ptAdapter == address(0)) {
77
- require(msg.value == 0, ExcessiveNativeFee());
101
+ if (claimFailed) {
102
+ _markFailedAndTakeFee(actionHash, box, ms.tokenSpent, ms.amountFee);
103
+ emit ClaimFeeForFailedAction(ms.owner, ms.boxId, actionHash, ms.tokenSpent, ms.amountFee);
78
104
  } else {
79
- netPtReceived = _bridgePt(intent, box, netPtReceived, msg.value);
105
+ uint256 netTokenReceived = _swapToken(ms, box);
106
+ require(netTokenReceived >= ms.minReceived, InsufficientTokenReceived());
107
+
108
+ _markSucceededAndTakeFee(actionHash, box, ms.tokenSpent, ms.amountFee);
109
+ emit SwapToken(
110
+ ms.owner,
111
+ ms.boxId,
112
+ actionHash,
113
+ ms.tokenSpent,
114
+ ms.amountSpent,
115
+ ms.amountFee,
116
+ ms.tokenReceived,
117
+ netTokenReceived
118
+ );
80
119
  }
120
+ }
81
121
 
82
- require(netPtReceived >= intent.minPtReceived, InsufficientTokenReceived());
122
+ function _handleBuyCrossChainPt(BuyCrossChainPtMessage memory ms, bytes memory sig, bool claimFailed) internal {
123
+ bytes32 actionHash = hashTypedData(ms);
124
+ _verifyOwnerSig(ms.owner, ms.expiry, ms.nonce, actionHash, sig, !claimFailed);
83
125
 
84
- emit BuyCrossChainPt(
85
- intent.owner,
86
- intent.boxId,
87
- intentHash,
88
- intent.tokenSpent,
89
- execMsg.amountSpent,
90
- intent.pt,
91
- intent.ptAdapter,
92
- netPtReceived
93
- );
126
+ IPDepositBox box = _checkAndDeployBox(ms.owner, ms.boxId);
127
+
128
+ if (claimFailed) {
129
+ _markFailedAndTakeFee(actionHash, box, ms.tokenSpent, ms.amountFee);
130
+ emit ClaimFeeForFailedAction(ms.owner, ms.boxId, actionHash, ms.tokenSpent, ms.amountFee);
131
+ } else {
132
+ address pt = IOFT(ms.ptAdapter).token();
133
+ uint256 netPtReceived = _buyPtAndBridge(ms, box, pt, msg.value);
134
+ require(netPtReceived >= ms.minPtReceived, InsufficientTokenReceived());
135
+
136
+ _markSucceededAndTakeFee(actionHash, box, ms.tokenSpent, ms.amountFee);
137
+ emit BuyCrossChainPt(
138
+ ms.owner,
139
+ ms.boxId,
140
+ actionHash,
141
+ ms.tokenSpent,
142
+ ms.amountSpent,
143
+ ms.amountFee,
144
+ ms.ptAdapter,
145
+ pt,
146
+ netPtReceived
147
+ );
148
+ }
94
149
  }
95
150
 
96
151
  function _bridgeToken(BridgeTokenMessage memory ms, IPDepositBox box, uint256 nativeFee) internal {
97
152
  // forgefmt: disable-next-item
98
153
  ApprovedCall memory call = ApprovedCall({
99
154
  token: ms.token,
100
- amount: ms.bridgeAmount,
155
+ amount: ms.amountBridge,
101
156
  spender: ms.bridgeExtRouter,
102
157
  data: ms.bridgeCalldata
103
158
  });
@@ -112,36 +167,26 @@ contract PendleCrossChainSwapHub is SwapHubBase {
112
167
  extRouter: ms.swapExtRouter,
113
168
  extCalldata: ms.swapCalldata
114
169
  });
115
- rawTokenReceived = _swapFromBox(box, ms.swapExecutor, swapData);
170
+ rawTokenReceived = _swapFromBox(box, ms.swapExecutor, swapData, ms.receiver);
116
171
  }
117
172
 
118
- function _buyPt(BuyCrossChainPtIntent memory intent, ExecuteBuyCrossChainPtMessage memory execMsg, IPDepositBox box)
173
+ function _buyPtAndBridge(BuyCrossChainPtMessage memory ms, IPDepositBox box, address pt, uint256 nativeFee)
119
174
  internal
120
- returns (uint256 rawPtReceived)
175
+ returns (uint256 netPtReceived)
121
176
  {
122
- require(
123
- execMsg.amountSpent <= PMath.min(intent.maxAmountSpent, _balanceOf(address(box), intent.tokenSpent)),
124
- InvalidAmountIn()
125
- );
126
-
127
177
  SwapData memory swapData = SwapData({
128
- tokenIn: intent.tokenSpent,
129
- amountIn: execMsg.amountSpent,
130
- tokenOut: intent.pt,
131
- extRouter: execMsg.swapExtRouter,
132
- extCalldata: execMsg.swapCalldata
178
+ tokenIn: ms.tokenSpent,
179
+ amountIn: ms.amountSpent,
180
+ tokenOut: pt,
181
+ extRouter: ms.swapExtRouter,
182
+ extCalldata: ms.swapCalldata
133
183
  });
134
- rawPtReceived = _swapFromBox(box, execMsg.swapExecutor, swapData);
135
- }
184
+ uint256 rawPtReceived = _swapFromBox(box, ms.swapExecutor, swapData, address(box));
136
185
 
137
- function _bridgePt(BuyCrossChainPtIntent memory intent, IPDepositBox box, uint256 amount, uint256 nativeFee)
138
- internal
139
- returns (uint256 netPtReceived)
140
- {
141
186
  SendParam memory sendParam = SendParam({
142
- dstEid: intent.dstLzEid,
143
- to: intent.receiver,
144
- amountLD: amount,
187
+ dstEid: ms.dstEid,
188
+ to: ms.receiver,
189
+ amountLD: rawPtReceived,
145
190
  minAmountLD: 0,
146
191
  extraOptions: "",
147
192
  composeMsg: "",
@@ -149,12 +194,11 @@ contract PendleCrossChainSwapHub is SwapHubBase {
149
194
  });
150
195
  MessagingFee memory sendFee = MessagingFee({nativeFee: nativeFee, lzTokenFee: 0});
151
196
  ApprovedCall memory call = ApprovedCall({
152
- token: intent.pt,
153
- amount: amount,
154
- spender: intent.ptAdapter,
197
+ token: pt,
198
+ amount: rawPtReceived,
199
+ spender: ms.ptAdapter,
155
200
  data: abi.encodeCall(IOFT.send, (sendParam, sendFee, msg.sender))
156
201
  });
157
-
158
202
  (, OFTReceipt memory oftReceipt) =
159
203
  abi.decode(box.approveAndCall{value: nativeFee}(call, msg.sender), (MessagingReceipt, OFTReceipt));
160
204
  netPtReceived = oftReceipt.amountReceivedLD;
@@ -23,8 +23,8 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
23
23
  //
24
24
  "address receiver,"
25
25
  "address token,"
26
- "uint256 withdrawAmount,"
27
- "uint256 feeAmount"
26
+ "uint256 amountWithdraw,"
27
+ "uint256 amountFee"
28
28
  ")"
29
29
  );
30
30
 
@@ -37,8 +37,8 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
37
37
  "uint256 nonce,"
38
38
  //
39
39
  "address token,"
40
- "uint256 bridgeAmount,"
41
- "uint256 feeAmount,"
40
+ "uint256 amountBridge,"
41
+ "uint256 amountFee,"
42
42
  //
43
43
  "address bridgeExtRouter,"
44
44
  "bytes bridgeCalldata"
@@ -55,9 +55,10 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
55
55
  //
56
56
  "address tokenSpent,"
57
57
  "uint256 amountSpent,"
58
+ "uint256 amountFee,"
58
59
  "address tokenReceived,"
59
60
  "uint256 minReceived,"
60
- "uint256 feeAmount,"
61
+ "address receiver,"
61
62
  //
62
63
  "address swapExecutor,"
63
64
  "address swapExtRouter,"
@@ -66,34 +67,24 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
66
67
  );
67
68
 
68
69
  // forgefmt: disable-next-item
69
- bytes32 internal constant BUY_CROSS_CHAIN_PT_INTENT_TYPEHASH = keccak256(
70
- "BuyCrossChainPtIntent("
70
+ bytes32 internal constant BUY_CROSS_CHAIN_PT_MESSAGE_TYPEHASH = keccak256(
71
+ "BuyCrossChainPtMessage("
71
72
  "address owner,"
72
73
  "uint32 boxId,"
73
- "uint256 salt,"
74
74
  "uint256 expiry,"
75
+ "uint256 nonce,"
75
76
  //
76
77
  "address tokenSpent,"
77
- "uint256 maxAmountSpent,"
78
- "address pt,"
78
+ "uint256 amountSpent,"
79
+ "uint256 amountFee,"
79
80
  "address ptAdapter,"
80
81
  "uint256 minPtReceived,"
81
- "uint32 dstLzEid,"
82
- "bytes32 receiver"
83
- ")"
84
- );
85
-
86
- // forgefmt: disable-next-item
87
- bytes32 internal constant EXECUTE_BUY_CROSS_CHAIN_PT_MESSAGE_TYPEHASH = keccak256(
88
- "ExecuteBuyCrossChainPtMessage("
89
- "address validator,"
90
- "bytes32 intentHash,"
91
- "uint256 amountSpent,"
92
- "uint256 feeAmount,"
82
+ "uint32 dstEid,"
83
+ "bytes32 receiver,"
84
+ //
93
85
  "address swapExecutor,"
94
86
  "address swapExtRouter,"
95
- "bytes swapCalldata,"
96
- "uint256 expiry"
87
+ "bytes swapCalldata"
97
88
  ")"
98
89
  );
99
90
 
@@ -103,9 +94,8 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
103
94
  bytes32 public immutable DEPOSIT_BOX_CODE_HASH;
104
95
 
105
96
  mapping(address owner => uint256 nonce) public ownerNonce;
106
- mapping(bytes32 intentHash => bool) public isIntentExecuted;
97
+ mapping(bytes32 actionStatus => ActionStatus) public actionStatus;
107
98
  mapping(address executor => bool) public isExecutor;
108
- mapping(address validator => bool) public isValidator;
109
99
 
110
100
  constructor(address beaconProxyCodeContract_, address depositBoxBeacon_) {
111
101
  BEACON_PROXY_CODE_CONTRACT = beaconProxyCodeContract_;
@@ -124,11 +114,6 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
124
114
  emit SetExecutor(executor, isExecutor_);
125
115
  }
126
116
 
127
- function setValidator(address validator, bool isValidator_) external onlyOwner {
128
- isValidator[validator] = isValidator_;
129
- emit SetValidator(validator, isValidator_);
130
- }
131
-
132
117
  function computeDepositBox(address owner, uint32 boxId) public view returns (address box, bytes32 salt) {
133
118
  salt = keccak256(abi.encode(owner, boxId));
134
119
  box = Create2.computeAddress(salt, DEPOSIT_BOX_CODE_HASH);
@@ -158,8 +143,8 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
158
143
  //
159
144
  message.receiver,
160
145
  message.token,
161
- message.withdrawAmount,
162
- message.feeAmount
146
+ message.amountWithdraw,
147
+ message.amountFee
163
148
  )
164
149
  )
165
150
  );
@@ -176,8 +161,8 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
176
161
  message.nonce,
177
162
  //
178
163
  message.token,
179
- message.bridgeAmount,
180
- message.feeAmount,
164
+ message.amountBridge,
165
+ message.amountFee,
181
166
  //
182
167
  message.bridgeExtRouter,
183
168
  keccak256(message.bridgeCalldata)
@@ -198,9 +183,10 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
198
183
  //
199
184
  message.tokenSpent,
200
185
  message.amountSpent,
186
+ message.amountFee,
201
187
  message.tokenReceived,
202
188
  message.minReceived,
203
- message.feeAmount,
189
+ message.receiver,
204
190
  //
205
191
  message.swapExecutor,
206
192
  message.swapExtRouter,
@@ -210,55 +196,42 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
210
196
  );
211
197
  }
212
198
 
213
- function hashTypedData(BuyCrossChainPtIntent memory intent) public view returns (bytes32) {
199
+ function hashTypedData(BuyCrossChainPtMessage memory message) public view returns (bytes32) {
214
200
  return _hashTypedDataV4(
215
201
  keccak256(
216
202
  abi.encode(
217
- BUY_CROSS_CHAIN_PT_INTENT_TYPEHASH,
218
- intent.owner,
219
- intent.boxId,
220
- intent.salt,
221
- intent.expiry,
203
+ BUY_CROSS_CHAIN_PT_MESSAGE_TYPEHASH,
204
+ message.owner,
205
+ message.boxId,
206
+ message.expiry,
207
+ message.nonce,
222
208
  //
223
- intent.tokenSpent,
224
- intent.maxAmountSpent,
225
- intent.pt,
226
- intent.ptAdapter,
227
- intent.minPtReceived,
228
- intent.dstLzEid,
229
- intent.receiver
230
- )
231
- )
232
- );
233
- }
234
-
235
- function hashTypedData(ExecuteBuyCrossChainPtMessage memory message) public view returns (bytes32) {
236
- return _hashTypedDataV4(
237
- keccak256(
238
- abi.encode(
239
- EXECUTE_BUY_CROSS_CHAIN_PT_MESSAGE_TYPEHASH,
240
- message.validator,
241
- message.intentHash,
209
+ message.tokenSpent,
242
210
  message.amountSpent,
243
- message.feeAmount,
211
+ message.amountFee,
212
+ message.ptAdapter,
213
+ message.minPtReceived,
214
+ message.dstEid,
215
+ message.receiver,
216
+ //
244
217
  message.swapExecutor,
245
218
  message.swapExtRouter,
246
- keccak256(message.swapCalldata),
247
- message.expiry
219
+ keccak256(message.swapCalldata)
248
220
  )
249
221
  )
250
222
  );
251
223
  }
252
224
 
253
- function _verifyOwnerSigAndNonce(
225
+ function _verifyOwnerSig(
254
226
  address owner,
255
227
  uint256 expiry,
256
228
  uint256 nonce,
257
229
  bytes32 messageHash,
258
- bytes memory signature
230
+ bytes memory signature,
231
+ bool verifyNonce
259
232
  ) internal {
260
233
  _verifyOwnerSig(owner, expiry, messageHash, signature);
261
- _verifyAndIncreaseNonce(owner, nonce);
234
+ if (verifyNonce) _verifyAndIncreaseNonce(owner, nonce);
262
235
  }
263
236
 
264
237
  function _verifyOwnerSig(address owner, uint256 expiry, bytes32 messageHash, bytes memory signature) internal view {
@@ -271,33 +244,30 @@ abstract contract SwapHubBase is IPCrossChainSwapHub, EIP712Upgradeable, BoringO
271
244
  ownerNonce[owner] = nonce;
272
245
  }
273
246
 
274
- function _verifyValidatorSig(address validator, uint256 expiry, bytes32 messageHash, bytes memory signature)
275
- internal
276
- view
277
- {
278
- require(SignatureChecker.isValidSignatureNow(validator, messageHash, signature), InvalidSignature());
279
- require(isValidator[validator], InvalidValidator());
280
- require(expiry > block.timestamp, MessageExpired());
247
+ function _balanceOf(address addr, address token) internal view returns (uint256) {
248
+ return (token == NATIVE) ? addr.balance : IERC20(token).balanceOf(addr);
281
249
  }
282
250
 
283
- function _verifyIntentHashAndMarkExecuted(bytes32 expectedHash, bytes32 actualHash) internal {
284
- require(expectedHash == actualHash, IntentHashMismatch());
285
- require(!isIntentExecuted[actualHash], IntentExecuted());
286
- isIntentExecuted[actualHash] = true;
251
+ function _markSucceededAndTakeFee(bytes32 actionHash, IPDepositBox box, address token, uint256 amount) internal {
252
+ require(actionStatus[actionHash] == ActionStatus.NOT_EXECUTED, ActionExecuted());
253
+ actionStatus[actionHash] = ActionStatus.SUCCEEDED;
254
+ box.payTreasury(token, amount);
287
255
  }
288
256
 
289
- function _balanceOf(address addr, address token) internal view returns (uint256) {
290
- return (token == NATIVE) ? addr.balance : IERC20(token).balanceOf(addr);
257
+ function _markFailedAndTakeFee(bytes32 actionHash, IPDepositBox box, address token, uint256 amount) internal {
258
+ require(actionStatus[actionHash] == ActionStatus.NOT_EXECUTED, ActionExecuted());
259
+ actionStatus[actionHash] = ActionStatus.FAILED;
260
+ box.payTreasury(token, amount);
291
261
  }
292
262
 
293
- function _swapFromBox(IPDepositBox box, address swapExecutor, SwapData memory swapData)
263
+ function _swapFromBox(IPDepositBox box, address swapExecutor, SwapData memory swapData, address receiver)
294
264
  internal
295
265
  returns (uint256 rawTokenOut)
296
266
  {
297
267
  box.withdrawTo(swapExecutor, swapData.tokenIn, swapData.amountIn);
298
268
 
299
- uint256 preBalance = _balanceOf(address(box), swapData.tokenOut);
300
- IPSwapExecutor(swapExecutor).swap(address(box), swapData);
301
- rawTokenOut = _balanceOf(address(box), swapData.tokenOut) - preBalance;
269
+ uint256 preBalance = _balanceOf(receiver, swapData.tokenOut);
270
+ IPSwapExecutor(swapExecutor).swap(receiver, swapData);
271
+ rawTokenOut = _balanceOf(receiver, swapData.tokenOut) - preBalance;
302
272
  }
303
273
  }