From 900bd79118db37fa85412363300620fdc9d3fc84 Mon Sep 17 00:00:00 2001 From: kexley <87971154+kexleyBeefy@users.noreply.github.com> Date: Tue, 3 Mar 2026 11:28:57 -0500 Subject: [PATCH 1/3] Add Tempo Bridge --- contracts/interfaces/ITIP20.sol | 347 +++++++++++++++++++++ contracts/token/TempoBridgeUpgradeable.sol | 89 ++++++ 2 files changed, 436 insertions(+) create mode 100644 contracts/interfaces/ITIP20.sol create mode 100644 contracts/token/TempoBridgeUpgradeable.sol diff --git a/contracts/interfaces/ITIP20.sol b/contracts/interfaces/ITIP20.sol new file mode 100644 index 00000000..08b19bef --- /dev/null +++ b/contracts/interfaces/ITIP20.sol @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +/// @title Interface for TIP20 tokens +/// @author Tempo +/// @notice Interface for TIP20 tokens on Tempo blockchain +interface ITIP20 { + // ========================================================================= + // ERC-20 standard functions + // ========================================================================= + + /// @notice Returns the name of the token + /// @return The token name + function name() external view returns (string memory); + + /// @notice Returns the symbol of the token + /// @return The token symbol + function symbol() external view returns (string memory); + + /// @notice Returns the number of decimals for the token + /// @return Always returns 6 for TIP-20 tokens + function decimals() external pure returns (uint8); + + /// @notice Returns the total amount of tokens in circulation + /// @return The total supply of tokens + function totalSupply() external view returns (uint256); + + /// @notice Returns the token balance of an account + /// @param account The address to check the balance for + /// @return The token balance of the account + function balanceOf(address account) external view returns (uint256); + + /// @notice Transfers tokens from caller to recipient + /// @param to The recipient address + /// @param amount The amount of tokens to transfer + /// @return True if successful + function transfer(address to, uint256 amount) external returns (bool); + + /// @notice Returns the remaining allowance for a spender + /// @param owner The token owner address + /// @param spender The spender address + /// @return The remaining allowance amount + function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Approves a spender to spend tokens on behalf of caller + /// @param spender The address to approve + /// @param amount The amount to approve + /// @return True if successful + function approve(address spender, uint256 amount) external returns (bool); + + /// @notice Transfers tokens from one address to another using allowance + /// @param from The sender address + /// @param to The recipient address + /// @param amount The amount to transfer + /// @return True if successful + function transferFrom(address from, address to, uint256 amount) external returns (bool); + + /// @notice Mints new tokens to an address (requires ISSUER_ROLE) + /// @param to The recipient address + /// @param amount The amount of tokens to mint + function mint(address to, uint256 amount) external; + + /// @notice Burns tokens from caller's balance (requires ISSUER_ROLE) + /// @param amount The amount of tokens to burn + function burn(uint256 amount) external; + + // ========================================================================= + // TIP-20 extended functions + // ========================================================================= + + /// @notice Transfers tokens from caller to recipient with a memo + /// @param to The recipient address + /// @param amount The amount of tokens to transfer + /// @param memo A 32-byte memo attached to the transfer + function transferWithMemo(address to, uint256 amount, bytes32 memo) external; + + /// @notice Transfers tokens from one address to another with a memo using allowance + /// @param from The sender address + /// @param to The recipient address + /// @param amount The amount to transfer + /// @param memo A 32-byte memo attached to the transfer + /// @return True if successful + function transferFromWithMemo(address from, address to, uint256 amount, bytes32 memo) external returns (bool); + + /// @notice Mints new tokens to an address with a memo (requires ISSUER_ROLE) + /// @param to The recipient address + /// @param amount The amount of tokens to mint + /// @param memo A 32-byte memo attached to the mint + function mintWithMemo(address to, uint256 amount, bytes32 memo) external; + + /// @notice Burns tokens from caller's balance with a memo (requires ISSUER_ROLE) + /// @param amount The amount of tokens to burn + /// @param memo A 32-byte memo attached to the burn + function burnWithMemo(uint256 amount, bytes32 memo) external; + + /// @notice Burns tokens from a blocked address (requires BURN_BLOCKED_ROLE) + /// @param from The address to burn tokens from (must be unauthorized by transfer policy) + /// @param amount The amount of tokens to burn + function burnBlocked(address from, uint256 amount) external; + + /// @notice Returns the quote token used for DEX pairing + /// @return The quote token address + function quoteToken() external view returns (ITIP20); + + /// @notice Returns the next quote token staged for update + /// @return The next quote token address (zero if none staged) + function nextQuoteToken() external view returns (ITIP20); + + /// @notice Returns the currency identifier for this token + /// @return The currency string + function currency() external view returns (string memory); + + /// @notice Returns whether the token is currently paused + /// @return True if paused, false otherwise + function paused() external view returns (bool); + + /// @notice Returns the maximum supply cap for the token + /// @return The supply cap (checked on mint operations) + function supplyCap() external view returns (uint256); + + /// @notice Returns the current transfer policy ID from TIP-403 registry + /// @return The transfer policy ID + function transferPolicyId() external view returns (uint64); + + // ========================================================================= + // Admin Functions + // ========================================================================= + + /// @notice Pauses the contract, blocking transfers (requires PAUSE_ROLE) + function pause() external; + + /// @notice Unpauses the contract, allowing transfers (requires UNPAUSE_ROLE) + function unpause() external; + + /// @notice Changes the transfer policy ID (requires DEFAULT_ADMIN_ROLE) + /// @param newPolicyId The new policy ID from TIP-403 registry + /// @dev Validates that the policy exists using TIP403Registry.policyExists(). + /// Built-in policies (ID 0 = always-reject, ID 1 = always-allow) are always valid. + /// For custom policies (ID >= 2), the policy must exist in the TIP-403 registry. + /// Reverts with InvalidTransferPolicyId if the policy does not exist. + function changeTransferPolicyId(uint64 newPolicyId) external; + + /// @notice Stages a new quote token for update (requires DEFAULT_ADMIN_ROLE) + /// @param newQuoteToken The new quote token address + function setNextQuoteToken(ITIP20 newQuoteToken) external; + + /// @notice Completes the quote token update process (requires DEFAULT_ADMIN_ROLE) + function completeQuoteTokenUpdate() external; + + /// @notice Sets the maximum supply cap (requires DEFAULT_ADMIN_ROLE) + /// @param newSupplyCap The new supply cap (cannot be less than current supply) + function setSupplyCap(uint256 newSupplyCap) external; + + // ========================================================================= + // Role Management + // ========================================================================= + + /// @notice Returns the BURN_BLOCKED_ROLE constant + /// @return keccak256("BURN_BLOCKED_ROLE") + function BURN_BLOCKED_ROLE() external view returns (bytes32); + + /// @notice Returns the ISSUER_ROLE constant + /// @return keccak256("ISSUER_ROLE") + function ISSUER_ROLE() external view returns (bytes32); + + /// @notice Returns the PAUSE_ROLE constant + /// @return keccak256("PAUSE_ROLE") + function PAUSE_ROLE() external view returns (bytes32); + + /// @notice Returns the UNPAUSE_ROLE constant + /// @return keccak256("UNPAUSE_ROLE") + function UNPAUSE_ROLE() external view returns (bytes32); + + /// @notice Grants a role to an account (requires role admin) + /// @param role The role to grant (keccak256 hash) + /// @param account The account to grant the role to + function grantRole(bytes32 role, address account) external; + + /// @notice Revokes a role from an account (requires role admin) + /// @param role The role to revoke (keccak256 hash) + /// @param account The account to revoke the role from + function revokeRole(bytes32 role, address account) external; + + /// @notice Allows an account to remove a role from itself + /// @param role The role to renounce (keccak256 hash) + function renounceRole(bytes32 role) external; + + /// @notice Changes the admin role for a specific role (requires current role admin) + /// @param role The role whose admin is being changed + /// @param adminRole The new admin role + function setRoleAdmin(bytes32 role, bytes32 adminRole) external; + + // ========================================================================= + // System Functions + // ========================================================================= + + /// @notice System-level transfer function (restricted to precompiles) + /// @param from The sender address + /// @param to The recipient address + /// @param amount The amount to transfer + /// @return True if successful + function systemTransferFrom(address from, address to, uint256 amount) external returns (bool); + + /// @notice Pre-transaction fee transfer (restricted to precompiles) + /// @param from The account to charge fees from + /// @param amount The fee amount + function transferFeePreTx(address from, uint256 amount) external; + + /// @notice Post-transaction fee handling (restricted to precompiles) + /// @param to The account to refund + /// @param refund The refund amount + /// @param actualUsed The actual fee used + function transferFeePostTx(address to, uint256 refund, uint256 actualUsed) external; + + // ========================================================================= + // Events + // ========================================================================= + + /// @notice Emitted when a new allowance is set by `owner` for `spender` + /// @param owner The account granting the allowance + /// @param spender The account being approved to spend tokens + /// @param amount The new allowance amount + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /// @notice Emitted when tokens are burned from an address + /// @param from The address whose tokens were burned + /// @param amount The amount of tokens that were burned + event Burn(address indexed from, uint256 amount); + + /// @notice Emitted when tokens are burned from a blocked address + /// @param from The blocked address whose tokens were burned + /// @param amount The amount of tokens that were burned + event BurnBlocked(address indexed from, uint256 amount); + + /// @notice Emitted when new tokens are minted to an address + /// @param to The address receiving the minted tokens + /// @param amount The amount of tokens that were minted + event Mint(address indexed to, uint256 amount); + + /// @notice Emitted when a new quote token is staged for this token + /// @param updater The account that staged the new quote token + /// @param nextQuoteToken The quote token that has been staged + event NextQuoteTokenSet(address indexed updater, ITIP20 indexed nextQuoteToken); + + /// @notice Emitted when the pause state of the token changes + /// @param updater The account that changed the pause state + /// @param isPaused The new pause state; true if paused, false if unpaused + event PauseStateUpdate(address indexed updater, bool isPaused); + + /// @notice Emitted when the quote token update process is completed + /// @param updater The account that completed the quote token update + /// @param newQuoteToken The new quote token that has been set + event QuoteTokenUpdate(address indexed updater, ITIP20 indexed newQuoteToken); + + /// @notice Emitted when a holder sets or updates their reward recipient address + /// @param holder The token holder configuring the recipient + /// @param recipient The address that will receive claimed rewards + event RewardRecipientSet(address indexed holder, address indexed recipient); + + /// @notice Emitted when a reward distribution is scheduled + /// @param funder The account funding the reward distribution + /// @param amount The total amount of tokens allocated to the reward + event RewardDistributed(address indexed funder, uint256 amount); + + /// @notice Emitted when the token's supply cap is updated + /// @param updater The account that updated the supply cap + /// @param newSupplyCap The new maximum total supply + event SupplyCapUpdate(address indexed updater, uint256 indexed newSupplyCap); + + /// @notice Emitted for all token movements, including mints and burns + /// @param from The address sending tokens (address(0) for mints) + /// @param to The address receiving tokens (address(0) for burns) + /// @param amount The amount of tokens transferred + event Transfer(address indexed from, address indexed to, uint256 amount); + + /// @notice Emitted when the transfer policy ID is updated + /// @param updater The account that updated the transfer policy + /// @param newPolicyId The new transfer policy ID from the TIP-403 registry + event TransferPolicyUpdate(address indexed updater, uint64 indexed newPolicyId); + + /// @notice Emitted when a transfer, mint, or burn is performed with an attached memo + /// @param from The address sending tokens (address(0) for mints) + /// @param to The address receiving tokens (address(0) for burns) + /// @param amount The amount of tokens transferred + /// @param memo The 32-byte memo associated with this movement + event TransferWithMemo(address indexed from, address indexed to, uint256 amount, bytes32 indexed memo); + + /// @notice Emitted when the membership of a role changes for an account + /// @param role The role being granted or revoked + /// @param account The account whose membership was changed + /// @param sender The account that performed the change + /// @param hasRole True if the role was granted, false if it was revoked + event RoleMembershipUpdated(bytes32 indexed role, address indexed account, address indexed sender, bool hasRole); + + /// @notice Emitted when the admin role for a role is updated + /// @param role The role whose admin role was changed + /// @param newAdminRole The new admin role for the given role + /// @param sender The account that performed the update + event RoleAdminUpdated(bytes32 indexed role, bytes32 indexed newAdminRole, address indexed sender); + + // ========================================================================= + // Errors + // ========================================================================= + + /// @notice The token operation is blocked because the contract is currently paused + error ContractPaused(); + + /// @notice The spender does not have enough allowance for the attempted transfer + error InsufficientAllowance(); + + /// @notice The account does not have the required token balance for the operation + /// @param currentBalance The current balance of the account + /// @param expectedBalance The required balance for the operation to succeed + /// @param token The address of the token contract + error InsufficientBalance(uint256 currentBalance, uint256 expectedBalance, address token); + + /// @notice The provided amount is zero or otherwise invalid for the attempted operation + error InvalidAmount(); + + /// @notice The provided currency identifier is invalid or unsupported + error InvalidCurrency(); + + /// @notice The specified quote token is invalid, incompatible, or would create a circular reference + error InvalidQuoteToken(); + + /// @notice The recipient address is not a valid destination for this operation + /// (for example, another TIP-20 token contract) + error InvalidRecipient(); + + /// @notice The specified transfer policy ID does not exist in the TIP-403 registry + error InvalidTransferPolicyId(); + + /// @notice The new supply cap is invalid, for example lower than the current total supply + error InvalidSupplyCap(); + + /// @notice A rewards operation was attempted when no opted-in supply exists + error NoOptedInSupply(); + + /// @notice The configured transfer policy denies authorization for the sender or recipient + error PolicyForbids(); + + /// @notice The attempted operation would cause total supply to exceed the configured supply cap + error SupplyCapExceeded(); + + /// @notice The caller does not have the required role or permission for this operation + error Unauthorized(); +} diff --git a/contracts/token/TempoBridgeUpgradeable.sol b/contracts/token/TempoBridgeUpgradeable.sol new file mode 100644 index 00000000..4e1eefe7 --- /dev/null +++ b/contracts/token/TempoBridgeUpgradeable.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.28; + +import { ITIP20 } from "../interfaces/ITIP20.sol"; +import { OFTCoreUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTCoreUpgradeable.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +/// @title Tempo Bridge +/// @author kexley, Cap Labs +/// @notice A bridge using LayerZero for sending tokens to and from Tempo +contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { + /// @dev The underlying TIP20 token. + ITIP20 internal immutable underlyingToken; + + /// @dev Constructor for the Tempo Bridge contract. + /// @param _underlyingToken The address of the TIP20 token to bridge. + /// @param _lzEndpoint The LayerZero endpoint address. + constructor(address _underlyingToken, address _lzEndpoint) + OFTCoreUpgradeable(ITIP20(_underlyingToken).decimals(), _lzEndpoint) + { + underlyingToken = ITIP20(_underlyingToken); + _disableInitializers(); + } + + /// @dev Initialize the Tempo Bridge contract. + /// @param _delegate The delegate address for OApp configuration. + function initialize(address _delegate) external initializer { + __OFTCore_init(_delegate); + __Ownable_init(_delegate); + __UUPSUpgradeable_init(); + } + + /// @notice Retrieves the address of the underlying TIP20 token. + /// @return tokenAddress The address of the underlying TIP20 token. + function token() public view returns (address tokenAddress) { + tokenAddress = address(underlyingToken); + } + + /// @notice Indicates whether approval is required to transfer tokens to the bridge for burning. + /// @return requiresApproval Indicates whether approval is required. + function approvalRequired() external pure virtual returns (bool requiresApproval) { + requiresApproval = true; + } + + /// @dev Burns tokens from the sender's balance to prepare for sending. + /// @param _from The address to debit the tokens from. + /// @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(address _from, uint256 _amountLD, uint256 _minAmountLD, uint32 _dstEid) + internal + virtual + override + returns (uint256 amountSentLD, uint256 amountReceivedLD) + { + (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); + // Transfers tokens from the sender to the bridge since `burnFrom` is not supported on TIP20 tokens. + underlyingToken.transferFrom(_from, address(this), amountSentLD); + // Burn tokens from the bridge. + underlyingToken.burn(amountSentLD); + } + + /// @dev Mints 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) + { + if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0) + // Mints the tokens and transfers to the recipient. + underlyingToken.mint(_to, _amountLD); + // In the case of Tempo Bridge, the amountLD is equal to amountReceivedLD. + return _amountLD; + } + + /// @dev Authorize the upgrade + function _authorizeUpgrade(address) internal view override onlyOwner { } +} From f7799e70879847f3057fe5bf64badc02aec05914 Mon Sep 17 00:00:00 2001 From: kexley <87971154+kexleyBeefy@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:52:31 -0500 Subject: [PATCH 2/3] Fix TIP20 decimals & add storage to bridge --- contracts/token/TempoBridgeUpgradeable.sol | 35 +++++++++++++++------- script/DeployTempo.s.sol | 28 +++++++++++++++++ 2 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 script/DeployTempo.s.sol diff --git a/contracts/token/TempoBridgeUpgradeable.sol b/contracts/token/TempoBridgeUpgradeable.sol index 4e1eefe7..a897ea8f 100644 --- a/contracts/token/TempoBridgeUpgradeable.sol +++ b/contracts/token/TempoBridgeUpgradeable.sol @@ -9,22 +9,34 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils /// @author kexley, Cap Labs /// @notice A bridge using LayerZero for sending tokens to and from Tempo contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { - /// @dev The underlying TIP20 token. - ITIP20 internal immutable underlyingToken; + struct TempoBridgeStorage { + // The underlying TIP20 token. + ITIP20 underlyingToken; + } - /// @dev Constructor for the Tempo Bridge contract. - /// @param _underlyingToken The address of the TIP20 token to bridge. + // keccak256(abi.encode(uint256(keccak256("cap.storage.TempoBridge")) - 1)) & ~bytes32(uint256(0xff)) + bytes32 private constant TempoBridgeStorageLocation = + 0xaff443d40d9449d0bb041d5986df9cd3a11be6e711f780b1d135421cee639900; + + /// @dev Get the tempo bridge storage. + /// @return $ Storage pointer + function _getTempoBridgeStorage() internal pure returns (TempoBridgeStorage storage $) { + assembly { + $.slot := TempoBridgeStorageLocation + } + } + + /// @dev Constructor for the Tempo Bridge contract. All TIP20 tokens have 6 decimals. /// @param _lzEndpoint The LayerZero endpoint address. - constructor(address _underlyingToken, address _lzEndpoint) - OFTCoreUpgradeable(ITIP20(_underlyingToken).decimals(), _lzEndpoint) - { - underlyingToken = ITIP20(_underlyingToken); + constructor(address _lzEndpoint) OFTCoreUpgradeable(6, _lzEndpoint) { _disableInitializers(); } /// @dev Initialize the Tempo Bridge contract. + /// @param _underlyingToken The address of the TIP20 token to bridge. /// @param _delegate The delegate address for OApp configuration. - function initialize(address _delegate) external initializer { + function initialize(address _underlyingToken, address _delegate) external initializer { + _getTempoBridgeStorage().underlyingToken = ITIP20(_underlyingToken); __OFTCore_init(_delegate); __Ownable_init(_delegate); __UUPSUpgradeable_init(); @@ -33,7 +45,7 @@ contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { /// @notice Retrieves the address of the underlying TIP20 token. /// @return tokenAddress The address of the underlying TIP20 token. function token() public view returns (address tokenAddress) { - tokenAddress = address(underlyingToken); + tokenAddress = address(_getTempoBridgeStorage().underlyingToken); } /// @notice Indicates whether approval is required to transfer tokens to the bridge for burning. @@ -56,6 +68,7 @@ contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { returns (uint256 amountSentLD, uint256 amountReceivedLD) { (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid); + ITIP20 underlyingToken = _getTempoBridgeStorage().underlyingToken; // Transfers tokens from the sender to the bridge since `burnFrom` is not supported on TIP20 tokens. underlyingToken.transferFrom(_from, address(this), amountSentLD); // Burn tokens from the bridge. @@ -79,7 +92,7 @@ contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { { if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0) // Mints the tokens and transfers to the recipient. - underlyingToken.mint(_to, _amountLD); + _getTempoBridgeStorage().underlyingToken.mint(_to, _amountLD); // In the case of Tempo Bridge, the amountLD is equal to amountReceivedLD. return _amountLD; } diff --git a/script/DeployTempo.s.sol b/script/DeployTempo.s.sol new file mode 100644 index 00000000..b2c8fd2b --- /dev/null +++ b/script/DeployTempo.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.28; + +import { TempoBridgeUpgradeable } from "../contracts/token/TempoBridgeUpgradeable.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import { Script } from "forge-std/Script.sol"; +import { console } from "forge-std/console.sol"; + +contract DeployTempo is Script { + function run() external { + vm.startBroadcast(); + + address delegate = address(0xc1ab5a9593E6e1662A9a44F84Df4F31Fc8A76B52); + address token = address(0x20C0000000000000000000000520792DcCccCccC); + address endpoint = address(0x8bC1e36F015b9902B54b1387A4d733cebc2f5A4e); + + TempoBridgeUpgradeable tempoBridgeImpl = new TempoBridgeUpgradeable(endpoint); + + // First, encode the initialize function call with all parameters + bytes memory initializeCalldata = abi.encodeWithSignature("initialize(address,address)", token, delegate); + + address tempoBridge = address(new ERC1967Proxy(address(tempoBridgeImpl), initializeCalldata)); + + console.log("Tempo Bridge implementation deployed at", address(tempoBridgeImpl)); + console.log("Tempo Bridge deployed at", tempoBridge); + vm.stopBroadcast(); + } +} From bfa392aafb542f7e3cdb759f7ed2cd25c6839aa1 Mon Sep 17 00:00:00 2001 From: kexley <87971154+kexleyBeefy@users.noreply.github.com> Date: Thu, 12 Mar 2026 16:24:00 -0400 Subject: [PATCH 3/3] Update Tempo OFT to alt version --- contracts/token/TempoBridgeUpgradeable.sol | 8 ++++---- foundry.toml | 2 ++ package.json | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contracts/token/TempoBridgeUpgradeable.sol b/contracts/token/TempoBridgeUpgradeable.sol index a897ea8f..4c299d2a 100644 --- a/contracts/token/TempoBridgeUpgradeable.sol +++ b/contracts/token/TempoBridgeUpgradeable.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.28; import { ITIP20 } from "../interfaces/ITIP20.sol"; -import { OFTCoreUpgradeable } from "@layerzerolabs/oft-evm-upgradeable/contracts/oft/OFTCoreUpgradeable.sol"; +import { OFTAltCoreUpgradeable } from "@layerzerolabs/oft-alt-evm/contracts/OFTAltCoreUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; /// @title Tempo Bridge /// @author kexley, Cap Labs /// @notice A bridge using LayerZero for sending tokens to and from Tempo -contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { +contract TempoBridgeUpgradeable is OFTAltCoreUpgradeable, UUPSUpgradeable { struct TempoBridgeStorage { // The underlying TIP20 token. ITIP20 underlyingToken; @@ -28,7 +28,7 @@ contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { /// @dev Constructor for the Tempo Bridge contract. All TIP20 tokens have 6 decimals. /// @param _lzEndpoint The LayerZero endpoint address. - constructor(address _lzEndpoint) OFTCoreUpgradeable(6, _lzEndpoint) { + constructor(address _lzEndpoint) OFTAltCoreUpgradeable(6, _lzEndpoint) { _disableInitializers(); } @@ -37,7 +37,7 @@ contract TempoBridgeUpgradeable is OFTCoreUpgradeable, UUPSUpgradeable { /// @param _delegate The delegate address for OApp configuration. function initialize(address _underlyingToken, address _delegate) external initializer { _getTempoBridgeStorage().underlyingToken = ITIP20(_underlyingToken); - __OFTCore_init(_delegate); + __OFTAltCore_init(_delegate); __Ownable_init(_delegate); __UUPSUpgradeable_init(); } diff --git a/foundry.toml b/foundry.toml index 41fa4b29..52d9da08 100644 --- a/foundry.toml +++ b/foundry.toml @@ -11,6 +11,8 @@ remappings = [ "@symbioticfi/burners/=node_modules/@symbioticfi/burners/", "@symbioticfi/hooks/=node_modules/@symbioticfi/hooks/", "@symbioticfi/rewards/=node_modules/@symbioticfi/rewards/", + "@layerzerolabs/oapp-alt-evm/=node_modules/@layerzerolabs/oapp-alt-evm/", + "@layerzerolabs/oft-alt-evm/=node_modules/@layerzerolabs/oft-alt-evm/", "@layerzerolabs/oft-evm/=lib/layerzero-devtools/packages/oft-evm/", "@layerzerolabs/oft-evm-upgradeable/=lib/layerzero-devtools/packages/oft-evm-upgradeable/", "@layerzerolabs/oapp-evm/=lib/layerzero-devtools/packages/oapp-evm/", diff --git a/package.json b/package.json index 3d3d7f92..bc375b7d 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,8 @@ "@openzeppelin/contracts": "^5.2.0" }, "dependencies": { + "@layerzerolabs/oapp-alt-evm": "^0.0.5", + "@layerzerolabs/oft-alt-evm": "^0.0.5", "@layerzerolabs/oft-evm-upgradeable": "^4.0.2", "@morenabarboni/sumo": "^2.5.4", "@openzeppelin/foundry-upgrades": "^0.3.7",