Skip to content

Commit dcb4bb8

Browse files
authored
Merge pull request #28 from skip-mev/jw/eureka-native-transfer
support native tokens in EurekaHandler.transfer
2 parents cf10299 + c30ce4c commit dcb4bb8

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

EurekaHandler/src/EurekaHandler.sol

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini
1010
import {IICS20TransferMsgs, IICS20Transfer} from "./interfaces/eureka/ICS20Transfer.sol";
1111
import {IIBCVoucher} from "./interfaces/lombard/IIBCVoucher.sol";
1212
import {IEurekaHandler} from "./interfaces/IEurekaHandler.sol";
13+
import {IWETH} from "./interfaces/IWETH.sol";
1314

1415
contract EurekaHandler is IEurekaHandler, Initializable, UUPSUpgradeable, OwnableUpgradeable {
1516
using SafeERC20 for IERC20;
@@ -41,16 +42,21 @@ contract EurekaHandler is IEurekaHandler, Initializable, UUPSUpgradeable, Ownabl
4142
lbtc = _lbtc;
4243
}
4344

44-
function transfer(uint256 amount, TransferParams memory transferParams, Fees memory fees) external {
45+
function transfer(uint256 amount, TransferParams memory transferParams, Fees memory fees) external payable {
4546
require(block.timestamp < fees.quoteExpiry, "Fee quote expired");
4647

48+
if (msg.value > 0) {
49+
require(msg.value == amount + fees.relayFee, "Insufficient native token");
50+
IWETH(transferParams.token).deposit{value: msg.value}();
51+
} else {
52+
IERC20(transferParams.token).safeTransferFrom(msg.sender, address(this), amount + fees.relayFee);
53+
}
54+
4755
// Collect fees
4856
if (fees.relayFee > 0) {
49-
IERC20(transferParams.token).safeTransferFrom(msg.sender, fees.relayFeeRecipient, fees.relayFee);
57+
IERC20(transferParams.token).safeTransfer(fees.relayFeeRecipient, fees.relayFee);
5058
}
5159

52-
IERC20(transferParams.token).safeTransferFrom(msg.sender, address(this), amount);
53-
5460
_sendTransfer(
5561
IICS20TransferMsgs.SendTransferMsg({
5662
denom: transferParams.token,

EurekaHandler/src/interfaces/IEurekaHandler.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface IEurekaHandler {
1717
uint64 quoteExpiry;
1818
}
1919

20-
function transfer(uint256 amount, TransferParams memory transferParams, Fees memory fees) external;
20+
function transfer(uint256 amount, TransferParams memory transferParams, Fees memory fees) external payable;
2121

2222
function swapAndTransfer(
2323
address swapInputToken,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.18;
3+
4+
interface IWETH {
5+
function deposit() external payable;
6+
7+
function withdraw(uint256 value) external;
8+
}

EurekaHandler/test/EurekaHandler.t.sol

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.s
88
import {EurekaHandler, IEurekaHandler} from "../src/EurekaHandler.sol";
99
import {IICS20Transfer, IICS20TransferMsgs} from "../src/interfaces/eureka/ICS20Transfer.sol";
1010
import {IIBCVoucher} from "../src/interfaces/lombard/IIBCVoucher.sol";
11-
11+
import {IWETH} from "../src/interfaces/IWETH.sol";
1212
contract EurekaHandlerTest is Test {
1313
address ics20Transfer = 0xbb87C1ACc6306ad2233a4c7BBE75a1230409b358;
1414
address swapRouter = 0x3bFA4769FB09eefC5a80d6E87c3B9C650f7Ae48E;
@@ -97,6 +97,53 @@ contract EurekaHandlerTest is Test {
9797
handler.transfer(amount, transferParams, fees);
9898
}
9999

100+
function testTransferWithNativeToken() public {
101+
address token = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
102+
uint256 amount = 1_000_000;
103+
104+
IEurekaHandler.TransferParams memory transferParams = IEurekaHandler.TransferParams({
105+
token: token,
106+
recipient: "cosmos1234",
107+
sourceClient: "client-0",
108+
destPort: "transfer",
109+
timeoutTimestamp: uint64(block.timestamp + 100),
110+
memo: ""
111+
});
112+
113+
IEurekaHandler.Fees memory fees = IEurekaHandler.Fees({
114+
relayFee: 100,
115+
relayFeeRecipient: relayFeeRecipient,
116+
quoteExpiry: uint64(block.timestamp + 100)
117+
});
118+
119+
address alice = makeAddr("alice");
120+
121+
vm.mockCall(token, abi.encodeWithSelector(IWETH.deposit.selector), abi.encode(true));
122+
123+
vm.mockCall(
124+
address(ics20Transfer),
125+
abi.encodeWithSelector(
126+
IICS20Transfer.sendTransferWithSender.selector,
127+
IICS20TransferMsgs.SendTransferMsg({
128+
denom: token,
129+
amount: amount,
130+
receiver: transferParams.recipient,
131+
sourceClient: transferParams.sourceClient,
132+
destPort: transferParams.destPort,
133+
timeoutTimestamp: transferParams.timeoutTimestamp,
134+
memo: transferParams.memo
135+
}),
136+
alice
137+
),
138+
abi.encode(1)
139+
);
140+
141+
vm.deal(alice, amount + fees.relayFee);
142+
143+
vm.startPrank(alice);
144+
handler.transfer{value: amount + fees.relayFee}(amount, transferParams, fees);
145+
}
146+
100147
function testSwapAndTransfer() public {
101148
address weth = 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14;
102149
address usdc = 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238;

0 commit comments

Comments
 (0)