From 31cbdbd481235f39ba39335c925d16bd12d748e7 Mon Sep 17 00:00:00 2001 From: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:30:13 +0000 Subject: [PATCH] fix: native ETH transfers to EOAs --- .../contracts-rfq/contracts/zaps/TokenZapV1.sol | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/contracts-rfq/contracts/zaps/TokenZapV1.sol b/packages/contracts-rfq/contracts/zaps/TokenZapV1.sol index f8eec13e27..c7eaef1c8c 100644 --- a/packages/contracts-rfq/contracts/zaps/TokenZapV1.sol +++ b/packages/contracts-rfq/contracts/zaps/TokenZapV1.sol @@ -55,7 +55,7 @@ contract TokenZapV1 is IZapRecipient { // Silimar to ERC20s, we allow to use pre-transferred native tokens for the Zap. msgValue = amount; // No approval needed since native token doesn't use allowances. - // Note: balance check is performed within `Address.functionCallWithValue`. + // Note: balance check is performed within `Address.sendValue` or `Address.functionCallWithValue` below. } else { // For ERC20 tokens, grant unlimited approval to the target if the current allowance is insufficient. // This is safe since the contract doesn't custody tokens between zaps. @@ -67,9 +67,16 @@ contract TokenZapV1 is IZapRecipient { // Construct the payload for the target contract call with the Zap action. // The payload is modified to replace the placeholder amount with the actual amount. bytes memory payload = zapData.payload(amount); - // Perform the Zap action, forwarding full msg.value to the target contract. - // Note: this will bubble up any revert from the target contract. - Address.functionCallWithValue({target: target, data: payload, value: msgValue}); + if (payload.length == 0) { + // No payload provided, perform the native gas token transfer to the target. + // Note: we avoid using `functionCallWithValue` because target might be an EOA. This will + // revert with a generic custom error should the target contract revert on incoming transfer. + Address.sendValue({recipient: payable(target), amount: msgValue}); + } else { + // Perform the Zap action, forwarding full msg.value to the target contract. + // Note: this will bubble up any revert from the target contract. + Address.functionCallWithValue({target: target, data: payload, value: msgValue}); + } // Return function selector to indicate successful execution return this.zap.selector; }