Skip to content

Commit

Permalink
Allow L2 calls
Browse files Browse the repository at this point in the history
  • Loading branch information
danhper committed Jun 12, 2024
1 parent a04a1af commit d7c450b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 20 deletions.
3 changes: 2 additions & 1 deletion src/CCIPHelpers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ library CCIPHelpers {
address gydAddress,
address recipient,
uint256 amount,
bytes memory data,
uint256 gasLimit
) internal pure returns (Client.EVM2AnyMessage memory) {
bytes memory messageData = abi.encode(recipient, amount);
bytes memory messageData = abi.encode(recipient, amount, data);
return Client.EVM2AnyMessage({
receiver: abi.encode(gydAddress),
data: messageData,
Expand Down
35 changes: 29 additions & 6 deletions src/GydL1CCIPEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ contract GydL1CCIPEscrow is
CCIPReceiverUpgradeable
{
using SafeERC20 for IERC20;
using Address for address;
using Address for address payable;

struct ChainMetadata {
Expand Down Expand Up @@ -155,16 +156,26 @@ contract GydL1CCIPEscrow is
emit GasLimitUpdated(chainSelector, gasLimit);
}

function bridgeToken(
uint64 destinationChainSelector,
address recipient,
uint256 amount
) external payable virtual {
bridgeToken(destinationChainSelector, recipient, amount, "");
}

/**
* @notice Bridge GYD from Ethereum mainnet to the specified chain
* @param recipient The recipient of the bridged token
* @param amount GYD amount
* @param data calldata for the recipient on the destination chain
*/
function bridgeToken(
uint64 destinationChainSelector,
address recipient,
uint256 amount
) external payable virtual {
uint256 amount,
bytes memory data
) public payable virtual {
gyd.safeTransferFrom(msg.sender, address(this), amount);

ChainMetadata memory chainMeta = chainsMetadata[destinationChainSelector];
Expand All @@ -173,7 +184,7 @@ contract GydL1CCIPEscrow is
}

Client.EVM2AnyMessage memory evm2AnyMessage = CCIPHelpers.buildCCIPMessage(
chainMeta.gydAddress, recipient, amount, chainMeta.gasLimit
chainMeta.gydAddress, recipient, amount, data, chainMeta.gasLimit
);
uint256 fees = router.getFee(destinationChainSelector, evm2AnyMessage);
CCIPHelpers.sendCCIPMessage(
Expand All @@ -191,13 +202,22 @@ contract GydL1CCIPEscrow is
address recipient,
uint256 amount
) external view returns (uint256) {
return getFee(destinationChainSelector, recipient, amount, "");
}

function getFee(
uint64 destinationChainSelector,
address recipient,
uint256 amount,
bytes memory data
) public view returns (uint256) {
ChainMetadata memory chainMeta = chainsMetadata[destinationChainSelector];
if (chainMeta.gydAddress == address(0)) {
revert ChainNotSupported(destinationChainSelector);
}

Client.EVM2AnyMessage memory evm2AnyMessage = CCIPHelpers.buildCCIPMessage(
chainMeta.gydAddress, recipient, amount, chainMeta.gasLimit
chainMeta.gydAddress, recipient, amount, data, chainMeta.gasLimit
);
return router.getFee(destinationChainSelector, evm2AnyMessage);
}
Expand Down Expand Up @@ -229,13 +249,16 @@ contract GydL1CCIPEscrow is
revert MessageInvalid();
}

(address recipient, uint256 amount) =
abi.decode(any2EvmMessage.data, (address, uint256));
(address recipient, uint256 amount, bytes memory data) =
abi.decode(any2EvmMessage.data, (address, uint256, bytes));
uint256 bridged = totalBridgedGYD[any2EvmMessage.sourceChainSelector];
bridged -= amount;
totalBridgedGYD[any2EvmMessage.sourceChainSelector] = bridged;

gyd.safeTransfer(recipient, amount);
if (data.length > 0) {
recipient.functionCall(data);
}

emit GYDClaimed(
any2EvmMessage.sourceChainSelector, recipient, amount, bridged
Expand Down
28 changes: 23 additions & 5 deletions src/L2Gyd.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {Address} from "oz/utils/Address.sol";
import {Initializable} from "upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {Ownable2StepUpgradeable} from
Expand All @@ -24,6 +25,8 @@ contract L2Gyd is
ERC20Upgradeable,
CCIPReceiverUpgradeable
{
using Address for address;

/// @notice The CCIP router contract
IRouterClient public router;

Expand Down Expand Up @@ -98,19 +101,23 @@ contract L2Gyd is
revert RenounceInvalid();
}

function bridgeToken(address recipient, uint256 amount) public payable {
bridgeToken(recipient, amount, "");
}

/**
* @notice Bridge GYD from the current chain to Ethereum mainnet
* @param recipient The recipient of the bridged token
* @param amount GYD amount
*/
function bridgeToken(address recipient, uint256 amount)
function bridgeToken(address recipient, uint256 amount, bytes memory data)
public
payable
virtual
{
_burn(msg.sender, amount);
Client.EVM2AnyMessage memory evm2AnyMessage = CCIPHelpers.buildCCIPMessage(
destAddress, recipient, amount, bridgeGasLimit
destAddress, recipient, amount, data, bridgeGasLimit
);
uint256 fees = router.getFee(mainnetChainSelector, evm2AnyMessage);
CCIPHelpers.sendCCIPMessage(
Expand All @@ -124,9 +131,17 @@ contract L2Gyd is
external
view
returns (uint256)
{
return getFee(recipient, amount, "");
}

function getFee(address recipient, uint256 amount, bytes memory data)
public
view
returns (uint256)
{
Client.EVM2AnyMessage memory evm2AnyMessage = CCIPHelpers.buildCCIPMessage(
destAddress, recipient, amount, bridgeGasLimit
destAddress, recipient, amount, data, bridgeGasLimit
);
return router.getFee(mainnetChainSelector, evm2AnyMessage);
}
Expand Down Expand Up @@ -154,9 +169,12 @@ contract L2Gyd is
revert MessageInvalid();
}

(address recipient, uint256 amount) =
abi.decode(any2EvmMessage.data, (address, uint256));
(address recipient, uint256 amount, bytes memory data) =
abi.decode(any2EvmMessage.data, (address, uint256, bytes));
_mint(recipient, amount);
if (data.length > 0) {
recipient.functionCall(data);
}

emit GYDClaimed(recipient, amount, totalSupply());
}
Expand Down
4 changes: 2 additions & 2 deletions test/GydL1Escrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ contract GydL1EscrowTest is Test {
address routerAddress = address(proxyV1.router());
(address originAddress,) = proxyV1.chainsMetadata(arbitrumChainSelector);
uint64 chainSelector = arbitrumChainSelector;
bytes memory data = abi.encode(bob, 1 ether);
bytes memory data = abi.encode(bob, 1 ether, "");

// Invalid caller
vm.startPrank(bob);
Expand Down Expand Up @@ -261,7 +261,7 @@ contract GydL1EscrowTest is Test {
address routerAddress = address(proxyV1.router());
(address originAddress,) = proxyV1.chainsMetadata(arbitrumChainSelector);
uint64 chainSelector = arbitrumChainSelector;
bytes memory messageData = abi.encode(bob, bridgeAmount);
bytes memory messageData = abi.encode(bob, bridgeAmount, "");

vm.startPrank(routerAddress);
proxyV1.ccipReceive(
Expand Down
12 changes: 6 additions & 6 deletions test/L2Gyd.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ contract L2GydTest is Test {

// Mint test NativeGYD
vm.startPrank(address(router));
bytes memory data = abi.encode(alice, bridgeAmount);
bytes memory data = abi.encode(alice, bridgeAmount, "");
mockedProxyV1.ccipReceive(
_receivedMessage(mainnetChainSelector, destAddress, data)
);
Expand Down Expand Up @@ -166,7 +166,7 @@ contract L2GydTest is Test {

// Mint test NativeGYD
vm.startPrank(routerAddress);
bytes memory data = abi.encode(alice, bridgeAmount);
bytes memory data = abi.encode(alice, bridgeAmount, "");
proxyV1.ccipReceive(
_receivedMessage(mainnetChainSelector, destAddress, data)
);
Expand Down Expand Up @@ -198,7 +198,7 @@ contract L2GydTest is Test {

// Mint test NativeGYD
vm.startPrank(routerAddress);
bytes memory data = abi.encode(alice, bridgeAmount);
bytes memory data = abi.encode(alice, bridgeAmount, "");
proxyV1.ccipReceive(
_receivedMessage(mainnetChainSelector, destAddress, data)
);
Expand All @@ -213,7 +213,7 @@ contract L2GydTest is Test {
address currentRouterAddress = address(proxyV1.router());
address originAddress = proxyV1.destAddress();
uint64 chainSelector = proxyV1.mainnetChainSelector();
bytes memory metadata = abi.encode(bob, 1 ether);
bytes memory metadata = abi.encode(bob, 1 ether, "");

// Invalid caller
vm.startPrank(bob);
Expand Down Expand Up @@ -253,7 +253,7 @@ contract L2GydTest is Test {

// Mint test NativeGYD
vm.startPrank(routerAddress);
bytes memory data = abi.encode(alice, bridgeAmount);
bytes memory data = abi.encode(alice, bridgeAmount, "");
proxyV1.ccipReceive(
_receivedMessage(mainnetChainSelector, destAddress, data)
);
Expand All @@ -268,7 +268,7 @@ contract L2GydTest is Test {
address currentRouterAddress = address(proxyV1.router());
address originAddress = proxyV1.destAddress();
uint64 chainSelector = proxyV1.mainnetChainSelector();
bytes memory messageData = abi.encode(bob, bridgeAmount);
bytes memory messageData = abi.encode(bob, bridgeAmount, "");

vm.startPrank(currentRouterAddress);
proxyV1.ccipReceive(
Expand Down

0 comments on commit d7c450b

Please sign in to comment.