// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 2 of 10: ERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)pragmasolidity ^0.8.0;import"./IERC20.sol";
import"./IERC20Metadata.sol";
import"./Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/contractERC20isContext, IERC20, IERC20Metadata{
mapping(address=>uint256) private _balances;
mapping(address=>mapping(address=>uint256)) private _allowances;
uint256private _totalSupply;
stringprivate _name;
stringprivate _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/functiondecimals() publicviewvirtualoverridereturns (uint8) {
return18;
}
/**
* @dev See {IERC20-totalSupply}.
*/functiontotalSupply() publicviewvirtualoverridereturns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/functionbalanceOf(address account) publicviewvirtualoverridereturns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/functiontransfer(address to, uint256 amount) publicvirtualoverridereturns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
returntrue;
}
/**
* @dev See {IERC20-allowance}.
*/functionallowance(address owner, address spender) publicviewvirtualoverridereturns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/functionapprove(address spender, uint256 amount) publicvirtualoverridereturns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
returntrue;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/functiontransferFrom(addressfrom,
address to,
uint256 amount
) publicvirtualoverridereturns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
returntrue;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/functionincreaseAllowance(address spender, uint256 addedValue) publicvirtualreturns (bool) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][spender] + addedValue);
returntrue;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/functiondecreaseAllowance(address spender, uint256 subtractedValue) publicvirtualreturns (bool) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
returntrue;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/function_transfer(addressfrom,
address to,
uint256 amount
) internalvirtual{
require(from!=address(0), "ERC20: transfer from the zero address");
require(to !=address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/function_mint(address account, uint256 amount) internalvirtual{
require(account !=address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/function_burn(address account, uint256 amount) internalvirtual{
require(account !=address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/function_approve(address owner,
address spender,
uint256 amount
) internalvirtual{
require(owner !=address(0), "ERC20: approve from the zero address");
require(spender !=address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/function_spendAllowance(address owner,
address spender,
uint256 amount
) internalvirtual{
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance !=type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_beforeTokenTransfer(addressfrom,
address to,
uint256 amount
) internalvirtual{}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_afterTokenTransfer(addressfrom,
address to,
uint256 amount
) internalvirtual{}
}
Contract Source Code
File 3 of 10: IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (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.
*/functiontransfer(address to, uint256 amount) externalreturns (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.
*/functionallowance(address owner, address spender) externalviewreturns (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.
*/functionapprove(address spender, uint256 amount) externalreturns (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.
*/functiontransferFrom(addressfrom,
address to,
uint256 amount
) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed 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.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
Contract Source Code
File 4 of 10: IERC20Metadata.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)pragmasolidity ^0.8.0;import"./IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/interfaceIERC20MetadataisIERC20{
/**
* @dev Returns the name of the token.
*/functionname() externalviewreturns (stringmemory);
/**
* @dev Returns the symbol of the token.
*/functionsymbol() externalviewreturns (stringmemory);
/**
* @dev Returns the decimals places of the token.
*/functiondecimals() externalviewreturns (uint8);
}
Contract Source Code
File 5 of 10: ILayerZeroEndpoint.sol
// SPDX-License-Identifier: BUSL-1.1pragmasolidity >=0.5.0;import"./ILayerZeroUserApplicationConfig.sol";
interfaceILayerZeroEndpointisILayerZeroUserApplicationConfig{
// @notice send a LayerZero message to the specified address at a LayerZero endpoint.// @param _dstChainId - the destination chain identifier// @param _destination - the address on destination chain (in bytes). address length/format may vary by chains// @param _payload - a custom bytes payload to send to the destination contract// @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address// @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction// @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destinationfunctionsend(uint16 _dstChainId, bytescalldata _destination, bytescalldata _payload, addresspayable _refundAddress, address _zroPaymentAddress, bytescalldata _adapterParams) externalpayable;
// @notice used by the messaging library to publish verified payload// @param _srcChainId - the source chain identifier// @param _srcAddress - the source contract (as bytes) at the source chain// @param _dstAddress - the address on destination chain// @param _nonce - the unbound message ordering nonce// @param _gasLimit - the gas limit for external contract execution// @param _payload - verified payload to send to the destination contractfunctionreceivePayload(uint16 _srcChainId, bytescalldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytescalldata _payload) external;
// @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain// @param _srcChainId - the source chain identifier// @param _srcAddress - the source chain contract addressfunctiongetInboundNonce(uint16 _srcChainId, bytescalldata _srcAddress) externalviewreturns (uint64);
// @notice get the outboundNonce from this source chain which, consequently, is always an EVM// @param _srcAddress - the source chain contract addressfunctiongetOutboundNonce(uint16 _dstChainId, address _srcAddress) externalviewreturns (uint64);
// @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery// @param _dstChainId - the destination chain identifier// @param _userApplication - the user app address on this EVM chain// @param _payload - the custom message to send over LayerZero// @param _payInZRO - if false, user app pays the protocol fee in native token// @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChainfunctionestimateFees(uint16 _dstChainId, address _userApplication, bytescalldata _payload, bool _payInZRO, bytescalldata _adapterParam) externalviewreturns (uint nativeFee, uint zroFee);
// @notice get this Endpoint's immutable source identifierfunctiongetChainId() externalviewreturns (uint16);
// @notice the interface to retry failed message on this Endpoint destination// @param _srcChainId - the source chain identifier// @param _srcAddress - the source chain contract address// @param _payload - the payload to be retriedfunctionretryPayload(uint16 _srcChainId, bytescalldata _srcAddress, bytescalldata _payload) external;
// @notice query if any STORED payload (message blocking) at the endpoint.// @param _srcChainId - the source chain identifier// @param _srcAddress - the source chain contract addressfunctionhasStoredPayload(uint16 _srcChainId, bytescalldata _srcAddress) externalviewreturns (bool);
// @notice query if the _libraryAddress is valid for sending msgs.// @param _userApplication - the user app address on this EVM chainfunctiongetSendLibraryAddress(address _userApplication) externalviewreturns (address);
// @notice query if the _libraryAddress is valid for receiving msgs.// @param _userApplication - the user app address on this EVM chainfunctiongetReceiveLibraryAddress(address _userApplication) externalviewreturns (address);
// @notice query if the non-reentrancy guard for send() is on// @return true if the guard is on. false otherwisefunctionisSendingPayload() externalviewreturns (bool);
// @notice query if the non-reentrancy guard for receive() is on// @return true if the guard is on. false otherwisefunctionisReceivingPayload() externalviewreturns (bool);
// @notice get the configuration of the LayerZero messaging library of the specified version// @param _version - messaging library version// @param _chainId - the chainId for the pending config change// @param _userApplication - the contract address of the user application// @param _configType - type of configuration. every messaging library has its own convention.functiongetConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) externalviewreturns (bytesmemory);
// @notice get the send() LayerZero messaging library version// @param _userApplication - the contract address of the user applicationfunctiongetSendVersion(address _userApplication) externalviewreturns (uint16);
// @notice get the lzReceive() LayerZero messaging library version// @param _userApplication - the contract address of the user applicationfunctiongetReceiveVersion(address _userApplication) externalviewreturns (uint16);
}
Contract Source Code
File 6 of 10: ILayerZeroReceiver.sol
// SPDX-License-Identifier: BUSL-1.1pragmasolidity >=0.5.0;interfaceILayerZeroReceiver{
// @notice LayerZero endpoint will invoke this function to deliver the message on the destination// @param _srcChainId - the source endpoint identifier// @param _srcAddress - the source sending contract address from the source chain// @param _nonce - the ordered message nonce// @param _payload - the signed payload is the UA bytes has encoded to be sentfunctionlzReceive(uint16 _srcChainId, bytescalldata _srcAddress, uint64 _nonce, bytescalldata _payload) external;
}
Contract Source Code
File 7 of 10: ILayerZeroUserApplicationConfig.sol
// SPDX-License-Identifier: BUSL-1.1pragmasolidity >=0.5.0;interfaceILayerZeroUserApplicationConfig{
// @notice set the configuration of the LayerZero messaging library of the specified version// @param _version - messaging library version// @param _chainId - the chainId for the pending config change// @param _configType - type of configuration. every messaging library has its own convention.// @param _config - configuration in the bytes. can encode arbitrary content.functionsetConfig(uint16 _version, uint16 _chainId, uint _configType, bytescalldata _config) external;
// @notice set the send() LayerZero messaging library version to _version// @param _version - new messaging library versionfunctionsetSendVersion(uint16 _version) external;
// @notice set the lzReceive() LayerZero messaging library version to _version// @param _version - new messaging library versionfunctionsetReceiveVersion(uint16 _version) external;
// @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload// @param _srcChainId - the chainId of the source chain// @param _srcAddress - the contract address of the source contract at the source chainfunctionforceResumeReceive(uint16 _srcChainId, bytescalldata _srcAddress) external;
}
Contract Source Code
File 8 of 10: NonBlockingReceiver.sol
pragmasolidity 0.8.4;import"./Ownable.sol";
import"./ILayerZeroReceiver.sol";
import"./ILayerZeroEndpoint.sol";
import"./ILayerZeroReceiver.sol";
abstractcontractNonblockingReceiverisOwnable, ILayerZeroReceiver{
ILayerZeroEndpoint public endpoint;
structFailedMessages {
uint payloadLength;
bytes32 payloadHash;
}
mapping(uint16=>mapping(bytes=>mapping(uint=> FailedMessages))) public failedMessages;
mapping(uint16=>bytes) public trustedSourceLookup;
eventMessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload);
// abstract functionfunction_LzReceive(uint16 _srcChainId, bytesmemory _srcAddress, uint64 _nonce, bytesmemory _payload) virtualinternal;
functionlzReceive(uint16 _srcChainId, bytesmemory _srcAddress, uint64 _nonce, bytesmemory _payload) externaloverride{
require(msg.sender==address(endpoint)); // boilerplate! lzReceive must be called by the endpoint for securityrequire(_srcAddress.length== trustedSourceLookup[_srcChainId].length&&keccak256(_srcAddress) ==keccak256(trustedSourceLookup[_srcChainId]), "NonblockingReceiver: invalid source sending contract");
// try-catch all errors/exceptions// having failed messages does not block messages passingtrythis.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload) {
// do nothing
} catch {
// error / exception
failedMessages[_srcChainId][_srcAddress][_nonce] = FailedMessages(_payload.length, keccak256(_payload));
emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload);
}
}
functiononLzReceive(uint16 _srcChainId, bytesmemory _srcAddress, uint64 _nonce, bytesmemory _payload) public{
// only internal transactionrequire(msg.sender==address(this) ||msg.sender== owner(), "NonblockingReceiver: caller must be Trusted.");
_LzReceive( _srcChainId, _srcAddress, _nonce, _payload);
}
function_lzSend(uint16 _dstChainId, bytesmemory _payload, addresspayable _refundAddress, address _zroPaymentAddress, bytesmemory _txParam) internal{
endpoint.send{value: msg.value}(_dstChainId, trustedSourceLookup[_dstChainId], _payload, _refundAddress, _zroPaymentAddress, _txParam);
}
functionretryMessage(uint16 _srcChainId, bytesmemory _srcAddress, uint64 _nonce, bytescalldata _payload) externalpayable{
// assert there is message to retry
FailedMessages storage failedMsg = failedMessages[_srcChainId][_srcAddress][_nonce];
require(failedMsg.payloadHash !=bytes32(0), "NonblockingReceiver: no stored message");
require(_payload.length== failedMsg.payloadLength &&keccak256(_payload) == failedMsg.payloadHash, "LayerZero: invalid payload");
// clear the stored message
failedMsg.payloadLength =0;
failedMsg.payloadHash =bytes32(0);
// execute the message. revert if it fails againthis.onLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
}
functionsetTrustedSource(uint16 _chainId, bytescalldata _trustedSource) externalonlyOwner{
trustedSourceLookup[_chainId] = _trustedSource;
}
}
Contract Source Code
File 9 of 10: OmniChainToken.sol
// SPDX-License-Identifier: BUSL-1.1pragmasolidity ^0.8.4;import"./IERC20.sol";
import"./ERC20.sol";
import"./Ownable.sol";
import"./ILayerZeroUserApplicationConfig.sol";
import"./ILayerZeroReceiver.sol";
import"./ILayerZeroEndpoint.sol";
import"./NonBlockingReceiver.sol";
// deploy this contract to 2+ chains for testing.//// sendTokens() function works like this:// 1. burn local tokens on the source chain// 2. send a LayerZero message to the destination OmniChainToken contract on another chain// 3. mint tokens on destination in lzReceive()contractOmniChainTokenisERC20, NonblockingReceiver, ILayerZeroUserApplicationConfig{
mapping(uint16=>bytes) public remotes;
addresspublic marketingWallet =payable(0x335b5b3bE5D0cDBcbdb1CBaBEA26a43Ec01f84e9);
addressprivate uniswapV2Router =0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
//New Featuresmapping (address=>bool) public automatedMarketMakerPairs;
mapping (address=>bool) private _isExcludedFromFees;
mapping (address=>bool) private bots;
address[] public potentialBots;
boolpublic tradingActive =false;
uint256private tradingBlock =0;
uint256private sellFees =14;
uint256private buyFees =7;
uint256public maxTxAmount;
uint256public maxWallet;
uint256public fixedSupply =1_000_000_000*10**18;
// constructor mints tokens to the deployerconstructor(stringmemory name_, stringmemory symbol_, address _layerZeroEndpoint) ERC20(name_, symbol_){
endpoint = ILayerZeroEndpoint(_layerZeroEndpoint);
_mint(msg.sender, fixedSupply); // give the deployer initial supply
maxTxAmount = fixedSupply *1/100; //1% of supply
maxWallet = fixedSupply *1/100; //1% of supply
excludeFromFees(owner(), true);
excludeFromFees(address(this), true);
excludeFromFees(marketingWallet, true);
}
functionsetAutomatedMarketMakerPair(address pair, bool value) publiconlyOwner{
automatedMarketMakerPairs[pair] = value;
}
functionsetBots(address[] memory bots_) publiconlyOwner{
for (uint i =0; i < bots_.length; i++) {
bots[bots_[i]] =true;
}
}
functiondelBot(address notbot) publiconlyOwner{
bots[notbot] =false;
}
functionisBot(address bot) publicviewreturns (bool) {
return bots[bot];
}
functionexcludeFromFees(address account, bool excluded) publiconlyOwner{
_isExcludedFromFees[account] = excluded;
}
functionsetMarketingWallet(address newWallet) publiconlyOwner{
marketingWallet = newWallet;
excludeFromFees(newWallet, true);
}
functionsetFees(uint256 _buyFees, uint256 _sellFees) publiconlyOwner{
require(_buyFees <=25&& _sellFees <=25, "Fees must be under 25%");
sellFees = _sellFees;
buyFees = _buyFees;
}
functionblackListPotentialBots() externalonlyOwner{
setBots(potentialBots);
}
functionenableTrading() externalonlyOwner{
tradingBlock =block.number;
tradingActive =true;
}
functionupdateMaxTxnAmount(uint256 newNum) externalonlyOwner{
require(newNum >= fixedSupply /1000, "Cannot set maxTxAmount lower than 0.1%");
maxTxAmount = newNum;
}
functionupdateMaxWalletAmount(uint256 newNum) externalonlyOwner{
require(newNum >= (fixedSupply *5/1000), "Cannot set maxWallet lower than 0.5%");
maxWallet = newNum ;
}
function_transfer(addressfrom,
address to,
uint256 amount
) internaloverride{
require(from!=address(0), "ERC20: transfer from the zero address");
require(to !=address(0), "ERC20: transfer to the zero address");
require(!bots[from] &&!bots[to]);
if(amount ==0) {
super._transfer(from, to, 0);
return;
}
if (
from!= owner() &&
to != owner() &&
to !=address(0) &&
to !=address(0xdead)
){
if(!tradingActive){
require(_isExcludedFromFees[from] || _isExcludedFromFees[to], "Trading is not active.");
}
if (automatedMarketMakerPairs[from] &&!_isExcludedFromFees[to]) {
require(amount <= maxTxAmount, "Buy transfer amount exceeds the maxTxAmount.");
}
//when sellelseif (automatedMarketMakerPairs[to] &&!_isExcludedFromFees[from]) {
require(amount <= maxTxAmount, "Sell transfer amount exceeds the maxTxAmount.");
}
if (!automatedMarketMakerPairs[to] &&!_isExcludedFromFees[from]) {
require(balanceOf(to) + amount < maxWallet, "TOKEN: Balance exceeds wallet size!");
}
if (tradingActive &&block.number<= tradingBlock +2&& automatedMarketMakerPairs[from] && to != uniswapV2Router && to !=address(this)) {
potentialBots.push(to);
}
}
bool takeFee =true;
if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
takeFee =false;
}
uint256 fees =0;
// only take fees on buys/sells, do not take on wallet transfersif(takeFee){
// on sellif (automatedMarketMakerPairs[to] && sellFees >0){
fees = amount * sellFees /100;
}
// on buyelseif(automatedMarketMakerPairs[from] && buyFees >0) {
fees = amount * buyFees /100;
}
if(fees >0){
super._transfer(from, marketingWallet, fees);
}
amount -= fees;
}
super._transfer(from, to, amount);
}
functionmanualSend() externalonlyOwner{
bool success;
(success,) =address(marketingWallet).call{value: address(this).balance}("");
}
// send tokens to another chain.// this function sends the tokens from your address to the same address on the destination.functionsendTokens(uint16 _chainId, // send tokens to this chainIdbytescalldata _dstOmniChainTokenAddr, // destination address of OmniChainTokenuint _qty // how many tokens to send)
publicpayable{
require(!bots[msg.sender]);
// and burn the local tokens *poof*
_burn(msg.sender, _qty);
// abi.encode() the payload with the values to sendbytesmemory payload =abi.encode(msg.sender, _qty);
// send LayerZero message
endpoint.send{value:msg.value}(
_chainId, // destination chainId
_dstOmniChainTokenAddr, // destination address of OmniChainToken
payload, // abi.encode()'ed bytespayable(msg.sender), // refund address (LayerZero will refund any superflous gas back to caller of send()address(0x0), // 'zroPaymentAddress' unused for this mock/examplebytes("") // 'txParameters' unused for this mock/example
);
}
// receive the bytes payload from the source chain via LayerZero// _fromAddress is the source OmniChainToken addressfunction_LzReceive(uint16 _srcChainId, bytesmemory _srcAddress, uint64 _nonce, bytesmemory _payload) internaloverride{
// decode
(address toAddr, uint qty) =abi.decode(_payload, (address, uint));
// mint the tokens back into existence, to the toAddr from the message payload
_mint(toAddr, qty);
}
//---------------------------DAO CALL----------------------------------------// generic config for user ApplicationfunctionsetConfig(uint16 _version,
uint16 _chainId,
uint256 _configType,
bytescalldata _config
) externaloverrideonlyOwner{
endpoint.setConfig(_version, _chainId, _configType, _config);
}
functionsetSendVersion(uint16 _version) externaloverrideonlyOwner{
endpoint.setSendVersion(_version);
}
functionsetReceiveVersion(uint16 _version) externaloverrideonlyOwner{
endpoint.setReceiveVersion(_version);
}
functionforceResumeReceive(uint16 _srcChainId, bytescalldata _srcAddress) externaloverrideonlyOwner{
endpoint.forceResumeReceive(_srcChainId, _srcAddress);
}
}
Contract Source Code
File 10 of 10: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)pragmasolidity ^0.8.0;import"./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.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
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) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}