Contract Name:
ChannelSlave
Contract Source Code:
<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./IMessageStruct.sol";
interface IMessageChannel is IMessageStruct {
/*
/// @notice LaunchPad is the function that user or DApps send omni-chain message to other chain
/// Once the message is sent, the Relay will validate the message and send it to the target chain
/// @dev 1. we will call the LaunchPad.Launch function to emit the message
/// @dev 2. the message will be sent to the destination chain
/// @param earliestArrivalTimestamp The earliest arrival time for the message
/// set to 0, vizing will forward the information ASAP.
/// @param latestArrivalTimestamp The latest arrival time for the message
/// set to 0, vizing will forward the information ASAP.
/// @param relayer the specify relayer for your message
/// set to 0, all the relayers will be able to forward the message
/// @param sender The sender address for the message
/// most likely the address of the EOA, the user of some DApps
/// @param value native token amount, will be sent to the target contract
/// @param destChainid The destination chain id for the message
/// @param additionParams The addition params for the message
/// if not in expert mode, set to 0 (`new bytes(0)`)
/// @param message Arbitrary information
///
/// bytes
/// message = abi.encodePacked(
/// byte1 uint256 uint24 uint64 bytes
/// messageType, activateContract, executeGasLimit, maxFeePerGas, signature
/// )
///
*/
function Launch(
uint64 earliestArrivalTimestamp,
uint64 latestArrivalTimestamp,
address relayer,
address sender,
uint256 value,
uint64 destChainid,
bytes calldata additionParams,
bytes calldata message
) external payable;
///
/// bytes byte1 uint256 uint24 uint64 bytes
/// message = abi.encodePacked(messageType, activateContract, executeGasLimit, maxFeePerGas, signature)
///
function launchMultiChain(
launchEnhanceParams calldata params
) external payable;
/// @notice batch landing message to the chain, execute the landing message
/// @dev trusted relayer will call this function to send omni-chain message to the Station
/// @param params the landing message params
/// @param proofs the proof of the validated message
function Landing(
landingParams[] calldata params,
bytes[][] calldata proofs
) external payable;
/// @notice similar to the Landing function, but with gasLimit
function LandingSpecifiedGas(
landingParams[] calldata params,
uint24 gasLimit,
bytes[][] calldata proofs
) external payable;
/// @dev feel free to call this function before pass message to the Station,
/// this method will return the protocol fee that the message need to pay, longer message will pay more
function estimateGas(
uint256[] calldata value,
uint64[] calldata destChainid,
bytes[] calldata additionParams,
bytes[] calldata message
) external view returns (uint256);
function estimateGas(
uint256 value,
uint64 destChainid,
bytes calldata additionParams,
bytes calldata message
) external view returns (uint256);
function estimatePrice(
address sender,
uint64 destChainid
) external view returns (uint64);
function gasSystemAddr() external view returns (address);
/// @dev get the message launch nonce of the sender on the specific chain
/// @param chainId the chain id of the sender
/// @param sender the address of the sender
function GetNonceLaunch(
uint64 chainId,
address sender
) external view returns (uint32);
/// @dev get the message landing nonce of the sender on the specific chain
/// @param chainId the chain id of the sender
/// @param sender the address of the sender
function GetNonceLanding(
uint64 chainId,
address sender
) external view returns (uint32);
/// @dev get the version of the Station
/// @return the version of the Station, like "v1.0.0"
function Version() external view returns (string memory);
/// @dev get the chainId of current Station
/// @return chainId, defined in the L2SupportLib.sol
function Chainid() external view returns (uint64);
function minArrivalTime() external view returns (uint64);
function maxArrivalTime() external view returns (uint64);
function expertLandingHook(bytes1 hook) external view returns (address);
function expertLaunchHook(bytes1 hook) external view returns (address);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./IMessageStruct.sol";
interface IMessageDashboard is IMessageStruct {
/// @dev Only owner can call this function to stop or restart the engine
/// @param stop true is stop, false is start
function PauseEngine(bool stop) external;
/// @notice return the states of the engine
/// @return 0x01 is stop, 0x02 is start
function engineState() external view returns (uint8);
/// @notice return the states of the engine & Landing Pad
function padState() external view returns (uint8, uint8);
// function mptRoot() external view returns (bytes32);
/// @dev withdraw the protocol fee from the contract, only owner can call this function
/// @param amount the amount of the withdraw protocol fee
function Withdraw(uint256 amount, address to) external;
/// @dev set the payment system address, only owner can call this function
/// @param gasSystemAddress the address of the payment system
function setGasSystem(address gasSystemAddress) external;
function setExpertLaunchHooks(
bytes1[] calldata ids,
address[] calldata hooks
) external;
function setExpertLandingHooks(
bytes1[] calldata ids,
address[] calldata hooks
) external;
/// notice reset the permission of the contract, only owner can call this function
function roleConfiguration(
bytes32 role,
address[] calldata accounts,
bool[] calldata states
) external;
function stationAdminSetRole(
bytes32 role,
address[] calldata accounts,
bool[] calldata states
) external;
/// @notice transfer the ownership of the contract, only owner can call this function
function transferOwnership(address newOwner) external;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import "./IMessageSpaceStation.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IMessageEmitter {
function minArrivalTime() external view returns (uint64);
function maxArrivalTime() external view returns (uint64);
function minGasLimit() external view returns (uint24);
function maxGasLimit() external view returns (uint24);
function defaultBridgeMode() external view returns (bytes1);
function selectedRelayer() external view returns (address);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./IMessageStruct.sol";
interface IMessageEvent is IMessageStruct {
/// @notice Throws event after a message which attempts to omni-chain is submitted to LaunchPad contract
event SuccessfulLaunchMessage(
uint32 indexed nonce,
uint64 earliestArrivalTimestamp,
uint64 latestArrivalTimestamp,
address relayer,
address sender,
address srcContract,
uint256 value,
uint64 destChainid,
bytes additionParams,
bytes message
);
/// @notice Throws event after a message which attempts to omni-chain is submitted to LaunchPad contract
event SuccessfulLaunchMultiMessages(
uint32[] indexed nonce,
uint64 earliestArrivalTimestamp,
uint64 latestArrivalTimestamp,
address relayer,
address sender,
address srcContract,
uint256[] value,
uint64[] destChainid,
bytes[] additionParams,
bytes[] message
);
/// @notice Throws event after a omni-chain message is submitted from source chain to target chain
event SuccessfulLanding(bytes32 indexed messageId, landingParams params);
/// @notice Throws event after protocol state is changed, such as pause or resume
event EngineStateRefreshing(bool indexed isPause);
/// @notice Throws event after protocol fee calculation is changed
event PaymentSystemChanging(address indexed gasSystemAddress);
/// @notice Throws event after successful withdrawa
event WithdrawRequest(address indexed to, uint256 amount);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IMessageReceiver {
function receiveStandardMessage(
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) external payable;
function receiveExtraMessage(
bytes32 messageId,
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) external payable;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./IMessageStruct.sol";
interface IMessageSimulation is IMessageStruct {
/// @dev for sequencer to simulate the landing message, call this function before call Landing
/// @param params the landing message params
/// check the revert message "SimulateResult" to get the result of the simulation
/// for example, if the result is [true, false, true], it means the first and third message is valid, the second message is invalid
function SimulateLanding(landingParams[] calldata params) external payable;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./IMessageStruct.sol";
import {IMessageDashboard} from "./IMessageDashboard.sol";
import {IMessageEvent} from "../interface/IMessageEvent.sol";
import {IMessageChannel} from "../interface/IMessageChannel.sol";
import {IMessageSimulation} from "../interface/IMessageSimulation.sol";
interface IMessageSpaceStation is
IMessageStruct,
IMessageDashboard,
IMessageEvent,
IMessageChannel,
IMessageSimulation
{} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IMessageStruct {
struct launchParams {
uint64 earliestArrivalTimestamp;
uint64 latestArrivalTimestamp;
address relayer;
address sender;
uint256 value;
uint64 destChainid;
bytes additionParams;
bytes message;
}
struct landingParams {
bytes32 messageId;
uint64 earliestArrivalTimestamp;
uint64 latestArrivalTimestamp;
uint64 srcChainid;
bytes32 srcTxHash;
uint256 srcContract;
uint32 srcChainNonce;
uint256 sender;
uint256 value;
bytes additionParams;
bytes message;
}
struct launchEnhanceParams {
uint64 earliestArrivalTimestamp;
uint64 latestArrivalTimestamp;
address relayer;
address sender;
uint256[] value;
uint64[] destChainid;
bytes[] additionParams;
bytes[] message;
}
struct RollupMessageStruct {
SignedMessageBase base;
IMessageStruct.launchParams params;
}
struct SignedMessageBase {
uint64 srcChainId;
uint24 nonceLaunch;
bytes32 srcTxHash;
bytes32 destTxHash;
uint64 srcTxTimestamp;
uint64 destTxTimestamp;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IVizingGasSystemChannel {
/*
/// @notice Estimate how many native token we should spend to exchange the amountOut in the destChainid
/// @param destChainid The chain id of the destination chain
/// @param amountOut The value we want to receive in the destination chain
/// @return amountIn the native token amount on the source chain we should spend
*/
function exactOutput(
uint64 destChainid,
uint256 amountOut
) external view returns (uint256 amountIn);
/*
/// @notice Estimate how many native token we could get in the destChainid if we input the amountIn
/// @param destChainid The chain id of the destination chain
/// @param amountIn The value we spent in the source chain
/// @return amountOut the native token amount the destination chain will receive
*/
function exactInput(
uint64 destChainid,
uint256 amountIn
) external view returns (uint256 amountOut);
/*
/// @notice Estimate the gas fee we should pay to vizing
/// @param destChainid The chain id of the destination chain
/// @param message The message we want to send to the destination chain
*/
function estimateGas(
uint256 amountOut,
uint64 destChainid,
bytes calldata message
) external view returns (uint256);
/*
/// @notice Estimate the gas fee & native token we should pay to vizing
/// @param amountOut amountOut in the destination chain
/// @param destChainid The chain id of the destination chain
/// @param message The message we want to send to the destination chain
*/
function batchEstimateTotalFee(
uint256[] calldata amountOut,
uint64[] calldata destChainid,
bytes[] calldata message
) external view returns (uint256 totalFee);
/*
/// @notice Estimate the total fee we should pay to vizing
/// @param value The value we spent in the source chain
/// @param destChainid The chain id of the destination chain
/// @param message The message we want to send to the destination chain
*/
function estimateTotalFee(
uint256 value,
uint64 destChainid,
bytes calldata message
) external view returns (uint256 totalFee);
/*
/// @notice Estimate the gas price we need to encode in message
/// @param sender most likely the address of the DApp, which forward the message from user
/// @param destChainid The chain id of the destination chain
*/
function estimatePrice(
address targetContract,
uint64 destChainid
) external view returns (uint64);
/*
/// @notice Estimate the gas price we need to encode in message
/// @param destChainid The chain id of the destination chain
*/
function estimatePrice(uint64 destChainid) external view returns (uint64);
/*
/// @notice Calculate the fee for the native token transfer
/// @param amount The value we spent in the source chain
*/
function computeTradeFee(
uint64 destChainid,
uint256 amountOut
) external view returns (uint256 fee);
/*
/// @notice Calculate the fee for the native token transfer
/// @param amount The value we spent in the source chain
*/
function computeTradeFee(
address targetContract,
uint64 destChainid,
uint256 amountOut
) external view returns (uint256 fee);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
library MessageTypeLib {
bytes1 constant DEFAULT = 0x00;
/* ********************* message type **********************/
bytes1 constant STANDARD_ACTIVATE = 0x01;
bytes1 constant ARBITRARY_ACTIVATE = 0x02;
bytes1 constant MESSAGE_POST = 0x03;
bytes1 constant NATIVE_TOKEN_SEND = 0x04;
/**
* additionParams type *********************
*/
// Single-Send mode
bytes1 constant SINGLE_SEND = 0x01;
bytes1 constant MULTI_UNIVERSAL = 0x03;
bytes1 constant ERC20_HANDLER = 0x04;
bytes1 constant MAX_MODE = 0xFF;
function fetchMsgMode(
bytes calldata message
) internal pure returns (bytes1) {
if (message.length < 1) {
return DEFAULT;
}
bytes1 messageSlice = bytes1(message[0:1]);
return messageSlice;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageStruct} from "./interface/IMessageStruct.sol";
import {IMessageChannel} from "./interface/IMessageChannel.sol";
import {IMessageEmitter} from "./interface/IMessageEmitter.sol";
import {IMessageReceiver} from "./interface/IMessageReceiver.sol";
import {IVizingGasSystemChannel} from "./interface/IVizingGasSystemChannel.sol";
abstract contract MessageEmitterUpgradeable is IMessageEmitter {
/// @dev bellow are the default parameters for the OmniToken,
/// we **Highly recommended** to use immutable variables to store these parameters
/// @notice minArrivalTime the minimal arrival timestamp for the omni-chain message
/// @notice maxArrivalTime the maximal arrival timestamp for the omni-chain message
/// @notice minGasLimit the minimal gas limit for target chain execute omni-chain message
/// @notice maxGasLimit the maximal gas limit for target chain execute omni-chain message
/// @notice defaultBridgeMode the default mode for the omni-chain message,
/// in OmniToken, we use MessageTypeLib.ARBITRARY_ACTIVATE (0x02), target chain will **ACTIVATE** the message
/// @notice selectedRelayer the specify relayer for your message
/// set to 0, all the relayers will be able to forward the message
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
function minArrivalTime() external view virtual override returns (uint64) {}
function maxArrivalTime() external view virtual override returns (uint64) {}
function minGasLimit() external view virtual override returns (uint24) {}
function maxGasLimit() external view virtual override returns (uint24) {}
function defaultBridgeMode()
external
view
virtual
override
returns (bytes1)
{}
function selectedRelayer()
external
view
virtual
override
returns (address)
{}
IMessageChannel public LaunchPad;
/*
/// rewrite set LaunchPad address function
/// @notice call this function to reset the LaunchPad contract address
/// @param _LaunchPad The new LaunchPad contract address
*/
function __LaunchPadInit(address _LaunchPad) internal virtual {
LaunchPad = IMessageChannel(_LaunchPad);
}
/*
/// @notice call this function to packet the message before sending it to the LandingPad contract
/// @param mode the emitter mode, check MessageTypeLib.sol for more details
/// eg: 0x02 for ARBITRARY_ACTIVATE, your message will be activated on the target chain
/// @param gasLimit the gas limit for executing the specific function on the target contract
/// @param targetContract the target contract address on the destination chain
/// @param message the message to be sent to the target contract
/// @return the packed message
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _packetMessage(
bytes1 mode,
address targetContract,
uint24 gasLimit,
uint64 price,
bytes memory message
) internal pure returns (bytes memory) {
return
abi.encodePacked(
mode,
uint256(uint160(targetContract)),
gasLimit,
price,
message
);
}
/*
/// @notice Calculate the amount of native tokens obtained on the target chain
/// @param value The value we send to vizing on the source chain
*/
function _computeTradeFee(
uint64 destChainid,
uint256 value
) internal view returns (uint256 amountIn) {
return
IVizingGasSystemChannel(LaunchPad.gasSystemAddr()).computeTradeFee(
destChainid,
value
);
}
/*
/// @notice Fetch the nonce of the user with specific destination chain
/// @param destChainid The chain id of the destination chain
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _fetchNonce(
uint64 destChainid
) internal view virtual returns (uint32 nonce) {
nonce = LaunchPad.GetNonceLaunch(destChainid, msg.sender);
}
/*
/// @notice Estimate the gas price we need to encode in message
/// @param destChainid The chain id of the destination chain
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _fetchPrice(
uint64 destChainid
) internal view virtual returns (uint64) {
return
IVizingGasSystemChannel(LaunchPad.gasSystemAddr()).estimatePrice(
destChainid
);
}
/*
/// @notice Estimate the gas price we need to encode in message
/// @param targetContract The target contract address on the destination chain
/// @param destChainid The chain id of the destination chain
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _fetchPrice(
address targetContract,
uint64 destChainid
) internal view virtual returns (uint64) {
return
IVizingGasSystemChannel(LaunchPad.gasSystemAddr()).estimatePrice(
targetContract,
destChainid
);
}
/*
/// @notice similar to uniswap Swap Router
/// @notice Estimate how many native token we should spend to exchange the amountOut in the destChainid
/// @param destChainid The chain id of the destination chain
/// @param amountOut The value we want to exchange in the destination chain
/// @return amountIn the native token amount on the source chain we should spend
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _exactOutput(
uint64 destChainid,
uint256 amountOut
) internal view returns (uint256 amountIn) {
return
IVizingGasSystemChannel(LaunchPad.gasSystemAddr()).exactOutput(
destChainid,
amountOut
);
}
/*
/// @notice similar to uniswap Swap Router
/// @notice Estimate how many native token we could get in the destChainid if we input the amountIn
/// @param destChainid The chain id of the destination chain
/// @param amountIn The value we spent in the source chain
/// @return amountOut the native token amount the destination chain will receive
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _exactInput(
uint64 destChainid,
uint256 amountIn
) internal view returns (uint256 amountOut) {
return
IVizingGasSystemChannel(LaunchPad.gasSystemAddr()).exactInput(
destChainid,
amountIn
);
}
/*
/// @notice Estimate the gas price we need to encode in message
/// @param value The native token that value target address will receive in the destination chain
/// @param destChainid The chain id of the destination chain
/// @param additionParams The addition params for the message
/// if not in expert mode, set to 0 (`new bytes(0)`)
/// @param message The message we want to send to the destination chain
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function _estimateVizingGasFee(
uint256 value,
uint64 destChainid,
bytes memory additionParams,
bytes memory message
) internal view returns (uint256 vizingGasFee) {
return
LaunchPad.estimateGas(value, destChainid, additionParams, message);
}
/*
/// @notice **Highly recommend** to call this function in your frontend program
/// @notice Estimate the gas price we need to encode in message
/// @param value The native token that value target address will receive in the destination chain
/// @param destChainid The chain id of the destination chain
/// @param additionParams The addition params for the message
/// if not in expert mode, set to 0 (`new bytes(0)`)
/// @param message The message we want to send to the destination chain
/// see https://docs.vizing.com/docs/BuildOnVizing/Contract
*/
function estimateVizingGasFee(
uint256 value,
uint64 destChainid,
bytes calldata additionParams,
bytes calldata message
) external view returns (uint256 vizingGasFee) {
return
_estimateVizingGasFee(value, destChainid, additionParams, message);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {MessageEmitterUpgradeable} from "./MessageEmitter-upgradeable.sol";
abstract contract MessageEmitter is MessageEmitterUpgradeable {
constructor(address _LaunchPad) {
__LaunchPadInit(_LaunchPad);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IMessageChannel} from "./interface/IMessageChannel.sol";
import {IMessageReceiver} from "./interface/IMessageReceiver.sol";
abstract contract MessageReceiverUpgradeable is IMessageReceiver {
error LandingPadAccessDenied();
error NotImplement();
IMessageChannel public LandingPad;
modifier onlyVizingPad() {
if (msg.sender != address(LandingPad)) revert LandingPadAccessDenied();
_;
}
/*
/// rewrite set LandingPad address function
/// @notice call this function to reset the LaunchPad contract address
/// @param _LaunchPad The new LaunchPad contract address
*/
function __LandingPadInit(address _LandingPad) internal virtual {
LandingPad = IMessageChannel(_LandingPad);
}
/// @notice the standard function to receive the omni-chain message
function receiveStandardMessage(
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) external payable virtual override onlyVizingPad {
_receiveMessage(srcChainId, srcContract, message);
}
function receiveExtraMessage(
bytes32 messageId,
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) external payable virtual override onlyVizingPad {
_receiveMessage(messageId, srcChainId, srcContract, message);
}
/// @dev override this function to handle the omni-chain message
/// @param srcChainId the source chain id
/// @param srcContract the source contract address
/// @param message the message from the source chain
function _receiveMessage(
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) internal virtual {
(srcChainId, srcContract, message);
revert NotImplement();
}
/// @dev override this function to handle the omni-chain message
/// @param srcChainId the source chain id
/// @param srcContract the source contract address
/// @param message the message from the source chain
function _receiveMessage(
bytes32 messageId,
uint64 srcChainId,
uint256 srcContract,
bytes calldata message
) internal virtual {
(messageId, srcChainId, srcContract, message);
revert NotImplement();
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {MessageReceiverUpgradeable} from "./MessageReceiver-upgradeable.sol";
abstract contract MessageReceiver is MessageReceiverUpgradeable {
constructor(address _LandingPad) {
__LandingPadInit(_LandingPad);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {MessageEmitter} from "./MessageEmitter.sol";
import {MessageReceiver} from "./MessageReceiver.sol";
abstract contract VizingOmni is MessageEmitter, MessageReceiver {
constructor(
address _vizingPad
) MessageEmitter(_vizingPad) MessageReceiver(_vizingPad) {}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {LikwidSlaveChannel} from "./lib/LikwidSlaveChannel.sol";
contract ChannelSlave is LikwidSlaveChannel {
constructor(
uint64 _masterChainId,
address _masterAddress,
address _vizingPad,
address _managerAddress
) LikwidSlaveChannel(_masterChainId, _masterAddress, _vizingPad) {
minArrivalTime = 1 minutes;
maxArrivalTime = 1 days;
minGasLimit = 100000;
maxGasLimit = 1000000;
selectedRelayer = address(0);
transferOwnership(_managerAddress);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
enum ActionType {
buyPing,
buyPong,
sellPing,
sellPong,
crossPing,
stakePing,
unStakePing,
unStakePong
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IChannelSlaveBase} from "./IChannelSlaveBase.sol";
interface IChannelSlave is IChannelSlaveBase {
function paramsEstimateGas(uint value, bytes memory params) external view returns (uint);
function paramsEmit2LaunchPad(uint bridgeFee, uint value, bytes memory params, address sender) external payable;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IChannelSlaveBase {
function getHash(
string memory biz,
string memory symbol,
uint amount,
address sender
) external pure returns (bytes32);
function buyPingEstimateGas(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) external view returns (uint pingFee);
function buyPing(
uint pingFee,
uint pongFee,
address sender,
string memory _symbol,
address target,
uint amountInETH,
uint amountOutMinimum,
uint nonce
) external payable;
function sellPingEstimateGas(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) external view returns (uint pingFee);
function sellPing(
uint pingFee,
uint pongFee,
address sender,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) external payable;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IProductBase} from "./IProductBase.sol";
interface IFactoryBase {
function getChannelAddress() external view returns (address);
function getProduct(string memory symbol_) external view returns (IProductBase);
function getSymbol(address _addr) external view returns (string memory);
function existProduct(address _addr) external view returns (bool);
function getShortByLong(address longAddr) external view returns (address);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IProductBase {
function actionCall(
bytes32 messageId,
uint64 srcChainId,
address sender,
uint8 action,
uint pongFee,
bytes memory params
) external payable;
function getFactoryAddress() external view returns (address);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IProductBase} from "./IProductBase.sol";
interface IProductInfo is IProductBase {
function symbol() external view returns (string memory);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IProductInfo} from "../interface/IProductInfo.sol";
import {IFactoryBase} from "../interface/IFactoryBase.sol";
contract ChannelBase is Ownable {
mapping(address => bool) public factories;
mapping(string => address) public products;
function setFactory(address addr) public onlyOwner {
factories[addr] = true;
}
function removeFactory(address addr) public onlyOwner {
delete factories[addr];
}
function addProduct(string memory _symbol, address addr) public onlyFactory {
products[_symbol] = addr;
}
modifier onlyFactory() {
require(factories[_msgSender()] || owner() == _msgSender(), "LikwidChannel: onlyFactory");
_;
}
modifier onlyProduct() {
IProductInfo product = IProductInfo(_msgSender());
require(factories[product.getFactoryAddress()], "LikwidChannel: factory error");
IFactoryBase _factory = IFactoryBase(product.getFactoryAddress());
require(_factory.existProduct(_msgSender()), "LikwidChannel: caller must be product");
require(products[product.symbol()] == _msgSender(), "LikwidChannel: error caller");
_;
}
function getProduct(string memory symbol_) public view returns (IProductInfo product) {
require(products[symbol_] != address(0), "product err");
product = IProductInfo(products[symbol_]);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {VizingOmni} from "@vizing/contracts/VizingOmni.sol";
import {MessageTypeLib} from "@vizing/contracts/library/MessageTypeLib.sol";
import {ActionType} from "../constants/ActionType.sol";
import {ChannelBase} from "./ChannelBase.sol";
import {IFactoryBase} from "../interface/IFactoryBase.sol";
import {IProductInfo} from "../interface/IProductInfo.sol";
import {IChannelSlave} from "../interface/IChannelSlave.sol";
abstract contract LikwidSlaveChannel is ChannelBase, VizingOmni, IChannelSlave {
event MessageReceived(uint64 _srcChainId, address _srcAddress, uint value, bytes _payload, bytes32 messageId);
event MessageFailed(uint64 _srcChainId, address _srcAddress, bytes _payload, bytes _reason, uint _value);
uint64 public immutable override minArrivalTime;
uint64 public immutable override maxArrivalTime;
uint24 public immutable override minGasLimit;
uint24 public immutable override maxGasLimit;
bytes1 public immutable override defaultBridgeMode;
address public immutable override selectedRelayer;
uint public messageFailed;
uint public messageReceived;
uint64 masterChainId;
address masterContract;
constructor(uint64 _masterChainId, address _masterAddress, address _vizingPad) VizingOmni(_vizingPad) {
require(_masterChainId != 0, "In contract deployment ...");
require(_masterAddress != address(0), "In contract deployment ...");
masterChainId = _masterChainId;
masterContract = _masterAddress;
defaultBridgeMode = MessageTypeLib.STANDARD_ACTIVATE;
}
//----vizing bridge common----
function paramsEstimateGas(uint value, bytes memory params) public view virtual returns (uint) {
bytes memory message = _packetMessage(
defaultBridgeMode,
masterContract,
maxGasLimit,
_fetchPrice(masterContract, masterChainId),
abi.encode(address(0), params)
);
return LaunchPad.estimateGas(value, masterChainId, new bytes(0), message);
}
function _paramsEmit2LaunchPad(uint bridgeFee, uint value, bytes memory params, address sender) internal {
bytes memory message = _packetMessage(
defaultBridgeMode,
masterContract,
maxGasLimit,
_fetchPrice(masterContract, masterChainId),
abi.encode(sender, params)
);
uint bridgeValue = value + bridgeFee;
require(msg.value >= bridgeValue, "bridgeFee err.");
LaunchPad.Launch{value: bridgeValue}(
0,
0,
selectedRelayer,
sender,
value,
masterChainId,
new bytes(0),
message
);
}
function paramsEmit2LaunchPad(
uint bridgeFee,
uint value,
bytes memory params,
address sender
) external payable onlyProduct {
_paramsEmit2LaunchPad(bridgeFee, value, params, sender);
}
// Signature
function getHash(
string memory biz,
string memory symbol,
uint amount,
address sender
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(biz, symbol, amount, sender));
}
function _buyPingSignature(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) internal view virtual returns (bytes memory) {
return
abi.encode(
uint8(ActionType.buyPing),
_symbol,
pongFee,
abi.encode(nonce, target, amountIn, amountOutMinimum)
);
}
function buyPingEstimateGas(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) public view virtual returns (uint pingFee) {
pingFee = paramsEstimateGas(
pongFee,
_buyPingSignature(pongFee, _symbol, target, amountIn, amountOutMinimum, nonce)
);
}
function buyPing(
uint pingFee,
uint pongFee,
address sender,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) external payable virtual onlyProduct {
bytes memory parmas = _buyPingSignature(pongFee, _symbol, target, amountIn, amountOutMinimum, nonce);
_paramsEmit2LaunchPad(pingFee, amountIn + pongFee, parmas, sender);
}
function _sellPingSignature(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) internal view virtual returns (bytes memory) {
return
abi.encode(
uint8(ActionType.sellPing),
_symbol,
pongFee,
abi.encode(nonce, target, amountIn, amountOutMinimum)
);
}
function sellPingEstimateGas(
uint pongFee,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) public view virtual returns (uint pingFee) {
pingFee = paramsEstimateGas(
pongFee,
_sellPingSignature(pongFee, _symbol, target, amountIn, amountOutMinimum, nonce)
);
}
function sellPing(
uint pingFee,
uint pongFee,
address sender,
string memory _symbol,
address target,
uint amountIn,
uint amountOutMinimum,
uint nonce
) external payable virtual onlyProduct {
bytes memory params = _sellPingSignature(pongFee, _symbol, target, amountIn, amountOutMinimum, nonce);
_paramsEmit2LaunchPad(pingFee, pongFee, params, sender);
}
function verifySource(uint64 srcChainId, address srcContract) internal view virtual returns (bool authorized) {
return srcChainId == masterChainId && srcContract == masterContract;
}
function _receiveMessage(
bytes32 messageId,
uint64 srcChainId,
uint256 srcContract,
bytes calldata _payload
) internal virtual override {
require(verifySource(srcChainId, address(uint160(srcContract))), "unauthorized.");
(address sender, bytes memory message) = abi.decode(_payload, (address, bytes));
messageReceived += 1;
emit MessageReceived(srcChainId, sender, msg.value, message, messageId);
_consumeMessage(srcChainId, sender, messageId, message);
}
function _consumeMessage(uint64 srcChainId, address sender, bytes32 messageId, bytes memory message) internal {
(uint8 action, string memory symbol_, uint pongFee, bytes memory params) = abi.decode(
message,
(uint8, string, uint, bytes)
);
IProductInfo product = getProduct(symbol_);
product.actionCall{value: msg.value}(messageId, srcChainId, sender, action, pongFee, params);
}
function withdrawFee(address to, uint amount) public onlyOwner {
transferNative(to, amount);
}
function transferNative(address to, uint amount) internal {
(bool success, ) = to.call{value: amount}("");
require(success, "Transfer failed.");
}
}