// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { TacProxy } from "./TacProxy.sol"; import { TacHeaderV1, OutMessageV1 } from "../core/Structs.sol"; import { ICrossChainLayer } from "../interfaces/ICrossChainLayer.sol"; abstract contract TacProxyV1Upgradeable is Initializable, TacProxy { // keccak256(abi.encode(uint256(keccak256("tac.storage.TacProxyV1Upgradeable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant TacProxyV1UpgradeableStorageLocation = 0x9b777d7f09ca6843192b146ee41249650756fb313cbc428aa2dd37d610f1d100; uint256 private constant TAC_HEADER_VERSION = 1; uint256 private constant TAC_OUT_MESSAGE_VERSION_1 = 1; /** * @dev Storage of the TacProxy contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:tac.storage.TacProxyV1Upgradeable */ struct TacProxyV1UpgradeableStorage { address _crossChainLayer; } /** * @dev Initialize the contract. * @param crossChainLayer Address of the CrossChainLayer contract. */ function __TacProxyV1Upgradeable_init(address crossChainLayer) internal onlyInitializing { __TacProxyV1Upgradeable_init_unchained(crossChainLayer); } function __TacProxyV1Upgradeable_init_unchained(address crossChainLayer) internal onlyInitializing { TacProxyV1UpgradeableStorage storage $ = _getTacProxyV1UpgradeableStorage(); $._crossChainLayer = crossChainLayer; } modifier _onlyCrossChainLayer() { if (msg.sender != _getCrossChainLayerAddress()) { revert OnlyCrossChainLayer(); } _; } /** * @dev Returns a pointer to the storage namespace. */ function _getTacProxyV1UpgradeableStorage() private pure returns (TacProxyV1UpgradeableStorage storage $) { assembly { $.slot := TacProxyV1UpgradeableStorageLocation } } function _getCrossChainLayerAddress() internal view returns (address) { return _getTacProxyV1UpgradeableStorage()._crossChainLayer; } /** * @dev Decode TacHeaderV1 data. * @param tacHeader encoded TacHeaderV1 data. * @return TacHeaderV1 struct. */ function _decodeTacHeader(bytes calldata tacHeader) internal pure returns (TacHeaderV1 memory) { return abi.decode(tacHeader, (TacHeaderV1)); } /** * @dev Send v1 message to TON * @param outMessage v1 message to TON * @param tacAmount Amount of TAC to send. */ function _sendMessageV1(OutMessageV1 memory outMessage, uint256 tacAmount) internal { ICrossChainLayer(_getCrossChainLayerAddress()).sendMessage{value: tacAmount}(TAC_OUT_MESSAGE_VERSION_1, abi.encode(outMessage)); } /** * @dev Get Tac Proxy contract version. * @return Contract version. */ function getVersion() public pure override returns (uint256) { return TAC_HEADER_VERSION; } /* All proxy functions must have the following signature: function (bytes calldata encodedTacHeader, bytes calldata arguments) external; */ }