Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

/**
* @title AbstractCCTP4626Strategy - Abstract contract for CCTP morpho strategy
* @author Origin Protocol Inc
*/

import { AbstractCCTPIntegrator } from "./AbstractCCTPIntegrator.sol";

abstract contract AbstractCCTP4626Strategy is
AbstractCCTPIntegrator
{

constructor(
CCTPIntegrationConfig memory _config
)
AbstractCCTPIntegrator(
_config
)
{}

function _encodeDepositMessage(uint64 nonce, uint256 depositAmount)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
DEPOSIT_MESSAGE,
abi.encode(nonce, depositAmount)
);
}

function _decodeDepositMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, DEPOSIT_MESSAGE);

(uint64 nonce, uint256 depositAmount) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, depositAmount);
}

function _encodeWithdrawMessage(uint64 nonce, uint256 withdrawAmount)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
WITHDRAW_MESSAGE,
abi.encode(nonce, withdrawAmount)
);
}

function _decodeWithdrawMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, WITHDRAW_MESSAGE);

(uint64 nonce, uint256 withdrawAmount) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, withdrawAmount);
}

function _encodeBalanceCheckMessage(uint64 nonce, uint256 balance)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
BALANCE_CHECK_MESSAGE,
abi.encode(nonce, balance)
);
}

function _decodeBalanceCheckMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, BALANCE_CHECK_MESSAGE);

(uint64 nonce, uint256 balance) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, balance);
}
}
212 changes: 21 additions & 191 deletions contracts/contracts/strategies/crosschain/AbstractCCTPIntegrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { IERC20 } from "../../utils/InitializableAbstractStrategy.sol";
import { ICCTPTokenMessenger, ICCTPMessageTransmitter, IMessageHandlerV2 } from "../../interfaces/cctp/ICCTP.sol";

import { Governable } from "../../governance/Governable.sol";

import { BytesHelper } from "../../utils/BytesHelper.sol";
import { CCTPMessageRelayer } from "./CCTPMessageRelayer.sol";
import "../../utils/Helpers.sol";

abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2, CCTPMessageRelayer {
using SafeERC20 for IERC20;

using BytesHelper for bytes;
Expand All @@ -27,10 +27,6 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
uint32 public constant WITHDRAW_ACK_MESSAGE = 20;
uint32 public constant BALANCE_CHECK_MESSAGE = 3;

// CCTP contracts
ICCTPTokenMessenger public immutable cctpTokenMessenger;
ICCTPMessageTransmitter public immutable cctpMessageTransmitter;

// CCTP Hook Wrapper
address public immutable cctpHookWrapper;

Expand All @@ -46,6 +42,7 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
// CCTP params
uint32 public minFinalityThreshold;
uint32 public feePremiumBps;
// Threshold imposed by the CCTP
uint256 public constant MAX_TRANSFER_AMOUNT = 10_000_000 * 10**6; // 10M USDC

// Nonce of the last known deposit or withdrawal
Expand All @@ -64,25 +61,27 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
_;
}

struct CCTPIntegrationConfig {
address cctpTokenMessenger;
address cctpMessageTransmitter;
uint32 destinationDomain;
address destinationStrategy;
address baseToken;
address cctpHookWrapper;
}

constructor(
address _cctpTokenMessenger,
address _cctpMessageTransmitter,
uint32 _destinationDomain,
address _destinationStrategy,
address _baseToken,
address _cctpHookWrapper
) {
cctpTokenMessenger = ICCTPTokenMessenger(_cctpTokenMessenger);
cctpMessageTransmitter = ICCTPMessageTransmitter(
_cctpMessageTransmitter
);
destinationDomain = _destinationDomain;
destinationStrategy = _destinationStrategy;
baseToken = _baseToken;
cctpHookWrapper = _cctpHookWrapper;
CCTPIntegrationConfig memory _config
) CCTPMessageRelayer(_config.cctpMessageTransmitter, _config.cctpTokenMessenger) {
cctpTokenMessenger = ICCTPTokenMessenger(_config.cctpTokenMessenger);
cctpMessageTransmitter = ICCTPMessageTransmitter(_config.cctpMessageTransmitter);
destinationDomain = _config.destinationDomain;
destinationStrategy = _config.destinationStrategy;
baseToken = _config.baseToken;
cctpHookWrapper = _config.cctpHookWrapper;

// Just a sanity check to ensure the base token is USDC
uint256 _baseTokenDecimals = Helpers.getDecimals(_baseToken);
uint256 _baseTokenDecimals = Helpers.getDecimals(_config.baseToken);
require(_baseTokenDecimals == 6, "Base token decimals must be 6");
}

Expand Down Expand Up @@ -176,24 +175,6 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
return true;
}

function onTokenReceived(
uint256 tokenAmount,
uint256 feeExecuted,
bytes memory payload
) external virtual {
require(
msg.sender == cctpHookWrapper,
"Caller is not the CCTP hook wrapper"
);
_onTokenReceived(tokenAmount, feeExecuted, payload);
}

function _onTokenReceived(
uint256 tokenAmount,
uint256 feeExecuted,
bytes memory payload
) internal virtual;

function _onMessageReceived(bytes memory payload) internal virtual;

function _sendTokens(uint256 tokenAmount, bytes memory hookData)
Expand Down Expand Up @@ -267,157 +248,6 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {
return message.extractSlice(8, message.length);
}

function _encodeDepositMessage(uint64 nonce, uint256 depositAmount)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
DEPOSIT_MESSAGE,
abi.encode(nonce, depositAmount)
);
}

function _decodeDepositMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, DEPOSIT_MESSAGE);

(uint64 nonce, uint256 depositAmount) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, depositAmount);
}

function _encodeDepositAckMessage(
uint64 nonce,
uint256 amountReceived,
uint256 feeExecuted,
uint256 balanceAfter
) internal virtual returns (bytes memory) {
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
DEPOSIT_ACK_MESSAGE,
abi.encode(nonce, amountReceived, feeExecuted, balanceAfter)
);
}

function _decodeDepositAckMessage(bytes memory message)
internal
virtual
returns (
uint64,
uint256,
uint256,
uint256
)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, DEPOSIT_ACK_MESSAGE);

(
uint64 nonce,
uint256 amountReceived,
uint256 feeExecuted,
uint256 balanceAfter
) = abi.decode(
_getMessagePayload(message),
(uint64, uint256, uint256, uint256)
);

return (nonce, amountReceived, feeExecuted, balanceAfter);
}

function _encodeWithdrawMessage(uint64 nonce, uint256 withdrawAmount)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
WITHDRAW_MESSAGE,
abi.encode(nonce, withdrawAmount)
);
}

function _decodeWithdrawMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, WITHDRAW_MESSAGE);

(uint64 nonce, uint256 withdrawAmount) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, withdrawAmount);
}

function _encodeWithdrawAckMessage(
uint64 nonce,
uint256 amountSent,
uint256 balanceAfter
) internal virtual returns (bytes memory) {
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
WITHDRAW_ACK_MESSAGE,
abi.encode(nonce, amountSent, balanceAfter)
);
}

function _decodeWithdrawAckMessage(bytes memory message)
internal
virtual
returns (
uint64,
uint256,
uint256
)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, WITHDRAW_ACK_MESSAGE);

(uint64 nonce, uint256 amountSent, uint256 balanceAfter) = abi.decode(
_getMessagePayload(message),
(uint64, uint256, uint256)
);
return (nonce, amountSent, balanceAfter);
}

function _encodeBalanceCheckMessage(uint64 nonce, uint256 balance)
internal
virtual
returns (bytes memory)
{
return
abi.encodePacked(
ORIGIN_MESSAGE_VERSION,
BALANCE_CHECK_MESSAGE,
abi.encode(nonce, balance)
);
}

function _decodeBalanceCheckMessage(bytes memory message)
internal
virtual
returns (uint64, uint256)
{
_verifyMessageVersionAndType(message, ORIGIN_MESSAGE_VERSION, BALANCE_CHECK_MESSAGE);

(uint64 nonce, uint256 balance) = abi.decode(
_getMessagePayload(message),
(uint64, uint256)
);
return (nonce, balance);
}

function _sendMessage(bytes memory message) internal virtual {
cctpMessageTransmitter.sendMessage(
destinationDomain,
Expand Down
Loading
Loading