Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/HubExecutorEntryPoint.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
import { IHubPortal } from "./interfaces/IHubPortal.sol";
import { ExecutorArgs, IHubExecutorEntryPoint } from "./interfaces/IHubExecutorEntryPoint.sol";
import { ExecutorEntryPoint } from "./ExecutorEntryPoint.sol";
/// @title ExecutorEntryPoint
/// @notice The ExecutorEntryPoint contract is a shim contract that initiates
/// an M NTT transfer using the executor for relaying.
contract HubExecutorEntryPoint is ExecutorEntryPoint, IHubExecutorEntryPoint {
constructor(
address _executor,
address _portal,
address _wormhole
) ExecutorEntryPoint(_executor, _portal, _wormhole) {}
/* ============ Interactive Functions ============ */
/// @inheritdoc IHubExecutorEntryPoint
function sendMTokenIndex(
uint16 destinationChainId,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence) {
address emitter;
(emitter, sequence) = _getNextTransceiverSequence();
IHubPortal(portal).sendMTokenIndex{ value: msg.value - executorArgs.value }(
destinationChainId,
refundAddress,
transceiverInstructions
);
// Generate the executor request event.
_requestExecution(destinationChainId, emitter, sequence, executorArgs);
}
/// @inheritdoc IHubExecutorEntryPoint
function sendEarnersMerkleRoot(
uint16 destinationChainId,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence) {
address emitter;
(emitter, sequence) = _getNextTransceiverSequence();
IHubPortal(portal).sendEarnersMerkleRoot{ value: msg.value - executorArgs.value }(
destinationChainId,
refundAddress,
transceiverInstructions
);
// Generate the executor request event.
_requestExecution(destinationChainId, emitter, sequence, executorArgs);
}
}
"
},
"src/interfaces/IHubPortal.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
import { IPortal } from "./IPortal.sol";
/**
* @title HubPortal interface.
* @author M^0 Labs
*/
interface IHubPortal is IPortal {
/* ============ Events ============ */
/**
* @notice Emitted when earning is enabled for the Hub Portal.
* @param index The index at which earning was enabled.
*/
event EarningEnabled(uint128 index);
/**
* @notice Emitted when earning is disabled for the Hub Portal.
* @param index The index at which earning was disabled.
*/
event EarningDisabled(uint128 index);
/**
* @notice Emitted when the M token index is sent to a destination chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param messageId The unique identifier for the sent message.
* @param index The the M token index.
*/
event MTokenIndexSent(uint16 indexed destinationChainId, bytes32 messageId, uint128 index);
/**
* @notice Emitted when the Registrar key is sent to a destination chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param messageId The unique identifier for the sent message.
* @param key The key that was sent.
* @param value The value that was sent.
*/
event RegistrarKeySent(uint16 indexed destinationChainId, bytes32 messageId, bytes32 indexed key, bytes32 value);
/**
* @notice Emitted when the Registrar list status for an account is sent to a destination chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param messageId The unique identifier for the sent message.
* @param listName The name of the list.
* @param account The account.
* @param status The status of the account in the list.
*/
event RegistrarListStatusSent(
uint16 indexed destinationChainId,
bytes32 messageId,
bytes32 indexed listName,
address indexed account,
bool status
);
/**
* @notice Emitted when Merkle Tree Builder contract is set.
* @param merkleTreeBuilder The address of Merkle Tree Builder contract.
*/
event MerkleTreeBuilderSet(address merkleTreeBuilder);
/**
* @notice Emitted when earners Merkle root is sent to Solana.
* @param destinationChainId The Wormhole chain ID for the destination.
* @param messageId The unique identifier for the sent message.
* @param earnersMerkleRoot The Merkle root of earners.
*/
event EarnersMerkleRootSent(uint16 indexed destinationChainId, bytes32 messageId, bytes32 earnersMerkleRoot);
/* ============ Custom Errors ============ */
/// @notice Emitted when trying to enable earning after it has been explicitly disabled.
error EarningCannotBeReenabled();
/// @notice Emitted when performing an operation that is not allowed when earning is disabled.
error EarningIsDisabled();
/// @notice Emitted when performing an operation that is not allowed when earning is enabled.
error EarningIsEnabled();
/// @notice Emitted when calling `setMerkleTreeBuilder` if Merkle Tree Builder address is 0x0.
error ZeroMerkleTreeBuilder();
/// @notice Emitted when the destination chain is not supported
error UnsupportedDestinationChain(uint16 destinationChainId);
/* ============ View/Pure Functions ============ */
/// @notice Indicates whether earning for HubPortal was ever enabled.
function wasEarningEnabled() external returns (bool);
/// @notice Returns the value of M Token index when earning for HubPortal was disabled.
function disableEarningIndex() external returns (uint128);
/// @notice Returns the address of Merkle tree builder.
function merkleTreeBuilder() external returns (address);
/* ============ Interactive Functions ============ */
/**
* @notice Sends the M token index to the destination chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param refundAddress The refund address to receive excess native gas.
* @param transceiverInstructions The transceiver specific instructions for quoting and sending.
* @return messageId The ID uniquely identifying the message.
*/
function sendMTokenIndex(
uint16 destinationChainId,
bytes32 refundAddress,
bytes memory transceiverInstructions
) external payable returns (bytes32 messageId);
/**
* @notice Sends the Registrar key to the destination chain.
* @dev Not supported for SVM chains.
* @param destinationChainId The Wormhole destination chain ID.
* @param key The key to dispatch.
* @param refundAddress The refund address to receive excess native gas.
* @param transceiverInstructions The transceiver specific instructions for quoting and sending.
* @return messageId The ID uniquely identifying the message
*/
function sendRegistrarKey(
uint16 destinationChainId,
bytes32 key,
bytes32 refundAddress,
bytes memory transceiverInstructions
) external payable returns (bytes32 messageId);
/**
* @notice Sends the Registrar list status for an account to the destination chain.
* @dev Not supported for SVM chains.
* @param destinationChainId The Wormhole destination chain ID.
* @param listName The name of the list.
* @param account The account.
* @param refundAddress The refund address to receive excess native gas.
* @param transceiverInstructions The transceiver specific instructions for quoting and sending.
* @return messageId The ID uniquely identifying the message.
*/
function sendRegistrarListStatus(
uint16 destinationChainId,
bytes32 listName,
address account,
bytes32 refundAddress,
bytes memory transceiverInstructions
) external payable returns (bytes32 messageId);
/**
* @notice Sends earners Merkle root to SVM chains.
* @param destinationChainId The Wormhole destination chain ID.
* @param refundAddress The refund address to receive excess native gas.
* @param transceiverInstructions The transceiver specific instructions for quoting and sending.
* @return messageId The ID uniquely identifying the message.
*/
function sendEarnersMerkleRoot(
uint16 destinationChainId,
bytes32 refundAddress,
bytes memory transceiverInstructions
) external payable returns (bytes32 messageId);
/**
* @notice Sets Merkle Tree Builder contract.
* @param merkleTreeBuilder The address of Merkle Tree Builder contract.
*/
function setMerkleTreeBuilder(address merkleTreeBuilder) external;
/// @notice Enables earning for the Hub Portal if allowed by TTG.
function enableEarning() external;
/// @notice Disables earning for the Hub Portal if disallowed by TTG.
function disableEarning() external;
}
"
},
"src/interfaces/IHubExecutorEntryPoint.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
import { IExecutorEntryPoint, ExecutorArgs } from "./IExecutorEntryPoint.sol";
interface IHubExecutorEntryPoint is IExecutorEntryPoint {
/// @notice Send the M token index to a given chain using the Executor for relaying.
/// @param destinationChainId The Wormhole chain ID for the destination.
/// @param refundAddress The Wormhole address to refund excess gas to.
/// @param executorArgs The arguments to be passed into the Executor.
/// @param transceiverInstructions The transceiver specific instructions for quoting and sending.
/// @return sequence The resulting sequence ID on the transceiver for the index send.
function sendMTokenIndex(
uint16 destinationChainId,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence);
/// @notice Send the earners Merkle root to SVM chains using the Executor for relaying.
/// @param destinationChainId The Wormhole chain ID for the destination.
/// @param refundAddress The Wormhole address to refund excess gas to.
/// @param executorArgs The arguments to be passed into the Executor.
/// @param transceiverInstructions The transceiver specific instructions for quoting and sending.
/// @return sequence The resulting sequence ID on the transceiver for the Merkle root send.
function sendEarnersMerkleRoot(
uint16 destinationChainId,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence);
}
"
},
"src/ExecutorEntryPoint.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
import { IERC20 } from "../lib/common/src/interfaces/IERC20.sol";
import { INttManager } from "../lib/native-token-transfers/evm/src/interfaces/INttManager.sol";
import { IWormhole } from "../lib/native-token-transfers/evm/lib/wormhole-solidity-sdk/src/interfaces/IWormhole.sol";
import { TransceiverRegistry } from "../lib/native-token-transfers/evm/src/NttManager/TransceiverRegistry.sol";
import { IPortal } from "./interfaces/IPortal.sol";
import { ExecutorArgs, IExecutorEntryPoint } from "./interfaces/IExecutorEntryPoint.sol";
import { IExecutor } from "./external/IExecutor.sol";
import { ExecutorMessages } from "./external/ExecutorMessages.sol";
import { TypeConverter } from "./libs/TypeConverter.sol";
/// @title ExecutorEntryPoint
/// @notice The ExecutorEntryPoint contract is a shim contract that initiates
/// an M NTT transfer using the executor for relaying.
contract ExecutorEntryPoint is IExecutorEntryPoint {
using TypeConverter for address;
uint16 public immutable chainId;
address public immutable executor;
address public immutable portal;
IWormhole public immutable wormhole;
string public constant VERSION = "ExecutorEntryPoint-0.0.2";
constructor(address _executor, address _portal, address _wormhole) {
if ((executor = _executor) == address(0)) revert ZeroExecutor();
if ((portal = _portal) == address(0)) revert ZeroPortal();
if (address(wormhole = IWormhole(_wormhole)) == address(0)) revert ZeroWormhole();
chainId = wormhole.chainId();
}
/* ============ Interactive Functions ============ */
/// @inheritdoc IExecutorEntryPoint
function transferMLikeToken(
uint256 amount,
address sourceToken,
uint16 destinationChainId,
bytes32 destinationToken,
bytes32 recipient,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence) {
// Custody the tokens in this contract and approve Portal to spend them.
amount = _custodyTokens(sourceToken, amount);
// Get the next sequence number for the transceiver.
address emitter;
(emitter, sequence) = _getNextTransceiverSequence();
// Initiate the transfer.
IERC20(sourceToken).approve(portal, amount);
IPortal(portal).transferMLikeToken{ value: msg.value - executorArgs.value }(
amount,
sourceToken,
destinationChainId,
destinationToken,
recipient,
refundAddress,
transceiverInstructions
);
// Generate the executor request event.
_requestExecution(destinationChainId, emitter, sequence, executorArgs);
}
// necessary for receiving native assets, e.g. refunds
receive() external payable {}
/* ============ Internal Functions ============ */
function _requestExecution(
uint16 destinationChainId,
address emitter,
uint64 sequence,
ExecutorArgs calldata executorArgs
) internal {
// Generate the executor event.
IExecutor(executor).requestExecution{ value: executorArgs.value }(
destinationChainId,
INttManager(portal).getPeer(destinationChainId).peerAddress,
executorArgs.refundAddress,
executorArgs.signedQuote,
ExecutorMessages.makeVAAv1Request(chainId, emitter.toBytes32(), sequence),
executorArgs.instructions
);
// Refund any excess value.
uint256 currentBalance = address(this).balance;
if (currentBalance > 0) {
(bool refundSuccessful, ) = payable(executorArgs.refundAddress).call{ value: currentBalance }("");
if (!refundSuccessful) {
revert RefundFailed(currentBalance);
}
}
}
function _custodyTokens(address token, uint256 amount) internal returns (uint256) {
// query own token balance before transfer
uint256 balanceBefore = _getBalance(token);
// deposit tokens
IERC20(token).transferFrom(msg.sender, address(this), amount);
// return the balance difference
return _getBalance(token) - balanceBefore;
}
function _getBalance(address token) internal view returns (uint256 balance) {
return IERC20(token).balanceOf(address(this));
}
function _getNextTransceiverSequence() internal view returns (address emitter, uint64 sequence) {
// Get the list of transceivers from the portal. Assume the first one is used.
address[] memory transceivers = TransceiverRegistry(portal).getTransceivers();
address transceiver = transceivers[0];
return (transceiver, wormhole.nextSequence(transceiver));
}
}
"
},
"src/interfaces/IPortal.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
/**
* @title Portal interface inherited by HubPortal and SpokePortal.
* @author M^0 Labs
*/
interface IPortal {
/* ============ Events ============ */
/**
* @notice Emitted when M token is sent to a destination chain.
* @param sourceToken The address of the token on the source chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param destinationToken The address of the token on the destination chain.
* @param sender The address that bridged the M tokens via the Portal.
* @param recipient The account receiving tokens on destination chain.
* @param amount The amount of tokens.
* @param index The M token index.
* @param messageId The unique identifier for the sent message.
*/
event MTokenSent(
address indexed sourceToken,
uint16 destinationChainId,
bytes32 destinationToken,
address indexed sender,
bytes32 indexed recipient,
uint256 amount,
uint128 index,
bytes32 messageId
);
/**
* @notice Emitted when M token is received from a source chain.
* @param sourceChainId The Wormhole source chain ID.
* @param destinationToken The address of the token on the destination chain.
* @param sender The account sending tokens.
* @param recipient The account receiving tokens.
* @param amount The amount of tokens.
* @param index The M token index.
* @param messageId The unique identifier for the received message.
*/
event MTokenReceived(
uint16 sourceChainId,
address indexed destinationToken,
bytes32 indexed sender,
address indexed recipient,
uint256 amount,
uint128 index,
bytes32 messageId
);
/**
* @notice Emitted when wrapping M token is failed on the destination.
* @param destinationWrappedToken The address of the Wrapped M Token on the destination chain.
* @param recipient The account receiving tokens.
* @param amount The amount of tokens.
*/
event WrapFailed(address indexed destinationWrappedToken, address indexed recipient, uint256 amount);
/**
* @notice Emitted when M token is set for the remote chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param mToken The address of M token on the destination chain.
*/
event DestinationMTokenSet(uint16 indexed destinationChainId, bytes32 mToken);
/**
* @notice Emitted when a bridging path support status is updated.
* @param sourceToken The address of the token on the current chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param destinationToken The address of the token on the destination chain.
* @param supported `True` if the token is supported, `false` otherwise.
*/
event SupportedBridgingPathSet(
address indexed sourceToken,
uint16 indexed destinationChainId,
bytes32 indexed destinationToken,
bool supported
);
/* ============ Custom Errors ============ */
/// @notice Emitted when the M token is 0x0.
error ZeroMToken();
/// @notice Emitted when the Registrar address is 0x0.
error ZeroRegistrar();
/// @notice Thrown when the Swap Facility address is 0x0.
error ZeroSwapFacility();
/// @notice Emitted when the source token address is 0x0.
error ZeroSourceToken();
/// @notice Emitted when the destination token address is 0x0.
error ZeroDestinationToken();
/// @notice Emitted when a message received if the block.chainId
/// isn't equal to EVM chainId set in the constructor.
error InvalidFork(uint256 evmChainId, uint256 blockChainId);
/// @notice Emitted when the destination chain id
/// is equal to the source one.
error InvalidDestinationChain(uint16 destinationChainId);
/// @notice Emitted in `transferMLikeToken` function when bridging path is not supported
error UnsupportedBridgingPath(address sourceToken, uint16 destinationChainId, bytes32 destinationToken);
/* ============ View/Pure Functions ============ */
/// @notice The current index of the Portal's earning mechanism.
function currentIndex() external view returns (uint128);
/// @notice The address of the M token.
function mToken() external view returns (address);
/// @notice The address of the Registrar contract.
function registrar() external view returns (address);
/// @notice The address of the Swap Facility contract.
function swapFacility() external view returns (address);
/// @notice The address of the original caller of `transfer` and `transferMLikeToken` functions.
function msgSender() external view returns (address);
/**
* @notice Returns the address of M token on the destination chain.
* @param destinationChainId The Wormhole destination chain ID.
* @return mToken The address of M token on the destination chain.
*/
function destinationMToken(uint16 destinationChainId) external view returns (bytes32);
/**
* @notice Indicates whether the provided bridging path is supported.
* @param sourceToken The address of the token on the current chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param destinationToken The address of the token on the destination chain.
* @return supported `True` if the token is supported, `false` otherwise.
*/
function supportedBridgingPath(
address sourceToken,
uint16 destinationChainId,
bytes32 destinationToken
) external view returns (bool supported);
/* ============ Interactive Functions ============ */
/**
* @notice Sets M token address on the remote chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param mToken The address of M token on the destination chain.
*/
function setDestinationMToken(uint16 destinationChainId, bytes32 mToken) external;
/**
* @notice Sets a bridging path support status.
* @param sourceToken The address of the token on the current chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param destinationToken The address of the token on the destination chain.
* @param supported `True` if the token is supported, `false` otherwise.
*/
function setSupportedBridgingPath(
address sourceToken,
uint16 destinationChainId,
bytes32 destinationToken,
bool supported
) external;
/**
* @notice Transfers M or Wrapped M Token to the destination chain.
* @dev If wrapping on the destination fails, the recipient will receive $M token.
* @param amount The amount of tokens to transfer.
* @param sourceToken The address of the token (M or Wrapped M) on the source chain.
* @param destinationChainId The Wormhole destination chain ID.
* @param destinationToken The address of the token (M or Wrapped M) on the destination chain.
* @param recipient The account to receive tokens.
* @param refundAddress The address to receive excess native gas on the destination chain.
* @param transceiverInstructions The transceiver specific instructions for quoting and sending.
* @return sequence The message sequence.
*/
function transferMLikeToken(
uint256 amount,
address sourceToken,
uint16 destinationChainId,
bytes32 destinationToken,
bytes32 recipient,
bytes32 refundAddress,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence);
}
"
},
"src/interfaces/IExecutorEntryPoint.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;
struct ExecutorArgs {
// The msg value to be passed into the Executor.
uint256 value;
// The refund address used by the Executor.
address refundAddress;
// The signed quote to be passed into the Executor.
bytes signedQuote;
// The relay instructions to be passed into the Executor.
bytes instructions;
}
interface IExecutorEntryPoint {
/// @notice Error when the refund to the sender fails.
/// @dev Selector 0x2ca23714.
/// @param refundAmount The refund amount.
error RefundFailed(uint256 refundAmount);
/// @notice Emitted in the constructor if chain ID is 0.
error ZeroChainId();
/// @notice Emitted in the constructor if Executor address is 0x0.
error ZeroExecutor();
/// @notice Emitted in the constructor if Portal address is 0x0.
error ZeroPortal();
/// @notice Emitted in the constructor if Wormhole address is 0x0.
error ZeroWormhole();
/// @notice Transfer a given amount to a recipient on a given chain using the Executor for relaying.
/// @param amount The amount to transfer.
/// @param sourceToken M or an M extension that is supported by the Portal.
/// @param destinationChainId The Wormhole chain ID for the destination.
/// @param destinationToken The token address on the destination chain (M or Wrapped M).
/// @param recipient The recipient address on the destination chain.
/// @param executorArgs The arguments to be passed into the Executor.
/// @param transceiverInstructions The transceiver specific instructions for quoting and sending.
/// @return sequence The resulting sequence ID on the transceiver for the transfer.
function transferMLikeToken(
uint256 amount,
address sourceToken,
uint16 destinationChainId,
bytes32 destinationToken,
bytes32 recipient,
bytes32 refundAddress,
ExecutorArgs calldata executorArgs,
bytes memory transceiverInstructions
) external payable returns (uint64 sequence);
}
"
},
"lib/common/src/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.20 <0.9.0;
/**
* @title ERC20 Token Standard.
* @author M^0 Labs
* @dev The interface as defined by EIP-20: https://eips.ethereum.org/EIPS/eip-20
*/
interface IERC20 {
/* ============ Events ============ */
/**
* @notice Emitted when `spender` has been approved for `amount` of the token balance of `account`.
* @param account The address of the account.
* @param spender The address of the spender being approved for the allowance.
* @param amount The amount of the allowance being approved.
*/
event Approval(address indexed account, address indexed spender, uint256 amount);
/**
* @notice Emitted when `amount` tokens is transferred from `sender` to `recipient`.
* @param sender The address of the sender who's token balance is decremented.
* @param recipient The address of the recipient who's token balance is incremented.
* @param amount The amount of tokens being transferred.
*/
event Transfer(address indexed sender, address indexed recipient, uint256 amount);
/* ============ Interactive Functions ============ */
/**
* @notice Allows a calling account to approve `spender` to spend up to `amount` of its token balance.
* @dev MUST emit an `Approval` event.
* @param spender The address of the account being allowed to spend up to the allowed amount.
* @param amount The amount of the allowance being approved.
* @return Whether or not the approval was successful.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @notice Allows a calling account to transfer `amount` tokens to `recipient`.
* @param recipient The address of the recipient who's token balance will be incremented.
* @param amount The amount of tokens being transferred.
* @return Whether or not the transfer was successful.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @notice Allows a calling account to transfer `amount` tokens from `sender`, with allowance, to a `recipient`.
* @param sender The address of the sender who's token balance will be decremented.
* @param recipient The address of the recipient who's token balance will be incremented.
* @param amount The amount of tokens being transferred.
* @return Whether or not the transfer was successful.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/* ============ View/Pure Functions ============ */
/**
* @notice Returns the allowance `spender` is allowed to spend on behalf of `account`.
* @param account The address of the account who's token balance `spender` is allowed to spend.
* @param spender The address of an account allowed to spend on behalf of `account`.
* @return The amount `spender` can spend on behalf of `account`.
*/
function allowance(address account, address spender) external view returns (uint256);
/**
* @notice Returns the token balance of `account`.
* @param account The address of some account.
* @return The token balance of `account`.
*/
function balanceOf(address account) external view returns (uint256);
/// @notice Returns the number of decimals UIs should assume all amounts have.
function decimals() external view returns (uint8);
/// @notice Returns the name of the contract/token.
function name() external view returns (string memory);
/// @notice Returns the symbol of the token.
function symbol() external view returns (string memory);
/// @notice Returns the current total supply of the token.
function totalSupply() external view returns (uint256);
}
"
},
"lib/native-token-transfers/evm/src/interfaces/INttManager.sol": {
"content": "// SPDX-License-Identifier: Apache 2
pragma solidity >=0.8.8 <0.9.0;
import "../libraries/TrimmedAmount.sol";
import "../libraries/TransceiverStructs.sol";
import "./IManagerBase.sol";
interface INttManager is IManagerBase {
/// @dev The peer on another chain.
struct NttManagerPeer {
bytes32 peerAddress;
uint8 tokenDecimals;
}
/// @notice Emitted when a message is sent from the nttManager.
/// @dev Topic0
/// 0xe54e51e42099622516fa3b48e9733581c9dbdcb771cafb093f745a0532a35982.
/// @param recipient The recipient of the message.
/// @param refundAddress The address on the destination chain to which the
/// refund of unused gas will be paid
/// @param amount The amount transferred.
/// @param fee The amount of ether sent along with the tx to cover the delivery fee.
/// @param recipientChain The chain ID of the recipient.
/// @param msgSequence The unique sequence ID of the message.
event TransferSent(
bytes32 indexed recipient,
bytes32 indexed refundAddress,
uint256 amount,
uint256 fee,
uint16 recipientChain,
uint64 msgSequence
);
/// @notice Emitted when a message is sent from the nttManager.
/// @dev Topic0
/// 0x3e6ae56314c6da8b461d872f41c6d0bb69317b9d0232805aaccfa45df1a16fa0.
/// @param digest The digest of the message.
event TransferSent(bytes32 indexed digest);
/// @notice Emitted when the peer contract is updated.
/// @dev Topic0
/// 0x1456404e7f41f35c3daac941bb50bad417a66275c3040061b4287d787719599d.
/// @param chainId_ The chain ID of the peer contract.
/// @param oldPeerContract The old peer contract address.
/// @param oldPeerDecimals The old peer contract decimals.
/// @param peerContract The new peer contract address.
/// @param peerDecimals The new peer contract decimals.
event PeerUpdated(
uint16 indexed chainId_,
bytes32 oldPeerContract,
uint8 oldPeerDecimals,
bytes32 peerContract,
uint8 peerDecimals
);
/// @notice Emitted when a transfer has been redeemed
/// (either minted or unlocked on the recipient chain).
/// @dev Topic0
/// 0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91.
/// @param digest The digest of the message.
event TransferRedeemed(bytes32 indexed digest);
/// @notice Emitted when an outbound transfer has been cancelled
/// @dev Topic0
/// 0xf80e572ae1b63e2449629b6c7d783add85c36473926f216077f17ee002bcfd07.
/// @param sequence The sequence number being cancelled
/// @param recipient The canceller and recipient of the funds
/// @param amount The amount of the transfer being cancelled
event OutboundTransferCancelled(uint256 sequence, address recipient, uint256 amount);
/// @notice The transfer has some dust.
/// @dev Selector 0x71f0634a
/// @dev This is a security measure to prevent users from losing funds.
/// This is the result of trimming the amount and then untrimming it.
/// @param amount The amount to transfer.
error TransferAmountHasDust(uint256 amount, uint256 dust);
/// @notice The mode is invalid. It is neither in LOCKING or BURNING mode.
/// @dev Selector 0x66001a89
/// @param mode The mode.
error InvalidMode(uint8 mode);
/// @notice Error when trying to execute a message on an unintended target chain.
/// @dev Selector 0x3dcb204a.
/// @param targetChain The target chain.
/// @param thisChain The current chain.
error InvalidTargetChain(uint16 targetChain, uint16 thisChain);
/// @notice Error when the transfer amount is zero.
/// @dev Selector 0x9993626a.
error ZeroAmount();
/// @notice Error when the recipient is invalid.
/// @dev Selector 0x9c8d2cd2.
error InvalidRecipient();
/// @notice Error when the recipient is invalid.
/// @dev Selector 0xe2fe2726.
error InvalidRefundAddress();
/// @notice Error when the amount burned is different than the balance difference,
/// since NTT does not support burn fees.
/// @dev Selector 0x02156a8f.
/// @param burnAmount The amount burned.
/// @param balanceDiff The balance after burning.
error BurnAmountDifferentThanBalanceDiff(uint256 burnAmount, uint256 balanceDiff);
/// @notice The caller is not the deployer.
error UnexpectedDeployer(address expectedOwner, address owner);
/// @notice Peer for the chain does not match the configuration.
/// @param chainId ChainId of the source chain.
/// @param peerAddress Address of the peer nttManager contract.
error InvalidPeer(uint16 chainId, bytes32 peerAddress);
/// @notice Peer chain ID cannot be zero.
error InvalidPeerChainIdZero();
/// @notice Peer cannot be the zero address.
error InvalidPeerZeroAddress();
/// @notice Peer cannot have zero decimals.
error InvalidPeerDecimals();
/// @notice Staticcall reverted
/// @dev Selector 0x1222cd83
error StaticcallFailed();
/// @notice Error when someone other than the original sender tries to cancel a queued outbound transfer.
/// @dev Selector 0xceb40a85.
/// @param canceller The address trying to cancel the transfer.
/// @param sender The original sender that initiated the transfer that was queued.
error CancellerNotSender(address canceller, address sender);
/// @notice An unexpected msg.value was passed with the call
/// @dev Selector 0xbd28e889.
error UnexpectedMsgValue();
/// @notice Peer cannot be on the same chain
/// @dev Selector 0x20371f2a.
error InvalidPeerSameChainId();
/// @notice Feature is not implemented.
error NotImplemented();
/// @notice Transfer a given amount to a recipient on a given chain. This function is called
/// by the user to send the token cross-chain. This function will either lock or burn the
/// sender's tokens. Finally, this function will call into registered `Endpoint` contracts
/// to send a message with the incrementing sequence number and the token transfer payload.
/// @param amount The amount to transfer.
/// @param recipientChain The Wormhole chain ID for the destination.
/// @param recipient The recipient address.
/// @return msgId The resulting message ID of the transfer
function transfer(
uint256 amount,
uint16 recipientChain,
bytes32 recipient
) external payable returns (uint64 msgId);
/// @notice Transfer a given amount to a recipient on a given chain. This function is called
/// by the user to send the token cross-chain. This function will either lock or burn the
/// sender's tokens. Finally, this function will call into registered `Endpoint` contracts
/// to send a message with the incrementing sequence number and the token transfer payload.
/// @dev Transfers are queued if the outbound limit is hit and must be completed by the client.
/// @param amount The amount to transfer.
/// @param recipientChain The Wormhole chain ID for the destination.
/// @param recipient The recipient address.
/// @param refundAddress The address to which a refund for unussed gas is issued on the recipient chain.
/// @param shouldQueue Whether the transfer should be queued if the outbound limit is hit.
/// @param encodedInstructions Additional instructions to be forwarded to the recipient chain.
/// @return msgId The resulting message ID of the transfer
function transfer(
uint256 amount,
uint16 recipientChain,
bytes32 recipient,
bytes32 refundAddress,
bool shouldQueue,
bytes memory encodedInstructions
) external payable returns (uint64 msgId);
/// @notice Complete an outbound transfer that's been queued.
/// @dev This method is called by the client to complete an outbound transfer that's been queued.
/// @param queueSequence The sequence of the message in the queue.
/// @return msgSequence The sequence of the message.
function completeOutboundQueuedTransfer(
uint64 queueSequence
) external payable returns (uint64 msgSequence);
/// @notice Cancels an outbound transfer that's been queued.
/// @dev This method is called by the client to cancel an outbound transfer that's been queued.
/// @param queueSequence The sequence of the message in the queue.
function cancelOutboundQueuedTransfer(
uint64 queueSequence
) external;
/// @notice Complete an inbound queued transfer.
/// @param digest The digest of the message to complete.
function completeInboundQueuedTransfer(
bytes32 digest
) external;
/// @notice Called by an Endpoint contract to deliver a verified attestation.
/// @dev This function enforces attestation threshold and replay logic for messages. Once all
/// validations are complete, this function calls `executeMsg` to execute the command specified
/// by the message.
/// @param sourceChainId The Wormhole chain id of the sender.
/// @param sourceNttManagerAddress The address of the sender's NTT Manager contract.
/// @param payload The VAA payload.
function attestationReceived(
uint16 sourceChainId,
bytes32 sourceNttManagerAddress,
TransceiverStructs.NttManagerMessage memory payload
) external;
/// @notice Called after a message has been sufficiently verified to execute
/// the command in the message. This function will decode the payload
/// as an NttManagerMessage to extract the sequence, msgType, and other parameters.
/// @dev This function is exposed as a fallback for when an `Transceiver` is deregistered
/// when a message is in flight.
/// @param sourceChainId The Wormhole chain id of the sender.
/// @param sourceNttManagerAddress The address of the sender's nttManager contract.
/// @param message The message to execute.
function executeMsg(
uint16 sourceChainId,
bytes32 sourceNttManagerAddress,
TransceiverStructs.NttManagerMessage memory message
) external;
/// @notice Returns the number of decimals of the token managed by the NttManager.
/// @return decimals The number of decimals of the token.
function tokenDecimals() external view returns (uint8);
/// @notice Returns registered peer contract for a given chain.
/// @param chainId_ Wormhole chain ID.
function getPeer(
uint16 chainId_
) external view returns (NttManagerPeer memory);
/// @notice Sets the corresponding peer.
/// @dev The nttManager that executes the message sets the source nttManager as the peer.
/// @param peerChainId The Wormhole chain ID of the peer.
/// @param peerContract The address of the peer nttManager contract.
/// @param decimals The number of decimals of the token on the peer chain.
/// @param inboundLimit The inbound rate limit for the peer chain id. This is formatted in the normal
/// token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
function setPeer(
uint16 peerChainId,
bytes32 peerContract,
uint8 decimals,
uint256 inboundLimit
) external;
/// @notice Sets the outbound transfer limit for a given chain.
/// @dev This method can only be executed by the `owner`.
/// @param limit The new outbound limit. This is formatted in the normal
/// token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
function setOutboundLimit(
uint256 limit
) external;
/// @notice Sets the inbound transfer limit for a given chain.
/// @dev This method can only be executed by the `owner`.
/// @param limit The new limit. This is formatted in the normal
/// token representation. e.g. a limit of 100 for a token with 6 decimals = 100_000_000
/// @param chainId The Wormhole chain ID to set the limit for.
function setInboundLimit(uint256 limit, uint16 chainId) external;
}
"
},
"lib/native-token-transfers/evm/lib/wormhole-solidity-sdk/src/interfaces/IWormhole.sol": {
"content": "// contracts/Messages.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
interface IWormhole {
struct GuardianSet {
address[] keys;
uint32 expirationTime;
}
struct Signature {
bytes32 r;
bytes32 s;
uint8 v;
uint8 guardianIndex;
}
struct VM {
uint8 version;
uint32 timestamp;
uint32 nonce;
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
uint8 consistencyLevel;
bytes payload;
uint32 guardianSetIndex;
Signature[] signatures;
bytes32 hash;
}
struct ContractUpgrade {
bytes32 module;
uint8 action;
uint16 chain;
address newContract;
}
struct GuardianSetUpgrade {
bytes32 module;
uint8 action;
uint16 chain;
GuardianSet newGuardianSet;
uint32 newGuardianSetIndex;
}
struct SetMessageFee {
bytes32 module;
uint8 action;
uint16 chain;
uint256 messageFee;
}
struct TransferFees {
bytes32 module;
uint8 action;
uint16 chain;
uint256 amount;
bytes32 recipient;
}
struct RecoverChainId {
bytes32 module;
uint8 action;
uint256 evmChainId;
uint16 newChainId;
}
event LogMessagePublished(
address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel
);
event ContractUpgraded(address indexed oldContract, address indexed newContract);
event GuardianSetAdded(uint32 indexed index);
function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel)
external
payable
returns (uint64 sequence);
function initialize() external;
function parseAndVerifyVM(bytes calldata encodedVM)
external
view
returns (VM memory vm, bool valid, string memory reason);
function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);
function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet)
external
pure
returns (bool valid, string memory reason);
function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);
function quorum(uint256 numGuardians) external pure returns (uint256 numSignaturesRequiredForQuorum);
function getGuardianSet(uint32 index) external view returns (GuardianSet memory);
function getCurrentGuardianSetIndex() external view returns (uint32);
function getGuardianSetExpiry() external view returns (uint32);
function governanceActionIsConsumed(bytes32 hash) external view returns (bool);
function isInitialized(address impl) external view returns (bool);
function chainId() external view returns (uint16);
function isFork() external view returns (bool);
function governanceChainId() external view returns (uint16);
function governanceContract() external view returns (bytes32);
function messageFee() external view returns (uint256);
function evmChainId() external view returns (uint256);
function nextSequence(address emitter) external view returns (uint64);
function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu);
function parseGuardianSetUpgrade(bytes memory encodedUpgrade)
external
pure
returns (GuardianSetUpgrade memory gsu);
function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf);
function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf);
function parseRecoverChainId(bytes memory encodedRecoverChainId)
external
pure
returns (RecoverChainId memory rci);
function submitContractUpgrade(bytes memory _vm) external;
function submitSetMessageFee(bytes memory _vm) external;
function submitNewGuardianSet(bytes memory _vm) external;
function submitTransferFees(bytes memory _vm) external;
function submitRecoverChainId(bytes memory _vm) external;
}
"
},
"lib/native-token-transfers/evm/src/NttManager/TransceiverRegistry.sol": {
"content": "// SPDX-License-Identifier: Apache 2
pragma solidity >=0.8.8 <0.9.0;
/// @title TransceiverRegistry
/// @author Wormhole Project Contributors.
/// @notice This contract is responsible for handling the registration of Transceivers.
/// @dev This contract checks that a few critical invariants hold when transceivers are added or removed,
/// including:
/// 1. If a transceiver is not registered, it should be enabled.
/// 2. The value set in the bitmap of trannsceivers
/// should directly correspond to the whether the transceiver is enabled
abstract contract TransceiverRegistry {
constructor() {
_checkTransceiversInvariants();
}
/// @dev Information about registered transceivers.
struct TransceiverInfo {
// whether this transceiver is registered
bool registered;
// whether this transceiver is enabled
bool enabled;
uint8 index;
}
/// @dev Bitmap encoding the enabled transceivers.
/// invariant: forall (i: uint8), enabledTransceiverBitmap & i == 1 <=> transceiverInfos[i].enabled
struct _EnabledTransceiverBitmap {
uint64 bitmap;
}
/// @dev Total number of registered transceivers. This number can only increase.
/// invariant: numRegisteredTransceivers <= MAX_TRANSCEIVERS
/// invariant: forall (i: uint8),
/// i < numRegisteredTransceivers <=> exists (a: address), transceiverInfos[a].index == i
struct _NumTransceivers {
uint8 registered;
uint8 enabled;
}
uint8 constant MAX_TRANSCEIVERS = 64;
/// @notice Error when the caller is not the transceiver.
/// @dev Selector 0xa0ae911d.
/// @param caller The address of the caller.
error CallerNotTransceiver(address caller);
/// @notice Error when the transceiver is the zero address.
/// @dev Selector 0x2f44bd77.
error InvalidTransceiverZeroAddress();
/// @notice Error when the transceiver is disabled.
/// @dev Selector 0x1f61ba44.
error DisabledTransceiver(address transceiver);
/// @notice Error when the number of registered transceivers
/// exceeeds (MAX_TRANSCEIVERS = 64).
/// @dev Selector 0x891684c3.
error TooManyTransceivers();
/// @notice Error when attempting to remove a transceiver
/// that is not registered.
/// @dev Selector 0xd583f470.
/// @param transceiver The address of the transceiver.
error NonRegisteredTransceiver(address transceiver);
/// @notice Error when attempting to enable a transceiver that is already enabled.
/// @dev Selector 0x8d68f84d.
/// @param transceiver The address of the transceiver.
error TransceiverAlreadyEnabled(address transceiver);
modifier onlyTransceiver() {
if (!_getTransceiverInfosStorage()[msg.sender].enabled) {
revert CallerNotTransceiver(msg.sender);
}
_;
}
// =============== Storage ===============================================
bytes32 private constant TRANSCEIVER_INFOS_SLOT =
bytes32(uint256(keccak256("ntt.transceiverInfos")) - 1);
bytes32 private constant TRANSCEIVER_BITMAP_SLOT =
bytes32(uint256(keccak256("ntt.transceiverBitmap")) - 1);
bytes32 private constant ENABLED_TRANSCEIVERS_SLOT =
bytes32(uint256(keccak256("ntt.enabledTransceivers")) - 1);
bytes32 private constant REGISTERED_TRANSCEIVERS_SLOT =
bytes32(uint256(keccak256("ntt.registeredTransceivers")) - 1);
bytes32 private constant NUM_REGISTERED_TRANSCEIVERS_SLOT =
bytes32(uint256(keccak256("ntt.numRegisteredTransceivers")) - 1);
function _getTransceiverInfosStorage()
internal
pure
returns (mapping(address => TransceiverInfo) storage $)
{
uint256 slot = uint256(TRANSCEIVER_INFOS_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}
function _getEnabledTransceiversStorage() internal pure returns (address[] storage $) {
uint256 slot = uint256(ENABLED_TRANSCEIVERS_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}
function _getTransceiverBitmapStorage()
private
pure
returns (_EnabledTransceiverBitmap storage $)
{
uint256 slot = uint256(TRANSCEIVER_BITMAP_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}
function _getRegisteredTransceiversStorage() internal pure returns (address[] storage $) {
uint256 slot = uint256(REGISTERED_TRANSCEIVERS_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}
function _getNumTransceiversStorage() internal pure returns (_NumTransceivers storage $) {
uint256 slot = uint256(NUM_REGISTERED_TRANSCEIVERS_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}
// =============== Storage Getters/Setters ========================================
function _setTransceiver(
address transceiver
) internal returns (uint8 index) {
mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();
_EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();
address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();
_NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();
if (transceiver == address(0)) {
revert InvalidTransceiverZeroAddress();
}
if (transceiverInfos[transceiver].registered) {
transceiverInfos[transceiver].enabled = true;
} else {
if (_numTransceivers.registered >= MAX_TRANSCEIVERS) {
revert TooManyTransceivers();
}
transceiverInfos[transceiver] = TransceiverInfo({
registered: true,
enabled: true,
index: _numTransceivers.registered
});
_numTransceivers.registered++;
_getRegisteredTransceiversStorage().push(transceiver);
}
_enabledTransceivers.push(transceiver);
_numTransceivers.enabled++;
uint64 updatedEnabledTransceiverBitmap =
_enabledTransceiverBitmap.bitmap | uint64(1 << transceiverInfos[transceiver].index);
// ensure that this actually changed the bitmap
if (updatedEnabledTransceiverBitmap == _enabledTransceiverBitmap.bitmap) {
revert TransceiverAlreadyEnabled(transceiver);
}
_enabledTransceiverBitmap.bitmap = updatedEnabledTransceiverBitmap;
_checkTransceiversInvariants();
return transceiverInfos[transceiver].index;
}
function _removeTransceiver(
address transceiver
) internal {
mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();
_EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();
address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();
if (transceiver == address(0)) {
revert InvalidTransceiverZeroAddress();
}
if (!transceiverInfos[transceiver].registered) {
revert NonRegisteredTransceiver(transceiver);
}
if (!transceiverInfos[transceiver].enabled) {
revert DisabledTransceiver(transceiver);
}
transceiverInfos[transceiver].enabled = false;
_getNumTransceiversStorage().enabled--;
uint64 updatedEnabledTransceiverBitmap =
_enabledTransceiverBitmap.bitmap & uint64(~(1 << transceiverInfos[transceiver].index));
// ensure that this actually changed the bitmap
assert(updatedEnabledTransceiverBitmap < _enabledTransceiverBitmap.bitmap);
_enabledTransceiverBitmap.bitmap = updatedEnabledTransceiverBitmap;
bool removed = false;
uint256 numEnabledTransceivers = _enabledTransceivers.length;
for (uint256 i = 0; i < numEnabledTransceivers; i++) {
if (_enabledTransceivers[i] == transceiver) {
_enabledTransceivers[i] = _enabledTransceivers[numEnabledTransceivers - 1];
_enabledTransceivers.pop();
removed = true;
break;
}
}
assert(removed);
_checkTransceiversInvariants();
// we call the invariant check on the transceiver here as well, since
// the above check only iterates through the enabled transceivers.
_checkTransceiverInvariants(transceiver);
}
function _getEnabledTransceiversBitmap() internal view virtual returns (uint64 bitmap) {
return _getTransceiverBitmapStorage().bitmap;
}
/// @notice Returns the Transceiver contracts that have been enabled via governance.
function getTransceivers() external pure returns (address[] memory result) {
result = _getEnabledTransceiversStorage();
}
/// @notice Returns the info for all enabled transceivers
function getTransceiverInfo() external view returns (TransceiverInfo[] memory) {
address[] memory enabledTransceivers = _getEnabledTransceiversStorage();
uint256 numEnabledTransceivers = enabledTransceivers.length;
TransceiverInfo[] memory result = new TransceiverInfo[](numEnabledTransceivers);
for (uint256 i = 0; i < numEnabledTransceivers; ++i) {
result[i] = _getTransceiverInfosStorage()[enabledTransceivers[i]];
}
return result;
}
// ============== Invariants =============================================
/// @dev Check that the transceiver nttManager is in a valid state.
/// Checking these invariants is somewhat costly, but we only need to do it
/// when modifying the transceivers, which happens infrequently.
function _checkTransceiversInvariants() internal view {
_NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();
address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();
uint256 numTransceiversEnabled = _numTransceivers.enabled;
assert(numTransceiversEnabled == _enabledTransceivers.length);
for (uint256 i = 0; i < numTransceiversEnabled; i++) {
_checkTransceiverInvariants(_enabledTransceivers[i]);
}
// invariant: each transceiver is only enabled once
for (uint256 i = 0; i < numTransceiversEnabled; i++) {
for (uint256 j = i + 1; j < numTransceiversEnabled; j++) {
assert(_enabledTransceivers[i] != _enabledTransceivers[j]);
}
}
// invariant: numRegisteredTransceivers <= MAX_TRANSCEIVERS
assert(_numTransceivers.registered <= MAX_TRANSCEIVERS);
}
// @dev Check that the transceiver is in a valid state.
function _checkTransceiverInvariants(
address transceiver
) private view {
mapping(address => TransceiverInfo) storage transceiverInfos = _getTransceiverInfosStorage();
_EnabledTransceiverBitmap storage _enabledTransceiverBitmap = _getTransceiverBitmapStorage();
_NumTransceivers storage _numTransceivers = _getNumTransceiversStorage();
address[] storage _enabledTransceivers = _getEnabledTransceiversStorage();
TransceiverInfo memory transceiverInfo = transceiverInfos[transceiver];
// if an transceiver is not registered, it should not be enabled
assert(
transceiverInfo.registered || (!transceiverInfo.enabled && transceiverInfo.index == 0)
);
bool transceiverInEnabledBitmap =
(_enabledTransceiverBitmap.bitmap & uint64(1 << transceiverInfo.index)) != 0;
bool transceiverEnabled = transceiverInfo.enabled;
bool transceiverInEnabledTransceivers = false;
for (uint256 i = 0; i < _numTransceivers.enabled; i++) {
if (_enabledTransceivers[i] == transceiver) {
transceiverInEnabledTransceivers = true;
break;
}
}
// invariant: transceiverInfos[transceiver].enabled
// <=> enabledTransceiverBitmap & (1 << transceiverInfos[transceiver].index) != 0
assert(transceiverInEnabledBitmap == transceiverEnabled);
// invariant: transceiverInfos[transceiver].enabled <=> transceiver in _enabledTransceivers
assert(transceiverInEnabledTransceivers == transceiverEnabled);
assert(transceiverInfo.index < _numTransceivers.registered);
}
}
"
},
"src/external/IExecutor.sol": {
"content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.26;
interface IExecutor {
struct SignedQuoteHeader {
bytes4 prefix;
address quoterAddress;
bytes32 payeeAddress;
uint16 srcChain;
uint16 dstChain;
uint64 expiryTime;
}
event RequestForExecution(
address indexed quoterAddress,
uint256 amtPaid,
uint16 dstChain,
bytes32 dstAddr,
address refundAddr,
bytes signedQuote,
bytes requestBytes,
bytes relayInstructions
);
function requestExecution(
uint16 dstChain,
bytes32 dstAddr,
address refundAddr,
bytes calldata signedQuote,
bytes calldata requestBytes,
bytes calldata relayInstructions
) external payable;
}
"
},
"src/external/ExecutorMessages.sol": {
"content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.26;
library ExecutorMessages {
bytes4 private constant REQ_MM = "ERM1";
bytes4 private constant REQ_VAA_V1 = "ERV1";
bytes4 private constant REQ_NTT_V1 = "ERN1";
bytes4 private constant REQ_CCTP_V1 = "ERC1";
/// @notice Payload length will not fit in a uint32.
/// @dev Selector: 492f620d.
error PayloadTooLarge();
/// @notice Encodes a modular messaging request payload.
/// @param srcChain The source chain for the message (usually this chain).
/// @param srcAddr The source address for the message.
/// @param sequence The sequence number returned by `endpoint.sendMessage`.
/// @param payload The full payload, the keccak of which was sent to `endpoint.sendMessage`.
/// @return bytes The encoded request.
function makeMMRequest(
uint16 srcChain,
address srcAddr,
uint64 sequence,
bytes memory payload
) internal pure returns (bytes memory) {
if (payload.length > type(uint32).max) {
revert PayloadTooLarge();
}
return
abi.encodePacked(
REQ_MM,
srcChain,
bytes32(uint256(uint160(srcAddr))),
sequence,
uint32(payload.length),
payload
);
}
/// @notice Encodes a version 1 VAA request payload.
/// @param emitterChain The emitter chain from the VAA.
/// @param emitterAddress The emitter address from the VAA.
/// @param sequence The sequence number from the VAA.
/// @return bytes The encoded request.
function makeVAAv1Request(
uint16 emitterChain,
bytes32 emitterAddress,
uint64 sequence
) internal pure returns (bytes memory) {
return abi.encodePacked(REQ_VAA_V1, emitterChain, emitterAddress, sequence);
}
/// @notice Encodes a version 1 NTT request payload.
/// @param srcChain The source chain for the NTT transfer.
/// @param srcManager The source manager for the NTT transfer.
/// @param messageId The manager message id for the NTT transfer.
/// @return bytes The encoded request.
function makeNTTv1Request(
uint16 srcChain,
bytes32 srcManager,
bytes32 messageId
) internal pure returns (bytes memory) {
return abi.encodePacked(REQ_NTT_V1, srcChain, srcManager, messageId);
}
/// @notice Encodes a version 1 CCTP request payload.
/// @param sourceDomain The source chain for the CCTP transfer.
/// @param nonce The nonce of the CCTP transfer.
/// @return bytes The encoded request.
function makeCCTPv1Request(uint32 sourceDomain, uint64 nonce) internal pure returns (bytes memory) {
return abi.encodePacked(REQ_CCTP_V1, sourceDomain, nonce);
}
}
"
},
"src/libs/TypeConverter.sol": {
"content": "// SPDX-License-Identifier
Submitted on: 2025-10-02 09:49:07
Comments
Log in to comment.
No comments yet.