forked from smartcontractkit/ccip-starter-kit-hardhat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BasicTokenSender.sol
100 lines (85 loc) · 3.05 KB
/
BasicTokenSender.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
import {IERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
import {Withdraw} from "./utils/Withdraw.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract BasicTokenSender is Withdraw {
enum PayFeesIn {
Native,
LINK
}
address immutable i_router;
address immutable i_link;
uint16 immutable i_maxTokensLength;
event MessageSent(bytes32 messageId);
constructor(address router, address link) {
i_router = router;
i_link = link;
i_maxTokensLength = 5;
LinkTokenInterface(i_link).approve(i_router, type(uint256).max);
}
receive() external payable {}
function getSupportedTokens(
uint64 chainSelector
) external view returns (address[] memory tokens) {
tokens = IRouterClient(i_router).getSupportedTokens(chainSelector);
}
function send(
uint64 destinationChainSelector,
address receiver,
Client.EVMTokenAmount[] memory tokensToSendDetails,
PayFeesIn payFeesIn
) external {
uint256 length = tokensToSendDetails.length;
require(
length <= i_maxTokensLength,
"Maximum 5 different tokens can be sent per CCIP Message"
);
for (uint256 i = 0; i < length; ) {
IERC20(tokensToSendDetails[i].token).transferFrom(
msg.sender,
address(this),
tokensToSendDetails[i].amount
);
IERC20(tokensToSendDetails[i].token).approve(
i_router,
tokensToSendDetails[i].amount
);
unchecked {
++i;
}
}
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(receiver),
data: "",
tokenAmounts: tokensToSendDetails,
extraArgs: "",
feeToken: payFeesIn == PayFeesIn.LINK ? i_link : address(0)
});
uint256 fee = IRouterClient(i_router).getFee(
destinationChainSelector,
message
);
bytes32 messageId;
if (payFeesIn == PayFeesIn.LINK) {
// LinkTokenInterface(i_link).approve(i_router, fee);
messageId = IRouterClient(i_router).ccipSend(
destinationChainSelector,
message
);
} else {
messageId = IRouterClient(i_router).ccipSend{value: fee}(
destinationChainSelector,
message
);
}
emit MessageSent(messageId);
}
}