// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { TacProxyV1 } from "@tonappchain/evm-ccl/contracts/proxies/TacProxyV1.sol";
import { TokenAmount, OutMessageV1, TacHeaderV1, NFTAmount } from "@tonappchain/evm-ccl/contracts/core/Structs.sol";
interface IDappContract {
function doSomething(address tokenFrom, address tokenTo, uint256 amount)
external returns (uint256);
}
contract MyProxy is TacProxyV1 {
IDappContract public dappContract;
struct MyProxyFunctionArguments {
address tokenFrom;
address tokenTo;
uint256 amount;
}
constructor(address _dappContract, address _crossChainLayer)
TacProxyV1(_crossChainLayer)
{
dappContract = IDappContract(_dappContract);
}
function myProxyFunction(bytes calldata tacHeader, bytes calldata arguments)
external
_onlyCrossChainLayer
{
// 1. Decode the custom arguments
MyProxyFunctionArguments memory args = abi.decode(arguments, (MyProxyFunctionArguments));
// 2. Approve tokens to your Dapp contract for some action
IERC20(args.tokenFrom).approve(address(dappContract), args.amount);
// 3. Call the Dapp contract
uint256 tokenToAmount = dappContract.doSomething(
args.tokenFrom,
args.tokenTo,
args.amount
);
// 4. Prepare tokens to send back to TON
TokenAmount[] memory tokensToBridge = new TokenAmount[](1);
tokensToBridge[0] = TokenAmount(args.tokenTo, tokenToAmount);
// 5. Approve the CrossChainLayer to pull them
IERC20(tokensToBridge[0].evmAddress).approve(
_getCrossChainLayerAddress(),
tokensToBridge[0].amount
);
// 6. Decode the TAC header
TacHeaderV1 memory header = _decodeTacHeader(tacHeader);
// 7. Form an OutMessage
OutMessageV1 memory outMsg = OutMessageV1({
shardsKey: header.shardsKey, // Use same key for RoundTrip
tvmTarget: header.tvmCaller, // Send back to caller
tvmPayload: "", // Must be empty - not supported
tvmProtocolFee: 0, // 0 for RoundTrip - already paid on TON
tvmExecutorFee: 0, // 0 for RoundTrip - already paid on TON
tvmValidExecutors: new string[](0), // Empty for RoundTrip - already defined on TON
toBridge: tokensToBridge, // Result tokens
toBridgeNFT: new NFTAmount[](0) // No NFTs
});
// 8. Send message back through CrossChainLayer with zero native
_sendMessageV1(outMsg, 0);
}
}