---
# System prepended metadata

title: "\n\n"

---

```js
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import "contracts/external/openzeppelin/contracts-upgradeable/token/ERC20/ERC20PresetMinterPauserUpgradeable.sol";
import {IOFT, OFTCore} from "./OFTCore.sol";


/**
 * @title 
 * 
 * 
 * Parallel -> ETH
 * burn on parallel
 * lz message on eth
 * unlock on ETH
 * 
 * 
 * 
 * ETH -> Parallel
 * lock on ETH
 * lz message on parallel
 * mint on parallel
 * 
 * 
 * 
 * ETH -> Arbitrum
 * lock on ETH
 * lz message on arbitrum
 * unlock on arbitrum
 * 
 * 
 * @author 
 * @notice 
 */


/**
 * @title OFT Contract
 * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.
 */
abstract contract OFT is OFTCore, ERC20PresetMinterPauserUpgradeable {
  /**
   * @dev Constructor for the OFT contract.
   * @param _name The name of the OFT.
   * @param _symbol The symbol of the OFT.
   * @param _lzEndpoint The LayerZero endpoint address.
   * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
   */
  constructor(
    string memory _name,
    string memory _symbol,
    address _lzEndpoint,
    address _delegate
  )
    ERC20PresetMinterPauserUpgradeable(_name, _symbol)
    OFTCore(decimals(), _lzEndpoint, _delegate)
  {}

  /**
   * @notice Retrieves interfaceID and the version of the OFT.
   * @return interfaceId The interface ID.
   * @return version The version.
   *
   * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
   * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
   * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
   * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
   */
  function oftVersion()
    external
    pure
    virtual
    returns (bytes4 interfaceId, uint64 version)
  {
    return (type(IOFT).interfaceId, 1);
  }

  /**
   * @dev Retrieves the address of the underlying ERC20 implementation.
   * @return The address of the OFT token.
   *
   * @dev In the case of OFT, address(this) and erc20 are the same contract.
   */
  function token() external view returns (address) {
    return address(this);
  }

  /**
   * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
   * @return requiresApproval Needs approval of the underlying token implementation.
   *
   * @dev In the case of OFT where the contract IS the token, approval is NOT required.
   */
  function approvalRequired() external pure virtual returns (bool) {
    return false;
  }

  /**
   * @dev Burns tokens from the sender's specified balance.
   * @param _amountLD The amount of tokens to send in local decimals.
   * @param _minAmountLD The minimum amount to send in local decimals.
   * @param _dstEid The destination chain ID.
   * @return amountSentLD The amount sent in local decimals.
   * @return amountReceivedLD The amount received in local decimals on the remote.
   */
  function _debit(
    uint256 _amountLD,
    uint256 _minAmountLD,
    uint32 _dstEid
  )
    internal
    virtual
    override
    returns (uint256 amountSentLD, uint256 amountReceivedLD)
  {
    (amountSentLD, amountReceivedLD) = _debitView(
      _amountLD,
      _minAmountLD,
      _dstEid
    );

    // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90,
    // therefore amountSentLD CAN differ from amountReceivedLD.

    // @dev Default OFT burns on src.
    _burn(msg.sender, amountSentLD);
  }

  /**
   * @dev Credits tokens to the specified address.
   * @param _to The address to credit the tokens to.
   * @param _amountLD The amount of tokens to credit in local decimals.
   * @dev _srcEid The source chain ID.
   * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
   */
  function _credit(
    address _to,
    uint256 _amountLD,
    uint32 /*_srcEid*/
  ) internal virtual override returns (uint256 amountReceivedLD) {
    // @dev Default OFT mints on dst.
    _mint(_to, _amountLD);
    // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD.
    return _amountLD;
  }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {IERC20Metadata, IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IOFT, OFTCore} from "./OFTCore.sol";

/**
 * @title OFTAdapter Contract
 * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.
 *
 * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.
 * @dev WARNING: ONLY 1 of these should exist for a given global mesh,
 * unless you make a NON-default implementation of OFT and needs to be done very carefully.
 * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
 * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
 * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.
 */
abstract contract OFTAdapter is OFTCore {
  using SafeERC20 for IERC20;

  IERC20 internal immutable innerToken;

  /**
   * @dev Constructor for the OFTAdapter contract.
   * @param _token The address of the ERC-20 token to be adapted.
   * @param _lzEndpoint The LayerZero endpoint address.
   * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
   */
  constructor(
    address _token,
    address _lzEndpoint,
    address _delegate
  ) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) {
    innerToken = IERC20(_token);
  }

  /**
   * @notice Retrieves interfaceID and the version of the OFT.
   * @return interfaceId The interface ID.
   * @return version The version.
   *
   * @dev interfaceId: This specific interface ID is '0x02e49c2c'.
   * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.
   * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.
   * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)
   */
  function oftVersion()
    external
    pure
    virtual
    returns (bytes4 interfaceId, uint64 version)
  {
    return (type(IOFT).interfaceId, 1);
  }

  /**
   * @dev Retrieves the address of the underlying ERC20 implementation.
   * @return The address of the adapted ERC-20 token.
   *
   * @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract.
   */
  function token() external view returns (address) {
    return address(innerToken);
  }

  /**
   * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.
   * @return requiresApproval Needs approval of the underlying token implementation.
   *
   * @dev In the case of default OFTAdapter, approval is required.
   * @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval.
   */
  function approvalRequired() external pure virtual returns (bool) {
    return true;
  }

  /**
   * @dev Burns tokens from the sender's specified balance, ie. pull method.
   * @param _amountLD The amount of tokens to send in local decimals.
   * @param _minAmountLD The minimum amount to send in local decimals.
   * @param _dstEid The destination chain ID.
   * @return amountSentLD The amount sent in local decimals.
   * @return amountReceivedLD The amount received in local decimals on the remote.
   *
   * @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract.
   * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
   * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
   * a pre/post balance check will need to be done to calculate the amountReceivedLD.
   */
  function _debit(
    uint256 _amountLD,
    uint256 _minAmountLD,
    uint32 _dstEid
  )
    internal
    virtual
    override
    returns (uint256 amountSentLD, uint256 amountReceivedLD)
  {
    (amountSentLD, amountReceivedLD) = _debitView(
      _amountLD,
      _minAmountLD,
      _dstEid
    );
    // @dev Lock tokens by moving them into this contract from the caller.
    innerToken.safeTransferFrom(msg.sender, address(this), amountSentLD);
  }

  /**
   * @dev Credits tokens to the specified address.
   * @param _to The address to credit the tokens to.
   * @param _amountLD The amount of tokens to credit in local decimals.
   * @dev _srcEid The source chain ID.
   * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
   *
   * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.
   * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...
   * a pre/post balance check will need to be done to calculate the amountReceivedLD.
   */
  function _credit(
    address _to,
    uint256 _amountLD,
    uint32 /*_srcEid*/
  ) internal virtual override returns (uint256 amountReceivedLD) {
    // @dev Unlock the tokens and transfer to the recipient.
    innerToken.safeTransfer(_to, _amountLD);
    // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.
    return _amountLD;
  }
}

contract ParallelOFT is OFT {
  constructor(
    string memory _name,
    string memory _symbol,
    address _lzEndpoint,
    address _delegate
  ) OFT(_name, _symbol, _lzEndpoint, _delegate) {}
}

contract ParallelOFTAdapter is OFTAdapter {
  constructor(
    address _token,
    address _lzEndpoint,
    address _delegate
  ) OFTAdapter(_token, _lzEndpoint, _delegate) {}
}




```